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"
45#include "llvm/IR/IRBuilder.h"
47#include "llvm/IR/IntrinsicsAMDGPU.h"
48#include "llvm/IR/IntrinsicsR600.h"
49#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
65 return MF.getInfo<SIMachineFunctionInfo>()->getMode().getDenormalFPEnv();
66}
67
72
77
78static unsigned findFirstFreeSGPR(CCState &CCInfo) {
79 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
80 for (unsigned Reg = 0; Reg < NumSGPRs; ++Reg) {
81 if (!CCInfo.isAllocated(AMDGPU::SGPR0 + Reg)) {
82 return AMDGPU::SGPR0 + Reg;
83 }
84 }
85 llvm_unreachable("Cannot allocate sgpr");
86}
87
89 const GCNSubtarget &STI)
90 : AMDGPUTargetLowering(TM, STI, STI), Subtarget(&STI) {
91 addRegisterClass(MVT::i1, &AMDGPU::VReg_1RegClass);
92 addRegisterClass(MVT::i64, &AMDGPU::SReg_64RegClass);
93
94 addRegisterClass(MVT::i32, &AMDGPU::SReg_32RegClass);
95
96 const SIRegisterInfo *TRI = STI.getRegisterInfo();
97 const TargetRegisterClass *V32RegClass =
98 TRI->getDefaultVectorSuperClassForBitWidth(32);
99 addRegisterClass(MVT::f32, V32RegClass);
100
101 addRegisterClass(MVT::v2i32, &AMDGPU::SReg_64RegClass);
102
103 const TargetRegisterClass *V64RegClass =
104 TRI->getDefaultVectorSuperClassForBitWidth(64);
105
106 addRegisterClass(MVT::f64, V64RegClass);
107 addRegisterClass(MVT::v2f32, V64RegClass);
108 addRegisterClass(MVT::Untyped, V64RegClass);
109
110 addRegisterClass(MVT::v3i32, &AMDGPU::SGPR_96RegClass);
111 addRegisterClass(MVT::v3f32, TRI->getDefaultVectorSuperClassForBitWidth(96));
112
113 addRegisterClass(MVT::v2i64, &AMDGPU::SGPR_128RegClass);
114 addRegisterClass(MVT::v2f64, &AMDGPU::SGPR_128RegClass);
115
116 addRegisterClass(MVT::v4i32, &AMDGPU::SGPR_128RegClass);
117 addRegisterClass(MVT::v4f32, TRI->getDefaultVectorSuperClassForBitWidth(128));
118
119 addRegisterClass(MVT::v5i32, &AMDGPU::SGPR_160RegClass);
120 addRegisterClass(MVT::v5f32, TRI->getDefaultVectorSuperClassForBitWidth(160));
121
122 addRegisterClass(MVT::v6i32, &AMDGPU::SGPR_192RegClass);
123 addRegisterClass(MVT::v6f32, TRI->getDefaultVectorSuperClassForBitWidth(192));
124
125 addRegisterClass(MVT::v3i64, &AMDGPU::SGPR_192RegClass);
126 addRegisterClass(MVT::v3f64, TRI->getDefaultVectorSuperClassForBitWidth(192));
127
128 addRegisterClass(MVT::v7i32, &AMDGPU::SGPR_224RegClass);
129 addRegisterClass(MVT::v7f32, TRI->getDefaultVectorSuperClassForBitWidth(224));
130
131 addRegisterClass(MVT::v8i32, &AMDGPU::SGPR_256RegClass);
132 addRegisterClass(MVT::v8f32, TRI->getDefaultVectorSuperClassForBitWidth(256));
133
134 addRegisterClass(MVT::v4i64, &AMDGPU::SGPR_256RegClass);
135 addRegisterClass(MVT::v4f64, TRI->getDefaultVectorSuperClassForBitWidth(256));
136
137 addRegisterClass(MVT::v9i32, &AMDGPU::SGPR_288RegClass);
138 addRegisterClass(MVT::v9f32, TRI->getDefaultVectorSuperClassForBitWidth(288));
139
140 addRegisterClass(MVT::v10i32, &AMDGPU::SGPR_320RegClass);
141 addRegisterClass(MVT::v10f32,
142 TRI->getDefaultVectorSuperClassForBitWidth(320));
143
144 addRegisterClass(MVT::v11i32, &AMDGPU::SGPR_352RegClass);
145 addRegisterClass(MVT::v11f32,
146 TRI->getDefaultVectorSuperClassForBitWidth(352));
147
148 addRegisterClass(MVT::v12i32, &AMDGPU::SGPR_384RegClass);
149 addRegisterClass(MVT::v12f32,
150 TRI->getDefaultVectorSuperClassForBitWidth(384));
151
152 addRegisterClass(MVT::v16i32, &AMDGPU::SGPR_512RegClass);
153 addRegisterClass(MVT::v16f32,
154 TRI->getDefaultVectorSuperClassForBitWidth(512));
155
156 addRegisterClass(MVT::v8i64, &AMDGPU::SGPR_512RegClass);
157 addRegisterClass(MVT::v8f64, TRI->getDefaultVectorSuperClassForBitWidth(512));
158
159 addRegisterClass(MVT::v16i64, &AMDGPU::SGPR_1024RegClass);
160 addRegisterClass(MVT::v16f64,
161 TRI->getDefaultVectorSuperClassForBitWidth(1024));
162
163 if (Subtarget->has16BitInsts()) {
164 if (Subtarget->useRealTrue16Insts()) {
165 addRegisterClass(MVT::i16, &AMDGPU::VGPR_16RegClass);
166 addRegisterClass(MVT::f16, &AMDGPU::VGPR_16RegClass);
167 addRegisterClass(MVT::bf16, &AMDGPU::VGPR_16RegClass);
168 } else {
169 addRegisterClass(MVT::i16, &AMDGPU::SReg_32RegClass);
170 addRegisterClass(MVT::f16, &AMDGPU::SReg_32RegClass);
171 addRegisterClass(MVT::bf16, &AMDGPU::SReg_32RegClass);
172 }
173
174 // Unless there are also VOP3P operations, not operations are really legal.
175 addRegisterClass(MVT::v2i16, &AMDGPU::SReg_32RegClass);
176 addRegisterClass(MVT::v2f16, &AMDGPU::SReg_32RegClass);
177 addRegisterClass(MVT::v2bf16, &AMDGPU::SReg_32RegClass);
178 addRegisterClass(MVT::v4i16, &AMDGPU::SReg_64RegClass);
179 addRegisterClass(MVT::v4f16, &AMDGPU::SReg_64RegClass);
180 addRegisterClass(MVT::v4bf16, &AMDGPU::SReg_64RegClass);
181 addRegisterClass(MVT::v8i16, &AMDGPU::SGPR_128RegClass);
182 addRegisterClass(MVT::v8f16, &AMDGPU::SGPR_128RegClass);
183 addRegisterClass(MVT::v8bf16, &AMDGPU::SGPR_128RegClass);
184 addRegisterClass(MVT::v16i16, &AMDGPU::SGPR_256RegClass);
185 addRegisterClass(MVT::v16f16, &AMDGPU::SGPR_256RegClass);
186 addRegisterClass(MVT::v16bf16, &AMDGPU::SGPR_256RegClass);
187 addRegisterClass(MVT::v32i16, &AMDGPU::SGPR_512RegClass);
188 addRegisterClass(MVT::v32f16, &AMDGPU::SGPR_512RegClass);
189 addRegisterClass(MVT::v32bf16, &AMDGPU::SGPR_512RegClass);
190 }
191
192 addRegisterClass(MVT::v32i32, &AMDGPU::VReg_1024RegClass);
193 addRegisterClass(MVT::v32f32,
194 TRI->getDefaultVectorSuperClassForBitWidth(1024));
195
196 computeRegisterProperties(Subtarget->getRegisterInfo());
197
200
201 // The boolean content concept here is too inflexible. Compares only ever
202 // really produce a 1-bit result. Any copy/extend from these will turn into a
203 // select, and zext/1 or sext/-1 are equally cheap. Arbitrarily choose 0/1, as
204 // it's what most targets use.
207
208 // We need to custom lower vector stores from local memory
210 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
211 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
212 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
213 MVT::i1, MVT::v32i32},
214 Custom);
215
217 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
218 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
219 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
220 MVT::i1, MVT::v32i32},
221 Custom);
222
223 if (isTypeLegal(MVT::bf16)) {
224 for (unsigned Opc :
233 ISD::SETCC}) {
234 setOperationAction(Opc, MVT::bf16, Promote);
235 }
236
237 // Only targets with packed bf16 instructions, e.g. gfx13.
238 if (Subtarget->hasBF16PackedInsts()) {
239 // Don't use Expand for fsub - the DAG combiner will undo fadd+fneg back
240 // to fsub, causing a libcall (which doesn't exist for bf16). Instead,
241 // directly expand to widened v2bf16 operations.
244 Promote);
245 // Promote scalar operations to a v2bf16 operation with an unused high
246 // lane.
247 for (unsigned Opc :
250 AddPromotedToType(Opc, MVT::bf16, MVT::v2bf16);
251 }
252
254
256 AddPromotedToType(ISD::SELECT, MVT::bf16, MVT::i16);
257
261
262 // We only need to custom lower because we can't specify an action for bf16
263 // sources.
266 }
267
268 setTruncStoreAction(MVT::v2i32, MVT::v2i16, Expand);
269 setTruncStoreAction(MVT::v3i32, MVT::v3i16, Expand);
270 setTruncStoreAction(MVT::v4i32, MVT::v4i16, Expand);
271 setTruncStoreAction(MVT::v8i32, MVT::v8i16, Expand);
272 setTruncStoreAction(MVT::v16i32, MVT::v16i16, Expand);
273 setTruncStoreAction(MVT::v32i32, MVT::v32i16, Expand);
274 setTruncStoreAction(MVT::v2i32, MVT::v2i8, Expand);
275 setTruncStoreAction(MVT::v4i32, MVT::v4i8, Expand);
276 setTruncStoreAction(MVT::v8i32, MVT::v8i8, Expand);
277 setTruncStoreAction(MVT::v16i32, MVT::v16i8, Expand);
278 setTruncStoreAction(MVT::v32i32, MVT::v32i8, Expand);
279 setTruncStoreAction(MVT::v2i16, MVT::v2i8, Expand);
280 setTruncStoreAction(MVT::v4i16, MVT::v4i8, Expand);
281 setTruncStoreAction(MVT::v8i16, MVT::v8i8, Expand);
282 setTruncStoreAction(MVT::v16i16, MVT::v16i8, Expand);
283 setTruncStoreAction(MVT::v32i16, MVT::v32i8, Expand);
284
285 setTruncStoreAction(MVT::v3i64, MVT::v3i16, Expand);
286 setTruncStoreAction(MVT::v3i64, MVT::v3i32, Expand);
287 setTruncStoreAction(MVT::v4i64, MVT::v4i8, Expand);
288 setTruncStoreAction(MVT::v8i64, MVT::v8i8, Expand);
289 setTruncStoreAction(MVT::v8i64, MVT::v8i16, Expand);
290 setTruncStoreAction(MVT::v8i64, MVT::v8i32, Expand);
291 setTruncStoreAction(MVT::v16i64, MVT::v16i32, Expand);
292
293 setOperationAction(ISD::GlobalAddress, {MVT::i32, MVT::i64}, Custom);
294 setOperationAction(ISD::BlockAddress, {MVT::i32, MVT::i64}, Custom);
295 setOperationAction(ISD::ExternalSymbol, {MVT::i32, MVT::i64}, Custom);
296
300 AddPromotedToType(ISD::SELECT, MVT::f64, MVT::i64);
301
302 setOperationAction(ISD::FSQRT, {MVT::f32, MVT::f64}, Custom);
303
305 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1}, Expand);
306
308 setOperationAction(ISD::SETCC, {MVT::v2i1, MVT::v4i1}, Expand);
309 AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32);
310
312 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
313 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
314 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
315 Expand);
317 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
318 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
319 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
320 Expand);
321
323 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
324 MVT::v3i16, MVT::v4i16, MVT::Other},
325 Custom);
326
329 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64}, Expand);
330
333
336
338 Expand);
339
341
342 // We only support LOAD/STORE and vector manipulation ops for vectors
343 // with > 4 elements.
344 for (MVT VT :
345 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
346 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
347 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
348 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
349 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
350 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
351 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
352 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
353 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
354 switch (Op) {
355 case ISD::LOAD:
356 case ISD::STORE:
357 case ISD::ATOMIC_LOAD:
360 case ISD::BITCAST:
361 case ISD::UNDEF:
362 case ISD::POISON:
366 case ISD::IS_FPCLASS:
367 break;
372 break;
373 default:
375 break;
376 }
377 }
378 }
379
381
382 // TODO: For dynamic 64-bit vector inserts/extracts, should emit a pseudo that
383 // is expanded to avoid having two separate loops in case the index is a VGPR.
384
385 // Most operations are naturally 32-bit vector operations. We only support
386 // load and store of i64 vectors, so promote v2i64 vector operations to v4i32.
387 for (MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
389 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v4i32);
390
392 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v4i32);
393
395 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v4i32);
396
398 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v4i32);
399 }
400
401 for (MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
403 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v6i32);
404
406 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v6i32);
407
409 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v6i32);
410
412 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v6i32);
413 }
414
415 for (MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
417 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v8i32);
418
420 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v8i32);
421
423 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v8i32);
424
426 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v8i32);
427 }
428
429 for (MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
431 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v16i32);
432
434 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v16i32);
435
437 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v16i32);
438
440 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v16i32);
441 }
442
443 for (MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
445 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v32i32);
446
448 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v32i32);
449
451 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v32i32);
452
454 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v32i32);
455 }
456
458 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
459 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
460 Custom);
461
462 if (Subtarget->hasPkMovB32()) {
463 // TODO: 16-bit element vectors should be legal with even aligned elements.
464 // TODO: Can be legal with wider source types than the result with
465 // subregister extracts.
466 setOperationAction(ISD::VECTOR_SHUFFLE, {MVT::v2i32, MVT::v2f32}, Legal);
467 }
468
470 // Prevent SELECT v2i32 from being implemented with the above bitwise ops and
471 // instead lower to cndmask in SITargetLowering::LowerSELECT().
473 // Enable MatchRotate to produce ISD::ROTR, which is later transformed to
474 // alignbit.
475 setOperationAction(ISD::ROTR, MVT::v2i32, Custom);
476
477 setOperationAction(ISD::BUILD_VECTOR, {MVT::v4f16, MVT::v4i16, MVT::v4bf16},
478 Custom);
479
480 // Avoid stack access for these.
481 // TODO: Generalize to wider i8 vectors.
483 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
484 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
485 Custom);
486
487 // Deal with vec3 vector operations when widened to vec4.
489 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32}, Custom);
490
491 // Deal with vec5/6/7 vector operations when widened to vec8.
493 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
494 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
495 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
496 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
497 Custom);
498
499 // BUFFER/FLAT_ATOMIC_CMP_SWAP on GCN GPUs needs input marshalling,
500 // and output demarshalling
501 setOperationAction(ISD::ATOMIC_CMP_SWAP, {MVT::i32, MVT::i64}, Custom);
502
503 // We can't return success/failure, only the old value,
504 // let LLVM add the comparison
506 Expand);
507
508 setOperationAction(ISD::ADDRSPACECAST, {MVT::i32, MVT::i64}, Custom);
509
510 setOperationAction(ISD::BITREVERSE, {MVT::i32, MVT::i64}, Legal);
511
512 // FIXME: This should be narrowed to i32, but that only happens if i64 is
513 // illegal.
514 // FIXME: Should lower sub-i32 bswaps to bit-ops without v_perm_b32.
515 setOperationAction(ISD::BSWAP, {MVT::i64, MVT::i32}, Legal);
516
517 // On SI this is s_memtime and s_memrealtime on VI.
519
520 if (Subtarget->hasSMemRealTime() ||
521 Subtarget->getGeneration() >= AMDGPUSubtarget::GFX11)
524
525 if (Subtarget->has16BitInsts()) {
528 setOperationAction(ISD::IS_FPCLASS, {MVT::f16, MVT::f32, MVT::f64}, Legal);
531 } else {
533 }
534
535 if (Subtarget->hasMadMacF32Insts())
537
541
542 // We only really have 32-bit BFE instructions (and 16-bit on VI).
543 //
544 // On SI+ there are 64-bit BFEs, but they are scalar only and there isn't any
545 // effort to match them now. We want this to be false for i64 cases when the
546 // extraction isn't restricted to the upper or lower half. Ideally we would
547 // have some pass reduce 64-bit extracts to 32-bit if possible. Extracts that
548 // span the midpoint are probably relatively rare, so don't worry about them
549 // for now.
551
552 // Clamp modifier on add/sub
553 if (Subtarget->hasIntClamp())
555
556 if (Subtarget->hasAddNoCarryInsts())
557 setOperationAction({ISD::SADDSAT, ISD::SSUBSAT}, {MVT::i16, MVT::i32},
558 Legal);
559
560 // Do not have s_{min|max}_*f64 instruction f64 will only be lowered to
561 // v_{min|max}_*f64
562 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
565 {MVT::f64, MVT::f32}, Legal);
566 } else {
569 {MVT::f64, MVT::f32}, Custom);
570 // These are really only legal for ieee_mode functions. We should be
571 // avoiding them for functions that don't have ieee_mode enabled, so just
572 // say they are legal.
574 {MVT::f64, MVT::f32}, Legal);
575 }
576
577 if (Subtarget->haveRoundOpsF64())
579 Legal);
580 else
582 MVT::f64, Custom);
583
585 setOperationAction({ISD::FLDEXP, ISD::STRICT_FLDEXP}, {MVT::f32, MVT::f64},
586 Legal);
587 setOperationAction(ISD::FFREXP, {MVT::f32, MVT::f64}, Custom);
588
591
592 setOperationAction(ISD::BF16_TO_FP, {MVT::i16, MVT::f32, MVT::f64}, Expand);
593 setOperationAction(ISD::FP_TO_BF16, {MVT::i16, MVT::f32, MVT::f64}, Expand);
594
596 Custom);
598 Custom);
600 Custom);
601
602 // Custom lower these because we can't specify a rule based on an illegal
603 // source bf16.
606
607 if (Subtarget->has16BitInsts()) {
610 MVT::i16, Legal);
611
612 AddPromotedToType(ISD::SIGN_EXTEND, MVT::i16, MVT::i32);
613
615 MVT::i16, Expand);
616
620 ISD::CTPOP},
621 MVT::i16, Promote);
622
624
625 setTruncStoreAction(MVT::i64, MVT::i16, Expand);
626
628 AddPromotedToType(ISD::FP16_TO_FP, MVT::i16, MVT::i32);
630 AddPromotedToType(ISD::FP_TO_FP16, MVT::i16, MVT::i32);
631
636
638
639 // F16 - Constant Actions.
642
643 // F16 - Load/Store Actions.
645 AddPromotedToType(ISD::LOAD, MVT::f16, MVT::i16);
647 AddPromotedToType(ISD::STORE, MVT::f16, MVT::i16);
648
649 // BF16 - Load/Store Actions.
651 AddPromotedToType(ISD::LOAD, MVT::bf16, MVT::i16);
653 AddPromotedToType(ISD::STORE, MVT::bf16, MVT::i16);
654
655 if (!Subtarget->useRealTrue16Insts() ||
656 !Subtarget->d16PreservesUnusedBits()) {
657 for (MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
659 AddPromotedToType(ISD::ATOMIC_LOAD, VT, MVT::i32);
660 }
661 }
662
663 if (!Subtarget->useRealTrue16Insts()) {
664 for (MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
667 }
668 }
669
670 // F16 - VOP1 Actions.
673 MVT::f16, Custom);
674
675 // BF16 - VOP1 Actions.
676 if (Subtarget->hasBF16TransInsts())
678
679 // F16 - VOP2 Actions.
680 setOperationAction({ISD::BR_CC, ISD::SELECT_CC}, {MVT::f16, MVT::bf16},
681 Expand);
685
686 // F16 - VOP3 Actions.
688 if (STI.hasMadF16())
690
691 for (MVT VT :
692 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
693 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
694 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
695 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
696 switch (Op) {
697 case ISD::LOAD:
698 case ISD::STORE:
699 case ISD::ATOMIC_LOAD:
702 case ISD::BITCAST:
703 case ISD::UNDEF:
704 case ISD::POISON:
709 case ISD::IS_FPCLASS:
710 break;
713 case ISD::FSIN:
714 case ISD::FCOS:
716 break;
717 default:
719 break;
720 }
721 }
722 }
723
724 // v_perm_b32 can handle either of these.
725 setOperationAction(ISD::BSWAP, {MVT::i16, MVT::v2i16}, Legal);
727
728 // Legalize vector types for sat conversions to select v_cvt_pk_[iu]16_f32.
729 if (Subtarget->hasVCvtPkIU16F32())
732 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
733 Custom);
734
735 // XXX - Do these do anything? Vector constants turn into build_vector.
736 setOperationAction(ISD::Constant, {MVT::v2i16, MVT::v2f16}, Legal);
737
739 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Legal);
740
742 AddPromotedToType(ISD::STORE, MVT::v2i16, MVT::i32);
744 AddPromotedToType(ISD::STORE, MVT::v2f16, MVT::i32);
745
747 AddPromotedToType(ISD::LOAD, MVT::v2i16, MVT::i32);
749 AddPromotedToType(ISD::LOAD, MVT::v2f16, MVT::i32);
750
751 setOperationAction(ISD::AND, MVT::v2i16, Promote);
752 AddPromotedToType(ISD::AND, MVT::v2i16, MVT::i32);
753 setOperationAction(ISD::OR, MVT::v2i16, Promote);
754 AddPromotedToType(ISD::OR, MVT::v2i16, MVT::i32);
755 setOperationAction(ISD::XOR, MVT::v2i16, Promote);
756 AddPromotedToType(ISD::XOR, MVT::v2i16, MVT::i32);
757
759 AddPromotedToType(ISD::LOAD, MVT::v4i16, MVT::v2i32);
761 AddPromotedToType(ISD::LOAD, MVT::v4f16, MVT::v2i32);
762 setOperationAction(ISD::LOAD, MVT::v4bf16, Promote);
763 AddPromotedToType(ISD::LOAD, MVT::v4bf16, MVT::v2i32);
764
766 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
768 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
770 AddPromotedToType(ISD::STORE, MVT::v4bf16, MVT::v2i32);
771
773 AddPromotedToType(ISD::LOAD, MVT::v8i16, MVT::v4i32);
775 AddPromotedToType(ISD::LOAD, MVT::v8f16, MVT::v4i32);
776 setOperationAction(ISD::LOAD, MVT::v8bf16, Promote);
777 AddPromotedToType(ISD::LOAD, MVT::v8bf16, MVT::v4i32);
778
780 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
782 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
783
785 AddPromotedToType(ISD::STORE, MVT::v8i16, MVT::v4i32);
787 AddPromotedToType(ISD::STORE, MVT::v8f16, MVT::v4i32);
789 AddPromotedToType(ISD::STORE, MVT::v8bf16, MVT::v4i32);
790
791 setOperationAction(ISD::LOAD, MVT::v16i16, Promote);
792 AddPromotedToType(ISD::LOAD, MVT::v16i16, MVT::v8i32);
793 setOperationAction(ISD::LOAD, MVT::v16f16, Promote);
794 AddPromotedToType(ISD::LOAD, MVT::v16f16, MVT::v8i32);
795 setOperationAction(ISD::LOAD, MVT::v16bf16, Promote);
796 AddPromotedToType(ISD::LOAD, MVT::v16bf16, MVT::v8i32);
797
799 AddPromotedToType(ISD::STORE, MVT::v16i16, MVT::v8i32);
801 AddPromotedToType(ISD::STORE, MVT::v16f16, MVT::v8i32);
802 setOperationAction(ISD::STORE, MVT::v16bf16, Promote);
803 AddPromotedToType(ISD::STORE, MVT::v16bf16, MVT::v8i32);
804
805 setOperationAction(ISD::LOAD, MVT::v32i16, Promote);
806 AddPromotedToType(ISD::LOAD, MVT::v32i16, MVT::v16i32);
807 setOperationAction(ISD::LOAD, MVT::v32f16, Promote);
808 AddPromotedToType(ISD::LOAD, MVT::v32f16, MVT::v16i32);
809 setOperationAction(ISD::LOAD, MVT::v32bf16, Promote);
810 AddPromotedToType(ISD::LOAD, MVT::v32bf16, MVT::v16i32);
811
813 AddPromotedToType(ISD::STORE, MVT::v32i16, MVT::v16i32);
815 AddPromotedToType(ISD::STORE, MVT::v32f16, MVT::v16i32);
816 setOperationAction(ISD::STORE, MVT::v32bf16, Promote);
817 AddPromotedToType(ISD::STORE, MVT::v32bf16, MVT::v16i32);
818
820 MVT::v2i32, Expand);
822
824 MVT::v4i32, Expand);
825
827 MVT::v8i32, Expand);
828
829 setOperationAction(ISD::BUILD_VECTOR, {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
830 Subtarget->hasVOP3PInsts() ? Legal : Custom);
831
832 setOperationAction(ISD::FNEG, {MVT::v2f16, MVT::v2bf16}, Legal);
833 // This isn't really legal, but this avoids the legalizer unrolling it (and
834 // allows matching fneg (fabs x) patterns)
835 setOperationAction(ISD::FABS, {MVT::v2f16, MVT::v2bf16}, Legal);
836
837 // Can do this in one BFI plus a constant materialize.
839 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
840 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
841 MVT::v32f16, MVT::v32bf16},
842 Custom);
843 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
846 MVT::f16, Legal);
847
850 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16}, Custom);
851 } else {
854 MVT::f16, Custom);
855
857 Legal);
858
861 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
862 Custom);
863
865 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
866 Expand);
867 }
868
869 for (MVT Vec16 :
870 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
871 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
874 Vec16, Custom);
875 }
876 }
877
878 if (Subtarget->hasVOP3PInsts()) {
882 MVT::v2i16, Legal);
883
886 MVT::v2f16, Legal);
887
889 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Custom);
890
892 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
893 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
894 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
895 Custom);
896
897 for (MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
898 // Split vector operations.
903 VT, Custom);
904
905 for (MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
906 // Split vector operations.
909 VT, Custom);
910
911 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
914 MVT::v2f16, Legal);
915 } else {
917 Legal);
918
921 {MVT::v2f16, MVT::v4f16}, Custom);
922 }
923 setOperationAction(ISD::FEXP, MVT::v2f16, Custom);
924 setOperationAction(ISD::SELECT, {MVT::v4i16, MVT::v4f16, MVT::v4bf16},
925 Custom);
926
927 if (Subtarget->hasBF16PackedInsts()) {
931 MVT::v2bf16, Legal);
932
933 for (MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
934 // Split vector operations.
938 VT, Custom);
939 }
940
941 if (Subtarget->hasAnyPackedFP32Ops()) {
943 MVT::v2f32, Legal);
945 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
946 Custom);
947 }
948 if (Subtarget->hasAnyPackedFP64Ops()) {
951 MVT::v2f64, Legal);
954 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64}, Custom);
955
956 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
959 MVT::v2f64, Legal);
960
963 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64}, Custom);
964 } else {
966 Legal);
969 MVT::v2f64, Custom);
972 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
973 Custom);
974 }
975 }
976
977 if (Subtarget->hasAnyPackedU64Ops()) {
979 MVT::v2i64, Legal);
981 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
982 Custom);
983 }
984 }
985
987
988 if (Subtarget->has16BitInsts()) {
990 AddPromotedToType(ISD::SELECT, MVT::v2i16, MVT::i32);
992 AddPromotedToType(ISD::SELECT, MVT::v2f16, MVT::i32);
994 AddPromotedToType(ISD::SELECT, MVT::v2bf16, MVT::i32);
995 } else {
996 // Legalization hack.
997 setOperationAction(ISD::SELECT, {MVT::v2i16, MVT::v2f16}, Custom);
998
1000 }
1001
1003 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
1004 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1005 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
1006 MVT::v32f16, MVT::v32bf16},
1007 Custom);
1008
1010
1011 if (Subtarget->useVMulU64Inst())
1012 setOperationAction(ISD::MUL, MVT::i64, Legal);
1013 else if (Subtarget->hasScalarSMulU64())
1015
1016 if (Subtarget->hasMad64_32())
1018
1019 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
1021 // Type legalization cannot expand the i128 pointer of a buffer resource
1022 // prefetch; lowerPREFETCH drops the prefetch instead.
1024
1025 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
1027 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16}, Legal);
1028 } else {
1029 // FIXME: For nnan fmaximum, emit the fmaximum3 instead of fmaxnum
1030 if (Subtarget->hasMinimum3Maximum3F32())
1032
1033 if (Subtarget->hasMinimum3Maximum3PKF16()) {
1035
1036 // If only the vector form is available, we need to widen to a vector.
1037 if (!Subtarget->hasMinimum3Maximum3F16())
1039 MVT::v2f16);
1040 }
1041 }
1042
1043 if (Subtarget->hasVOP3PInsts()) {
1044 // We want to break these into v2f16 pieces, not scalarize.
1046 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1047 Custom);
1048 }
1049
1050 if (Subtarget->useMinMaxI64Insts())
1052 Legal);
1053
1055 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1056 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1057 MVT::i8},
1058 Custom);
1059
1061 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1062 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1063 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1064 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1065 Custom);
1066
1067 // The s_buffer_load intrinsics accept any result type in IR, but only a few
1068 // of them can be selected. Mark the remaining illegal result types Custom so
1069 // ReplaceNodeResults gets a chance to diagnose them instead of letting the
1070 // type legalizer abort. Its INTRINSIC_WO_CHAIN case dispatches on the
1071 // intrinsic ID, but INTRINSIC_W_CHAIN does not, so remember the types added
1072 // here to keep other chained intrinsics on generic legalization.
1073 for (MVT VT : MVT::all_valuetypes()) {
1074 if (VT.isScalableVector() || isTypeLegal(VT))
1075 continue;
1079 SBufferLoadDiagnosticVTs.set(VT.SimpleTy);
1080 }
1081 }
1082
1084 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1085 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1086 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1087 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1088 Custom);
1089
1095
1096 // TODO: Could move this to custom lowering, could benefit from combines on
1097 // extract of relevant bits.
1099
1101
1102 if (Subtarget->hasBF16ConversionInsts()) {
1104 {MVT::bf16, MVT::v2bf16}, Custom);
1106 }
1107
1108 if (Subtarget->hasBF16TransInsts()) {
1110 }
1111
1112 const bool HasE5M3ConversionInsts =
1113 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
1114 if (Subtarget->hasOCPFP8ConversionInsts() || HasE5M3ConversionInsts) {
1115 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f32, MVT::v2f32},
1116 Custom);
1118
1119 // i8 result promotes to i16, wider vectors split down to v2i8, and v2i8 is
1120 // handled in ReplaceNodeResults before the legalizer splits it per lane.
1121 setOperationAction(ISD::CONVERT_TO_ARBITRARY_FP, {MVT::i16, MVT::v2i8},
1122 Custom);
1123 }
1124
1125 if (Subtarget->hasFP8F16ConversionInsts()) {
1126 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f16, MVT::v2f16},
1127 Custom);
1128 }
1129
1130 if (Subtarget->hasCvtPkF16F32Inst()) {
1132 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1133 Custom);
1134 }
1135
1138 ISD::SUB,
1139 ISD::MUL,
1140 ISD::FADD,
1141 ISD::FSUB,
1142 ISD::FDIV,
1143 ISD::FMUL,
1152 ISD::FMA,
1153 ISD::ABS,
1154 ISD::SMIN,
1155 ISD::SMAX,
1156 ISD::UMIN,
1157 ISD::UMAX,
1158 ISD::SETCC,
1160 ISD::SMIN,
1161 ISD::SMAX,
1162 ISD::UMIN,
1163 ISD::UMAX,
1166 ISD::AND,
1167 ISD::OR,
1168 ISD::XOR,
1169 ISD::SHL,
1170 ISD::SRL,
1171 ISD::SRA,
1172 ISD::FSHR,
1184
1185 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1187
1188 // All memory operations. Some folding on the pointer operand is done to help
1189 // matching the constant offsets in the addressing modes.
1191 ISD::STORE,
1216
1217 // FIXME: In other contexts we pretend this is a per-function property.
1219
1221}
1222
1223const GCNSubtarget *SITargetLowering::getSubtarget() const { return Subtarget; }
1224
1226 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1227 return RCRegs;
1228}
1229
1230//===----------------------------------------------------------------------===//
1231// TargetLowering queries
1232//===----------------------------------------------------------------------===//
1233
1234// v_mad_mix* support a conversion from f16 to f32.
1235//
1236// There is only one special case when denormals are enabled we don't currently,
1237// where this is OK to use.
1238bool SITargetLowering::isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode,
1239 EVT DestVT, EVT SrcVT) const {
1240 return DestVT.getScalarType() == MVT::f32 &&
1241 ((((Opcode == ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1242 (Opcode == ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1243 SrcVT.getScalarType() == MVT::f16) ||
1244 (Opcode == ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1245 SrcVT.getScalarType() == MVT::bf16)) &&
1246 // TODO: This probably only requires no input flushing?
1248}
1249
1251 LLT DestTy, LLT SrcTy) const {
1252 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1253 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1254 DestTy.getScalarSizeInBits() == 32 &&
1255 SrcTy.getScalarSizeInBits() == 16 &&
1256 // TODO: This probably only requires no input flushing?
1257 denormalModeIsFlushAllF32(*MI.getMF());
1258}
1259
1261 // SI has some legal vector types, but no legal vector operations. Say no
1262 // shuffles are legal in order to prefer scalarizing some vector operations.
1263 return false;
1264}
1265
1268 EVT VT) const {
1271
1272 if (VT.isVector()) {
1273 EVT ScalarVT = VT.getScalarType();
1274 unsigned Size = ScalarVT.getSizeInBits();
1275 if (Size == 16) {
1276 return Subtarget->has16BitInsts()
1277 ? MVT::getVectorVT(ScalarVT.getSimpleVT(), 2)
1278 : MVT::i32;
1279 }
1280
1281 if (Size < 16)
1282 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1283 return Size == 32 ? ScalarVT.getSimpleVT() : MVT::i32;
1284 }
1285
1286 if (!Subtarget->has16BitInsts() && VT.getSizeInBits() == 16)
1287 return MVT::i32;
1288
1289 if (VT.getSizeInBits() > 32)
1290 return MVT::i32;
1291
1293}
1294
1297 EVT VT) const {
1300
1301 if (VT.isVector()) {
1302 unsigned NumElts = VT.getVectorNumElements();
1303 EVT ScalarVT = VT.getScalarType();
1304 unsigned Size = ScalarVT.getSizeInBits();
1305
1306 // FIXME: Should probably promote 8-bit vectors to i16.
1307 if (Size == 16)
1308 return (NumElts + 1) / 2;
1309
1310 if (Size <= 32)
1311 return NumElts;
1312
1313 if (Size > 32)
1314 return NumElts * ((Size + 31) / 32);
1315 } else if (VT.getSizeInBits() > 32)
1316 return (VT.getSizeInBits() + 31) / 32;
1317
1319}
1320
1322 LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT,
1323 unsigned &NumIntermediates, MVT &RegisterVT) const {
1324 if (CC != CallingConv::AMDGPU_KERNEL && VT.isVector()) {
1325 unsigned NumElts = VT.getVectorNumElements();
1326 EVT ScalarVT = VT.getScalarType();
1327 unsigned Size = ScalarVT.getSizeInBits();
1328 // FIXME: We should fix the ABI to be the same on targets without 16-bit
1329 // support, but unless we can properly handle 3-vectors, it will be still be
1330 // inconsistent.
1331 if (Size == 16) {
1332 MVT SimpleIntermediateVT =
1334 IntermediateVT = SimpleIntermediateVT;
1335 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1336 NumIntermediates = (NumElts + 1) / 2;
1337 return (NumElts + 1) / 2;
1338 }
1339
1340 if (Size == 32) {
1341 RegisterVT = ScalarVT.getSimpleVT();
1342 IntermediateVT = RegisterVT;
1343 NumIntermediates = NumElts;
1344 return NumIntermediates;
1345 }
1346
1347 if (Size < 16 && Subtarget->has16BitInsts()) {
1348 // FIXME: Should probably form v2i16 pieces
1349 RegisterVT = MVT::i16;
1350 IntermediateVT = ScalarVT;
1351 NumIntermediates = NumElts;
1352 return NumIntermediates;
1353 }
1354
1355 if (Size != 16 && Size <= 32) {
1356 RegisterVT = MVT::i32;
1357 IntermediateVT = ScalarVT;
1358 NumIntermediates = NumElts;
1359 return NumIntermediates;
1360 }
1361
1362 if (Size > 32) {
1363 RegisterVT = MVT::i32;
1364 IntermediateVT = RegisterVT;
1365 NumIntermediates = NumElts * ((Size + 31) / 32);
1366 return NumIntermediates;
1367 }
1368 }
1369
1371 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1372}
1373
1375 const DataLayout &DL, Type *Ty,
1376 unsigned MaxNumLanes) {
1377 assert(MaxNumLanes != 0);
1378
1379 LLVMContext &Ctx = Ty->getContext();
1380 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1381 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1382 return EVT::getVectorVT(Ctx, TLI.getValueType(DL, VT->getElementType()),
1383 NumElts);
1384 }
1385
1386 return TLI.getValueType(DL, Ty);
1387}
1388
1389// Peek through TFE struct returns to only use the data size.
1391 const DataLayout &DL, Type *Ty,
1392 unsigned MaxNumLanes) {
1393 auto *ST = dyn_cast<StructType>(Ty);
1394 if (!ST)
1395 return memVTFromLoadIntrData(TLI, DL, Ty, MaxNumLanes);
1396
1397 // TFE intrinsics return an aggregate type.
1398 assert(ST->getNumContainedTypes() == 2 &&
1399 ST->getContainedType(1)->isIntegerTy(32));
1400 return memVTFromLoadIntrData(TLI, DL, ST->getContainedType(0), MaxNumLanes);
1401}
1402
1403/// Map address space 7 to MVT::amdgpuBufferFatPointer because that's its
1404/// in-memory representation. This return value is a custom type because there
1405/// is no MVT::i160 and adding one breaks integer promotion logic. While this
1406/// could cause issues during codegen, these address space 7 pointers will be
1407/// rewritten away by then. Therefore, we can return MVT::amdgpuBufferFatPointer
1408/// in order to allow pre-codegen passes that query TargetTransformInfo, often
1409/// for cost modeling, to work. (This also sets us up decently for doing the
1410/// buffer lowering in GlobalISel if SelectionDAG ever goes away.)
1412 if (AMDGPUAS::BUFFER_FAT_POINTER == AS && DL.getPointerSizeInBits(AS) == 160)
1413 return MVT::amdgpuBufferFatPointer;
1415 DL.getPointerSizeInBits(AS) == 192)
1416 return MVT::amdgpuBufferStridedPointer;
1418}
1419/// Similarly, the in-memory representation of a p7 is {p8, i32}, aka
1420/// v8i32 when padding is added.
1421/// The in-memory representation of a p9 is {p8, i32, i32}, which is
1422/// also v8i32 with padding.
1424 if ((AMDGPUAS::BUFFER_FAT_POINTER == AS &&
1425 DL.getPointerSizeInBits(AS) == 160) ||
1427 DL.getPointerSizeInBits(AS) == 192))
1428 return MVT::v8i32;
1430}
1431
1432static unsigned getIntrMemWidth(unsigned IntrID) {
1433 switch (IntrID) {
1434 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1435 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1436 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1437 return 8;
1438 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1439 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1440 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1441 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1442 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1443 case Intrinsic::amdgcn_flat_load_monitor_b32:
1444 case Intrinsic::amdgcn_global_load_monitor_b32:
1445 return 32;
1446 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1447 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1448 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1449 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1450 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1451 case Intrinsic::amdgcn_flat_load_monitor_b64:
1452 case Intrinsic::amdgcn_global_load_monitor_b64:
1453 return 64;
1454 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1455 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1456 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1457 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1458 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1459 case Intrinsic::amdgcn_flat_load_monitor_b128:
1460 case Intrinsic::amdgcn_global_load_monitor_b128:
1461 return 128;
1462 default:
1463 llvm_unreachable("Unknown width");
1464 }
1465}
1466
1468 unsigned ArgIdx) {
1469 Value *OrderingArg = CI.getArgOperand(ArgIdx);
1470 unsigned Ord = cast<ConstantInt>(OrderingArg)->getZExtValue();
1471 switch (AtomicOrderingCABI(Ord)) {
1474 break;
1477 break;
1480 break;
1481 default:
1483 }
1484}
1485
1486static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx) {
1487 MDNode *ScopeMD = cast<MDNode>(
1488 cast<MetadataAsValue>(CI.getArgOperand(ArgIdx))->getMetadata());
1489 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1490 return CI.getContext().getOrInsertSyncScopeID(Scope);
1491}
1492
1494 const CallBase &CI,
1495 MachineFunction &MF,
1496 unsigned IntrID) const {
1498 if (CI.hasMetadata(LLVMContext::MD_invariant_load))
1500 if (CI.hasMetadata(LLVMContext::MD_nontemporal))
1502 Flags |= getTargetMMOFlags(CI);
1503
1504 if (const AMDGPU::RsrcIntrinsic *RsrcIntr =
1506 AttributeSet Attr =
1508 MemoryEffects ME = Attr.getMemoryEffects();
1509 if (ME.doesNotAccessMemory())
1510 return;
1511
1512 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1513 if (!IsSPrefetch) {
1514 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1515 if (Aux->getZExtValue() & AMDGPU::CPol::VOLATILE)
1517 }
1518
1520
1521 IntrinsicInfo Info;
1522 // TODO: Should images get their own address space?
1524
1525 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = nullptr;
1526 if (RsrcIntr->IsImage) {
1527 const AMDGPU::ImageDimIntrinsicInfo *Intr =
1529 BaseOpcode = AMDGPU::getMIMGBaseOpcodeInfo(Intr->BaseOpcode);
1530 Info.align.reset();
1531 }
1532
1533 Value *RsrcArg = CI.getArgOperand(RsrcIntr->RsrcArg);
1534 if (auto *RsrcPtrTy = dyn_cast<PointerType>(RsrcArg->getType())) {
1535 if (RsrcPtrTy->getAddressSpace() == AMDGPUAS::BUFFER_RESOURCE)
1536 // We conservatively set the memory operand of a buffer intrinsic to the
1537 // base resource pointer, so that we can access alias information about
1538 // those pointers. Cases like "this points at the same value
1539 // but with a different offset" are handled in
1540 // areMemAccessesTriviallyDisjoint.
1541 Info.ptrVal = RsrcArg;
1542 }
1543
1544 if (ME.onlyReadsMemory()) {
1545 if (RsrcIntr->IsImage) {
1546 unsigned MaxNumLanes = 4;
1547
1548 if (!BaseOpcode->Gather4) {
1549 // If this isn't a gather, we may have excess loaded elements in the
1550 // IR type. Check the dmask for the real number of elements loaded.
1551 unsigned DMask =
1552 cast<ConstantInt>(CI.getArgOperand(0))->getZExtValue();
1553 MaxNumLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1554 }
1555
1556 Info.memVT = memVTFromLoadIntrReturn(*this, MF.getDataLayout(),
1557 CI.getType(), MaxNumLanes);
1558 } else {
1559 Info.memVT =
1561 std::numeric_limits<unsigned>::max());
1562 }
1563
1564 // FIXME: What does alignment mean for an image?
1565 Info.opc = ISD::INTRINSIC_W_CHAIN;
1566 Info.flags = Flags | MachineMemOperand::MOLoad;
1567 } else if (ME.onlyWritesMemory()) {
1568 Info.opc = ISD::INTRINSIC_VOID;
1569
1570 Type *DataTy = CI.getArgOperand(0)->getType();
1571 if (RsrcIntr->IsImage) {
1572 unsigned DMask = cast<ConstantInt>(CI.getArgOperand(1))->getZExtValue();
1573 unsigned DMaskLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1574 Info.memVT = memVTFromLoadIntrData(*this, MF.getDataLayout(), DataTy,
1575 DMaskLanes);
1576 } else
1577 Info.memVT = getValueType(MF.getDataLayout(), DataTy);
1578
1579 Info.flags = Flags | MachineMemOperand::MOStore;
1580 } else {
1581 // Atomic, NoReturn Sampler or prefetch
1582 Info.opc = CI.getType()->isVoidTy() ? ISD::INTRINSIC_VOID
1584
1585 switch (IntrID) {
1586 default:
1587 Info.flags = Flags | MachineMemOperand::MOLoad;
1588 if (!IsSPrefetch)
1589 Info.flags |= MachineMemOperand::MOStore;
1590
1591 if ((RsrcIntr->IsImage && BaseOpcode->NoReturn) || IsSPrefetch) {
1592 // Fake memory access type for no return sampler intrinsics
1593 Info.memVT = MVT::i32;
1594 } else {
1595 // XXX - Should this be volatile without known ordering?
1596 Info.flags |= MachineMemOperand::MOVolatile;
1597 Info.memVT = MVT::getVT(CI.getArgOperand(0)->getType());
1598 }
1599 break;
1600 case Intrinsic::amdgcn_raw_buffer_load_lds:
1601 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1602 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1603 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1604 case Intrinsic::amdgcn_struct_buffer_load_lds:
1605 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1606 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1607 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1608 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1609
1610 // Entry 0: Load from buffer.
1611 // Don't set an offset, since the pointer value always represents the
1612 // base of the buffer.
1613 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1614 Info.flags = Flags | MachineMemOperand::MOLoad;
1615 Infos.push_back(Info);
1616
1617 // Entry 1: Store to LDS.
1618 // Instruction offset is applied, and an additional per-lane offset
1619 // which we simulate using a larger memory type.
1620 Info.memVT = EVT::getIntegerVT(
1621 CI.getContext(), Width * 8 * Subtarget->getWavefrontSize());
1622 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1623 Info.offset = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 2))
1624 ->getZExtValue();
1625 Info.fallbackAddressSpace = AMDGPUAS::LOCAL_ADDRESS;
1626 Info.flags = Flags | MachineMemOperand::MOStore;
1627 Infos.push_back(Info);
1628 return;
1629 }
1630 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1631 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1632 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1633 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1634 Info.memVT =
1636 std::numeric_limits<unsigned>::max());
1637 Info.flags = Flags | MachineMemOperand::MOLoad;
1638 Infos.push_back(Info);
1639 return;
1640 }
1641 }
1642 }
1643 Infos.push_back(Info);
1644 return;
1645 }
1646
1647 IntrinsicInfo Info;
1648 switch (IntrID) {
1649 case Intrinsic::amdgcn_ds_ordered_add:
1650 case Intrinsic::amdgcn_ds_ordered_swap: {
1651 Info.opc = ISD::INTRINSIC_W_CHAIN;
1652 Info.memVT = MVT::getVT(CI.getType());
1653 Info.ptrVal = CI.getOperand(0);
1654 Info.align.reset();
1656
1657 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(4));
1658 if (!Vol->isZero())
1659 Info.flags |= MachineMemOperand::MOVolatile;
1660
1661 Infos.push_back(Info);
1662 return;
1663 }
1664 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1665 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1666 Info.opc = ISD::INTRINSIC_W_CHAIN;
1667 Info.memVT = MVT::getVT(CI.getOperand(0)->getType());
1668 Info.ptrVal = nullptr;
1669 Info.fallbackAddressSpace = AMDGPUAS::STREAMOUT_REGISTER;
1671 Infos.push_back(Info);
1672 return;
1673 }
1674 case Intrinsic::amdgcn_ds_append:
1675 case Intrinsic::amdgcn_ds_consume: {
1676 Info.opc = ISD::INTRINSIC_W_CHAIN;
1677 Info.memVT = MVT::getVT(CI.getType());
1678 Info.ptrVal = CI.getOperand(0);
1679 Info.align.reset();
1681
1682 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(1));
1683 if (!Vol->isZero())
1684 Info.flags |= MachineMemOperand::MOVolatile;
1685
1686 Infos.push_back(Info);
1687 return;
1688 }
1689 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1690 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1691 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1694 Info.memVT = MVT::getVT(CI.getType());
1695 Info.ptrVal = CI.getOperand(0);
1696 Info.memVT = MVT::i64;
1697 Info.size = 8;
1698 Info.align.reset();
1700 Info.order = AtomicOrdering::Monotonic;
1701 Infos.push_back(Info);
1702 return;
1703 }
1704 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1705 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1706 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1707 Info.opc = ISD::INTRINSIC_W_CHAIN;
1708 Info.memVT =
1709 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1710 ? CI.getType()
1712 ->getElementType(0)); // XXX: what is correct VT?
1713
1714 Info.fallbackAddressSpace = AMDGPUAS::BUFFER_RESOURCE;
1715 Info.align.reset();
1716 Info.flags = Flags | MachineMemOperand::MOLoad |
1718 Infos.push_back(Info);
1719 return;
1720 }
1721 case Intrinsic::amdgcn_global_atomic_fmin_num:
1722 case Intrinsic::amdgcn_global_atomic_fmax_num:
1723 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1724 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1725 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1726 Info.opc = ISD::INTRINSIC_W_CHAIN;
1727 Info.memVT = MVT::getVT(CI.getType());
1728 Info.ptrVal = CI.getOperand(0);
1729 Info.align.reset();
1730 Info.flags =
1733 Infos.push_back(Info);
1734 return;
1735 }
1736 case Intrinsic::amdgcn_cluster_load_b32:
1737 case Intrinsic::amdgcn_cluster_load_b64:
1738 case Intrinsic::amdgcn_cluster_load_b128:
1739 case Intrinsic::amdgcn_ds_load_tr6_b96:
1740 case Intrinsic::amdgcn_ds_load_tr4_b64:
1741 case Intrinsic::amdgcn_ds_load_tr8_b64:
1742 case Intrinsic::amdgcn_ds_load_tr16_b128:
1743 case Intrinsic::amdgcn_global_load_tr6_b96:
1744 case Intrinsic::amdgcn_global_load_tr4_b64:
1745 case Intrinsic::amdgcn_global_load_tr_b64:
1746 case Intrinsic::amdgcn_global_load_tr_b128:
1747 case Intrinsic::amdgcn_ds_read_tr4_b64:
1748 case Intrinsic::amdgcn_ds_read_tr6_b96:
1749 case Intrinsic::amdgcn_ds_read_tr8_b64:
1750 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1751 Info.opc = ISD::INTRINSIC_W_CHAIN;
1752 Info.memVT = MVT::getVT(CI.getType());
1753 Info.ptrVal = CI.getOperand(0);
1754 Info.align.reset();
1755 Info.flags = Flags | MachineMemOperand::MOLoad;
1756 Infos.push_back(Info);
1757 return;
1758 }
1759 case Intrinsic::amdgcn_flat_load_monitor_b32:
1760 case Intrinsic::amdgcn_flat_load_monitor_b64:
1761 case Intrinsic::amdgcn_flat_load_monitor_b128:
1762 case Intrinsic::amdgcn_global_load_monitor_b32:
1763 case Intrinsic::amdgcn_global_load_monitor_b64:
1764 case Intrinsic::amdgcn_global_load_monitor_b128: {
1765 Info.opc = ISD::INTRINSIC_W_CHAIN;
1766 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1767 Info.ptrVal = CI.getOperand(0);
1768 Info.align.reset();
1769 Info.flags = MachineMemOperand::MOLoad;
1770 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1771 Info.ssid = parseSyncscopeMDArg(CI, 2);
1772 Infos.push_back(Info);
1773 return;
1774 }
1775 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1776 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1777 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1778 Info.opc = ISD::INTRINSIC_W_CHAIN;
1779 Info.memVT = MVT::getVT(CI.getType());
1780 Info.ptrVal = CI.getOperand(0);
1781 Info.align.reset();
1783 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1784 Info.ssid = parseSyncscopeMDArg(CI, 2);
1785 Infos.push_back(Info);
1786 return;
1787 }
1788 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1789 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1790 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1791 Info.opc = ISD::INTRINSIC_VOID;
1792 Info.memVT = MVT::getVT(CI.getArgOperand(1)->getType());
1793 Info.ptrVal = CI.getArgOperand(0);
1794 Info.align.reset();
1796 Info.order = parseAtomicOrderingCABIArg(CI, 2);
1797 Info.ssid = parseSyncscopeMDArg(CI, 3);
1798 Infos.push_back(Info);
1799 return;
1800 }
1801 case Intrinsic::amdgcn_ds_gws_init:
1802 case Intrinsic::amdgcn_ds_gws_barrier:
1803 case Intrinsic::amdgcn_ds_gws_sema_v:
1804 case Intrinsic::amdgcn_ds_gws_sema_br:
1805 case Intrinsic::amdgcn_ds_gws_sema_p:
1806 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1807 Info.opc = ISD::INTRINSIC_VOID;
1808
1809 const GCNTargetMachine &TM =
1810 static_cast<const GCNTargetMachine &>(getTargetMachine());
1811
1813 Info.ptrVal = MFI->getGWSPSV(TM);
1814
1815 // This is an abstract access, but we need to specify a type and size.
1816 Info.memVT = MVT::i32;
1817 Info.size = 4;
1818 Info.align = Align(4);
1819
1820 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1821 Info.flags = Flags | MachineMemOperand::MOLoad;
1822 else
1823 Info.flags = Flags | MachineMemOperand::MOStore;
1824 Infos.push_back(Info);
1825 return;
1826 }
1827 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1828 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1829 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1830 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1831 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1832 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1833 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1834 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1835 // Entry 0: Load from source (global/flat).
1836 Info.opc = ISD::INTRINSIC_VOID;
1837 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1838 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1839 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1840 Info.flags = Flags | MachineMemOperand::MOLoad;
1841 Infos.push_back(Info);
1842
1843 // Entry 1: Store to LDS (same offset).
1844 Info.flags = Flags | MachineMemOperand::MOStore;
1845 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1846 Infos.push_back(Info);
1847 return;
1848 }
1849 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1850 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1851 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1852 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1853 // Entry 0: Load from LDS.
1854 Info.opc = ISD::INTRINSIC_VOID;
1855 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1856 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1857 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1858 Info.flags = Flags | MachineMemOperand::MOLoad;
1859 Infos.push_back(Info);
1860
1861 // Entry 1: Store to global (same offset).
1862 Info.flags = Flags | MachineMemOperand::MOStore;
1863 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1864 Infos.push_back(Info);
1865 return;
1866 }
1867 case Intrinsic::amdgcn_av_load_b8:
1868 case Intrinsic::amdgcn_av_load_b16:
1869 case Intrinsic::amdgcn_av_load_b32:
1870 case Intrinsic::amdgcn_av_load_b64:
1871 case Intrinsic::amdgcn_av_load_b128:
1872 case Intrinsic::amdgcn_av_store_b8:
1873 case Intrinsic::amdgcn_av_store_b16:
1874 case Intrinsic::amdgcn_av_store_b32:
1875 case Intrinsic::amdgcn_av_store_b64:
1876 case Intrinsic::amdgcn_av_store_b128: {
1877 bool IsStore = CI.getType()->isVoidTy();
1878 Type *DataTy = IsStore ? CI.getArgOperand(1)->getType() : CI.getType();
1879 Info.opc = IsStore ? ISD::INTRINSIC_VOID : ISD::INTRINSIC_W_CHAIN;
1880 Info.memVT = MVT::getVT(DataTy);
1881 Info.ptrVal = CI.getArgOperand(0);
1882 Info.align = Align(Info.memVT.getStoreSize());
1883 Info.flags |=
1885 // Pretend to be atomic so that SIMemoryLegalizer::expandStore sets cache
1886 // flags appropriately.
1887 Info.order = AtomicOrdering::Monotonic;
1888
1889 LLVMContext &Ctx = CI.getContext();
1890 unsigned ScopeIdx = CI.arg_size() - 1;
1891 MDNode *ScopeMD = cast<MDNode>(
1892 cast<MetadataAsValue>(CI.getArgOperand(ScopeIdx))->getMetadata());
1893 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1894 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1895 Infos.push_back(Info);
1896 return;
1897 }
1898 case Intrinsic::amdgcn_load_to_lds:
1899 case Intrinsic::amdgcn_load_async_to_lds:
1900 case Intrinsic::amdgcn_global_load_lds:
1901 case Intrinsic::amdgcn_global_load_async_lds: {
1902 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1903 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1904 bool IsVolatile = Aux->getZExtValue() & AMDGPU::CPol::VOLATILE;
1905 if (IsVolatile)
1907
1908 // Entry 0: Load from source (global/flat).
1909 Info.opc = ISD::INTRINSIC_VOID;
1910 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1911 Info.ptrVal = CI.getArgOperand(0); // Source pointer
1912 Info.offset = cast<ConstantInt>(CI.getArgOperand(3))->getSExtValue();
1913 Info.flags = Flags | MachineMemOperand::MOLoad;
1914 Infos.push_back(Info);
1915
1916 // Entry 1: Store to LDS.
1917 // Same offset from the instruction, but an additional per-lane offset is
1918 // added. Represent that using a wider memory type.
1919 Info.memVT = EVT::getIntegerVT(CI.getContext(),
1920 Width * 8 * Subtarget->getWavefrontSize());
1921 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1922 Info.flags = Flags | MachineMemOperand::MOStore;
1923 Infos.push_back(Info);
1924 return;
1925 }
1926 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1927 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1928 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1929 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1930 Info.opc = ISD::INTRINSIC_W_CHAIN;
1931
1932 const GCNTargetMachine &TM =
1933 static_cast<const GCNTargetMachine &>(getTargetMachine());
1934
1936 Info.ptrVal = MFI->getGWSPSV(TM);
1937
1938 // This is an abstract access, but we need to specify a type and size.
1939 Info.memVT = MVT::i32;
1940 Info.size = 4;
1941 Info.align = Align(4);
1942
1944 Infos.push_back(Info);
1945 return;
1946 }
1947 case Intrinsic::amdgcn_s_prefetch_data:
1948 case Intrinsic::amdgcn_s_prefetch_inst:
1949 case Intrinsic::amdgcn_flat_prefetch:
1950 case Intrinsic::amdgcn_global_prefetch: {
1951 Info.opc = ISD::INTRINSIC_VOID;
1952 Info.memVT = EVT::getIntegerVT(CI.getContext(), 8);
1953 Info.ptrVal = CI.getArgOperand(0);
1954 Info.flags = Flags | MachineMemOperand::MOLoad;
1955 Infos.push_back(Info);
1956 return;
1957 }
1958 default:
1959 return;
1960 }
1961}
1962
1965 Type *&AccessTy) const {
1966 Value *Ptr = nullptr;
1967 switch (II->getIntrinsicID()) {
1968 case Intrinsic::amdgcn_cluster_load_b128:
1969 case Intrinsic::amdgcn_cluster_load_b64:
1970 case Intrinsic::amdgcn_cluster_load_b32:
1971 case Intrinsic::amdgcn_ds_append:
1972 case Intrinsic::amdgcn_ds_consume:
1973 case Intrinsic::amdgcn_ds_load_tr8_b64:
1974 case Intrinsic::amdgcn_ds_load_tr16_b128:
1975 case Intrinsic::amdgcn_ds_load_tr4_b64:
1976 case Intrinsic::amdgcn_ds_load_tr6_b96:
1977 case Intrinsic::amdgcn_ds_read_tr4_b64:
1978 case Intrinsic::amdgcn_ds_read_tr6_b96:
1979 case Intrinsic::amdgcn_ds_read_tr8_b64:
1980 case Intrinsic::amdgcn_ds_read_tr16_b64:
1981 case Intrinsic::amdgcn_ds_ordered_add:
1982 case Intrinsic::amdgcn_ds_ordered_swap:
1983 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1984 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1985 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1986 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1987 case Intrinsic::amdgcn_global_atomic_fmax_num:
1988 case Intrinsic::amdgcn_global_atomic_fmin_num:
1989 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1990 case Intrinsic::amdgcn_global_load_tr_b64:
1991 case Intrinsic::amdgcn_global_load_tr_b128:
1992 case Intrinsic::amdgcn_global_load_tr4_b64:
1993 case Intrinsic::amdgcn_global_load_tr6_b96:
1994 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1995 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1996 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1997 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1998 case Intrinsic::amdgcn_av_load_b8:
1999 case Intrinsic::amdgcn_av_load_b16:
2000 case Intrinsic::amdgcn_av_load_b32:
2001 case Intrinsic::amdgcn_av_load_b64:
2002 case Intrinsic::amdgcn_av_load_b128:
2003 case Intrinsic::amdgcn_av_store_b8:
2004 case Intrinsic::amdgcn_av_store_b16:
2005 case Intrinsic::amdgcn_av_store_b32:
2006 case Intrinsic::amdgcn_av_store_b64:
2007 case Intrinsic::amdgcn_av_store_b128:
2008 Ptr = II->getArgOperand(0);
2009 break;
2010 case Intrinsic::amdgcn_load_to_lds:
2011 case Intrinsic::amdgcn_load_async_to_lds:
2012 case Intrinsic::amdgcn_global_load_lds:
2013 case Intrinsic::amdgcn_global_load_async_lds:
2014 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
2015 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
2016 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
2017 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
2018 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
2019 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
2020 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
2021 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
2022 Ptr = II->getArgOperand(1);
2023 break;
2024 default:
2025 return false;
2026 }
2027 AccessTy = II->getType();
2028 Ops.push_back(Ptr);
2029 return true;
2030}
2031
2033 unsigned AddrSpace) const {
2034 if (!Subtarget->hasFlatInstOffsets()) {
2035 // Flat instructions do not have offsets, and only have the register
2036 // address.
2037 return AM.BaseOffs == 0 && AM.Scale == 0;
2038 }
2039
2041 FlatAddrSpace FlatVariant =
2042 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS ? FlatAddrSpace::FlatGlobal
2043 : AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ? FlatAddrSpace::FlatScratch
2044 : FlatAddrSpace::FLAT;
2045
2046 return AM.Scale == 0 &&
2047 (AM.BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
2048 AM.BaseOffs, AddrSpace, FlatVariant));
2049}
2050
2052 if (Subtarget->hasFlatGlobalInsts())
2054
2055 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
2056 // Assume the we will use FLAT for all global memory accesses
2057 // on VI.
2058 // FIXME: This assumption is currently wrong. On VI we still use
2059 // MUBUF instructions for the r + i addressing mode. As currently
2060 // implemented, the MUBUF instructions only work on buffer < 4GB.
2061 // It may be possible to support > 4GB buffers with MUBUF instructions,
2062 // by setting the stride value in the resource descriptor which would
2063 // increase the size limit to (stride * 4GB). However, this is risky,
2064 // because it has never been validated.
2066 }
2067
2068 return isLegalMUBUFAddressingMode(AM);
2069}
2070
2071bool SITargetLowering::isLegalMUBUFAddressingMode(const AddrMode &AM) const {
2072 // MUBUF / MTBUF instructions have a 12-bit unsigned byte offset, and
2073 // additionally can do r + r + i with addr64. 32-bit has more addressing
2074 // mode options. Depending on the resource constant, it can also do
2075 // (i64 r0) + (i32 r1) * (i14 i).
2076 //
2077 // Private arrays end up using a scratch buffer most of the time, so also
2078 // assume those use MUBUF instructions. Scratch loads / stores are currently
2079 // implemented as mubuf instructions with offen bit set, so slightly
2080 // different than the normal addr64.
2081 const SIInstrInfo *TII = Subtarget->getInstrInfo();
2082 if (!TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2083 return false;
2084
2085 // FIXME: Since we can split immediate into soffset and immediate offset,
2086 // would it make sense to allow any immediate?
2087
2088 switch (AM.Scale) {
2089 case 0: // r + i or just i, depending on HasBaseReg.
2090 return true;
2091 case 1:
2092 return true; // We have r + r or r + i.
2093 case 2:
2094 if (AM.HasBaseReg) {
2095 // Reject 2 * r + r.
2096 return false;
2097 }
2098
2099 // Allow 2 * r as r + r
2100 // Or 2 * r + i is allowed as r + r + i.
2101 return true;
2102 default: // Don't allow n * r
2103 return false;
2104 }
2105}
2106
2108 const AddrMode &AM, Type *Ty,
2109 unsigned AS,
2110 Instruction *I) const {
2111 // No global is ever allowed as a base.
2112 if (AM.BaseGV)
2113 return false;
2114
2115 if (AS == AMDGPUAS::GLOBAL_ADDRESS)
2116 return isLegalGlobalAddressingMode(AM);
2117
2118 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
2122 // If the offset isn't a multiple of 4, it probably isn't going to be
2123 // correctly aligned.
2124 // FIXME: Can we get the real alignment here?
2125 if (AM.BaseOffs % 4 != 0)
2126 return isLegalMUBUFAddressingMode(AM);
2127
2128 if (!Subtarget->hasScalarSubwordLoads()) {
2129 // There are no SMRD extloads, so if we have to do a small type access we
2130 // will use a MUBUF load.
2131 // FIXME?: We also need to do this if unaligned, but we don't know the
2132 // alignment here.
2133 if (Ty->isSized() && DL.getTypeStoreSize(Ty) < 4)
2134 return isLegalGlobalAddressingMode(AM);
2135 }
2136
2137 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS) {
2138 // SMRD instructions have an 8-bit, dword offset on SI.
2139 if (!isUInt<8>(AM.BaseOffs / 4))
2140 return false;
2141 } else if (Subtarget->getGeneration() == AMDGPUSubtarget::SEA_ISLANDS) {
2142 // On CI+, this can also be a 32-bit literal constant offset. If it fits
2143 // in 8-bits, it can use a smaller encoding.
2144 if (!isUInt<32>(AM.BaseOffs / 4))
2145 return false;
2146 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX9) {
2147 // On VI, these use the SMEM format and the offset is 20-bit in bytes.
2148 if (!isUInt<20>(AM.BaseOffs))
2149 return false;
2150 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX12) {
2151 // On GFX9 the offset is signed 21-bit in bytes (but must not be negative
2152 // for S_BUFFER_* instructions).
2153 if (!isInt<21>(AM.BaseOffs))
2154 return false;
2155 } else {
2156 // On GFX12, all offsets are signed 24-bit in bytes.
2157 if (!isInt<24>(AM.BaseOffs))
2158 return false;
2159 }
2160
2161 if ((AS == AMDGPUAS::CONSTANT_ADDRESS ||
2163 AM.BaseOffs < 0) {
2164 // Scalar (non-buffer) loads can only use a negative offset if
2165 // soffset+offset is non-negative. Since the compiler can only prove that
2166 // in a few special cases, it is safer to claim that negative offsets are
2167 // not supported.
2168 return false;
2169 }
2170
2171 if (AM.Scale == 0) // r + i or just i, depending on HasBaseReg.
2172 return true;
2173
2174 if (AM.Scale == 1 && AM.HasBaseReg)
2175 return true;
2176
2177 return false;
2178 }
2179
2180 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
2181 return Subtarget->hasFlatScratchEnabled()
2183 : isLegalMUBUFAddressingMode(AM);
2184
2185 if (AS == AMDGPUAS::LOCAL_ADDRESS ||
2186 (AS == AMDGPUAS::REGION_ADDRESS && Subtarget->hasGDS())) {
2187 // Basic, single offset DS instructions allow a 16-bit unsigned immediate
2188 // field.
2189 // XXX - If doing a 4-byte aligned 8-byte type access, we effectively have
2190 // an 8-bit dword offset but we don't know the alignment here.
2191 if (!isUInt<16>(AM.BaseOffs))
2192 return false;
2193
2194 if (AM.Scale == 0) // r + i or just i, depending on HasBaseReg.
2195 return true;
2196
2197 if (AM.Scale == 1 && AM.HasBaseReg)
2198 return true;
2199
2200 return false;
2201 }
2202
2204 // For an unknown address space, this usually means that this is for some
2205 // reason being used for pure arithmetic, and not based on some addressing
2206 // computation. We don't have instructions that compute pointers with any
2207 // addressing modes, so treat them as having no offset like flat
2208 // instructions.
2210 }
2211
2212 // Assume a user alias of global for unknown address spaces.
2213 return isLegalGlobalAddressingMode(AM);
2214}
2215
2217 const MachineFunction &MF) const {
2219 return (MemVT.getSizeInBits() <= 4 * 32);
2220 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
2221 unsigned MaxPrivateBits = 8 * getSubtarget()->getMaxPrivateElementSize();
2222 return (MemVT.getSizeInBits() <= MaxPrivateBits);
2223 }
2225 return (MemVT.getSizeInBits() <= 2 * 32);
2226 return true;
2227}
2228
2230 unsigned Size, unsigned AddrSpace, Align Alignment,
2231 MachineMemOperand::Flags Flags, unsigned *IsFast) const {
2232 if (IsFast)
2233 *IsFast = 0;
2234
2235 if (AddrSpace == AMDGPUAS::LOCAL_ADDRESS ||
2236 AddrSpace == AMDGPUAS::REGION_ADDRESS) {
2237 // Check if alignment requirements for ds_read/write instructions are
2238 // disabled.
2239 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment < Align(4))
2240 return false;
2241
2242 Align RequiredAlignment(
2243 PowerOf2Ceil(divideCeil(Size, 8))); // Natural alignment.
2244 if (Subtarget->hasLDSMisalignedBugInWGPMode() && Size > 32 &&
2245 Alignment < RequiredAlignment)
2246 return false;
2247
2248 // Either, the alignment requirements are "enabled", or there is an
2249 // unaligned LDS access related hardware bug though alignment requirements
2250 // are "disabled". In either case, we need to check for proper alignment
2251 // requirements.
2252 //
2253 switch (Size) {
2254 case 64:
2255 // SI has a hardware bug in the LDS / GDS bounds checking: if the base
2256 // address is negative, then the instruction is incorrectly treated as
2257 // out-of-bounds even if base + offsets is in bounds. Split vectorized
2258 // loads here to avoid emitting ds_read2_b32. We may re-combine the
2259 // load later in the SILoadStoreOptimizer.
2260 if (!Subtarget->hasUsableDSOffset() && Alignment < Align(8))
2261 return false;
2262
2263 // 8 byte accessing via ds_read/write_b64 require 8-byte alignment, but we
2264 // can do a 4 byte aligned, 8 byte access in a single operation using
2265 // ds_read2/write2_b32 with adjacent offsets.
2266 RequiredAlignment = Align(4);
2267
2268 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2269 // We will either select ds_read_b64/ds_write_b64 or ds_read2_b32/
2270 // ds_write2_b32 depending on the alignment. In either case with either
2271 // alignment there is no faster way of doing this.
2272
2273 // The numbers returned here and below are not additive, it is a 'speed
2274 // rank'. They are just meant to be compared to decide if a certain way
2275 // of lowering an operation is faster than another. For that purpose
2276 // naturally aligned operation gets it bitsize to indicate that "it
2277 // operates with a speed comparable to N-bit wide load". With the full
2278 // alignment ds128 is slower than ds96 for example. If underaligned it
2279 // is comparable to a speed of a single dword access, which would then
2280 // mean 32 < 128 and it is faster to issue a wide load regardless.
2281 // 1 is simply "slow, don't do it". I.e. comparing an aligned load to a
2282 // wider load which will not be aligned anymore the latter is slower.
2283 if (IsFast)
2284 *IsFast = (Alignment >= RequiredAlignment) ? 64
2285 : (Alignment < Align(4)) ? 32
2286 : 1;
2287 return true;
2288 }
2289
2290 break;
2291 case 96:
2292 if (!Subtarget->hasDS96AndDS128())
2293 return false;
2294
2295 // 12 byte accessing via ds_read/write_b96 require 16-byte alignment on
2296 // gfx8 and older.
2297
2298 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2299 // Naturally aligned access is fastest. However, also report it is Fast
2300 // if memory is aligned less than DWORD. A narrow load or store will be
2301 // be equally slow as a single ds_read_b96/ds_write_b96, but there will
2302 // be more of them, so overall we will pay less penalty issuing a single
2303 // instruction.
2304
2305 // See comment on the values above.
2306 if (IsFast)
2307 *IsFast = (Alignment >= RequiredAlignment) ? 96
2308 : (Alignment < Align(4)) ? 32
2309 : 1;
2310 return true;
2311 }
2312
2313 break;
2314 case 128:
2315 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2316 return false;
2317
2318 // 16 byte accessing via ds_read/write_b128 require 16-byte alignment on
2319 // gfx8 and older, but we can do a 8 byte aligned, 16 byte access in a
2320 // single operation using ds_read2/write2_b64.
2321 RequiredAlignment = Align(8);
2322
2323 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2324 // Naturally aligned access is fastest. However, also report it is Fast
2325 // if memory is aligned less than DWORD. A narrow load or store will be
2326 // be equally slow as a single ds_read_b128/ds_write_b128, but there
2327 // will be more of them, so overall we will pay less penalty issuing a
2328 // single instruction.
2329
2330 // See comment on the values above.
2331 if (IsFast)
2332 *IsFast = (Alignment >= RequiredAlignment) ? 128
2333 : (Alignment < Align(4)) ? 32
2334 : 1;
2335 return true;
2336 }
2337
2338 break;
2339 default:
2340 if (Size > 32)
2341 return false;
2342
2343 break;
2344 }
2345
2346 // See comment on the values above.
2347 // Note that we have a single-dword or sub-dword here, so if underaligned
2348 // it is a slowest possible access, hence returned value is 0.
2349 if (IsFast)
2350 *IsFast = (Alignment >= RequiredAlignment) ? Size : 0;
2351
2352 return Alignment >= RequiredAlignment ||
2353 Subtarget->hasUnalignedDSAccessEnabled();
2354 }
2355
2356 // FIXME: We have to be conservative here and assume that flat operations
2357 // will access scratch. If we had access to the IR function, then we
2358 // could determine if any private memory was used in the function.
2359 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ||
2360 AddrSpace == AMDGPUAS::FLAT_ADDRESS) {
2361 bool AlignedBy4 = Alignment >= Align(4);
2362 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2363 if (IsFast)
2364 *IsFast = AlignedBy4 ? Size : 1;
2365 return true;
2366 }
2367
2368 if (IsFast)
2369 *IsFast = AlignedBy4;
2370
2371 return AlignedBy4;
2372 }
2373
2374 // So long as they are correct, wide global memory operations perform better
2375 // than multiple smaller memory ops -- even when misaligned
2376 if (AMDGPU::isExtendedGlobalAddrSpace(AddrSpace)) {
2377 if (IsFast)
2378 *IsFast = Size;
2379
2380 return Alignment >= Align(4) ||
2381 Subtarget->hasUnalignedBufferAccessEnabled();
2382 }
2383
2384 // Ensure robust out-of-bounds guarantees for buffer accesses are met when the
2385 // "amdgpu.buffer.oob.mode" module flag has not enabled relaxed untyped-buffer
2386 // OOB semantics. Normally hardware will ensure proper
2387 // out-of-bounds behavior, but in the edge case where an access starts
2388 // out-of-bounds and then enters in-bounds, the entire access would be treated
2389 // as out-of-bounds. Prevent misaligned memory accesses by requiring the
2390 // natural alignment of buffer accesses.
2391 if (AddrSpace == AMDGPUAS::BUFFER_FAT_POINTER ||
2392 AddrSpace == AMDGPUAS::BUFFER_RESOURCE ||
2393 AddrSpace == AMDGPUAS::BUFFER_STRIDED_POINTER) {
2394 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2395 Alignment < Align(PowerOf2Ceil(divideCeil(Size, 8))))
2396 return false;
2397 }
2398
2399 // Smaller than dword value must be aligned.
2400 if (Size < 32)
2401 return false;
2402
2403 // 8.1.6 - For Dword or larger reads or writes, the two LSBs of the
2404 // byte-address are ignored, thus forcing Dword alignment.
2405 // This applies to private, global, and constant memory.
2406 if (IsFast)
2407 *IsFast = 1;
2408
2409 return Size >= 32 && Alignment >= Align(4);
2410}
2411
2413 EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
2414 unsigned *IsFast) const {
2416 Alignment, Flags, IsFast);
2417}
2418
2420 LLVMContext &Context, const MemOp &Op,
2421 const AttributeList &FuncAttributes) const {
2422 // FIXME: Should account for address space here.
2423
2424 // The default fallback uses the private pointer size as a guess for a type to
2425 // use. Make sure we switch these to 64-bit accesses.
2426
2427 if (Op.size() >= 16 &&
2428 Op.isDstAligned(Align(4))) // XXX: Should only do for global
2429 return MVT::v4i32;
2430
2431 if (Op.size() >= 8 && Op.isDstAligned(Align(4)))
2432 return MVT::v2i32;
2433
2434 // Use the default.
2435 return MVT::Other;
2436}
2437
2439 const MemSDNode *MemNode = cast<MemSDNode>(N);
2440 return MemNode->getMemOperand()->getFlags() & MONoClobber;
2441}
2442
2447
2449 unsigned DestAS) const {
2450 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
2451 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
2452 Subtarget->hasGloballyAddressableScratch()) {
2453 // Flat -> private requires subtracting src_flat_scratch_base_lo.
2454 return false;
2455 }
2456
2457 // Flat -> private/local is a simple truncate.
2458 // Flat -> global is no-op
2459 return true;
2460 }
2461
2462 const GCNTargetMachine &TM =
2463 static_cast<const GCNTargetMachine &>(getTargetMachine());
2464 return TM.isNoopAddrSpaceCast(DL, SrcAS, DestAS);
2465}
2466
2474
2476 Type *Ty) const {
2477 // FIXME: Could be smarter if called for vector constants.
2478 return true;
2479}
2480
2483 unsigned Index) const {
2486
2487 // TODO: Add more cases that are cheap.
2488 if (Index == 0)
2491}
2492
2493bool SITargetLowering::isExtractVecEltCheap(EVT VT, unsigned Index) const {
2494 // TODO: This should be more aggressive, particular for 16-bit element
2495 // vectors. However there are some mixed improvements and regressions.
2496 EVT EltTy = VT.getVectorElementType();
2497 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2498 return EltTy.getSizeInBits() % MinAlign == 0;
2499}
2500
2502 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2503 switch (Op) {
2504 case ISD::LOAD:
2505 case ISD::STORE:
2506 return true;
2507 default:
2508 return false;
2509 }
2510 }
2511
2512 // SimplifySetCC uses this function to determine whether or not it should
2513 // create setcc with i1 operands. We don't have instructions for i1 setcc.
2514 if (VT == MVT::i1 && Op == ISD::SETCC)
2515 return false;
2516
2517 if (VT.getScalarType() == MVT::i64 &&
2519 return false;
2520
2522}
2523
2525 // Do not convert uniform loads to 16-bit.
2526 // Uniform 16-bit loads are legalized to i16 = trunc (zextload i16->i32)
2527 // to match subword load patterns. Allowing conversion back to a 16-bit
2528 // load would create an infinite loop.
2529 if (Subtarget->hasScalarSubwordLoads() && N->getOpcode() == ISD::LOAD &&
2530 !VT.isVector() && VT.getSizeInBits() == 16) {
2531 auto *Load = dyn_cast<LoadSDNode>(N);
2532 if (Load && isUniformLoad(Load)) {
2533 return false;
2534 }
2535 }
2536
2537 return isTypeDesirableForOp(N->getOpcode(), VT);
2538}
2539
2541 const MachineMemOperand *MMO = Load->getMemOperand();
2542
2543 // FIXME: We ought to able able to take the direct isDivergent result. We
2544 // cannot rely on the MMO for a uniformity check, and should stop using
2545 // it. This is a hack for 2 ways that the IR divergence analysis is superior
2546 // to the DAG divergence: Recognizing shift-of-workitem-id as always
2547 // uniform, and isSingleLaneExecution. These should be handled in the DAG
2548 // version, and then this can be dropped.
2549 if (Load->isDivergent() && !AMDGPU::isUniformMMO(MMO))
2550 return false;
2551
2552 return MMO->getSize().hasValue() &&
2553 Load->getAlign() >=
2554 Align(std::min(MMO->getSize().getValue().getKnownMinValue(),
2555 uint64_t(4))) &&
2556 (MMO->isInvariant() ||
2557 (Load->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS ||
2558 Load->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT) ||
2559 (Load->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS &&
2560 Load->isSimple() && isMemOpHasNoClobberedMemOperand(Load)));
2561}
2562
2565 // This isn't really a constant pool but close enough.
2568 return PtrInfo;
2569}
2570
2571SDValue SITargetLowering::lowerKernArgParameterPtr(SelectionDAG &DAG,
2572 const SDLoc &SL,
2573 SDValue Chain,
2574 uint64_t Offset) const {
2575 const DataLayout &DL = DAG.getDataLayout();
2579
2580 auto [InputPtrReg, RC, ArgTy] =
2581 Info->getPreloadedValue(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
2582
2583 // We may not have the kernarg segment argument if we have no kernel
2584 // arguments.
2585 if (!InputPtrReg)
2586 return DAG.getConstant(Offset, SL, PtrVT);
2587
2589 SDValue BasePtr = DAG.getCopyFromReg(
2590 Chain, SL, MRI.getLiveInVirtReg(InputPtrReg->getRegister()), PtrVT);
2591
2592 return DAG.getObjectPtrOffset(SL, BasePtr, TypeSize::getFixed(Offset));
2593}
2594
2595SDValue SITargetLowering::getImplicitArgPtr(SelectionDAG &DAG,
2596 const SDLoc &SL) const {
2599 return lowerKernArgParameterPtr(DAG, SL, DAG.getEntryNode(), Offset);
2600}
2601
2602SDValue SITargetLowering::getLDSKernelId(SelectionDAG &DAG,
2603 const SDLoc &SL) const {
2604
2606 std::optional<uint32_t> KnownSize =
2608 if (KnownSize.has_value())
2609 return DAG.getConstant(*KnownSize, SL, MVT::i32);
2610 return SDValue();
2611}
2612
2613SDValue SITargetLowering::convertArgType(SelectionDAG &DAG, EVT VT, EVT MemVT,
2614 const SDLoc &SL, SDValue Val,
2615 bool Signed,
2616 const ISD::InputArg *Arg) const {
2617 // First, if it is a widened vector, narrow it.
2618 if (VT.isVector() &&
2620 EVT NarrowedVT =
2623 Val = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, NarrowedVT, Val,
2624 DAG.getConstant(0, SL, MVT::i32));
2625 }
2626
2627 // Then convert the vector elements or scalar value.
2628 if (Arg && (Arg->Flags.isSExt() || Arg->Flags.isZExt()) && VT.bitsLT(MemVT)) {
2629 unsigned Opc = Arg->Flags.isZExt() ? ISD::AssertZext : ISD::AssertSext;
2630 Val = DAG.getNode(Opc, SL, MemVT, Val, DAG.getValueType(VT));
2631 }
2632
2633 if (MemVT.isFloatingPoint()) {
2634 if (VT.isFloatingPoint()) {
2635 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2636 } else {
2637 assert(!MemVT.isVector());
2638 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
2639 SDValue Cast = DAG.getBitcast(IntVT, Val);
2640 Val = DAG.getAnyExtOrTrunc(Cast, SL, VT);
2641 }
2642 } else if (Signed)
2643 Val = DAG.getSExtOrTrunc(Val, SL, VT);
2644 else
2645 Val = DAG.getZExtOrTrunc(Val, SL, VT);
2646
2647 return Val;
2648}
2649
2650SDValue SITargetLowering::lowerKernargMemParameter(
2651 SelectionDAG &DAG, EVT VT, EVT MemVT, const SDLoc &SL, SDValue Chain,
2652 uint64_t Offset, Align Alignment, bool Signed,
2653 const ISD::InputArg *Arg) const {
2654
2655 MachinePointerInfo PtrInfo =
2657
2658 // Try to avoid using an extload by loading earlier than the argument address,
2659 // and extracting the relevant bits. The load should hopefully be merged with
2660 // the previous argument.
2661 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
2662 // TODO: Handle align < 4 and size >= 4 (can happen with packed structs).
2663 int64_t AlignDownOffset = alignDown(Offset, 4);
2664 int64_t OffsetDiff = Offset - AlignDownOffset;
2665
2666 EVT IntVT = MemVT.changeTypeToInteger();
2667
2668 // TODO: If we passed in the base kernel offset we could have a better
2669 // alignment than 4, but we don't really need it.
2670 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2671 SDValue Load = DAG.getLoad(MVT::i32, SL, Chain, Ptr,
2672 PtrInfo.getWithOffset(AlignDownOffset), Align(4),
2675
2676 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, SL, MVT::i32);
2677 SDValue Extract = DAG.getNode(ISD::SRL, SL, MVT::i32, Load, ShiftAmt);
2678
2679 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, SL, IntVT, Extract);
2680 ArgVal = DAG.getNode(ISD::BITCAST, SL, MemVT, ArgVal);
2681 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal, Signed, Arg);
2682
2683 return DAG.getMergeValues({ArgVal, Load.getValue(1)}, SL);
2684 }
2685
2686 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, Offset);
2687 SDValue Load = DAG.getLoad(
2688 MemVT, SL, Chain, Ptr, PtrInfo.getWithOffset(Offset), Alignment,
2690
2691 SDValue Val = convertArgType(DAG, VT, MemVT, SL, Load, Signed, Arg);
2692 return DAG.getMergeValues({Val, Load.getValue(1)}, SL);
2693}
2694
2695/// Coerce an argument which was passed in a different ABI type to the original
2696/// expected value type.
2697SDValue SITargetLowering::convertABITypeToValueType(SelectionDAG &DAG,
2698 SDValue Val,
2699 CCValAssign &VA,
2700 const SDLoc &SL) const {
2701 EVT ValVT = VA.getValVT();
2702
2703 // If this is an 8 or 16-bit value, it is really passed promoted
2704 // to 32 bits. Insert an assert[sz]ext to capture this, then
2705 // truncate to the right size.
2706 switch (VA.getLocInfo()) {
2707 case CCValAssign::Full:
2708 return Val;
2709 case CCValAssign::BCvt:
2710 return DAG.getNode(ISD::BITCAST, SL, ValVT, Val);
2711 case CCValAssign::SExt:
2712 Val = DAG.getNode(ISD::AssertSext, SL, VA.getLocVT(), Val,
2713 DAG.getValueType(ValVT));
2714 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2715 case CCValAssign::ZExt:
2716 Val = DAG.getNode(ISD::AssertZext, SL, VA.getLocVT(), Val,
2717 DAG.getValueType(ValVT));
2718 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2719 case CCValAssign::AExt:
2720 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2721 default:
2722 llvm_unreachable("Unknown loc info!");
2723 }
2724}
2725
2726SDValue SITargetLowering::lowerStackParameter(SelectionDAG &DAG,
2727 CCValAssign &VA, const SDLoc &SL,
2728 SDValue Chain,
2729 const ISD::InputArg &Arg) const {
2731 MachineFrameInfo &MFI = MF.getFrameInfo();
2732
2733 if (Arg.Flags.isByVal()) {
2734 unsigned Size = Arg.Flags.getByValSize();
2735 int FrameIdx = MFI.CreateFixedObject(Size, VA.getLocMemOffset(), false);
2736 return DAG.getFrameIndex(FrameIdx, MVT::i32);
2737 }
2738
2739 unsigned ArgOffset = VA.getLocMemOffset();
2740 unsigned ArgSize = VA.getValVT().getStoreSize();
2741
2742 int FI = MFI.CreateFixedObject(ArgSize, ArgOffset, true);
2743
2744 // Create load nodes to retrieve arguments from the stack.
2745 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
2746
2747 // For NON_EXTLOAD, generic code in getLoad assert(ValVT == MemVT)
2749 MVT MemVT = VA.getValVT();
2750
2751 switch (VA.getLocInfo()) {
2752 default:
2753 break;
2754 case CCValAssign::BCvt:
2755 MemVT = VA.getLocVT();
2756 break;
2757 case CCValAssign::SExt:
2758 ExtType = ISD::SEXTLOAD;
2759 break;
2760 case CCValAssign::ZExt:
2761 ExtType = ISD::ZEXTLOAD;
2762 break;
2763 case CCValAssign::AExt:
2764 ExtType = ISD::EXTLOAD;
2765 break;
2766 }
2767
2768 SDValue ArgValue = DAG.getExtLoad(
2769 ExtType, SL, VA.getLocVT(), Chain, FIN,
2771
2772 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2773 if (ConvertedVal == ArgValue)
2774 return ConvertedVal;
2775
2776 return DAG.getMergeValues({ConvertedVal, ArgValue.getValue(1)}, SL);
2777}
2778
2779SDValue SITargetLowering::lowerWorkGroupId(
2780 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2783 AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const {
2784 if (!Subtarget->hasClusters())
2785 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2786
2787 // Clusters are supported. Return the global position in the grid. If clusters
2788 // are enabled, WorkGroupIdPV returns the cluster ID not the workgroup ID.
2789
2790 // WorkGroupIdXYZ = ClusterId == 0 ?
2791 // ClusterIdXYZ :
2792 // ClusterIdXYZ * (ClusterMaxIdXYZ + 1) + ClusterWorkGroupIdXYZ
2793 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2794 SDLoc SL(ClusterIdXYZ);
2795 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2796 SDValue One = DAG.getConstant(1, SL, VT);
2797 SDValue ClusterSizeXYZ = DAG.getNode(ISD::ADD, SL, VT, ClusterMaxIdXYZ, One);
2798 SDValue ClusterWorkGroupIdXYZ =
2799 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2800 SDValue GlobalIdXYZ =
2801 DAG.getNode(ISD::ADD, SL, VT, ClusterWorkGroupIdXYZ,
2802 DAG.getNode(ISD::MUL, SL, VT, ClusterIdXYZ, ClusterSizeXYZ));
2803
2804 switch (MFI.getClusterDims().getKind()) {
2807 return GlobalIdXYZ;
2809 return ClusterIdXYZ;
2811 using namespace AMDGPU::Hwreg;
2812 SDValue ClusterIdField =
2813 DAG.getTargetConstant(HwregEncoding::encode(ID_IB_STS2, 6, 4), SL, VT);
2814 SDNode *GetReg =
2815 DAG.getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2816 SDValue ClusterId(GetReg, 0);
2817 SDValue Zero = DAG.getConstant(0, SL, VT);
2818 return DAG.getNode(ISD::SELECT_CC, SL, VT, ClusterId, Zero, ClusterIdXYZ,
2819 GlobalIdXYZ, DAG.getCondCode(ISD::SETEQ));
2820 }
2821 }
2822
2823 llvm_unreachable("nothing should reach here");
2824}
2825
2826SDValue SITargetLowering::getPreloadedValue(
2827 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2829 const ArgDescriptor *Reg = nullptr;
2830 const TargetRegisterClass *RC = nullptr;
2831 LLT Ty;
2832
2834 const ArgDescriptor WorkGroupIDX =
2835 ArgDescriptor::createRegister(AMDGPU::TTMP9);
2836 // If GridZ is not programmed in an entry function then the hardware will set
2837 // it to all zeros, so there is no need to mask the GridY value in the low
2838 // order bits.
2839 const ArgDescriptor WorkGroupIDY = ArgDescriptor::createRegister(
2840 AMDGPU::TTMP7,
2841 AMDGPU::isEntryFunctionCC(CC) && !MFI.hasWorkGroupIDZ() ? ~0u : 0xFFFFu);
2842 const ArgDescriptor WorkGroupIDZ =
2843 ArgDescriptor::createRegister(AMDGPU::TTMP7, 0xFFFF0000u);
2844 const ArgDescriptor ClusterWorkGroupIDX =
2845 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000000Fu);
2846 const ArgDescriptor ClusterWorkGroupIDY =
2847 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000000F0u);
2848 const ArgDescriptor ClusterWorkGroupIDZ =
2849 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00000F00u);
2850 const ArgDescriptor ClusterWorkGroupMaxIDX =
2851 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000F000u);
2852 const ArgDescriptor ClusterWorkGroupMaxIDY =
2853 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000F0000u);
2854 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2855 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00F00000u);
2856 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2857 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0F000000u);
2858
2859 auto LoadConstant = [&](unsigned N) {
2860 return DAG.getConstant(N, SDLoc(), VT);
2861 };
2862
2863 if (Subtarget->hasArchitectedSGPRs() &&
2866 AMDGPU::ClusterDimsAttr ClusterDims = MFI.getClusterDims();
2867 bool HasFixedDims = ClusterDims.isFixedDims();
2868
2869 switch (PVID) {
2871 Reg = &WorkGroupIDX;
2872 RC = &AMDGPU::SReg_32RegClass;
2873 Ty = LLT::scalar(32);
2874 break;
2876 Reg = &WorkGroupIDY;
2877 RC = &AMDGPU::SReg_32RegClass;
2878 Ty = LLT::scalar(32);
2879 break;
2881 Reg = &WorkGroupIDZ;
2882 RC = &AMDGPU::SReg_32RegClass;
2883 Ty = LLT::scalar(32);
2884 break;
2886 if (HasFixedDims && ClusterDims.getDims()[0] == 1)
2887 return LoadConstant(0);
2888 Reg = &ClusterWorkGroupIDX;
2889 RC = &AMDGPU::SReg_32RegClass;
2890 Ty = LLT::scalar(32);
2891 break;
2893 if (HasFixedDims && ClusterDims.getDims()[1] == 1)
2894 return LoadConstant(0);
2895 Reg = &ClusterWorkGroupIDY;
2896 RC = &AMDGPU::SReg_32RegClass;
2897 Ty = LLT::scalar(32);
2898 break;
2900 if (HasFixedDims && ClusterDims.getDims()[2] == 1)
2901 return LoadConstant(0);
2902 Reg = &ClusterWorkGroupIDZ;
2903 RC = &AMDGPU::SReg_32RegClass;
2904 Ty = LLT::scalar(32);
2905 break;
2907 if (HasFixedDims)
2908 return LoadConstant(ClusterDims.getDims()[0] - 1);
2909 Reg = &ClusterWorkGroupMaxIDX;
2910 RC = &AMDGPU::SReg_32RegClass;
2911 Ty = LLT::scalar(32);
2912 break;
2914 if (HasFixedDims)
2915 return LoadConstant(ClusterDims.getDims()[1] - 1);
2916 Reg = &ClusterWorkGroupMaxIDY;
2917 RC = &AMDGPU::SReg_32RegClass;
2918 Ty = LLT::scalar(32);
2919 break;
2921 if (HasFixedDims)
2922 return LoadConstant(ClusterDims.getDims()[2] - 1);
2923 Reg = &ClusterWorkGroupMaxIDZ;
2924 RC = &AMDGPU::SReg_32RegClass;
2925 Ty = LLT::scalar(32);
2926 break;
2928 Reg = &ClusterWorkGroupMaxFlatID;
2929 RC = &AMDGPU::SReg_32RegClass;
2930 Ty = LLT::scalar(32);
2931 break;
2932 default:
2933 break;
2934 }
2935 }
2936
2937 if (!Reg)
2938 std::tie(Reg, RC, Ty) = MFI.getPreloadedValue(PVID);
2939 if (!Reg) {
2941 // It's possible for a kernarg intrinsic call to appear in a kernel with
2942 // no allocated segment, in which case we do not add the user sgpr
2943 // argument, so just return null.
2944 return DAG.getConstant(0, SDLoc(), VT);
2945 }
2946
2947 // It's undefined behavior if a function marked with the amdgpu-no-*
2948 // attributes uses the corresponding intrinsic.
2949 return DAG.getPOISON(VT);
2950 }
2951
2952 return loadInputValue(DAG, RC, VT, SDLoc(DAG.getEntryNode()), *Reg);
2953}
2954
2956 CallingConv::ID CallConv,
2957 ArrayRef<ISD::InputArg> Ins, BitVector &Skipped,
2958 FunctionType *FType,
2959 SIMachineFunctionInfo *Info) {
2960 for (unsigned I = 0, E = Ins.size(), PSInputNum = 0; I != E; ++I) {
2961 const ISD::InputArg *Arg = &Ins[I];
2962
2963 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2964 "vector type argument should have been split");
2965
2966 // First check if it's a PS input addr.
2967 if (CallConv == CallingConv::AMDGPU_PS && !Arg->Flags.isInReg() &&
2968 PSInputNum <= 15) {
2969 bool SkipArg = !Arg->Used && !Info->isPSInputAllocated(PSInputNum);
2970
2971 // Inconveniently only the first part of the split is marked as isSplit,
2972 // so skip to the end. We only want to increment PSInputNum once for the
2973 // entire split argument.
2974 if (Arg->Flags.isSplit()) {
2975 while (!Arg->Flags.isSplitEnd()) {
2976 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2977 "unexpected vector split in ps argument type");
2978 if (!SkipArg)
2979 Splits.push_back(*Arg);
2980 Arg = &Ins[++I];
2981 }
2982 }
2983
2984 if (SkipArg) {
2985 // We can safely skip PS inputs.
2986 Skipped.set(Arg->getOrigArgIndex());
2987 ++PSInputNum;
2988 continue;
2989 }
2990
2991 Info->markPSInputAllocated(PSInputNum);
2992 if (Arg->Used)
2993 Info->markPSInputEnabled(PSInputNum);
2994
2995 ++PSInputNum;
2996 }
2997
2998 Splits.push_back(*Arg);
2999 }
3000}
3001
3002// Allocate special inputs passed in VGPRs.
3004 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3005 SIMachineFunctionInfo &Info) const {
3006 const LLT I32 = LLT::integer(32);
3008
3009 if (Info.hasWorkItemIDX()) {
3010 Register Reg = AMDGPU::VGPR0;
3011 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3012
3013 CCInfo.AllocateReg(Reg);
3014 unsigned Mask =
3015 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
3016 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
3017 }
3018
3019 if (Info.hasWorkItemIDY()) {
3020 assert(Info.hasWorkItemIDX());
3021 if (Subtarget->hasPackedTID()) {
3022 Info.setWorkItemIDY(
3023 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 10));
3024 } else {
3025 unsigned Reg = AMDGPU::VGPR1;
3026 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3027
3028 CCInfo.AllocateReg(Reg);
3029 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg));
3030 }
3031 }
3032
3033 if (Info.hasWorkItemIDZ()) {
3034 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
3035 if (Subtarget->hasPackedTID()) {
3036 Info.setWorkItemIDZ(
3037 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 20));
3038 } else {
3039 unsigned Reg = AMDGPU::VGPR2;
3040 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3041
3042 CCInfo.AllocateReg(Reg);
3043 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg));
3044 }
3045 }
3046}
3047
3049 const TargetRegisterClass *RC,
3050 unsigned NumArgRegs) {
3051 ArrayRef<MCPhysReg> ArgSGPRs = ArrayRef(RC->begin(), 32);
3052 unsigned RegIdx = CCInfo.getFirstUnallocated(ArgSGPRs);
3053 if (RegIdx == ArgSGPRs.size())
3054 report_fatal_error("ran out of SGPRs for arguments");
3055
3056 unsigned Reg = ArgSGPRs[RegIdx];
3057 Reg = CCInfo.AllocateReg(Reg);
3058 assert(Reg != AMDGPU::NoRegister);
3059
3060 MachineFunction &MF = CCInfo.getMachineFunction();
3061 MF.addLiveIn(Reg, RC);
3063}
3064
3065// If this has a fixed position, we still should allocate the register in the
3066// CCInfo state. Technically we could get away with this for values passed
3067// outside of the normal argument range.
3069 const TargetRegisterClass *RC,
3070 MCRegister Reg) {
3071 Reg = CCInfo.AllocateReg(Reg);
3072 assert(Reg != AMDGPU::NoRegister);
3073 MachineFunction &MF = CCInfo.getMachineFunction();
3074 MF.addLiveIn(Reg, RC);
3075}
3076
3077static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg) {
3078 if (Arg) {
3079 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_32RegClass,
3080 Arg.getRegister());
3081 } else
3082 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_32RegClass, 32);
3083}
3084
3085static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg) {
3086 if (Arg) {
3087 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_64RegClass,
3088 Arg.getRegister());
3089 } else
3090 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_64RegClass, 16);
3091}
3092
3093/// Allocate implicit function VGPR arguments in fixed registers.
3095 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3096 SIMachineFunctionInfo &Info) const {
3097 Register Reg = CCInfo.AllocateReg(AMDGPU::VGPR31);
3098 if (!Reg)
3099 report_fatal_error("failed to allocate VGPR for implicit arguments");
3100
3101 const unsigned Mask = 0x3ff;
3102 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
3103 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg, Mask << 10));
3104 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg, Mask << 20));
3105}
3106
3108 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3109 SIMachineFunctionInfo &Info) const {
3110 auto &ArgInfo = Info.getArgInfo();
3111 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3112
3113 // TODO: Unify handling with private memory pointers.
3114 if (UserSGPRInfo.hasDispatchPtr())
3115 allocateSGPR64Input(CCInfo, ArgInfo.DispatchPtr);
3116
3117 if (UserSGPRInfo.hasQueuePtr())
3118 allocateSGPR64Input(CCInfo, ArgInfo.QueuePtr);
3119
3120 // Implicit arg ptr takes the place of the kernarg segment pointer. This is a
3121 // constant offset from the kernarg segment.
3122 if (Info.hasImplicitArgPtr())
3123 allocateSGPR64Input(CCInfo, ArgInfo.ImplicitArgPtr);
3124
3125 if (UserSGPRInfo.hasDispatchID())
3126 allocateSGPR64Input(CCInfo, ArgInfo.DispatchID);
3127
3128 // flat_scratch_init is not applicable for non-kernel functions.
3129
3130 if (Info.hasWorkGroupIDX())
3131 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDX);
3132
3133 if (Info.hasWorkGroupIDY())
3134 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDY);
3135
3136 if (Info.hasWorkGroupIDZ())
3137 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDZ);
3138
3139 if (Info.hasLDSKernelId())
3140 allocateSGPR32Input(CCInfo, ArgInfo.LDSKernelId);
3141}
3142
3143// Allocate special inputs passed in user SGPRs.
3145 MachineFunction &MF,
3146 const SIRegisterInfo &TRI,
3147 SIMachineFunctionInfo &Info) const {
3148 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3149 if (UserSGPRInfo.hasImplicitBufferPtr()) {
3150 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(TRI);
3151 MF.addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3152 CCInfo.AllocateReg(ImplicitBufferPtrReg);
3153 }
3154
3155 // FIXME: How should these inputs interact with inreg / custom SGPR inputs?
3156 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
3157 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(TRI);
3158 MF.addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3159 CCInfo.AllocateReg(PrivateSegmentBufferReg);
3160 }
3161
3162 if (UserSGPRInfo.hasDispatchPtr()) {
3163 Register DispatchPtrReg = Info.addDispatchPtr(TRI);
3164 MF.addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3165 CCInfo.AllocateReg(DispatchPtrReg);
3166 }
3167
3168 if (UserSGPRInfo.hasQueuePtr()) {
3169 Register QueuePtrReg = Info.addQueuePtr(TRI);
3170 MF.addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3171 CCInfo.AllocateReg(QueuePtrReg);
3172 }
3173
3174 if (UserSGPRInfo.hasKernargSegmentPtr()) {
3176 Register InputPtrReg = Info.addKernargSegmentPtr(TRI);
3177 CCInfo.AllocateReg(InputPtrReg);
3178
3179 Register VReg = MF.addLiveIn(InputPtrReg, &AMDGPU::SGPR_64RegClass);
3180 MRI.setType(VReg, LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS, 64));
3181 }
3182
3183 if (UserSGPRInfo.hasDispatchID()) {
3184 Register DispatchIDReg = Info.addDispatchID(TRI);
3185 MF.addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3186 CCInfo.AllocateReg(DispatchIDReg);
3187 }
3188
3189 if (UserSGPRInfo.hasFlatScratchInit() && !getSubtarget()->isAmdPalOS()) {
3190 Register FlatScratchInitReg = Info.addFlatScratchInit(TRI);
3191 MF.addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3192 CCInfo.AllocateReg(FlatScratchInitReg);
3193 }
3194
3195 if (UserSGPRInfo.hasPrivateSegmentSize()) {
3196 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(TRI);
3197 MF.addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3198 CCInfo.AllocateReg(PrivateSegmentSizeReg);
3199 }
3200
3201 // TODO: Add GridWorkGroupCount user SGPRs when used. For now with HSA we read
3202 // these from the dispatch pointer.
3203}
3204
3205// Allocate pre-loaded kernel arguemtns. Arguments to be preloading must be
3206// sequential starting from the first argument.
3208 CCState &CCInfo, SmallVectorImpl<CCValAssign> &ArgLocs,
3210 const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const {
3211 Function &F = MF.getFunction();
3212 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3213 GCNUserSGPRUsageInfo &SGPRInfo = Info.getUserSGPRInfo();
3214 bool InPreloadSequence = true;
3215 unsigned InIdx = 0;
3216 bool AlignedForImplictArgs = false;
3217 unsigned ImplicitArgOffset = 0;
3218 for (auto &Arg : F.args()) {
3219 if (!InPreloadSequence || !Arg.hasInRegAttr())
3220 break;
3221
3222 unsigned ArgIdx = Arg.getArgNo();
3223 // Don't preload non-original args or parts not in the current preload
3224 // sequence.
3225 if (InIdx < Ins.size() &&
3226 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3227 break;
3228
3229 for (; InIdx < Ins.size() && Ins[InIdx].isOrigArg() &&
3230 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3231 InIdx++) {
3232 assert(ArgLocs[ArgIdx].isMemLoc());
3233 auto &ArgLoc = ArgLocs[InIdx];
3234 const Align KernelArgBaseAlign = Align(16);
3235 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3236 Align Alignment = commonAlignment(KernelArgBaseAlign, ArgOffset);
3237 unsigned NumAllocSGPRs =
3238 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3239
3240 // Fix alignment for hidden arguments.
3241 if (Arg.hasAttribute("amdgpu-hidden-argument")) {
3242 if (!AlignedForImplictArgs) {
3243 ImplicitArgOffset =
3244 alignTo(LastExplicitArgOffset,
3245 Subtarget->getAlignmentForImplicitArgPtr()) -
3246 LastExplicitArgOffset;
3247 AlignedForImplictArgs = true;
3248 }
3249 ArgOffset += ImplicitArgOffset;
3250 }
3251
3252 // Arg is preloaded into the previous SGPR.
3253 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3254 assert(InIdx >= 1 && "No previous SGPR");
3255 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3256 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3257 continue;
3258 }
3259
3260 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3261 unsigned PaddingSGPRs = alignTo(Padding, 4) / 4;
3262 // Check for free user SGPRs for preloading.
3263 if (PaddingSGPRs + NumAllocSGPRs > SGPRInfo.getNumFreeUserSGPRs()) {
3264 InPreloadSequence = false;
3265 break;
3266 }
3267
3268 // Preload this argument.
3269 const TargetRegisterClass *RC =
3270 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3271 SmallVectorImpl<MCRegister> *PreloadRegs =
3272 Info.addPreloadedKernArg(TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3273
3274 if (PreloadRegs->size() > 1)
3275 RC = &AMDGPU::SGPR_32RegClass;
3276 for (auto &Reg : *PreloadRegs) {
3277 assert(Reg);
3278 MF.addLiveIn(Reg, RC);
3279 CCInfo.AllocateReg(Reg);
3280 }
3281
3282 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3283 }
3284 }
3285}
3286
3288 const SIRegisterInfo &TRI,
3289 SIMachineFunctionInfo &Info) const {
3290 // Always allocate this last since it is a synthetic preload.
3291 if (Info.hasLDSKernelId()) {
3292 Register Reg = Info.addLDSKernelId();
3293 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3294 CCInfo.AllocateReg(Reg);
3295 }
3296}
3297
3298// Allocate special input registers that are initialized per-wave.
3301 CallingConv::ID CallConv,
3302 bool IsShader) const {
3303 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3304 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3305 // Note: user SGPRs are handled by the front-end for graphics shaders
3306 // Pad up the used user SGPRs with dead inputs.
3307
3308 // TODO: NumRequiredSystemSGPRs computation should be adjusted appropriately
3309 // before enabling architected SGPRs for workgroup IDs.
3310 assert(!HasArchitectedSGPRs && "Unhandled feature for the subtarget");
3311
3312 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3313 // Note we do not count the PrivateSegmentWaveByteOffset. We do not want to
3314 // rely on it to reach 16 since if we end up having no stack usage, it will
3315 // not really be added.
3316 unsigned NumRequiredSystemSGPRs =
3317 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3318 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3319 for (unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3320 Register Reg = Info.addReservedUserSGPR();
3321 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3322 CCInfo.AllocateReg(Reg);
3323 }
3324 }
3325
3326 if (!HasArchitectedSGPRs) {
3327 if (Info.hasWorkGroupIDX()) {
3328 Register Reg = Info.addWorkGroupIDX();
3329 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3330 CCInfo.AllocateReg(Reg);
3331 }
3332
3333 if (Info.hasWorkGroupIDY()) {
3334 Register Reg = Info.addWorkGroupIDY();
3335 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3336 CCInfo.AllocateReg(Reg);
3337 }
3338
3339 if (Info.hasWorkGroupIDZ()) {
3340 Register Reg = Info.addWorkGroupIDZ();
3341 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3342 CCInfo.AllocateReg(Reg);
3343 }
3344 }
3345
3346 if (Info.hasWorkGroupInfo()) {
3347 Register Reg = Info.addWorkGroupInfo();
3348 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3349 CCInfo.AllocateReg(Reg);
3350 }
3351
3352 if (Info.hasPrivateSegmentWaveByteOffset()) {
3353 // Scratch wave offset passed in system SGPR.
3354 unsigned PrivateSegmentWaveByteOffsetReg;
3355
3356 if (IsShader) {
3357 PrivateSegmentWaveByteOffsetReg =
3358 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3359
3360 // This is true if the scratch wave byte offset doesn't have a fixed
3361 // location.
3362 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3363 PrivateSegmentWaveByteOffsetReg = findFirstFreeSGPR(CCInfo);
3364 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3365 }
3366 } else
3367 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3368
3369 MF.addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3370 CCInfo.AllocateReg(PrivateSegmentWaveByteOffsetReg);
3371 }
3372
3373 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3374 Info.getNumPreloadedSGPRs() >= 16);
3375}
3376
3378 MachineFunction &MF,
3379 const SIRegisterInfo &TRI,
3380 SIMachineFunctionInfo &Info) {
3381 // Now that we've figured out where the scratch register inputs are, see if
3382 // should reserve the arguments and use them directly.
3383 MachineFrameInfo &MFI = MF.getFrameInfo();
3384 bool HasStackObjects = MFI.hasStackObjects();
3385 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3386
3387 // Record that we know we have non-spill stack objects so we don't need to
3388 // check all stack objects later.
3389 if (HasStackObjects)
3390 Info.setHasNonSpillStackObjects(true);
3391
3392 // Everything live out of a block is spilled with fast regalloc, so it's
3393 // almost certain that spilling will be required.
3395 HasStackObjects = true;
3396
3397 // For now assume stack access is needed in any callee functions, so we need
3398 // the scratch registers to pass in.
3399 bool RequiresStackAccess = HasStackObjects || MFI.hasCalls();
3400
3401 if (!ST.hasFlatScratchEnabled()) {
3402 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.getFunction())) {
3403 // If we have stack objects, we unquestionably need the private buffer
3404 // resource. For the Code Object V2 ABI, this will be the first 4 user
3405 // SGPR inputs. We can reserve those and use them directly.
3406
3407 Register PrivateSegmentBufferReg =
3409 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3410 } else {
3411 unsigned ReservedBufferReg = TRI.reservedPrivateSegmentBufferReg(MF);
3412 // We tentatively reserve the last registers (skipping the last registers
3413 // which may contain VCC, FLAT_SCR, and XNACK). After register allocation,
3414 // we'll replace these with the ones immediately after those which were
3415 // really allocated. In the prologue copies will be inserted from the
3416 // argument to these reserved registers.
3417
3418 // Without HSA, relocations are used for the scratch pointer and the
3419 // buffer resource setup is always inserted in the prologue. Scratch wave
3420 // offset is still in an input SGPR.
3421 Info.setScratchRSrcReg(ReservedBufferReg);
3422 }
3423 }
3424
3426
3427 // For entry functions we have to set up the stack pointer if we use it,
3428 // whereas non-entry functions get this "for free". This means there is no
3429 // intrinsic advantage to using S32 over S34 in cases where we do not have
3430 // calls but do need a frame pointer (i.e. if we are requested to have one
3431 // because frame pointer elimination is disabled). To keep things simple we
3432 // only ever use S32 as the call ABI stack pointer, and so using it does not
3433 // imply we need a separate frame pointer.
3434 //
3435 // Try to use s32 as the SP, but move it if it would interfere with input
3436 // arguments. This won't work with calls though.
3437 //
3438 // FIXME: Move SP to avoid any possible inputs, or find a way to spill input
3439 // registers.
3440 if (!MRI.isLiveIn(AMDGPU::SGPR32)) {
3441 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3442 } else {
3444
3445 if (MFI.hasCalls())
3446 report_fatal_error("call in graphics shader with too many input SGPRs");
3447
3448 for (unsigned Reg : AMDGPU::SGPR_32RegClass) {
3449 if (!MRI.isLiveIn(Reg)) {
3450 Info.setStackPtrOffsetReg(Reg);
3451 break;
3452 }
3453 }
3454
3455 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3456 report_fatal_error("failed to find register for SP");
3457 }
3458
3459 // hasFP should be accurate for entry functions even before the frame is
3460 // finalized, because it does not rely on the known stack size, only
3461 // properties like whether variable sized objects are present.
3462 if (ST.getFrameLowering()->hasFP(MF)) {
3463 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3464 }
3465}
3466
3469 return !Info->isEntryFunction();
3470}
3471
3473
3475 MachineBasicBlock *Entry,
3476 const SmallVectorImpl<MachineBasicBlock *> &Exits) const {
3478
3479 const MCPhysReg *IStart = TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3480 if (!IStart)
3481 return;
3482
3483 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3484 MachineRegisterInfo *MRI = &Entry->getParent()->getRegInfo();
3485 MachineBasicBlock::iterator MBBI = Entry->begin();
3486 for (const MCPhysReg *I = IStart; *I; ++I) {
3487 const TargetRegisterClass *RC = nullptr;
3488 if (AMDGPU::SReg_64RegClass.contains(*I))
3489 RC = &AMDGPU::SGPR_64RegClass;
3490 else if (AMDGPU::SReg_32RegClass.contains(*I))
3491 RC = &AMDGPU::SGPR_32RegClass;
3492 else
3493 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3494
3495 Register NewVR = MRI->createVirtualRegister(RC);
3496 // Create copy from CSR to a virtual register.
3497 Entry->addLiveIn(*I);
3498 BuildMI(*Entry, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY), NewVR)
3499 .addReg(*I);
3500
3501 // Insert the copy-back instructions right before the terminator.
3502 for (auto *Exit : Exits)
3503 BuildMI(*Exit, Exit->getFirstTerminator(), DebugLoc(),
3504 TII->get(TargetOpcode::COPY), *I)
3505 .addReg(NewVR);
3506 }
3507}
3508
3510 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
3511 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3512 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
3514
3516 const Function &Fn = MF.getFunction();
3519 bool IsError = false;
3520
3521 if (Subtarget->isAmdHsaOS() && AMDGPU::isGraphics(CallConv)) {
3523 Fn, "unsupported non-compute shaders with HSA", DL.getDebugLoc()));
3524 IsError = true;
3525 }
3526
3529 BitVector Skipped(Fn.arg_size());
3530 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
3531 *DAG.getContext());
3532
3533 bool IsGraphics = AMDGPU::isGraphics(CallConv);
3534 bool IsKernel = AMDGPU::isKernel(CallConv);
3535 bool IsEntryFunc = AMDGPU::isEntryFunctionCC(CallConv);
3536
3537 if (IsGraphics) {
3538 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info->getUserSGPRInfo();
3539 assert(!UserSGPRInfo.hasDispatchPtr() &&
3540 !UserSGPRInfo.hasKernargSegmentPtr() && !Info->hasWorkGroupInfo() &&
3541 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3542 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3543 (void)UserSGPRInfo;
3544 if (!Subtarget->hasFlatScratchEnabled())
3545 assert(!UserSGPRInfo.hasFlatScratchInit());
3546 if ((CallConv != CallingConv::AMDGPU_CS &&
3547 CallConv != CallingConv::AMDGPU_Gfx &&
3548 CallConv != CallingConv::AMDGPU_Gfx_WholeWave) ||
3549 !Subtarget->hasArchitectedSGPRs())
3550 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3551 !Info->hasWorkGroupIDZ());
3552 }
3553
3554 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3555
3556 if (CallConv == CallingConv::AMDGPU_PS) {
3557 processPSInputArgs(Splits, CallConv, Ins, Skipped, FType, Info);
3558
3559 // At least one interpolation mode must be enabled or else the GPU will
3560 // hang.
3561 //
3562 // Check PSInputAddr instead of PSInputEnable. The idea is that if the user
3563 // set PSInputAddr, the user wants to enable some bits after the compilation
3564 // based on run-time states. Since we can't know what the final PSInputEna
3565 // will look like, so we shouldn't do anything here and the user should take
3566 // responsibility for the correct programming.
3567 //
3568 // Otherwise, the following restrictions apply:
3569 // - At least one of PERSP_* (0xF) or LINEAR_* (0x70) must be enabled.
3570 // - If POS_W_FLOAT (11) is enabled, at least one of PERSP_* must be
3571 // enabled too.
3572 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3573 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3574 CCInfo.AllocateReg(AMDGPU::VGPR0);
3575 CCInfo.AllocateReg(AMDGPU::VGPR1);
3576 Info->markPSInputAllocated(0);
3577 Info->markPSInputEnabled(0);
3578 }
3579 if (Subtarget->isAmdPalOS()) {
3580 // For isAmdPalOS, the user does not enable some bits after compilation
3581 // based on run-time states; the register values being generated here are
3582 // the final ones set in hardware. Therefore we need to apply the
3583 // workaround to PSInputAddr and PSInputEnable together. (The case where
3584 // a bit is set in PSInputAddr but not PSInputEnable is where the
3585 // frontend set up an input arg for a particular interpolation mode, but
3586 // nothing uses that input arg. Really we should have an earlier pass
3587 // that removes such an arg.)
3588 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3589 if ((PsInputBits & 0x7F) == 0 ||
3590 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3591 Info->markPSInputEnabled(llvm::countr_zero(Info->getPSInputAddr()));
3592 }
3593 } else if (IsKernel) {
3594 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3595 } else {
3596 Splits.append(IsWholeWaveFunc ? std::next(Ins.begin()) : Ins.begin(),
3597 Ins.end());
3598 }
3599
3600 if (IsKernel)
3601 analyzeFormalArgumentsCompute(CCInfo, Ins);
3602
3603 if (IsEntryFunc) {
3604 allocateSpecialEntryInputVGPRs(CCInfo, MF, *TRI, *Info);
3605 allocateHSAUserSGPRs(CCInfo, MF, *TRI, *Info);
3606 if (IsKernel && Subtarget->hasKernargPreload())
3607 allocatePreloadKernArgSGPRs(CCInfo, ArgLocs, Ins, MF, *TRI, *Info);
3608
3609 allocateLDSKernelId(CCInfo, MF, *TRI, *Info);
3610 } else if (!IsGraphics) {
3611 // For the fixed ABI, pass workitem IDs in the last argument register.
3612 allocateSpecialInputVGPRsFixed(CCInfo, MF, *TRI, *Info);
3613
3614 // FIXME: Sink this into allocateSpecialInputSGPRs
3615 if (!Subtarget->hasFlatScratchEnabled())
3616 CCInfo.AllocateReg(Info->getScratchRSrcReg());
3617
3618 allocateSpecialInputSGPRs(CCInfo, MF, *TRI, *Info);
3619 }
3620
3621 if (!IsKernel) {
3622 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, isVarArg);
3623 CCInfo.AnalyzeFormalArguments(Splits, AssignFn);
3624
3625 // This assumes the registers are allocated by CCInfo in ascending order
3626 // with no gaps.
3627 Info->setNumWaveDispatchSGPRs(
3628 CCInfo.getFirstUnallocated(AMDGPU::SGPR_32RegClass.getRegisters()));
3629 Info->setNumWaveDispatchVGPRs(
3630 CCInfo.getFirstUnallocated(AMDGPU::VGPR_32RegClass.getRegisters()));
3631 } else if (Info->getNumKernargPreloadedSGPRs()) {
3632 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3633 }
3634
3636
3637 if (IsWholeWaveFunc) {
3638 SDValue Setup = DAG.getNode(AMDGPUISD::WHOLE_WAVE_SETUP, DL,
3639 {MVT::i1, MVT::Other}, Chain);
3640 InVals.push_back(Setup.getValue(0));
3641 Chains.push_back(Setup.getValue(1));
3642 }
3643
3644 // FIXME: This is the minimum kernel argument alignment. We should improve
3645 // this to the maximum alignment of the arguments.
3646 //
3647 // FIXME: Alignment of explicit arguments totally broken with non-0 explicit
3648 // kern arg offset.
3649 const Align KernelArgBaseAlign = Align(16);
3650
3651 for (unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.size(), ArgIdx = 0; i != e;
3652 ++i) {
3653 const ISD::InputArg &Arg = Ins[i];
3654 if ((Arg.isOrigArg() && Skipped[Arg.getOrigArgIndex()]) || IsError) {
3655 InVals.push_back(DAG.getPOISON(Arg.VT));
3656 continue;
3657 }
3658
3659 CCValAssign &VA = ArgLocs[ArgIdx++];
3660 MVT VT = VA.getLocVT();
3661
3662 if (IsEntryFunc && VA.isMemLoc()) {
3663 VT = Ins[i].VT;
3664 EVT MemVT = VA.getLocVT();
3665
3666 const uint64_t Offset = VA.getLocMemOffset();
3667 Align Alignment = commonAlignment(KernelArgBaseAlign, Offset);
3668
3669 if (Arg.Flags.isByRef()) {
3670 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, Chain, Offset);
3671
3672 const GCNTargetMachine &TM =
3673 static_cast<const GCNTargetMachine &>(getTargetMachine());
3674 if (!TM.isNoopAddrSpaceCast(DAG.getDataLayout(),
3676 Arg.Flags.getPointerAddrSpace())) {
3679 }
3680
3681 InVals.push_back(Ptr);
3682 continue;
3683 }
3684
3685 SDValue NewArg;
3686 if (Arg.isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3687 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
3688 // In this case the argument is packed into the previous preload SGPR.
3689 int64_t AlignDownOffset = alignDown(Offset, 4);
3690 int64_t OffsetDiff = Offset - AlignDownOffset;
3691 EVT IntVT = MemVT.changeTypeToInteger();
3692
3693 const SIMachineFunctionInfo *Info =
3696 Register Reg =
3697 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3698
3699 assert(Reg);
3700 Register VReg = MRI.getLiveInVirtReg(Reg);
3701 SDValue Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3702
3703 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, DL, MVT::i32);
3704 SDValue Extract = DAG.getNode(ISD::SRL, DL, MVT::i32, Copy, ShiftAmt);
3705
3706 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Extract);
3707 ArgVal = DAG.getNode(ISD::BITCAST, DL, MemVT, ArgVal);
3708 NewArg = convertArgType(DAG, VT, MemVT, DL, ArgVal,
3709 Ins[i].Flags.isSExt(), &Ins[i]);
3710
3711 NewArg = DAG.getMergeValues({NewArg, Copy.getValue(1)}, DL);
3712 } else {
3713 const SIMachineFunctionInfo *Info =
3716 const SmallVectorImpl<MCRegister> &PreloadRegs =
3717 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3718
3719 SDValue Copy;
3720 if (PreloadRegs.size() == 1) {
3721 Register VReg = MRI.getLiveInVirtReg(PreloadRegs[0]);
3722 const TargetRegisterClass *RC = MRI.getRegClass(VReg);
3723 NewArg = DAG.getCopyFromReg(
3724 Chain, DL, VReg,
3726 TRI->getRegSizeInBits(*RC)));
3727
3728 } else {
3729 // If the kernarg alignment does not match the alignment of the SGPR
3730 // tuple RC that can accommodate this argument, it will be built up
3731 // via copies from from the individual SGPRs that the argument was
3732 // preloaded to.
3734 for (auto Reg : PreloadRegs) {
3735 Register VReg = MRI.getLiveInVirtReg(Reg);
3736 Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3737 Elts.push_back(Copy);
3738 }
3739 NewArg =
3740 DAG.getBuildVector(EVT::getVectorVT(*DAG.getContext(), MVT::i32,
3741 PreloadRegs.size()),
3742 DL, Elts);
3743 }
3744
3745 // If the argument was preloaded to multiple consecutive 32-bit
3746 // registers because of misalignment between addressable SGPR tuples
3747 // and the argument size, we can still assume that because of kernarg
3748 // segment alignment restrictions that NewArg's size is the same as
3749 // MemVT and just do a bitcast. If MemVT is less than 32-bits we add a
3750 // truncate since we cannot preload to less than a single SGPR and the
3751 // MemVT may be smaller.
3752 EVT MemVTInt =
3754 if (MemVT.bitsLT(NewArg.getSimpleValueType()))
3755 NewArg = DAG.getNode(ISD::TRUNCATE, DL, MemVTInt, NewArg);
3756
3757 NewArg = DAG.getBitcast(MemVT, NewArg);
3758 NewArg = convertArgType(DAG, VT, MemVT, DL, NewArg,
3759 Ins[i].Flags.isSExt(), &Ins[i]);
3760 NewArg = DAG.getMergeValues({NewArg, Chain}, DL);
3761 }
3762 } else {
3763 // Hidden arguments that are in the kernel signature must be preloaded
3764 // to user SGPRs. Print a diagnostic error if a hidden argument is in
3765 // the argument list and is not preloaded.
3766 if (Arg.isOrigArg()) {
3767 Argument *OrigArg = Fn.getArg(Arg.getOrigArgIndex());
3768 if (OrigArg->hasAttribute("amdgpu-hidden-argument")) {
3770 *OrigArg->getParent(),
3771 "hidden argument in kernel signature was not preloaded",
3772 DL.getDebugLoc()));
3773 }
3774 }
3775
3776 NewArg =
3777 lowerKernargMemParameter(DAG, VT, MemVT, DL, Chain, Offset,
3778 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3779 }
3780 Chains.push_back(NewArg.getValue(1));
3781
3782 auto *ParamTy =
3783 dyn_cast<PointerType>(FType->getParamType(Ins[i].getOrigArgIndex()));
3784 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS &&
3785 ParamTy &&
3786 (ParamTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
3787 ParamTy->getAddressSpace() == AMDGPUAS::REGION_ADDRESS)) {
3788 // On SI local pointers are just offsets into LDS, so they are always
3789 // less than 16-bits. On CI and newer they could potentially be
3790 // real pointers, so we can't guarantee their size.
3791 NewArg = DAG.getNode(ISD::AssertZext, DL, NewArg.getValueType(), NewArg,
3792 DAG.getValueType(MVT::i16));
3793 }
3794
3795 InVals.push_back(NewArg);
3796 continue;
3797 }
3798 if (!IsEntryFunc && VA.isMemLoc()) {
3799 SDValue Val = lowerStackParameter(DAG, VA, DL, Chain, Arg);
3800 InVals.push_back(Val);
3801 if (!Arg.Flags.isByVal())
3802 Chains.push_back(Val.getValue(1));
3803 continue;
3804 }
3805
3806 assert(VA.isRegLoc() && "Parameter must be in a register!");
3807
3808 Register Reg = VA.getLocReg();
3809 const TargetRegisterClass *RC = nullptr;
3810 if (AMDGPU::VGPR_32RegClass.contains(Reg))
3811 RC = &AMDGPU::VGPR_32RegClass;
3812 else if (AMDGPU::SGPR_32RegClass.contains(Reg))
3813 RC = &AMDGPU::SGPR_32RegClass;
3814 else
3815 llvm_unreachable("Unexpected register class in LowerFormalArguments!");
3816
3817 Reg = MF.addLiveIn(Reg, RC);
3818 SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, VT);
3819 if (Arg.Flags.isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3820 // FIXME: Need to forward the chains created by `CopyFromReg`s, make sure
3821 // they will read physical regs before any side effect instructions.
3822 SDValue ReadFirstLane =
3823 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3825 ReadFirstLane, Val);
3826 }
3827
3828 if (Arg.Flags.isSRet()) {
3829 // The return object should be reasonably addressable.
3830 Val = annotateStackObjectPointer(Val, DAG, DL,
3832 }
3833
3834 Val = convertABITypeToValueType(DAG, Val, VA, DL);
3835 InVals.push_back(Val);
3836 }
3837
3838 // Start adding system SGPRs.
3839 if (IsEntryFunc)
3840 allocateSystemSGPRs(CCInfo, MF, *Info, CallConv, IsGraphics);
3841
3842 unsigned StackArgSize = CCInfo.getStackSize();
3843 Info->setBytesInStackArgArea(StackArgSize);
3844
3845 return Chains.empty() ? Chain
3846 : DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
3847}
3848
3849// TODO: If return values can't fit in registers, we should return as many as
3850// possible in registers before passing on stack.
3852 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
3853 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
3854 const Type *RetTy) const {
3855 // Replacing returns with sret/stack usage doesn't make sense for shaders.
3856 // FIXME: Also sort of a workaround for custom vector splitting in LowerReturn
3857 // for shaders. Vector types should be explicitly handled by CC.
3858 if (AMDGPU::isEntryFunctionCC(CallConv))
3859 return true;
3860
3862 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3863 if (!CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)))
3864 return false;
3865
3866 // We must use the stack if return would require unavailable registers.
3867 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3868 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3869 for (unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3870 if (CCInfo.isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3871 return false;
3872
3873 return true;
3874}
3875
3876SDValue
3878 bool isVarArg,
3880 const SmallVectorImpl<SDValue> &OutVals,
3881 const SDLoc &DL, SelectionDAG &DAG) const {
3885
3886 if (AMDGPU::isKernel(CallConv)) {
3887 return AMDGPUTargetLowering::LowerReturn(Chain, CallConv, isVarArg, Outs,
3888 OutVals, DL, DAG);
3889 }
3890
3891 bool IsShader = AMDGPU::isShader(CallConv);
3892
3893 Info->setIfReturnsVoid(Outs.empty());
3894 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3895
3896 // CCValAssign - represent the assignment of the return value to a location.
3898
3899 // CCState - Info about the registers and stack slots.
3900 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
3901 *DAG.getContext());
3902
3903 // Analyze outgoing return values.
3904 CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, isVarArg));
3905
3906 SDValue Glue;
3908 RetOps.push_back(Chain); // Operand #0 = Chain (updated below)
3909
3910 SDValue ReadFirstLane =
3911 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3912 // Copy the result values into the output registers.
3913 for (unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.size(); I != E;
3914 ++I, ++RealRVLocIdx) {
3915 CCValAssign &VA = RVLocs[I];
3916 assert(VA.isRegLoc() && "Can only return in registers!");
3917 // TODO: Partially return in registers if return values don't fit.
3918 SDValue Arg = OutVals[RealRVLocIdx];
3919
3920 // Copied from other backends.
3921 switch (VA.getLocInfo()) {
3922 case CCValAssign::Full:
3923 break;
3924 case CCValAssign::BCvt:
3925 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
3926 break;
3927 case CCValAssign::SExt:
3928 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
3929 break;
3930 case CCValAssign::ZExt:
3931 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
3932 break;
3933 case CCValAssign::AExt:
3934 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
3935 break;
3936 default:
3937 llvm_unreachable("Unknown loc info!");
3938 }
3939 if (TRI->isSGPRPhysReg(VA.getLocReg()))
3941 ReadFirstLane, Arg);
3942 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Glue);
3943 Glue = Chain.getValue(1);
3944 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
3945 }
3946
3947 // FIXME: Does sret work properly?
3948 if (!Info->isEntryFunction()) {
3949 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
3950 const MCPhysReg *I =
3951 TRI->getCalleeSavedRegsViaCopy(&DAG.getMachineFunction());
3952 if (I) {
3953 for (; *I; ++I) {
3954 if (AMDGPU::SReg_64RegClass.contains(*I))
3955 RetOps.push_back(DAG.getRegister(*I, MVT::i64));
3956 else if (AMDGPU::SReg_32RegClass.contains(*I))
3957 RetOps.push_back(DAG.getRegister(*I, MVT::i32));
3958 else
3959 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3960 }
3961 }
3962 }
3963
3964 // Update chain and glue.
3965 RetOps[0] = Chain;
3966 if (Glue.getNode())
3967 RetOps.push_back(Glue);
3968
3969 unsigned Opc = AMDGPUISD::ENDPGM;
3970 if (!IsWaveEnd)
3971 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3972 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3973 : AMDGPUISD::RET_GLUE;
3974 return DAG.getNode(Opc, DL, MVT::Other, RetOps);
3975}
3976
3978 SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
3979 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3980 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, bool IsThisReturn,
3981 SDValue ThisVal) const {
3982 CCAssignFn *RetCC = CCAssignFnForReturn(CallConv, IsVarArg);
3983
3984 // Assign locations to each value returned by this call.
3986 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
3987 *DAG.getContext());
3988 CCInfo.AnalyzeCallResult(Ins, RetCC);
3989
3990 // Copy all of the result registers out of their specified physreg.
3991 for (CCValAssign VA : RVLocs) {
3992 SDValue Val;
3993
3994 if (VA.isRegLoc()) {
3995 Val =
3996 DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), InGlue);
3997 Chain = Val.getValue(1);
3998 InGlue = Val.getValue(2);
3999 } else if (VA.isMemLoc()) {
4000 report_fatal_error("TODO: return values in memory");
4001 } else
4002 llvm_unreachable("unknown argument location type");
4003
4004 switch (VA.getLocInfo()) {
4005 case CCValAssign::Full:
4006 break;
4007 case CCValAssign::BCvt:
4008 Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
4009 break;
4010 case CCValAssign::ZExt:
4011 Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val,
4012 DAG.getValueType(VA.getValVT()));
4013 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4014 break;
4015 case CCValAssign::SExt:
4016 Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val,
4017 DAG.getValueType(VA.getValVT()));
4018 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4019 break;
4020 case CCValAssign::AExt:
4021 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4022 break;
4023 default:
4024 llvm_unreachable("Unknown loc info!");
4025 }
4026
4027 InVals.push_back(Val);
4028 }
4029
4030 return Chain;
4031}
4032
4033// Add code to pass special inputs required depending on used features separate
4034// from the explicit user arguments present in the IR.
4036 CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info,
4037 SmallVectorImpl<std::pair<unsigned, SDValue>> &RegsToPass,
4038 SmallVectorImpl<SDValue> &MemOpChains, SDValue Chain) const {
4039 // If we don't have a call site, this was a call inserted by
4040 // legalization. These can never use special inputs.
4041 if (!CLI.CB)
4042 return;
4043
4044 SelectionDAG &DAG = CLI.DAG;
4045 const SDLoc &DL = CLI.DL;
4046 const Function &F = DAG.getMachineFunction().getFunction();
4047
4048 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
4049 const AMDGPUFunctionArgInfo &CallerArgInfo = Info.getArgInfo();
4050
4051 const AMDGPUFunctionArgInfo &CalleeArgInfo =
4053
4054 // TODO: Unify with private memory register handling. This is complicated by
4055 // the fact that at least in kernels, the input argument is not necessarily
4056 // in the same location as the input.
4057 // clang-format off
4058 static constexpr std::pair<AMDGPUFunctionArgInfo::PreloadedValue,
4059 std::array<StringLiteral, 2>> ImplicitAttrs[] = {
4060 {AMDGPUFunctionArgInfo::DISPATCH_PTR, {"amdgpu-no-dispatch-ptr", ""}},
4061 {AMDGPUFunctionArgInfo::QUEUE_PTR, {"amdgpu-no-queue-ptr", ""}},
4062 {AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR, {"amdgpu-no-implicitarg-ptr", ""}},
4063 {AMDGPUFunctionArgInfo::DISPATCH_ID, {"amdgpu-no-dispatch-id", ""}},
4064 {AMDGPUFunctionArgInfo::WORKGROUP_ID_X, {"amdgpu-no-workgroup-id-x", "amdgpu-no-cluster-id-x"}},
4065 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Y, {"amdgpu-no-workgroup-id-y", "amdgpu-no-cluster-id-y"}},
4066 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Z, {"amdgpu-no-workgroup-id-z", "amdgpu-no-cluster-id-z"}},
4067 {AMDGPUFunctionArgInfo::LDS_KERNEL_ID, {"amdgpu-no-lds-kernel-id", ""}},
4068 };
4069 // clang-format on
4070
4071 for (auto [InputID, Attrs] : ImplicitAttrs) {
4072 // If the callee does not use the attribute value, skip copying the value.
4073 if (all_of(Attrs, [&](StringRef Attr) {
4074 return Attr.empty() || CLI.CB->hasFnAttr(Attr);
4075 }))
4076 continue;
4077
4078 const auto [OutgoingArg, ArgRC, ArgTy] =
4079 CalleeArgInfo.getPreloadedValue(InputID);
4080 if (!OutgoingArg)
4081 continue;
4082
4083 const auto [IncomingArg, IncomingArgRC, Ty] =
4084 CallerArgInfo.getPreloadedValue(InputID);
4085 assert(IncomingArgRC == ArgRC);
4086
4087 // All special arguments are ints for now.
4088 EVT ArgVT = TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4089 SDValue InputReg;
4090
4091 if (IncomingArg) {
4092 InputReg = loadInputValue(DAG, ArgRC, ArgVT, DL, *IncomingArg);
4093 } else if (InputID == AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR) {
4094 // The implicit arg ptr is special because it doesn't have a corresponding
4095 // input for kernels, and is computed from the kernarg segment pointer.
4096 InputReg = getImplicitArgPtr(DAG, DL);
4097 } else if (InputID == AMDGPUFunctionArgInfo::LDS_KERNEL_ID) {
4098 std::optional<uint32_t> Id =
4100 if (Id.has_value()) {
4101 InputReg = DAG.getConstant(*Id, DL, ArgVT);
4102 } else {
4103 InputReg = DAG.getPOISON(ArgVT);
4104 }
4105 } else {
4106 // We may have proven the input wasn't needed, although the ABI is
4107 // requiring it. We just need to allocate the register appropriately.
4108 InputReg = DAG.getPOISON(ArgVT);
4109 }
4110
4111 if (OutgoingArg->isRegister()) {
4112 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4113 if (!CCInfo.AllocateReg(OutgoingArg->getRegister()))
4114 report_fatal_error("failed to allocate implicit input argument");
4115 } else {
4116 unsigned SpecialArgOffset =
4117 CCInfo.AllocateStack(ArgVT.getStoreSize(), Align(4));
4118 SDValue ArgStore =
4119 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4120 MemOpChains.push_back(ArgStore);
4121 }
4122 }
4123
4124 // Pack workitem IDs into a single register or pass it as is if already
4125 // packed.
4126
4127 auto [OutgoingArg, ArgRC, Ty] =
4129 if (!OutgoingArg)
4130 std::tie(OutgoingArg, ArgRC, Ty) =
4132 if (!OutgoingArg)
4133 std::tie(OutgoingArg, ArgRC, Ty) =
4135 if (!OutgoingArg)
4136 return;
4137
4138 const ArgDescriptor *IncomingArgX = std::get<0>(
4140 const ArgDescriptor *IncomingArgY = std::get<0>(
4142 const ArgDescriptor *IncomingArgZ = std::get<0>(
4144
4145 SDValue InputReg;
4146 SDLoc SL;
4147
4148 const bool NeedWorkItemIDX = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-x");
4149 const bool NeedWorkItemIDY = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-y");
4150 const bool NeedWorkItemIDZ = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-z");
4151
4152 // If incoming ids are not packed we need to pack them.
4153 if (IncomingArgX && !IncomingArgX->isMasked() && CalleeArgInfo.WorkItemIDX &&
4154 NeedWorkItemIDX) {
4155 if (Subtarget->getMaxWorkitemID(F, 0) != 0) {
4156 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgX);
4157 } else {
4158 InputReg = DAG.getConstant(0, DL, MVT::i32);
4159 }
4160 }
4161
4162 if (IncomingArgY && !IncomingArgY->isMasked() && CalleeArgInfo.WorkItemIDY &&
4163 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(F, 1) != 0) {
4164 SDValue Y = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgY);
4165 Y = DAG.getNode(ISD::SHL, SL, MVT::i32, Y,
4166 DAG.getShiftAmountConstant(10, MVT::i32, SL));
4167 InputReg = InputReg.getNode()
4168 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Y)
4169 : Y;
4170 }
4171
4172 if (IncomingArgZ && !IncomingArgZ->isMasked() && CalleeArgInfo.WorkItemIDZ &&
4173 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(F, 2) != 0) {
4174 SDValue Z = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgZ);
4175 Z = DAG.getNode(ISD::SHL, SL, MVT::i32, Z,
4176 DAG.getShiftAmountConstant(20, MVT::i32, SL));
4177 InputReg = InputReg.getNode()
4178 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Z)
4179 : Z;
4180 }
4181
4182 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4183 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4184 // We're in a situation where the outgoing function requires the workitem
4185 // ID, but the calling function does not have it (e.g a graphics function
4186 // calling a C calling convention function). This is illegal, but we need
4187 // to produce something.
4188 InputReg = DAG.getPOISON(MVT::i32);
4189 } else {
4190 // Workitem ids are already packed, any of present incoming arguments
4191 // will carry all required fields.
4192 ArgDescriptor IncomingArg =
4193 ArgDescriptor::createArg(IncomingArgX ? *IncomingArgX
4194 : IncomingArgY ? *IncomingArgY
4195 : *IncomingArgZ,
4196 ~0u);
4197 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, IncomingArg);
4198 }
4199 }
4200
4201 if (OutgoingArg->isRegister()) {
4202 if (InputReg)
4203 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4204
4205 CCInfo.AllocateReg(OutgoingArg->getRegister());
4206 } else {
4207 unsigned SpecialArgOffset = CCInfo.AllocateStack(4, Align(4));
4208 if (InputReg) {
4209 SDValue ArgStore =
4210 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4211 MemOpChains.push_back(ArgStore);
4212 }
4213 }
4214}
4215
4217 SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg,
4219 const SmallVectorImpl<SDValue> &OutVals,
4220 const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const {
4221 if (AMDGPU::isChainCC(CalleeCC))
4222 return true;
4223
4224 if (!AMDGPU::mayTailCallThisCC(CalleeCC))
4225 return false;
4226
4227 // For a divergent call target, we need to do a waterfall loop over the
4228 // possible callees which precludes us from using a simple jump.
4229 if (Callee->isDivergent())
4230 return false;
4231
4233 const Function &CallerF = MF.getFunction();
4234 CallingConv::ID CallerCC = CallerF.getCallingConv();
4236 const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC);
4237
4238 // Kernels aren't callable, and don't have a live in return address so it
4239 // doesn't make sense to do a tail call with entry functions.
4240 if (!CallerPreserved)
4241 return false;
4242
4243 bool CCMatch = CallerCC == CalleeCC;
4244
4246 if (AMDGPU::canGuaranteeTCO(CalleeCC) && CCMatch)
4247 return true;
4248 return false;
4249 }
4250
4251 // TODO: Can we handle var args?
4252 if (IsVarArg)
4253 return false;
4254
4255 for (const Argument &Arg : CallerF.args()) {
4256 if (Arg.hasByValAttr())
4257 return false;
4258 }
4259
4260 LLVMContext &Ctx = *DAG.getContext();
4261
4262 // Check that the call results are passed in the same way.
4263 if (!CCState::resultsCompatible(CalleeCC, CallerCC, MF, Ctx, Ins,
4264 CCAssignFnForCall(CalleeCC, IsVarArg),
4265 CCAssignFnForCall(CallerCC, IsVarArg)))
4266 return false;
4267
4268 // The callee has to preserve all registers the caller needs to preserve.
4269 if (!CCMatch) {
4270 const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC);
4271 if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4272 return false;
4273 }
4274
4275 // Nothing more to check if the callee is taking no arguments.
4276 if (Outs.empty())
4277 return true;
4278
4280 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4281
4282 // FIXME: We are not allocating special input registers, so we will be
4283 // deciding based on incorrect register assignments.
4284 CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CalleeCC, IsVarArg));
4285
4286 const SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
4287 // If the stack arguments for this call do not fit into our own save area then
4288 // the call cannot be made tail.
4289 // TODO: Is this really necessary?
4290 if (CCInfo.getStackSize() > FuncInfo->getBytesInStackArgArea())
4291 return false;
4292
4293 for (const auto &[CCVA, ArgVal] : zip_equal(ArgLocs, OutVals)) {
4294 // FIXME: What about inreg arguments that end up passed in memory?
4295 if (!CCVA.isRegLoc())
4296 continue;
4297
4298 // If we are passing an argument in an SGPR, and the value is divergent,
4299 // this call requires a waterfall loop.
4300 if (ArgVal->isDivergent() && TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4301 LLVM_DEBUG(
4302 dbgs() << "Cannot tail call due to divergent outgoing argument in "
4303 << printReg(CCVA.getLocReg(), TRI) << '\n');
4304 return false;
4305 }
4306 }
4307
4308 const MachineRegisterInfo &MRI = MF.getRegInfo();
4309 return parametersInCSRMatch(MRI, CallerPreserved, ArgLocs, OutVals);
4310}
4311
4313 if (!CI->isTailCall())
4314 return false;
4315
4316 const Function *ParentFn = CI->getFunction();
4318 return false;
4319 return true;
4320}
4321
4322namespace {
4323// Chain calls have special arguments that we need to handle. These are
4324// tagging along at the end of the arguments list(s), after the SGPR and VGPR
4325// arguments (index 0 and 1 respectively).
4326enum ChainCallArgIdx {
4327 Exec = 2,
4328 Flags,
4329 NumVGPRs,
4330 FallbackExec,
4331 FallbackCallee
4332};
4333} // anonymous namespace
4334
4335// The wave scratch offset register is used as the global base pointer.
4337 SmallVectorImpl<SDValue> &InVals) const {
4338 CallingConv::ID CallConv = CLI.CallConv;
4339 bool IsChainCallConv = AMDGPU::isChainCC(CallConv);
4340
4341 SelectionDAG &DAG = CLI.DAG;
4342
4343 const SDLoc &DL = CLI.DL;
4344 SDValue Chain = CLI.Chain;
4345 SDValue Callee = CLI.Callee;
4346
4347 llvm::SmallVector<SDValue, 6> ChainCallSpecialArgs;
4348 bool UsesDynamicVGPRs = false;
4349 if (IsChainCallConv) {
4350 // The last arguments should be the value that we need to put in EXEC,
4351 // followed by the flags and any other arguments with special meanings.
4352 // Pop them out of CLI.Outs and CLI.OutVals before we do any processing so
4353 // we don't treat them like the "real" arguments.
4354 auto RequestedExecIt =
4355 llvm::find_if(CLI.Outs, [](const ISD::OutputArg &Arg) {
4356 return Arg.OrigArgIndex == 2;
4357 });
4358 assert(RequestedExecIt != CLI.Outs.end() && "No node for EXEC");
4359
4360 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.Outs.begin();
4361 CLI.OutVals.erase(CLI.OutVals.begin() + SpecialArgsBeginIdx,
4362 CLI.OutVals.end());
4363 CLI.Outs.erase(RequestedExecIt, CLI.Outs.end());
4364
4365 assert(CLI.Outs.back().OrigArgIndex < 2 &&
4366 "Haven't popped all the special args");
4367
4368 TargetLowering::ArgListEntry RequestedExecArg =
4369 CLI.Args[ChainCallArgIdx::Exec];
4370 if (!RequestedExecArg.Ty->isIntegerTy(Subtarget->getWavefrontSize()))
4371 return lowerUnhandledCall(CLI, InVals, "Invalid value for EXEC");
4372
4373 // Convert constants into TargetConstants, so they become immediate operands
4374 // instead of being selected into S_MOV.
4375 auto PushNodeOrTargetConstant = [&](TargetLowering::ArgListEntry Arg) {
4376 if (const auto *ArgNode = dyn_cast<ConstantSDNode>(Arg.Node)) {
4377 ChainCallSpecialArgs.push_back(DAG.getTargetConstant(
4378 ArgNode->getAPIntValue(), DL, ArgNode->getValueType(0)));
4379 } else
4380 ChainCallSpecialArgs.push_back(Arg.Node);
4381 };
4382
4383 PushNodeOrTargetConstant(RequestedExecArg);
4384
4385 // Process any other special arguments depending on the value of the flags.
4386 TargetLowering::ArgListEntry Flags = CLI.Args[ChainCallArgIdx::Flags];
4387
4388 const APInt &FlagsValue = cast<ConstantSDNode>(Flags.Node)->getAPIntValue();
4389 if (FlagsValue.isZero()) {
4390 if (CLI.Args.size() > ChainCallArgIdx::Flags + 1)
4391 return lowerUnhandledCall(CLI, InVals,
4392 "no additional args allowed if flags == 0");
4393 } else if (FlagsValue.isOneBitSet(0)) {
4394 if (CLI.Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4395 return lowerUnhandledCall(CLI, InVals, "expected 3 additional args");
4396 }
4397
4398 if (!Subtarget->isWave32()) {
4399 return lowerUnhandledCall(
4400 CLI, InVals, "dynamic VGPR mode is only supported for wave32");
4401 }
4402
4403 UsesDynamicVGPRs = true;
4404 std::for_each(CLI.Args.begin() + ChainCallArgIdx::NumVGPRs,
4405 CLI.Args.end(), PushNodeOrTargetConstant);
4406 }
4407 }
4408
4410 SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
4412 bool &IsTailCall = CLI.IsTailCall;
4413 bool IsVarArg = CLI.IsVarArg;
4414 bool IsSibCall = false;
4416
4417 if (Callee.isUndef() || isNullConstant(Callee)) {
4418 if (!CLI.IsTailCall) {
4419 for (ISD::InputArg &Arg : CLI.Ins)
4420 InVals.push_back(DAG.getPOISON(Arg.VT));
4421 }
4422
4423 return Chain;
4424 }
4425
4426 if (IsVarArg) {
4427 return lowerUnhandledCall(CLI, InVals,
4428 "unsupported call to variadic function ");
4429 }
4430
4431 if (!CLI.CB)
4432 return lowerUnhandledCall(CLI, InVals, "unsupported libcall legalization");
4433
4434 if (IsTailCall && MF.getTarget().Options.GuaranteedTailCallOpt) {
4435 return lowerUnhandledCall(CLI, InVals,
4436 "unsupported required tail call to function ");
4437 }
4438
4439 if (IsTailCall) {
4440 IsTailCall = isEligibleForTailCallOptimization(Callee, CallConv, IsVarArg,
4441 Outs, OutVals, Ins, DAG);
4442 if (!IsTailCall &&
4443 ((CLI.CB && CLI.CB->isMustTailCall()) || IsChainCallConv)) {
4444 report_fatal_error("failed to perform tail call elimination on a call "
4445 "site marked musttail or on llvm.amdgcn.cs.chain");
4446 }
4447
4448 bool TailCallOpt = MF.getTarget().Options.GuaranteedTailCallOpt;
4449
4450 // A sibling call is one where we're under the usual C ABI and not planning
4451 // to change that but can still do a tail call:
4452 if (!TailCallOpt && IsTailCall)
4453 IsSibCall = true;
4454
4455 if (IsTailCall)
4456 ++NumTailCalls;
4457 }
4458
4461 SmallVector<SDValue, 8> MemOpChains;
4462
4463 // Analyze operands of the call, assigning locations to each operand.
4465 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
4466 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, IsVarArg);
4467
4468 if (CallConv != CallingConv::AMDGPU_Gfx && !AMDGPU::isChainCC(CallConv) &&
4470 // With a fixed ABI, allocate fixed registers before user arguments.
4471 passSpecialInputs(CLI, CCInfo, *Info, RegsToPass, MemOpChains, Chain);
4472 }
4473
4474 // Mark the scratch resource descriptor as allocated so the CC analysis
4475 // does not assign user arguments to these registers, matching the callee.
4476 if (!Subtarget->hasFlatScratchEnabled()) {
4477 CCInfo.AllocateReg(
4479 }
4480
4481 CCInfo.AnalyzeCallOperands(Outs, AssignFn);
4482
4483 // Get a count of how many bytes are to be pushed on the stack.
4484 unsigned NumBytes = CCInfo.getStackSize();
4485
4486 if (IsSibCall) {
4487 // Since we're not changing the ABI to make this a tail call, the memory
4488 // operands are already available in the caller's incoming argument space.
4489 NumBytes = 0;
4490 }
4491
4492 // FPDiff is the byte offset of the call's argument area from the callee's.
4493 // Stores to callee stack arguments will be placed in FixedStackSlots offset
4494 // by this amount for a tail call. In a sibling call it must be 0 because the
4495 // caller will deallocate the entire stack and the callee still expects its
4496 // arguments to begin at SP+0. Completely unused for non-tail calls.
4497 int32_t FPDiff = 0;
4498 MachineFrameInfo &MFI = MF.getFrameInfo();
4499 auto *TRI = Subtarget->getRegisterInfo();
4500
4501 // Adjust the stack pointer for the new arguments...
4502 // These operations are automatically eliminated by the prolog/epilog pass
4503 if (!IsSibCall)
4504 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL);
4505
4506 if (!IsSibCall || IsChainCallConv) {
4507 if (!Subtarget->hasFlatScratchEnabled()) {
4508 SmallVector<SDValue, 4> CopyFromChains;
4509
4510 // In the HSA case, this should be an identity copy.
4511 SDValue ScratchRSrcReg =
4512 DAG.getCopyFromReg(Chain, DL, Info->getScratchRSrcReg(), MVT::v4i32);
4513 RegsToPass.emplace_back(
4515 ScratchRSrcReg);
4516 CopyFromChains.push_back(ScratchRSrcReg.getValue(1));
4517 Chain = DAG.getTokenFactor(DL, CopyFromChains);
4518 }
4519 }
4520
4521 const unsigned NumSpecialInputs = RegsToPass.size();
4522
4523 MVT PtrVT = MVT::i32;
4524
4525 // Walk the register/memloc assignments, inserting copies/loads.
4526 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4527 CCValAssign &VA = ArgLocs[i];
4528 SDValue Arg = OutVals[i];
4529
4530 // Promote the value if needed.
4531 switch (VA.getLocInfo()) {
4532 case CCValAssign::Full:
4533 break;
4534 case CCValAssign::BCvt:
4535 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
4536 break;
4537 case CCValAssign::ZExt:
4538 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
4539 break;
4540 case CCValAssign::SExt:
4541 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
4542 break;
4543 case CCValAssign::AExt:
4544 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
4545 break;
4546 case CCValAssign::FPExt:
4547 Arg = DAG.getNode(ISD::FP_EXTEND, DL, VA.getLocVT(), Arg);
4548 break;
4549 default:
4550 llvm_unreachable("Unknown loc info!");
4551 }
4552
4553 if (VA.isRegLoc()) {
4554 RegsToPass.push_back(std::pair(VA.getLocReg(), Arg));
4555 } else {
4556 assert(VA.isMemLoc());
4557
4558 SDValue DstAddr;
4559 MachinePointerInfo DstInfo;
4560
4561 unsigned LocMemOffset = VA.getLocMemOffset();
4562 int32_t Offset = LocMemOffset;
4563
4564 SDValue PtrOff = DAG.getConstant(Offset, DL, PtrVT);
4565 MaybeAlign Alignment;
4566
4567 if (IsTailCall) {
4568 ISD::ArgFlagsTy Flags = Outs[i].Flags;
4569 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4570 : VA.getValVT().getStoreSize();
4571
4572 // FIXME: We can have better than the minimum byval required alignment.
4573 Alignment =
4574 Flags.isByVal()
4575 ? Flags.getNonZeroByValAlign()
4576 : commonAlignment(Subtarget->getStackAlignment(), Offset);
4577
4578 Offset = Offset + FPDiff;
4579 int FI = MFI.CreateFixedObject(OpSize, Offset, true);
4580
4581 DstAddr = DAG.getFrameIndex(FI, PtrVT);
4582 DstInfo = MachinePointerInfo::getFixedStack(MF, FI);
4583
4584 // Make sure any stack arguments overlapping with where we're storing
4585 // are loaded before this eventual operation. Otherwise they'll be
4586 // clobbered.
4587
4588 // FIXME: Why is this really necessary? This seems to just result in a
4589 // lot of code to copy the stack and write them back to the same
4590 // locations, which are supposed to be immutable?
4591 Chain = addTokenForArgument(Chain, DAG, MFI, FI);
4592 } else {
4593 // Stores to the argument stack area are relative to the stack pointer.
4594 SDValue SP = DAG.getCopyFromReg(Chain, DL, Info->getStackPtrOffsetReg(),
4595 MVT::i32);
4596 DstAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, SP, PtrOff);
4597 DstInfo = MachinePointerInfo::getStack(MF, LocMemOffset);
4598 Alignment =
4599 commonAlignment(Subtarget->getStackAlignment(), LocMemOffset);
4600 }
4601
4602 if (Outs[i].Flags.isByVal()) {
4603 SDValue SizeNode =
4604 DAG.getConstant(Outs[i].Flags.getByValSize(), DL, MVT::i32);
4605 SDValue Cpy =
4606 DAG.getMemcpy(Chain, DL, DstAddr, Arg, SizeNode,
4607 Outs[i].Flags.getNonZeroByValAlign(),
4608 Outs[i].Flags.getNonZeroByValAlign(),
4609 /*isVol = */ false, /*AlwaysInline = */ true,
4610 /*CI=*/nullptr, std::nullopt, DstInfo,
4612
4613 MemOpChains.push_back(Cpy);
4614 } else {
4615 SDValue Store =
4616 DAG.getStore(Chain, DL, Arg, DstAddr, DstInfo, Alignment);
4617 MemOpChains.push_back(Store);
4618 }
4619 }
4620 }
4621
4622 if (!MemOpChains.empty())
4623 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
4624
4625 SDValue ReadFirstLaneID =
4626 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4627
4628 SDValue TokenGlue;
4629 if (CLI.ConvergenceControlToken) {
4630 TokenGlue = DAG.getNode(ISD::CONVERGENCECTRL_GLUE, DL, MVT::Glue,
4632 }
4633
4634 // Build a sequence of copy-to-reg nodes chained together with token chain
4635 // and flag operands which copy the outgoing args into the appropriate regs.
4636 SDValue InGlue;
4637
4638 unsigned ArgIdx = 0;
4639 for (auto [Reg, Val] : RegsToPass) {
4640 if (ArgIdx++ >= NumSpecialInputs &&
4641 (IsChainCallConv || !Val->isDivergent()) && TRI->isSGPRPhysReg(Reg)) {
4642 // For chain calls, the inreg arguments are required to be
4643 // uniform. Speculatively Insert a readfirstlane in case we cannot prove
4644 // they are uniform.
4645 //
4646 // For other calls, if an inreg arguments is known to be uniform,
4647 // speculatively insert a readfirstlane in case it is in a VGPR.
4648 //
4649 // FIXME: We need to execute this in a waterfall loop if it is a divergent
4650 // value, so let that continue to produce invalid code.
4651
4652 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Val});
4653 if (TokenGlue)
4654 ReadfirstlaneArgs.push_back(TokenGlue);
4656 ReadfirstlaneArgs);
4657 }
4658
4659 Chain = DAG.getCopyToReg(Chain, DL, Reg, Val, InGlue);
4660 InGlue = Chain.getValue(1);
4661 }
4662
4663 // We don't usually want to end the call-sequence here because we would tidy
4664 // the frame up *after* the call, however in the ABI-changing tail-call case
4665 // we've carefully laid out the parameters so that when sp is reset they'll be
4666 // in the correct location.
4667 if (IsTailCall && !IsSibCall) {
4668 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
4669 InGlue = Chain.getValue(1);
4670 }
4671
4672 std::vector<SDValue> Ops({Chain});
4673
4674 // Add a redundant copy of the callee global which will not be legalized, as
4675 // we need direct access to the callee later.
4677 const GlobalValue *GV = GSD->getGlobal();
4678 Ops.push_back(Callee);
4679 Ops.push_back(DAG.getTargetGlobalAddress(GV, DL, MVT::i64));
4680 } else {
4681 if (IsTailCall) {
4682 // isEligibleForTailCallOptimization considered whether the call target is
4683 // divergent, but we may still end up with a uniform value in a VGPR.
4684 // Insert a readfirstlane just in case.
4685 SDValue ReadFirstLaneID =
4686 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4687
4688 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Callee});
4689 if (TokenGlue)
4690 ReadfirstlaneArgs.push_back(TokenGlue); // Wire up convergence token.
4691 Callee = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Callee.getValueType(),
4692 ReadfirstlaneArgs);
4693 }
4694
4695 Ops.push_back(Callee);
4696 Ops.push_back(DAG.getTargetConstant(0, DL, MVT::i64));
4697 }
4698
4699 if (IsTailCall) {
4700 // Each tail call may have to adjust the stack by a different amount, so
4701 // this information must travel along with the operation for eventual
4702 // consumption by emitEpilogue.
4703 Ops.push_back(DAG.getTargetConstant(FPDiff, DL, MVT::i32));
4704 }
4705
4706 if (IsChainCallConv)
4707 llvm::append_range(Ops, ChainCallSpecialArgs);
4708
4709 // Add argument registers to the end of the list so that they are known live
4710 // into the call.
4711 for (auto &[Reg, Val] : RegsToPass)
4712 Ops.push_back(DAG.getRegister(Reg, Val.getValueType()));
4713
4714 // Add a register mask operand representing the call-preserved registers.
4715 const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
4716 assert(Mask && "Missing call preserved mask for calling convention");
4717 Ops.push_back(DAG.getRegisterMask(Mask));
4718
4719 if (SDValue Token = CLI.ConvergenceControlToken) {
4721 GlueOps.push_back(Token);
4722 if (InGlue)
4723 GlueOps.push_back(InGlue);
4724
4725 InGlue = SDValue(DAG.getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, DL,
4726 MVT::Glue, GlueOps),
4727 0);
4728 }
4729
4730 if (InGlue)
4731 Ops.push_back(InGlue);
4732
4733 // If we're doing a tall call, use a TC_RETURN here rather than an
4734 // actual call instruction.
4735 if (IsTailCall) {
4736 MFI.setHasTailCall();
4737 unsigned OPC = AMDGPUISD::TC_RETURN;
4738 switch (CallConv) {
4740 OPC = AMDGPUISD::TC_RETURN_GFX;
4741 break;
4744 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4745 : AMDGPUISD::TC_RETURN_CHAIN;
4746 break;
4747 }
4748
4749 // If the caller is a whole wave function, we need to use a special opcode
4750 // so we can patch up EXEC.
4751 if (Info->isWholeWaveFunction())
4752 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4753
4754 SDValue Ret = DAG.getNode(OPC, DL, MVT::Other, Ops);
4755 DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
4756 return Ret;
4757 }
4758
4759 // Returns a chain and a flag for retval copy to use.
4760 SDValue Call = DAG.getNode(AMDGPUISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops);
4761 DAG.addNoMergeSiteInfo(Call.getNode(), CLI.NoMerge);
4762 Chain = Call.getValue(0);
4763 InGlue = Call.getValue(1);
4764
4765 uint64_t CalleePopBytes = NumBytes;
4766 Chain = DAG.getCALLSEQ_END(Chain, 0, CalleePopBytes, InGlue, DL);
4767 if (!Ins.empty())
4768 InGlue = Chain.getValue(1);
4769
4770 // Handle result values, copying them out of physregs into vregs that we
4771 // return.
4772 return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG,
4773 InVals, /*IsThisReturn=*/false, SDValue());
4774}
4775
4776// This is similar to the default implementation in ExpandDYNAMIC_STACKALLOC,
4777// except for:
4778// 1. Stack growth direction(default: downwards, AMDGPU: upwards), and
4779// 2. Scale size where, scale = wave-reduction(alloca-size) * wave-size
4781 SelectionDAG &DAG) const {
4782 const MachineFunction &MF = DAG.getMachineFunction();
4784
4785 SDLoc dl(Op);
4786 EVT VT = Op.getValueType();
4787 SDValue Chain = Op.getOperand(0);
4788 Register SPReg = Info->getStackPtrOffsetReg();
4789
4790 // Chain the dynamic stack allocation so that it doesn't modify the stack
4791 // pointer when other instructions are using the stack.
4792 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, dl);
4793
4794 SDValue Size = Op.getOperand(1);
4795 SDValue BaseAddr = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
4796 Align Alignment = cast<ConstantSDNode>(Op.getOperand(2))->getAlignValue();
4797
4798 const TargetFrameLowering *TFL = Subtarget->getFrameLowering();
4800 "Stack grows upwards for AMDGPU");
4801
4802 Chain = BaseAddr.getValue(1);
4803 // When using flat-scratch, the stack offset is unscaled.
4804 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4805 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4806
4807 Align StackAlign = TFL->getStackAlign();
4808 if (Alignment > StackAlign) {
4809 uint64_t ScaledAlignment = Alignment.value()
4810 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4811 uint64_t StackAlignMask = ScaledAlignment - 1;
4812 SDValue TmpAddr = DAG.getNode(ISD::ADD, dl, VT, BaseAddr,
4813 DAG.getConstant(StackAlignMask, dl, VT));
4814 BaseAddr = DAG.getNode(ISD::AND, dl, VT, TmpAddr,
4815 DAG.getSignedConstant(-ScaledAlignment, dl, VT));
4816 }
4817
4818 assert(Size.getValueType() == MVT::i32 && "Size must be 32-bit");
4819 SDValue NewSP;
4821 // Increase the stack pointer by the size of the alloca.
4822 // If not using flat-scratch, we have to scale the size by the wave-size.
4823 SDValue ScaledSize =
4824 HasFlatScratch
4825 ? Size
4826 : DAG.getNode(ISD::SHL, dl, VT, Size,
4827 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4828 NewSP = DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value
4829 } else {
4830 // For dynamic sized alloca, perform wave-wide reduction to get max of
4831 // alloca size(divergent), and then scale it (when not using flat-scratch)
4832 // by wave-size.
4833 SDValue WaveReduction =
4834 DAG.getTargetConstant(Intrinsic::amdgcn_wave_reduce_umax, dl, MVT::i32);
4835 Size = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, WaveReduction,
4836 Size, DAG.getTargetConstant(0, dl, MVT::i32));
4837 SDValue ScaledSize = Size;
4838 if (!HasFlatScratch) {
4839 ScaledSize =
4840 DAG.getNode(ISD::SHL, dl, VT, Size,
4841 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4842 }
4843 NewSP =
4844 DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value in vgpr.
4845 SDValue ReadFirstLaneID =
4846 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, dl, MVT::i32);
4847 NewSP = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, ReadFirstLaneID,
4848 NewSP);
4849 }
4850
4851 Chain = DAG.getCopyToReg(Chain, dl, SPReg, NewSP); // Output chain
4852 SDValue CallSeqEnd = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), dl);
4853
4854 return DAG.getMergeValues({BaseAddr, CallSeqEnd}, dl);
4855}
4856
4858 if (Op.getValueType() != MVT::i32)
4859 return Op; // Defer to cannot select error.
4860
4862 SDLoc SL(Op);
4863
4864 SDValue CopyFromSP = DAG.getCopyFromReg(Op->getOperand(0), SL, SP, MVT::i32);
4865
4866 // Convert from wave uniform to swizzled vector address. This should protect
4867 // from any edge cases where the stacksave result isn't directly used with
4868 // stackrestore.
4869 SDValue VectorAddress =
4870 DAG.getNode(AMDGPUISD::WAVE_ADDRESS, SL, MVT::i32, CopyFromSP);
4871 return DAG.getMergeValues({VectorAddress, CopyFromSP.getValue(1)}, SL);
4872}
4873
4875 SelectionDAG &DAG) const {
4876 SDLoc SL(Op);
4877 assert(Op.getValueType() == MVT::i32);
4878
4879 uint32_t BothRoundHwReg =
4881 SDValue GetRoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
4882
4883 SDValue IntrinID =
4884 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
4885 SDValue GetReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, Op->getVTList(),
4886 Op.getOperand(0), IntrinID, GetRoundBothImm);
4887
4888 // There are two rounding modes, one for f32 and one for f64/f16. We only
4889 // report in the standard value range if both are the same.
4890 //
4891 // The raw values also differ from the expected FLT_ROUNDS values. Nearest
4892 // ties away from zero is not supported, and the other values are rotated by
4893 // 1.
4894 //
4895 // If the two rounding modes are not the same, report a target defined value.
4896
4897 // Mode register rounding mode fields:
4898 //
4899 // [1:0] Single-precision round mode.
4900 // [3:2] Double/Half-precision round mode.
4901 //
4902 // 0=nearest even; 1= +infinity; 2= -infinity, 3= toward zero.
4903 //
4904 // Hardware Spec
4905 // Toward-0 3 0
4906 // Nearest Even 0 1
4907 // +Inf 1 2
4908 // -Inf 2 3
4909 // NearestAway0 N/A 4
4910 //
4911 // We have to handle 16 permutations of a 4-bit value, so we create a 64-bit
4912 // table we can index by the raw hardware mode.
4913 //
4914 // (trunc (FltRoundConversionTable >> MODE.fp_round)) & 0xf
4915
4916 SDValue BitTable =
4918
4919 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4920 SDValue RoundModeTimesNumBits =
4921 DAG.getNode(ISD::SHL, SL, MVT::i32, GetReg, Two);
4922
4923 // TODO: We could possibly avoid a 64-bit shift and use a simpler table if we
4924 // knew only one mode was demanded.
4925 SDValue TableValue =
4926 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
4927 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
4928
4929 SDValue EntryMask = DAG.getConstant(0xf, SL, MVT::i32);
4930 SDValue TableEntry =
4931 DAG.getNode(ISD::AND, SL, MVT::i32, TruncTable, EntryMask);
4932
4933 // There's a gap in the 4-bit encoded table and actual enum values, so offset
4934 // if it's an extended value.
4935 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
4936 SDValue IsStandardValue =
4937 DAG.getSetCC(SL, MVT::i1, TableEntry, Four, ISD::SETULT);
4938 SDValue EnumOffset = DAG.getNode(ISD::ADD, SL, MVT::i32, TableEntry, Four);
4939 SDValue Result = DAG.getNode(ISD::SELECT, SL, MVT::i32, IsStandardValue,
4940 TableEntry, EnumOffset);
4941
4942 return DAG.getMergeValues({Result, GetReg.getValue(1)}, SL);
4943}
4944
4946 SelectionDAG &DAG) const {
4947 SDLoc SL(Op);
4948
4949 SDValue NewMode = Op.getOperand(1);
4950 assert(NewMode.getValueType() == MVT::i32);
4951
4952 // Index a table of 4-bit entries mapping from the C FLT_ROUNDS values to the
4953 // hardware MODE.fp_round values.
4954 if (auto *ConstMode = dyn_cast<ConstantSDNode>(NewMode)) {
4955 uint32_t ClampedVal = std::min(
4956 static_cast<uint32_t>(ConstMode->getZExtValue()),
4958 NewMode = DAG.getConstant(
4959 AMDGPU::decodeFltRoundToHWConversionTable(ClampedVal), SL, MVT::i32);
4960 } else {
4961 // If we know the input can only be one of the supported standard modes in
4962 // the range 0-3, we can use a simplified mapping to hardware values.
4963 KnownBits KB = DAG.computeKnownBits(NewMode);
4964 const bool UseReducedTable = KB.countMinLeadingZeros() >= 30;
4965 // The supported standard values are 0-3. The extended values start at 8. We
4966 // need to offset by 4 if the value is in the extended range.
4967
4968 if (UseReducedTable) {
4969 // Truncate to the low 32-bits.
4970 SDValue BitTable = DAG.getConstant(
4971 AMDGPU::FltRoundToHWConversionTable & 0xffff, SL, MVT::i32);
4972
4973 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4974 SDValue RoundModeTimesNumBits =
4975 DAG.getNode(ISD::SHL, SL, MVT::i32, NewMode, Two);
4976
4977 NewMode =
4978 DAG.getNode(ISD::SRL, SL, MVT::i32, BitTable, RoundModeTimesNumBits);
4979
4980 // TODO: SimplifyDemandedBits on the setreg source here can likely reduce
4981 // the table extracted bits into inline immediates.
4982 } else {
4983 // table_index = umin(value, value - 4)
4984 // MODE.fp_round = (bit_table >> (table_index << 2)) & 0xf
4985 SDValue BitTable =
4987
4988 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
4989 SDValue OffsetEnum = DAG.getNode(ISD::SUB, SL, MVT::i32, NewMode, Four);
4990 SDValue IndexVal =
4991 DAG.getNode(ISD::UMIN, SL, MVT::i32, NewMode, OffsetEnum);
4992
4993 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4994 SDValue RoundModeTimesNumBits =
4995 DAG.getNode(ISD::SHL, SL, MVT::i32, IndexVal, Two);
4996
4997 SDValue TableValue =
4998 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
4999 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
5000
5001 // No need to mask out the high bits since the setreg will ignore them
5002 // anyway.
5003 NewMode = TruncTable;
5004 }
5005
5006 // Insert a readfirstlane in case the value is a VGPR. We could do this
5007 // earlier and keep more operations scalar, but that interferes with
5008 // combining the source.
5009 SDValue ReadFirstLaneID =
5010 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
5011 NewMode = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5012 ReadFirstLaneID, NewMode);
5013 }
5014
5015 // N.B. The setreg will be later folded into s_round_mode on supported
5016 // targets.
5017 SDValue IntrinID =
5018 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
5019 uint32_t BothRoundHwReg =
5021 SDValue RoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
5022
5023 SDValue SetReg =
5024 DAG.getNode(ISD::INTRINSIC_VOID, SL, Op->getVTList(), Op.getOperand(0),
5025 IntrinID, RoundBothImm, NewMode);
5026
5027 return SetReg;
5028}
5029
5031 unsigned AS = cast<MemSDNode>(Op)->getAddressSpace();
5032 if (AS == AMDGPUAS::BUFFER_RESOURCE)
5033 return Op.getOperand(0);
5035 return SDValue();
5036
5037 // I$ prefetch
5038 if (!Subtarget->hasSafeSmemPrefetch() && !Op.getConstantOperandVal(4))
5039 return SDValue();
5040
5041 // Prefetch the 64-bit address that a 32-bit constant pointer is cast to, as
5042 // a load does.
5043 SDValue Ptr = Op.getOperand(1);
5044 if (Ptr.getValueType() != MVT::i32)
5045 return Op;
5047 Ops[1] = DAG.getAddrSpaceCast(SDLoc(Op), MVT::i64, Ptr,
5050 return SDValue(DAG.UpdateNodeOperands(Op.getNode(), Ops), 0);
5051}
5052
5053// Work around DAG legality rules only based on the result type.
5055 bool IsStrict = Op.getOpcode() == ISD::STRICT_FP_EXTEND;
5056 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
5057 EVT SrcVT = Src.getValueType();
5058
5059 if (SrcVT.getScalarType() != MVT::bf16)
5060 return Op;
5061
5062 SDLoc SL(Op);
5063 SDValue BitCast =
5064 DAG.getNode(ISD::BITCAST, SL, SrcVT.changeTypeToInteger(), Src);
5065
5066 EVT DstVT = Op.getValueType();
5067 if (IsStrict)
5068 llvm_unreachable("Need STRICT_BF16_TO_FP");
5069
5070 return DAG.getNode(ISD::BF16_TO_FP, SL, DstVT, BitCast);
5071}
5072
5074 SDLoc SL(Op);
5075 if (Op.getValueType() != MVT::i64)
5076 return Op;
5077
5078 uint32_t ModeHwReg =
5080 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5081 uint32_t TrapHwReg =
5083 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5084
5085 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::Other);
5086 SDValue IntrinID =
5087 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
5088 SDValue GetModeReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5089 Op.getOperand(0), IntrinID, ModeHwRegImm);
5090 SDValue GetTrapReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5091 Op.getOperand(0), IntrinID, TrapHwRegImm);
5092 SDValue TokenReg =
5093 DAG.getNode(ISD::TokenFactor, SL, MVT::Other, GetModeReg.getValue(1),
5094 GetTrapReg.getValue(1));
5095
5096 SDValue CvtPtr =
5097 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, GetModeReg, GetTrapReg);
5098 SDValue Result = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
5099
5100 return DAG.getMergeValues({Result, TokenReg}, SL);
5101}
5102
5104 SDLoc SL(Op);
5105 if (Op.getOperand(1).getValueType() != MVT::i64)
5106 return Op;
5107
5108 SDValue Input = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op.getOperand(1));
5109 SDValue NewModeReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5110 DAG.getConstant(0, SL, MVT::i32));
5111 SDValue NewTrapReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5112 DAG.getConstant(1, SL, MVT::i32));
5113
5114 SDValue ReadFirstLaneID =
5115 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
5116 NewModeReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5117 ReadFirstLaneID, NewModeReg);
5118 NewTrapReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5119 ReadFirstLaneID, NewTrapReg);
5120
5121 unsigned ModeHwReg =
5123 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5124 unsigned TrapHwReg =
5126 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5127
5128 SDValue IntrinID =
5129 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
5130 SDValue SetModeReg =
5131 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5132 IntrinID, ModeHwRegImm, NewModeReg);
5133 SDValue SetTrapReg =
5134 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5135 IntrinID, TrapHwRegImm, NewTrapReg);
5136 return DAG.getNode(ISD::TokenFactor, SL, MVT::Other, SetTrapReg, SetModeReg);
5137}
5138
5140 const MachineFunction &MF) const {
5141 Register Reg =
5143 .Case("m0", AMDGPU::M0)
5144 .Case("exec", AMDGPU::EXEC)
5145 .Case("exec_lo", AMDGPU::EXEC_LO)
5146 .Case("exec_hi", AMDGPU::EXEC_HI)
5147 .Case("flat_scratch", AMDGPU::FLAT_SCR)
5148 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5149 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5150 .Case("src_flat_scratch_base", AMDGPU::SRC_FLAT_SCRATCH_BASE)
5151 .Case("src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
5152 .Case("src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
5153 .Default(Register());
5154 if (!Reg)
5155 return Reg;
5156
5157 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
5158 if (!Subtarget->hasFlatScrRegister() &&
5159 TRI->regsOverlap(Reg, AMDGPU::FLAT_SCR))
5160 return Register();
5161
5162 if (!Subtarget->hasGloballyAddressableScratch() &&
5163 TRI->regsOverlap(Reg, AMDGPU::SRC_FLAT_SCRATCH_BASE))
5164 return Register();
5165
5166 switch (Reg) {
5167 case AMDGPU::M0:
5168 case AMDGPU::EXEC_LO:
5169 case AMDGPU::EXEC_HI:
5170 case AMDGPU::FLAT_SCR_LO:
5171 case AMDGPU::FLAT_SCR_HI:
5172 case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
5173 case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
5174 if (VT.getSizeInBits() == 32)
5175 return Reg;
5176 break;
5177 case AMDGPU::EXEC:
5178 case AMDGPU::FLAT_SCR:
5179 case AMDGPU::SRC_FLAT_SCRATCH_BASE:
5180 if (VT.getSizeInBits() == 64)
5181 return Reg;
5182 break;
5183 default:
5184 llvm_unreachable("missing register type checking");
5185 }
5186
5188 Twine("invalid type for register \"" + StringRef(RegName) + "\"."));
5189}
5190
5191// If kill is not the last instruction, split the block so kill is always a
5192// proper terminator.
5195 MachineBasicBlock *BB) const {
5196 MachineBasicBlock *SplitBB = BB->splitAt(MI, /*UpdateLiveIns=*/true);
5198 MI.setDesc(TII->getKillTerminatorFromPseudo(MI.getOpcode()));
5199 return SplitBB;
5200}
5201
5202// Split block \p MBB at \p MI, as to insert a loop. If \p InstInLoop is true,
5203// \p MI will be the only instruction in the loop body block. Otherwise, it will
5204// be the first instruction in the remainder block.
5205//
5206/// \returns { LoopBody, Remainder }
5207static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5209 MachineFunction *MF = MBB.getParent();
5211
5212 // To insert the loop we need to split the block. Move everything after this
5213 // point to a new block, and insert a new empty block between the two.
5215 MachineBasicBlock *RemainderBB = MF->CreateMachineBasicBlock();
5217 ++MBBI;
5218
5219 MF->insert(MBBI, LoopBB);
5220 MF->insert(MBBI, RemainderBB);
5221
5222 LoopBB->addSuccessor(LoopBB);
5223 LoopBB->addSuccessor(RemainderBB);
5224
5225 // Move the rest of the block into a new block.
5226 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
5227
5228 if (InstInLoop) {
5229 auto Next = std::next(I);
5230
5231 // Move instruction to loop body.
5232 LoopBB->splice(LoopBB->begin(), &MBB, I, Next);
5233
5234 // Move the rest of the block.
5235 RemainderBB->splice(RemainderBB->begin(), &MBB, Next, MBB.end());
5236 } else {
5237 RemainderBB->splice(RemainderBB->begin(), &MBB, I, MBB.end());
5238 }
5239
5240 MBB.addSuccessor(LoopBB);
5241
5242 return std::pair(LoopBB, RemainderBB);
5243}
5244
5245/// Insert \p MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
5247 MachineBasicBlock *MBB = MI.getParent();
5249 auto I = MI.getIterator();
5250 auto E = std::next(I);
5251
5252 // clang-format off
5253 BuildMI(*MBB, E, MI.getDebugLoc(), TII->get(AMDGPU::S_WAITCNT))
5254 .addImm(0);
5255 // clang-format on
5256
5257 MIBundleBuilder Bundler(*MBB, I, E);
5258 finalizeBundle(*MBB, Bundler.begin());
5259}
5260
5263 MachineBasicBlock *BB) const {
5264 const DebugLoc &DL = MI.getDebugLoc();
5265
5267
5269
5270 // Apparently kill flags are only valid if the def is in the same block?
5271 if (MachineOperand *Src = TII->getNamedOperand(MI, AMDGPU::OpName::data0))
5272 Src->setIsKill(false);
5273
5274 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, *BB, true);
5275
5276 MachineBasicBlock::iterator I = LoopBB->end();
5277
5278 const unsigned EncodedReg = AMDGPU::Hwreg::HwregEncoding::encode(
5280
5281 // Clear TRAP_STS.MEM_VIOL
5282 BuildMI(*LoopBB, LoopBB->begin(), DL, TII->get(AMDGPU::S_SETREG_IMM32_B32))
5283 .addImm(0)
5284 .addImm(EncodedReg);
5285
5287
5288 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5289
5290 // Load and check TRAP_STS.MEM_VIOL
5291 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_GETREG_B32), Reg)
5292 .addImm(EncodedReg);
5293
5294 // clang-format off
5295 // FIXME: Do we need to use an isel pseudo that may clobber scc?
5296 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CMP_LG_U32))
5297 .addReg(Reg)
5298 .addImm(0);
5299 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
5300 .addMBB(LoopBB);
5301 // clang-format on
5302
5303 return RemainderBB;
5304}
5305
5306// Do a v_movrels_b32 or v_movreld_b32 for each unique value of \p IdxReg in the
5307// wavefront. If the value is uniform and just happens to be in a VGPR, this
5308// will only do one iteration. In the worst case, this will loop 64 times.
5309//
5310// TODO: Just use v_readlane_b32 if we know the VGPR has a uniform value.
5313 MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB,
5314 const DebugLoc &DL, const MachineOperand &Idx,
5315 unsigned InitReg, unsigned ResultReg, unsigned PhiReg,
5316 unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode,
5317 Register &SGPRIdxReg) {
5318
5319 MachineFunction *MF = OrigBB.getParent();
5320 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5321 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5324
5325 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5326 Register PhiExec = MRI.createVirtualRegister(BoolRC);
5327 Register NewExec = MRI.createVirtualRegister(BoolRC);
5328 Register CurrentIdxReg =
5329 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5330 Register CondReg = MRI.createVirtualRegister(BoolRC);
5331
5332 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiReg)
5333 .addReg(InitReg)
5334 .addMBB(&OrigBB)
5335 .addReg(ResultReg)
5336 .addMBB(&LoopBB);
5337
5338 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiExec)
5339 .addReg(InitSaveExecReg)
5340 .addMBB(&OrigBB)
5341 .addReg(NewExec)
5342 .addMBB(&LoopBB);
5343
5344 // Read the next variant <- also loop target.
5345 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5346 .addReg(Idx.getReg(), getUndefRegState(Idx.isUndef()));
5347
5348 // Compare the just read M0 value to all possible Idx values.
5349 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5350 .addReg(CurrentIdxReg)
5351 .addReg(Idx.getReg(), {}, Idx.getSubReg());
5352
5353 // Update EXEC, save the original EXEC value to VCC.
5354 BuildMI(LoopBB, I, DL, TII->get(LMC.AndSaveExecOpc), NewExec)
5355 .addReg(CondReg)
5356 .setOperandDead(3); // Dead scc
5357
5358 MRI.setSimpleHint(NewExec, CondReg);
5359
5360 if (UseGPRIdxMode) {
5361 if (Offset == 0) {
5362 SGPRIdxReg = CurrentIdxReg;
5363 } else {
5364 SGPRIdxReg = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
5365 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5366 .addReg(CurrentIdxReg)
5367 .addImm(Offset)
5368 .setOperandDead(3); // Dead scc
5369 }
5370 } else {
5371 // Move index from VCC into M0
5372 if (Offset == 0) {
5373 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5374 .addReg(CurrentIdxReg);
5375 } else {
5376 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5377 .addReg(CurrentIdxReg)
5378 .addImm(Offset)
5379 .setOperandDead(3); // Dead scc
5380 }
5381 }
5382
5383 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
5384 MachineInstr *InsertPt =
5385 BuildMI(LoopBB, I, DL, TII->get(LMC.XorTermOpc), LMC.ExecReg)
5386 .addReg(LMC.ExecReg)
5387 .addReg(NewExec)
5388 .setOperandDead(3); // Dead scc
5389
5390 // XXX - s_xor_b64 sets scc to 1 if the result is nonzero, so can we use
5391 // s_cbranch_scc0?
5392
5393 // Loop back to V_READFIRSTLANE_B32 if there are still variants to cover.
5394 // clang-format off
5395 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
5396 .addMBB(&LoopBB);
5397 // clang-format on
5398
5399 return InsertPt->getIterator();
5400}
5401
5402// This has slightly sub-optimal regalloc when the source vector is killed by
5403// the read. The register allocator does not understand that the kill is
5404// per-workitem, so is kept alive for the whole loop so we end up not re-using a
5405// subregister from it, using 1 more VGPR than necessary. This was saved when
5406// this was expanded after register allocation.
5409 unsigned InitResultReg, unsigned PhiReg, int Offset,
5410 bool UseGPRIdxMode, Register &SGPRIdxReg) {
5411 MachineFunction *MF = MBB.getParent();
5412 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5413 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5415 const DebugLoc &DL = MI.getDebugLoc();
5417
5418 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
5419 Register DstReg = MI.getOperand(0).getReg();
5420 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
5421 Register TmpExec = MRI.createVirtualRegister(BoolXExecRC);
5423
5424 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), TmpExec);
5425
5426 // Save the EXEC mask
5427 // clang-format off
5428 BuildMI(MBB, I, DL, TII->get(LMC.MovOpc), SaveExec)
5429 .addReg(LMC.ExecReg);
5430 // clang-format on
5431
5432 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, MBB, false);
5433
5434 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5435
5436 auto InsPt = emitLoadM0FromVGPRLoop(TII, MRI, MBB, *LoopBB, DL, *Idx,
5437 InitResultReg, DstReg, PhiReg, TmpExec,
5438 Offset, UseGPRIdxMode, SGPRIdxReg);
5439
5440 MachineBasicBlock *LandingPad = MF->CreateMachineBasicBlock();
5442 ++MBBI;
5443 MF->insert(MBBI, LandingPad);
5444 LoopBB->removeSuccessor(RemainderBB);
5445 LandingPad->addSuccessor(RemainderBB);
5446 LoopBB->addSuccessor(LandingPad);
5447 MachineBasicBlock::iterator First = LandingPad->begin();
5448 // clang-format off
5449 BuildMI(*LandingPad, First, DL, TII->get(LMC.MovOpc), LMC.ExecReg)
5450 .addReg(SaveExec);
5451 // clang-format on
5452
5453 return InsPt;
5454}
5455
5456// Returns subreg index, offset
5457static std::pair<unsigned, int>
5459 const TargetRegisterClass *SuperRC, unsigned VecReg,
5460 int Offset) {
5461 int NumElts = TRI.getRegSizeInBits(*SuperRC) / 32;
5462
5463 // Skip out of bounds offsets, or else we would end up using an undefined
5464 // register.
5465 if (Offset >= NumElts || Offset < 0)
5466 return std::pair(AMDGPU::sub0, Offset);
5467
5468 return std::pair(SIRegisterInfo::getSubRegFromChannel(Offset), 0);
5469}
5470
5473 int Offset) {
5474 MachineBasicBlock *MBB = MI.getParent();
5475 const DebugLoc &DL = MI.getDebugLoc();
5477
5478 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5479
5480 assert(Idx->getReg() != AMDGPU::NoRegister);
5481
5482 if (Offset == 0) {
5483 // clang-format off
5484 BuildMI(*MBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5485 .add(*Idx);
5486 // clang-format on
5487 } else {
5488 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5489 .add(*Idx)
5490 .addImm(Offset)
5491 .setOperandDead(3); // Dead scc
5492 }
5493}
5494
5497 int Offset) {
5498 MachineBasicBlock *MBB = MI.getParent();
5499 const DebugLoc &DL = MI.getDebugLoc();
5501
5502 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5503
5504 if (Offset == 0)
5505 return Idx->getReg();
5506
5507 Register Tmp = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5508 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), Tmp)
5509 .add(*Idx)
5510 .addImm(Offset)
5511 .setOperandDead(3); // Dead scc
5512 return Tmp;
5513}
5514
5517 const GCNSubtarget &ST) {
5518 const SIInstrInfo *TII = ST.getInstrInfo();
5519 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5520 MachineFunction *MF = MBB.getParent();
5522
5523 Register Dst = MI.getOperand(0).getReg();
5524 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5525 Register SrcReg = TII->getNamedOperand(MI, AMDGPU::OpName::src)->getReg();
5526 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5527
5528 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcReg);
5529 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5530
5531 unsigned SubReg;
5532 std::tie(SubReg, Offset) =
5533 computeIndirectRegAndOffset(TRI, VecRC, SrcReg, Offset);
5534
5535 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5536
5537 // Check for a SGPR index.
5538 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5540 const DebugLoc &DL = MI.getDebugLoc();
5541
5542 if (UseGPRIdxMode) {
5543 // TODO: Look at the uses to avoid the copy. This may require rescheduling
5544 // to avoid interfering with other uses, so probably requires a new
5545 // optimization pass.
5547
5548 const MCInstrDesc &GPRIDXDesc =
5549 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5550 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5551 .addReg(SrcReg)
5552 .addReg(Idx)
5553 .addImm(SubReg);
5554 } else {
5556
5557 BuildMI(MBB, I, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5558 .addReg(SrcReg, {}, SubReg)
5559 .addReg(SrcReg, RegState::Implicit);
5560 }
5561
5562 MI.eraseFromParent();
5563
5564 return &MBB;
5565 }
5566
5567 // Control flow needs to be inserted if indexing with a VGPR.
5568 const DebugLoc &DL = MI.getDebugLoc();
5570
5571 Register PhiReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5572 Register InitReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5573
5574 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), InitReg);
5575
5576 Register SGPRIdxReg;
5577 auto InsPt = loadM0FromVGPR(TII, MBB, MI, InitReg, PhiReg, Offset,
5578 UseGPRIdxMode, SGPRIdxReg);
5579
5580 MachineBasicBlock *LoopBB = InsPt->getParent();
5581
5582 if (UseGPRIdxMode) {
5583 const MCInstrDesc &GPRIDXDesc =
5584 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5585
5586 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5587 .addReg(SrcReg)
5588 .addReg(SGPRIdxReg)
5589 .addImm(SubReg);
5590 } else {
5591 BuildMI(*LoopBB, InsPt, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5592 .addReg(SrcReg, {}, SubReg)
5593 .addReg(SrcReg, RegState::Implicit);
5594 }
5595
5596 MI.eraseFromParent();
5597
5598 return LoopBB;
5599}
5600
5603 const GCNSubtarget &ST) {
5604 const SIInstrInfo *TII = ST.getInstrInfo();
5605 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5606 MachineFunction *MF = MBB.getParent();
5608
5609 Register Dst = MI.getOperand(0).getReg();
5610 const MachineOperand *SrcVec = TII->getNamedOperand(MI, AMDGPU::OpName::src);
5611 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5612 const MachineOperand *Val = TII->getNamedOperand(MI, AMDGPU::OpName::val);
5613 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5614 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcVec->getReg());
5615 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5616
5617 // This can be an immediate, but will be folded later.
5618 assert(Val->getReg());
5619
5620 unsigned SubReg;
5621 std::tie(SubReg, Offset) =
5622 computeIndirectRegAndOffset(TRI, VecRC, SrcVec->getReg(), Offset);
5623 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5624
5625 if (Idx->getReg() == AMDGPU::NoRegister) {
5627 const DebugLoc &DL = MI.getDebugLoc();
5628
5629 assert(Offset == 0);
5630
5631 BuildMI(MBB, I, DL, TII->get(TargetOpcode::INSERT_SUBREG), Dst)
5632 .add(*SrcVec)
5633 .add(*Val)
5634 .addImm(SubReg);
5635
5636 MI.eraseFromParent();
5637 return &MBB;
5638 }
5639
5640 // Check for a SGPR index.
5641 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5643 const DebugLoc &DL = MI.getDebugLoc();
5644
5645 if (UseGPRIdxMode) {
5647
5648 const MCInstrDesc &GPRIDXDesc =
5649 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5650 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5651 .addReg(SrcVec->getReg())
5652 .add(*Val)
5653 .addReg(Idx)
5654 .addImm(SubReg);
5655 } else {
5657
5658 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5659 TRI.getRegSizeInBits(*VecRC), 32, false);
5660 BuildMI(MBB, I, DL, MovRelDesc, Dst)
5661 .addReg(SrcVec->getReg())
5662 .add(*Val)
5663 .addImm(SubReg);
5664 }
5665 MI.eraseFromParent();
5666 return &MBB;
5667 }
5668
5669 // Control flow needs to be inserted if indexing with a VGPR.
5670 const DebugLoc &DL = MI.getDebugLoc();
5671
5672 Register PhiReg = MRI.createVirtualRegister(VecRC);
5673
5674 Register SGPRIdxReg;
5675 auto InsPt = loadM0FromVGPR(TII, MBB, MI, SrcVec->getReg(), PhiReg, Offset,
5676 UseGPRIdxMode, SGPRIdxReg);
5677 MachineBasicBlock *LoopBB = InsPt->getParent();
5678
5679 if (UseGPRIdxMode) {
5680 const MCInstrDesc &GPRIDXDesc =
5681 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5682
5683 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5684 .addReg(PhiReg)
5685 .add(*Val)
5686 .addReg(SGPRIdxReg)
5687 .addImm(SubReg);
5688 } else {
5689 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5690 TRI.getRegSizeInBits(*VecRC), 32, false);
5691 BuildMI(*LoopBB, InsPt, DL, MovRelDesc, Dst)
5692 .addReg(PhiReg)
5693 .add(*Val)
5694 .addImm(SubReg);
5695 }
5696
5697 MI.eraseFromParent();
5698 return LoopBB;
5699}
5700
5702 MachineBasicBlock *BB) {
5703 // For targets older than GFX12, we emit a sequence of 32-bit operations.
5704 // For GFX12, we emit s_add_u64 and s_sub_u64.
5705 MachineFunction *MF = BB->getParent();
5706 const SIInstrInfo *TII = MF->getSubtarget<GCNSubtarget>().getInstrInfo();
5707 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5709 const DebugLoc &DL = MI.getDebugLoc();
5710 MachineOperand &Dest = MI.getOperand(0);
5711 MachineOperand &Src0 = MI.getOperand(1);
5712 MachineOperand &Src1 = MI.getOperand(2);
5713 bool IsAdd = (MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5714 if (ST.hasScalarAddSub64()) {
5715 // FIXME: If scc is used, this deletes the def
5716 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5717 // clang-format off
5718 BuildMI(*BB, MI, DL, TII->get(Opc), Dest.getReg())
5719 .add(Src0)
5720 .add(Src1);
5721 // clang-format on
5722 } else {
5723 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5724 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5725
5726 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5727 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5728
5729 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5730 MI, MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5731 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5732 MI, MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5733
5734 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5735 MI, MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5736 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5737 MI, MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5738
5739 const MachineOperand &ImpDefSCC = MI.getOperand(3);
5740 assert(ImpDefSCC.getReg() == AMDGPU::SCC && ImpDefSCC.isDef());
5741
5742 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5743 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5744 BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0).add(Src0Sub0).add(Src1Sub0);
5745 auto Hi = BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1)
5746 .add(Src0Sub1)
5747 .add(Src1Sub1);
5748 if (ImpDefSCC.isDead())
5749 Hi.setOperandDead(3);
5750 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
5751 .addReg(DestSub0)
5752 .addImm(AMDGPU::sub0)
5753 .addReg(DestSub1)
5754 .addImm(AMDGPU::sub1);
5755 }
5756 MI.eraseFromParent();
5757 return BB;
5758}
5759
5761 MachineFunction *MF = BB->getParent();
5762 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5763 const SIInstrInfo *TII = ST.getInstrInfo();
5764 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5766 const DebugLoc &DL = MI.getDebugLoc();
5767 Register Dst = MI.getOperand(0).getReg();
5768 const MachineOperand &Src0 = MI.getOperand(1);
5769 const MachineOperand &Src1 = MI.getOperand(2);
5770 Register SrcCond = MI.getOperand(3).getReg();
5771
5772 Register DstLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5773 Register DstHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5774 const TargetRegisterClass *CondRC = TRI->getWaveMaskRegClass();
5775 Register SrcCondCopy = MRI.createVirtualRegister(CondRC);
5776
5777 int Src0Idx =
5778 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
5779 int Src1Idx =
5780 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);
5781 const TargetRegisterClass *Src0RC =
5782 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src0Idx));
5783 const TargetRegisterClass *Src1RC =
5784 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src1Idx));
5785
5786 const TargetRegisterClass *Src0SubRC =
5787 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5788 const TargetRegisterClass *Src1SubRC =
5789 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5790
5791 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5792 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5793 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5794 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5795
5796 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5797 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5798 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5799 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5800
5801 BuildMI(*BB, MI, DL, TII->get(AMDGPU::COPY), SrcCondCopy).addReg(SrcCond);
5802 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstLo)
5803 .addImm(0)
5804 .add(Src0Sub0)
5805 .addImm(0)
5806 .add(Src1Sub0)
5807 .addReg(SrcCondCopy);
5808
5809 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstHi)
5810 .addImm(0)
5811 .add(Src0Sub1)
5812 .addImm(0)
5813 .add(Src1Sub1)
5814 .addReg(SrcCondCopy);
5815
5816 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE), Dst)
5817 .addReg(DstLo)
5818 .addImm(AMDGPU::sub0)
5819 .addReg(DstHi)
5820 .addImm(AMDGPU::sub1);
5821 MI.eraseFromParent();
5822}
5823
5825 switch (Opc) {
5826 case AMDGPU::S_MIN_U32:
5827 return std::numeric_limits<uint32_t>::max();
5828 case AMDGPU::S_MIN_I32:
5829 return std::numeric_limits<int32_t>::max();
5830 case AMDGPU::S_MAX_U32:
5831 return std::numeric_limits<uint32_t>::min();
5832 case AMDGPU::S_MAX_I32:
5833 return std::numeric_limits<int32_t>::min();
5834 case AMDGPU::V_ADD_F32_e64: // -0.0
5835 return 0x80000000;
5836 case AMDGPU::V_SUB_F32_e64: // +0.0
5837 return 0x0;
5838 case AMDGPU::S_ADD_I32:
5839 case AMDGPU::S_SUB_I32:
5840 case AMDGPU::S_OR_B32:
5841 case AMDGPU::S_XOR_B32:
5842 return std::numeric_limits<uint32_t>::min();
5843 case AMDGPU::S_AND_B32:
5844 return std::numeric_limits<uint32_t>::max();
5845 case AMDGPU::V_MIN_F32_e64:
5846 case AMDGPU::V_MAX_F32_e64:
5847 return 0x7fc00000; // qNAN
5848 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5849 return std::numeric_limits<uint64_t>::max();
5850 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5851 return std::numeric_limits<int64_t>::max();
5852 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5853 return std::numeric_limits<uint64_t>::min();
5854 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5855 return std::numeric_limits<int64_t>::min();
5856 case AMDGPU::V_MIN_F64_e64:
5857 case AMDGPU::V_MAX_F64_e64:
5858 case AMDGPU::V_MIN_NUM_F64_e64:
5859 case AMDGPU::V_MAX_NUM_F64_e64:
5860 return 0x7FF8000000000000; // qNAN
5861 case AMDGPU::S_ADD_U64_PSEUDO:
5862 case AMDGPU::S_SUB_U64_PSEUDO:
5863 case AMDGPU::S_OR_B64:
5864 case AMDGPU::S_XOR_B64:
5865 return std::numeric_limits<uint64_t>::min();
5866 case AMDGPU::S_AND_B64:
5867 return std::numeric_limits<uint64_t>::max();
5868 case AMDGPU::V_ADD_F64_e64:
5869 case AMDGPU::V_ADD_F64_pseudo_e64:
5870 return 0x8000000000000000; // -0.0
5871 default:
5872 llvm_unreachable("Unexpected opcode in getIdentityValueForWaveReduction");
5873 }
5874}
5875
5876static bool is32bitWaveReduceOperation(unsigned Opc) {
5877 return Opc == AMDGPU::S_MIN_U32 || Opc == AMDGPU::S_MIN_I32 ||
5878 Opc == AMDGPU::S_MAX_U32 || Opc == AMDGPU::S_MAX_I32 ||
5879 Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32 ||
5880 Opc == AMDGPU::S_AND_B32 || Opc == AMDGPU::S_OR_B32 ||
5881 Opc == AMDGPU::S_XOR_B32 || Opc == AMDGPU::V_MIN_F32_e64 ||
5882 Opc == AMDGPU::V_MAX_F32_e64 || Opc == AMDGPU::V_ADD_F32_e64 ||
5883 Opc == AMDGPU::V_SUB_F32_e64;
5884}
5885
5887 return Opc == AMDGPU::V_MIN_F32_e64 || Opc == AMDGPU::V_MAX_F32_e64 ||
5888 Opc == AMDGPU::V_ADD_F32_e64 || Opc == AMDGPU::V_SUB_F32_e64 ||
5889 Opc == AMDGPU::V_MIN_F64_e64 || Opc == AMDGPU::V_MAX_F64_e64 ||
5890 Opc == AMDGPU::V_MIN_NUM_F64_e64 || Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5891 Opc == AMDGPU::V_ADD_F64_e64 || Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5892}
5893
5894static std::tuple<unsigned, unsigned>
5896 unsigned DPPOpc;
5897 switch (Opc) {
5898 case AMDGPU::S_MIN_U32:
5899 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5900 break;
5901 case AMDGPU::S_MIN_I32:
5902 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5903 break;
5904 case AMDGPU::S_MAX_U32:
5905 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5906 break;
5907 case AMDGPU::S_MAX_I32:
5908 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5909 break;
5910 case AMDGPU::S_ADD_I32:
5911 case AMDGPU::S_SUB_I32:
5912 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5913 : AMDGPU::V_ADD_CO_U32_dpp;
5914 break;
5915 case AMDGPU::S_AND_B32:
5916 DPPOpc = AMDGPU::V_AND_B32_dpp;
5917 break;
5918 case AMDGPU::S_OR_B32:
5919 DPPOpc = AMDGPU::V_OR_B32_dpp;
5920 break;
5921 case AMDGPU::S_XOR_B32:
5922 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5923 break;
5924 case AMDGPU::V_ADD_F32_e64:
5925 case AMDGPU::V_SUB_F32_e64:
5926 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5927 break;
5928 case AMDGPU::V_MIN_F32_e64:
5929 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5930 break;
5931 case AMDGPU::V_MAX_F32_e64:
5932 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5933 break;
5934 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5935 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5936 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5937 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5938 case AMDGPU::S_ADD_U64_PSEUDO:
5939 case AMDGPU::S_SUB_U64_PSEUDO:
5940 case AMDGPU::S_AND_B64:
5941 case AMDGPU::S_OR_B64:
5942 case AMDGPU::S_XOR_B64:
5943 case AMDGPU::V_MIN_NUM_F64_e64:
5944 case AMDGPU::V_MIN_F64_e64:
5945 case AMDGPU::V_MAX_NUM_F64_e64:
5946 case AMDGPU::V_MAX_F64_e64:
5947 case AMDGPU::V_ADD_F64_pseudo_e64:
5948 case AMDGPU::V_ADD_F64_e64:
5949 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5950 break;
5951 default:
5952 llvm_unreachable("unhandled lane op");
5953 }
5954 unsigned ClampOpc = Opc;
5955 if (Opc == AMDGPU::V_SUB_F32_e64)
5956 ClampOpc = AMDGPU::V_ADD_F32_e64;
5957 if (!ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
5958 if (Opc == AMDGPU::S_SUB_I32)
5959 ClampOpc = AMDGPU::S_ADD_I32;
5960 if (Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO)
5961 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5962 else if (Opc == AMDGPU::S_AND_B64)
5963 ClampOpc = AMDGPU::V_AND_B32_e64;
5964 else if (Opc == AMDGPU::S_OR_B64)
5965 ClampOpc = AMDGPU::V_OR_B32_e64;
5966 else if (Opc == AMDGPU::S_XOR_B64)
5967 ClampOpc = AMDGPU::V_XOR_B32_e64;
5968 else
5969 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5970 }
5971 return {DPPOpc, ClampOpc};
5972}
5973
5974static std::pair<Register, Register>
5976 const TargetRegisterClass *SrcRC, const GCNSubtarget &ST,
5978 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5979 const SIInstrInfo *TII = ST.getInstrInfo();
5980 const TargetRegisterClass *SrcSubRC =
5981 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5982 Register Op1L =
5983 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5984 Register Op1H =
5985 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub1, SrcSubRC);
5986 return {Op1L, Op1H};
5987}
5988
5991 const GCNSubtarget &ST,
5992 unsigned Opc) {
5994 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5995 const DebugLoc &DL = MI.getDebugLoc();
5996 const SIInstrInfo *TII = ST.getInstrInfo();
5997
5998 // Reduction operations depend on whether the input operand is SGPR or VGPR.
5999 Register SrcReg = MI.getOperand(1).getReg();
6000 bool isSGPR = TRI->isSGPRClass(MRI.getRegClass(SrcReg));
6001 Register DstReg = MI.getOperand(0).getReg();
6002 unsigned Stratergy = static_cast<unsigned>(MI.getOperand(2).getImm());
6003 enum WAVE_REDUCE_STRATEGY : unsigned { DEFAULT = 0, ITERATIVE = 1, DPP = 2 };
6004 MachineBasicBlock *RetBB = nullptr;
6005 unsigned MIOpc = MI.getOpcode();
6006 auto BuildRegSequence = [&](MachineBasicBlock &BB,
6008 Register Src0, Register Src1) {
6009 auto RegSequence =
6010 BuildMI(BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dst)
6011 .addReg(Src0)
6012 .addImm(AMDGPU::sub0)
6013 .addReg(Src1)
6014 .addImm(AMDGPU::sub1);
6015 return RegSequence;
6016 };
6017 if (isSGPR) {
6018 switch (Opc) {
6019 case AMDGPU::S_MIN_U32:
6020 case AMDGPU::S_MIN_I32:
6021 case AMDGPU::V_MIN_F32_e64:
6022 case AMDGPU::S_MAX_U32:
6023 case AMDGPU::S_MAX_I32:
6024 case AMDGPU::V_MAX_F32_e64:
6025 case AMDGPU::S_AND_B32:
6026 case AMDGPU::S_OR_B32: {
6027 // Idempotent operations.
6028 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstReg).addReg(SrcReg);
6029 RetBB = &BB;
6030 break;
6031 }
6032 case AMDGPU::V_CMP_LT_U64_e64: // umin
6033 case AMDGPU::V_CMP_LT_I64_e64: // min
6034 case AMDGPU::V_CMP_GT_U64_e64: // umax
6035 case AMDGPU::V_CMP_GT_I64_e64: // max
6036 case AMDGPU::V_MIN_F64_e64:
6037 case AMDGPU::V_MIN_NUM_F64_e64:
6038 case AMDGPU::V_MAX_F64_e64:
6039 case AMDGPU::V_MAX_NUM_F64_e64:
6040 case AMDGPU::S_AND_B64:
6041 case AMDGPU::S_OR_B64: {
6042 // Idempotent operations.
6043 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B64), DstReg).addReg(SrcReg);
6044 RetBB = &BB;
6045 break;
6046 }
6047 case AMDGPU::S_XOR_B32:
6048 case AMDGPU::S_XOR_B64:
6049 case AMDGPU::S_ADD_I32:
6050 case AMDGPU::S_ADD_U64_PSEUDO:
6051 case AMDGPU::V_ADD_F32_e64:
6052 case AMDGPU::V_ADD_F64_e64:
6053 case AMDGPU::V_ADD_F64_pseudo_e64:
6054 case AMDGPU::S_SUB_I32:
6055 case AMDGPU::S_SUB_U64_PSEUDO:
6056 case AMDGPU::V_SUB_F32_e64: {
6057 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
6058 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
6059 Register ExecMask = MRI.createVirtualRegister(WaveMaskRegClass);
6060 Register NumActiveLanes =
6061 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6062
6063 bool IsWave32 = ST.isWave32();
6064 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6065 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6066 unsigned BitCountOpc =
6067 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
6068
6069 BuildMI(BB, MI, DL, TII->get(MovOpc), ExecMask).addReg(ExecReg);
6070
6071 auto NewAccumulator =
6072 BuildMI(BB, MI, DL, TII->get(BitCountOpc), NumActiveLanes)
6073 .addReg(ExecMask)
6074 .setOperandDead(2); // Dead scc
6075
6076 switch (Opc) {
6077 case AMDGPU::S_XOR_B32:
6078 case AMDGPU::S_XOR_B64: {
6079 // Performing an XOR operation on a uniform value
6080 // depends on the parity of the number of active lanes.
6081 // For even parity, the result will be 0, for odd
6082 // parity the result will be the same as the input value.
6083 Register ParityRegister =
6084 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6085 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_AND_B32), ParityRegister)
6086 .addReg(NewAccumulator->getOperand(0).getReg())
6087 .addImm(1)
6088 .setOperandDead(3); // Dead scc
6089 // Check if Src is a known identity constant.
6090 if (TII->getImmOrMaterializedImm(MRI, SrcReg) == 1) {
6091 // 1 * parity(exec) = parity(exec)
6092 if (Opc == AMDGPU::S_XOR_B32) {
6093 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstReg)
6094 .addReg(ParityRegister);
6095 } else {
6096 Register DstHi =
6097 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6098 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstHi).addImm(0);
6099 BuildRegSequence(BB, MI, DstReg, ParityRegister, DstHi);
6100 }
6101 break;
6102 }
6103 if (Opc == AMDGPU::S_XOR_B32) {
6104 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6105 .addReg(SrcReg)
6106 .addReg(ParityRegister);
6107 } else {
6108 Register DestSub0 =
6109 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6110 Register DestSub1 =
6111 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6112 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6113 MRI.getRegClass(SrcReg), ST, MRI);
6114 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6115 .addReg(Op1L)
6116 .addReg(ParityRegister);
6117 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub1)
6118 .addReg(Op1H)
6119 .addReg(ParityRegister);
6120 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6121 }
6122 break;
6123 }
6124 case AMDGPU::S_SUB_I32: {
6125 Register NegatedVal = MRI.createVirtualRegister(DstRegClass);
6126 // Take the negation of the source operand.
6127 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedVal)
6128 .addImm(0)
6129 .addReg(SrcReg)
6130 .setOperandDead(3); // Dead scc
6131 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6132 .addReg(NegatedVal)
6133 .addReg(NewAccumulator->getOperand(0).getReg());
6134 break;
6135 }
6136 case AMDGPU::S_ADD_I32: {
6137 // Check if Src is a known identity constant.
6138 if (TII->getImmOrMaterializedImm(MRI, SrcReg) == 1) {
6139 // 1 * bitcount(exec) = bitcount(exec)
6140 BuildMI(BB, MI, DL, TII->get(AMDGPU::COPY), DstReg)
6141 .addReg(NewAccumulator->getOperand(0).getReg());
6142 break;
6143 }
6144 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6145 .addReg(SrcReg)
6146 .addReg(NewAccumulator->getOperand(0).getReg());
6147 break;
6148 }
6149 case AMDGPU::S_ADD_U64_PSEUDO:
6150 case AMDGPU::S_SUB_U64_PSEUDO: {
6151 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6152 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6153 Register Op1H_Op0L_Reg =
6154 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6155 Register Op1L_Op0H_Reg =
6156 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6157 Register CarryReg =
6158 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6159 Register AddReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6160 Register NegatedValLo =
6161 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6162 Register NegatedValHi =
6163 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6164 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6165 MRI.getRegClass(SrcReg), ST, MRI);
6166 // Check if Src is a known identity constant.
6167 if (Opc == AMDGPU::S_ADD_U64_PSEUDO &&
6168 TII->getImmOrMaterializedImm(MRI, SrcReg) == 1) {
6169 // 1 * bitcount(exec) = bitcount(exec)
6170 Register DstHi = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6171 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstHi).addImm(0);
6172 BuildRegSequence(BB, MI, DstReg,
6173 NewAccumulator->getOperand(0).getReg(), DstHi);
6174 break;
6175 }
6176 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6177 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedValLo)
6178 .addImm(0)
6179 .addReg(NewAccumulator->getOperand(0).getReg())
6180 .setOperandDead(3); // Dead scc
6181 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ASHR_I32), NegatedValHi)
6182 .addReg(NegatedValLo)
6183 .addImm(31)
6184 .setOperandDead(3); // Dead scc
6185 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1L_Op0H_Reg)
6186 .addReg(Op1L)
6187 .addReg(NegatedValHi);
6188 }
6189 Register LowOpcode = Opc == AMDGPU::S_SUB_U64_PSEUDO
6190 ? NegatedValLo
6191 : NewAccumulator->getOperand(0).getReg();
6192 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6193 .addReg(Op1L)
6194 .addReg(LowOpcode);
6195 if (ST.hasScalarMulHiInsts()) {
6196 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_HI_U32), CarryReg)
6197 .addReg(Op1L)
6198 .addReg(LowOpcode);
6199 } else {
6200 Register VCarryReg =
6201 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6202 Register LowOpVGPR =
6203 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6204 BuildMI(BB, MI, DL, TII->get(AMDGPU::COPY), LowOpVGPR)
6205 .addReg(LowOpcode);
6206 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6207 .addReg(Op1L)
6208 .addReg(LowOpVGPR);
6209 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6210 .addReg(VCarryReg);
6211 }
6212 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1H_Op0L_Reg)
6213 .addReg(Op1H)
6214 .addReg(LowOpcode);
6215
6216 Register HiVal = Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6217 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), HiVal)
6218 .addReg(CarryReg)
6219 .addReg(Op1H_Op0L_Reg)
6220 .setOperandDead(3); // Dead scc
6221
6222 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6223 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), DestSub1)
6224 .addReg(HiVal)
6225 .addReg(Op1L_Op0H_Reg)
6226 .setOperandDead(3); // Dead scc
6227 }
6228 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6229 break;
6230 }
6231 case AMDGPU::V_ADD_F32_e64:
6232 case AMDGPU::V_ADD_F64_e64:
6233 case AMDGPU::V_ADD_F64_pseudo_e64:
6234 case AMDGPU::V_SUB_F32_e64: {
6235 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6236 const TargetRegisterClass *VregRC = TII->getRegClass(TII->get(Opc), 0);
6237 Register ActiveLanesVreg = MRI.createVirtualRegister(VregRC);
6238 Register DstVreg = MRI.createVirtualRegister(VregRC);
6239 // Get number of active lanes as a float val.
6240 BuildMI(BB, MI, DL,
6241 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6242 : AMDGPU::V_CVT_F64_I32_e64),
6243 ActiveLanesVreg)
6244 .addReg(NewAccumulator->getOperand(0).getReg())
6245 .addImm(0) // clamp
6246 .addImm(0); // output-modifier
6247
6248 // Take negation of input for SUB reduction
6249 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6250 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6253 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6254 : ST.getGeneration() >= AMDGPUSubtarget::GFX12
6255 ? AMDGPU::V_MUL_F64_pseudo_e64
6256 : AMDGPU::V_MUL_F64_e64;
6257 auto DestVregInst = BuildMI(BB, MI, DL, TII->get(MulOpc),
6258 DstVreg)
6259 .addImm(srcMod) // src0 modifier
6260 .addReg(SrcReg)
6261 .addImm(SISrcMods::NONE) // src1 modifier
6262 .addReg(ActiveLanesVreg)
6263 .addImm(SISrcMods::NONE) // clamp
6264 .addImm(SISrcMods::NONE); // output-mod
6265 if (is32BitOpc) {
6266 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6267 .addReg(DstVreg);
6268 } else {
6269 Register LaneValueLoReg =
6270 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6271 Register LaneValueHiReg =
6272 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6273 auto [Op1L, Op1H] =
6274 ExtractSubRegs(MI, DestVregInst->getOperand(0), VregRC, ST, MRI);
6275 // lane value input should be in an sgpr
6276 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6277 LaneValueLoReg)
6278 .addReg(Op1L);
6279 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6280 LaneValueHiReg)
6281 .addReg(Op1H);
6282 NewAccumulator =
6283 BuildRegSequence(BB, MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6284 }
6285 }
6286 }
6287 RetBB = &BB;
6288 }
6289 }
6290 } else {
6292 Register SrcReg = MI.getOperand(1).getReg();
6293 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6295 bool NeedsMovDPP = !is32BitOpc;
6296 // Create virtual registers required for lowering.
6297 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
6298 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
6299 const TargetRegisterClass *SrcRegClass = MRI.getRegClass(SrcReg);
6300 bool IsWave32 = ST.isWave32();
6301 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6302 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6303 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6304 !ST.hasDPP()) { // If target doesn't support DPP operations, default to
6305 // iterative stratergy
6306
6307 // To reduce the VGPR using iterative approach, we need to iterate
6308 // over all the active lanes. Lowering consists of ComputeLoop,
6309 // which iterate over only active lanes. We use copy of EXEC register
6310 // as induction variable and every active lane modifies it using bitset0
6311 // so that we will get the next active lane for next iteration.
6312
6313 // Create Control flow for loop
6314 // Split MI's Machine Basic block into For loop
6315 auto [ComputeLoop, ComputeEnd] = splitBlockForLoop(MI, BB, true);
6316
6317 Register LoopIterator = MRI.createVirtualRegister(WaveMaskRegClass);
6318 Register IdentityValReg = MRI.createVirtualRegister(DstRegClass);
6319 Register AccumulatorReg = MRI.createVirtualRegister(DstRegClass);
6320 Register ActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6321 Register NewActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6322 Register FF1Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6323 Register LaneValueReg = MRI.createVirtualRegister(DstRegClass);
6324
6325 // Create initial values of induction variable from Exec, Accumulator and
6326 // insert branch instr to newly created ComputeBlock
6327 BuildMI(BB, I, DL, TII->get(MovOpcForExec), LoopIterator).addReg(ExecReg);
6328 uint64_t IdentityValue =
6329 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6330 ? 0x0 // +0.0 for double sub reduction
6332 BuildMI(BB, I, DL,
6333 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6334 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6335 IdentityValReg)
6336 .addImm(IdentityValue);
6337 // clang-format off
6338 BuildMI(BB, I, DL, TII->get(AMDGPU::S_BRANCH))
6339 .addMBB(ComputeLoop);
6340 // clang-format on
6341
6342 // Start constructing ComputeLoop
6343 I = ComputeLoop->begin();
6344 auto Accumulator =
6345 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), AccumulatorReg)
6346 .addReg(IdentityValReg)
6347 .addMBB(&BB);
6348 auto ActiveBits =
6349 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), ActiveBitsReg)
6350 .addReg(LoopIterator)
6351 .addMBB(&BB);
6352
6353 I = ComputeLoop->end();
6354 MachineInstr *NewAccumulator;
6355 // Perform the computations
6356 unsigned SFFOpc =
6357 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6358 BuildMI(*ComputeLoop, I, DL, TII->get(SFFOpc), FF1Reg)
6359 .addReg(ActiveBitsReg);
6360 if (is32BitOpc) {
6361 Register OpDstReg = DstReg;
6362 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6363 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6364 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6365 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6366 bool hasClamp =
6367 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1;
6368 bool hasOpSel =
6369 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel) != -1;
6370 bool hasOMod =
6371 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1;
6372 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6373 LaneValueReg)
6374 .addReg(SrcReg)
6375 .addReg(FF1Reg);
6376 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6377 // Get the Lane Value in VGPR to avoid the Constant Bus Restriction
6378 Register LaneValVgpr = MRI.createVirtualRegister(SrcRegClass);
6379 Register VgprResultReg = MRI.createVirtualRegister(SrcRegClass);
6380 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), LaneValVgpr)
6381 .addReg(LaneValueReg);
6382 OpDstReg = VgprResultReg;
6383 LaneValueReg = LaneValVgpr;
6384 }
6385 auto OpInstr = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), OpDstReg);
6386 if (hasSrc0Modifier)
6387 OpInstr.addImm(SISrcMods::NONE); // src0 modifier
6388 OpInstr.addReg(AccumulatorReg); // src0
6389 if (hasSrc1Modifier)
6390 OpInstr.addImm(SISrcMods::NONE); // src1 modifier
6391 OpInstr.addReg(LaneValueReg); // src1
6392 if (hasClamp)
6393 OpInstr.addImm(0); // clamp
6394 if (hasOpSel)
6395 OpInstr.addImm(0); // opsel
6396 if (hasOMod)
6397 OpInstr.addImm(0); // omod
6398 if (TII->isSALU(Opc))
6399 OpInstr.setOperandDead(3); // Dead scc
6400 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6401 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6402 DstReg)
6403 .addReg(OpDstReg);
6404 }
6405 } else {
6406 Register LaneValueLoReg =
6407 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6408 Register LaneValueHiReg =
6409 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6410 Register LaneValReg =
6411 MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
6412 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6413 MRI.getRegClass(SrcReg), ST, MRI);
6414 // lane value input should be in an sgpr
6415 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6416 LaneValueLoReg)
6417 .addReg(Op1L)
6418 .addReg(FF1Reg);
6419 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6420 LaneValueHiReg)
6421 .addReg(Op1H)
6422 .addReg(FF1Reg);
6423 auto LaneValue = BuildRegSequence(*ComputeLoop, I, LaneValReg,
6424 LaneValueLoReg, LaneValueHiReg);
6425 switch (Opc) {
6426 case AMDGPU::S_OR_B64:
6427 case AMDGPU::S_AND_B64:
6428 case AMDGPU::S_XOR_B64: {
6429 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6430 .addReg(Accumulator->getOperand(0).getReg())
6431 .addReg(LaneValue->getOperand(0).getReg())
6432 .setOperandDead(3); // Dead scc
6433 break;
6434 }
6435 case AMDGPU::V_CMP_GT_I64_e64:
6436 case AMDGPU::V_CMP_GT_U64_e64:
6437 case AMDGPU::V_CMP_LT_I64_e64:
6438 case AMDGPU::V_CMP_LT_U64_e64: {
6439 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6440 Register ComparisonResultReg =
6441 MRI.createVirtualRegister(WaveMaskRegClass);
6442 int SrcIdx =
6443 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6444 const TargetRegisterClass *VregClass =
6445 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6446 Register AccumulatorVReg = MRI.createVirtualRegister(VregClass);
6447 auto [SrcReg0Sub0, SrcReg0Sub1] = ExtractSubRegs(
6448 MI, Accumulator->getOperand(0), VregClass, ST, MRI);
6449 BuildRegSequence(*ComputeLoop, I, AccumulatorVReg, SrcReg0Sub0,
6450 SrcReg0Sub1);
6451 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), LaneMaskReg)
6452 .addReg(LaneValue->getOperand(0).getReg())
6453 .addReg(AccumulatorVReg);
6454
6455 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6456 BuildMI(*ComputeLoop, I, DL, TII->get(AndOpc), ComparisonResultReg)
6457 .addReg(LaneMaskReg)
6458 .addReg(ActiveBitsReg);
6459
6460 NewAccumulator = BuildMI(*ComputeLoop, I, DL,
6461 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6462 .addReg(LaneValue->getOperand(0).getReg())
6463 .addReg(Accumulator->getOperand(0).getReg());
6464 break;
6465 }
6466 case AMDGPU::V_MIN_F64_e64:
6467 case AMDGPU::V_MIN_NUM_F64_e64:
6468 case AMDGPU::V_MAX_F64_e64:
6469 case AMDGPU::V_MAX_NUM_F64_e64:
6470 case AMDGPU::V_ADD_F64_e64:
6471 case AMDGPU::V_ADD_F64_pseudo_e64: {
6472 int SrcIdx =
6473 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6474 const TargetRegisterClass *VregRC =
6475 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6476 Register AccumulatorVReg = MRI.createVirtualRegister(VregRC);
6477 Register DstVreg = MRI.createVirtualRegister(VregRC);
6478 Register LaneValLo =
6479 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6480 Register LaneValHi =
6481 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6482 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), AccumulatorVReg)
6483 .addReg(Accumulator->getOperand(0).getReg());
6484 unsigned Modifier =
6485 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6488 auto DstVregInst =
6489 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstVreg)
6490 .addImm(Modifier) // src0 modifiers
6491 .addReg(LaneValue->getOperand(0).getReg())
6492 .addImm(SISrcMods::NONE) // src1 modifiers
6493 .addReg(AccumulatorVReg)
6494 .addImm(SISrcMods::NONE) // clamp
6495 .addImm(SISrcMods::NONE); // omod
6496 auto ReadLaneLo =
6497 BuildMI(*ComputeLoop, I, DL,
6498 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6499 auto ReadLaneHi =
6500 BuildMI(*ComputeLoop, I, DL,
6501 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6502 MachineBasicBlock::iterator Iters = *ReadLaneLo;
6503 auto [Op1L, Op1H] = ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6504 VregRC, ST, MRI);
6505 ReadLaneLo.addReg(Op1L);
6506 ReadLaneHi.addReg(Op1H);
6507 NewAccumulator =
6508 BuildRegSequence(*ComputeLoop, I, DstReg, LaneValLo, LaneValHi);
6509 break;
6510 }
6511 case AMDGPU::S_ADD_U64_PSEUDO:
6512 case AMDGPU::S_SUB_U64_PSEUDO: {
6513 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6514 .addReg(Accumulator->getOperand(0).getReg())
6515 .addReg(LaneValue->getOperand(0).getReg())
6516 .setOperandDead(3); // Dead scc
6517 ComputeLoop =
6518 expand64BitScalarArithmetic(*NewAccumulator, ComputeLoop);
6519 break;
6520 }
6521 }
6522 }
6523 // Manipulate the iterator to get the next active lane
6524 unsigned BITSETOpc =
6525 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6526 BuildMI(*ComputeLoop, I, DL, TII->get(BITSETOpc), NewActiveBitsReg)
6527 .addReg(FF1Reg)
6528 .addReg(ActiveBitsReg);
6529
6530 // Add phi nodes
6531 Accumulator.addReg(DstReg).addMBB(ComputeLoop);
6532 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6533
6534 // Creating branching
6535 MachineInstrBuilder SetSCCInstr;
6536 if (!ST.hasScalarCompareEq64()) {
6537 // For targets <= gfx7, use an S_OR_B32/B64 instruction to set SCC.
6538 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6539 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6540 SetSCCInstr =
6541 BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc), LaneMaskReg);
6542 } else {
6543 unsigned CMPOpc =
6544 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6545 SetSCCInstr = BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc));
6546 }
6547 SetSCCInstr.addReg(NewActiveBitsReg);
6548 if (ST.hasScalarCompareEq64())
6549 SetSCCInstr.addImm(0);
6550 else
6551 SetSCCInstr.addReg(NewActiveBitsReg);
6552 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
6553 .addMBB(ComputeLoop);
6554
6555 RetBB = ComputeEnd;
6556 } else {
6557 assert(ST.hasDPP() && "Sub Target does not support DPP Operations");
6558 MachineBasicBlock *CurrBB = &BB;
6559 Register SrcWithIdentity = MRI.createVirtualRegister(SrcRegClass);
6560 Register IdentityVGPR = MRI.createVirtualRegister(SrcRegClass);
6561 Register IdentitySGPR = MRI.createVirtualRegister(DstRegClass);
6562 Register DPPRowShr1 = MRI.createVirtualRegister(SrcRegClass);
6563 Register DPPRowShr2 = MRI.createVirtualRegister(SrcRegClass);
6564 Register DPPRowShr4 = MRI.createVirtualRegister(SrcRegClass);
6565 Register DPPRowShr8 = MRI.createVirtualRegister(SrcRegClass);
6566 Register RowBcast15 = MRI.createVirtualRegister(SrcRegClass);
6567 Register ReducedValSGPR = MRI.createVirtualRegister(DstRegClass);
6568 Register NegatedReducedVal = MRI.createVirtualRegister(DstRegClass);
6569 Register RowBcast31 = MRI.createVirtualRegister(SrcRegClass);
6570 Register UndefExec = MRI.createVirtualRegister(WaveMaskRegClass);
6571 Register FinalDPPResult;
6572 MachineInstr *SrcWithIdentityInstr;
6573 MachineInstr *LastBcastInstr;
6574 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6575
6577 BuildMI(*CurrBB, MI, DL,
6578 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6579 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6580 IdentitySGPR)
6581 .addImm(IdentityValue);
6582 auto IdentityCopyInstr =
6583 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::COPY), IdentityVGPR)
6584 .addReg(IdentitySGPR);
6585 unsigned DPPOpc, ClampOpc;
6586 std::tie(DPPOpc, ClampOpc) = getDPPOpcForWaveReduction(Opc, ST);
6587 auto BuildSetInactiveInstr = [&](Register Dst, Register Src0,
6588 Register Src1) {
6589 return BuildMI(BB, MI, DL, TII->get(AMDGPU::V_SET_INACTIVE_B32),
6590 Dst)
6591 .addImm(0) // src0 modifiers
6592 .addReg(Src0) // src0
6593 .addImm(0) // src1 modifiers
6594 .addReg(Src1) // identity value for inactive lanes
6595 .addReg(UndefExec); // bool i1
6596 };
6597 auto BuildDPPMachineInstr = [&](Register Dst, Register Src,
6598 unsigned DPPCtrl) {
6599 auto DPPInstr =
6600 BuildMI(*CurrBB, MI, DL, TII->get(DPPOpc), Dst).addReg(Src); // old
6601 if (isFPOp && !NeedsMovDPP)
6602 DPPInstr.addImm(SISrcMods::NONE); // src0 modifier
6603 DPPInstr.addReg(Src); // src0
6604 if (isFPOp && !NeedsMovDPP)
6605 DPPInstr.addImm(SISrcMods::NONE); // src1 modifier
6606 if (!NeedsMovDPP)
6607 DPPInstr.addReg(Src); // src1
6608 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6609 DPPInstr.addImm(0); // clamp
6610 DPPInstr
6611 .addImm(DPPCtrl) // dpp-ctrl
6612 .addImm(0xf) // row-mask
6613 .addImm(0xf) // bank-mask
6614 .addImm(0); // bound-control
6615 };
6616 auto BuildClampInstr = [&](Register Dst, Register Src0, Register Src1,
6617 bool isAddSub = false,
6618 bool needsCarryIn = false,
6619 Register CarryIn = Register()) {
6620 unsigned InstrOpc = ClampOpc;
6621 Register CarryOutReg = MRI.createVirtualRegister(WaveMaskRegClass);
6622 if (needsCarryIn)
6623 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6624 auto ClampInstr = BuildMI(*CurrBB, MI, DL, TII->get(InstrOpc), Dst);
6625 if (isFPOp)
6626 ClampInstr.addImm(SISrcMods::NONE); // src0 mod
6627 if (isAddSub) {
6628 if (needsCarryIn)
6629 ClampInstr.addReg(CarryOutReg,
6631 RegState::Dead); // killed carry-out reg
6632 else
6633 ClampInstr.addReg(CarryOutReg, RegState::Define); // carry-out reg
6634 }
6635 ClampInstr.addReg(Src0); // src0
6636 if (isFPOp)
6637 ClampInstr.addImm(SISrcMods::NONE); // src1 mod
6638 ClampInstr.addReg(Src1); // src1
6639 if (needsCarryIn)
6640 ClampInstr.addReg(CarryIn); // carry-in reg
6641 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6642 ClampInstr.addImm(0); // clamp
6643 if (isFPOp)
6644 ClampInstr.addImm(0); // omod
6645 LastBcastInstr = ClampInstr;
6646 return CarryOutReg;
6647 };
6648 auto BuildPostDPPInstr = [&](Register Src0, Register Src1) {
6649 bool isAddSubOpc =
6650 Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO;
6651 bool isBitWiseOpc = Opc == AMDGPU::S_AND_B64 ||
6652 Opc == AMDGPU::S_OR_B64 || Opc == AMDGPU::S_XOR_B64;
6653 Register ReturnReg = MRI.createVirtualRegister(SrcRegClass);
6654 if (isAddSubOpc || isBitWiseOpc) {
6655 Register ResLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6656 Register ResHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6657 MachineOperand Src0Operand =
6658 MachineOperand::CreateReg(Src0, /*isDef=*/false);
6659 MachineOperand Src1Operand =
6660 MachineOperand::CreateReg(Src1, /*isDef=*/false);
6661 auto [Src0Lo, Src0Hi] =
6662 ExtractSubRegs(MI, Src0Operand, SrcRegClass, ST, MRI);
6663 auto [Src1Lo, Src1Hi] =
6664 ExtractSubRegs(MI, Src1Operand, SrcRegClass, ST, MRI);
6665 Register CarryReg = BuildClampInstr(
6666 ResLo, Src0Lo, Src1Lo, isAddSubOpc, /*needsCarryIn*/ false);
6667 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6668 /*needsCarryIn*/ isAddSubOpc, CarryReg);
6669 BuildRegSequence(*CurrBB, MI, ReturnReg, ResLo, ResHi);
6670 } else {
6671 if (isFPOp) {
6672 BuildMI(*CurrBB, MI, DL, TII->get(Opc), ReturnReg)
6673 .addImm(SISrcMods::NONE) // src0 modifiers
6674 .addReg(Src0)
6675 .addImm(SISrcMods::NONE) // src1 modifiers
6676 .addReg(Src1)
6677 .addImm(SISrcMods::NONE) // clamp
6678 .addImm(SISrcMods::NONE); // omod
6679 } else {
6680 Register CmpMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6681 BuildMI(*CurrBB, MI, DL, TII->get(Opc), CmpMaskReg)
6682 .addReg(Src0) // src0
6683 .addReg(Src1); // src1
6684 LastBcastInstr =
6685 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B64_PSEUDO),
6686 ReturnReg)
6687 .addReg(Src1) // src0
6688 .addReg(Src0) // src1
6689 .addReg(CmpMaskReg); // src2
6690 expand64BitV_CNDMASK(*LastBcastInstr, CurrBB);
6691 }
6692 }
6693 return ReturnReg;
6694 };
6695
6696 // Set inactive lanes to the identity value.
6697 if (is32BitOpc) {
6698 SrcWithIdentityInstr =
6699 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6700 } else {
6701 Register SrcWithIdentitylo =
6702 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6703 Register SrcWithIdentityhi =
6704 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6705 auto [Reg0Sub0, Reg0Sub1] = ExtractSubRegs(
6706 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST, MRI);
6707 auto [SrcReg0Sub0, SrcReg0Sub1] =
6708 ExtractSubRegs(MI, MI.getOperand(1), SrcRegClass, ST, MRI);
6709 MachineInstr *SetInactiveLoInstr =
6710 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6711 MachineInstr *SetInactiveHiInstr =
6712 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6713 SrcWithIdentityInstr =
6714 BuildRegSequence(*CurrBB, MI, SrcWithIdentity,
6715 SetInactiveLoInstr->getOperand(0).getReg(),
6716 SetInactiveHiInstr->getOperand(0).getReg());
6717 }
6718 // DPP reduction
6719 Register SrcWithIdentityReg =
6720 SrcWithIdentityInstr->getOperand(0).getReg();
6721 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6723 if (NeedsMovDPP)
6724 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6725
6726 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6728 if (NeedsMovDPP)
6729 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6730
6731 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6733 if (NeedsMovDPP)
6734 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6735
6736 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6738 if (NeedsMovDPP)
6739 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6740
6741 if (ST.hasDPPBroadcasts()) {
6742 BuildDPPMachineInstr(RowBcast15, DPPRowShr8, AMDGPU::DPP::BCAST15);
6743 if (NeedsMovDPP)
6744 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6745 } else {
6746 // magic constant: 0x1E0
6747 // To Set BIT_MODE : bit 15 = 0
6748 // XOR mask : bit [14:10] = 0
6749 // OR mask : bit [9:5] = 15
6750 // AND mask : bit [4:0] = 0
6751 if (is32BitOpc) {
6752 Register SwizzledValue =
6753 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6754 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6755 SwizzledValue)
6756 .addReg(DPPRowShr8) // addr
6757 .addImm(0x1E0) // swizzle offset (i16)
6758 .addImm(0x0); // gds (i1)
6759 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6760 } else {
6761 Register SwizzledValuelo =
6762 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6763 Register SwizzledValuehi =
6764 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6765 Register SwizzledValue64 = MRI.createVirtualRegister(SrcRegClass);
6766 MachineOperand DPPRowShr8Op =
6767 MachineOperand::CreateReg(DPPRowShr8, /*isDef=*/false);
6768 auto [Op1L, Op1H] =
6769 ExtractSubRegs(MI, DPPRowShr8Op, SrcRegClass, ST, MRI);
6770 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6771 SwizzledValuelo)
6772 .addReg(Op1L) // addr
6773 .addImm(0x1E0) // swizzle offset (i16)
6774 .addImm(0x0); // gds (i1)
6775 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6776 SwizzledValuehi)
6777 .addReg(Op1H) // addr
6778 .addImm(0x1E0) // swizzle offset (i16)
6779 .addImm(0x0); // gds (i1)
6780 BuildRegSequence(*CurrBB, MI, SwizzledValue64, SwizzledValuelo,
6781 SwizzledValuehi);
6782 if (NeedsMovDPP)
6783 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6784 else
6785 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6786 }
6787 }
6788 FinalDPPResult = RowBcast15;
6789 if (!IsWave32) {
6790 if (ST.hasDPPBroadcasts()) {
6791 BuildDPPMachineInstr(RowBcast31, RowBcast15, AMDGPU::DPP::BCAST31);
6792 if (NeedsMovDPP)
6793 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6794 } else {
6795 Register ShiftedThreadID =
6796 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6797 Register PermuteByteOffset =
6798 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6799 Register PermutedValue = MRI.createVirtualRegister(SrcRegClass);
6800 Register Lane32Offset =
6801 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6802 Register WordSizeConst =
6803 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6804 Register ThreadIDRegLo =
6805 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6806 Register ThreadIDReg =
6807 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6808 // Get the thread ID.
6809 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6810 ThreadIDRegLo)
6811 .addImm(-1)
6812 .addImm(0);
6813 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6814 ThreadIDReg)
6815 .addImm(-1)
6816 .addReg(ThreadIDRegLo);
6817 // shift each lane over by 32 positions, so value in 31st lane is
6818 // present in 63rd lane.
6819 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6820 .addImm(0x20);
6821 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_ADD_U32_e64),
6822 ShiftedThreadID)
6823 .addReg(ThreadIDReg)
6824 .addReg(Lane32Offset)
6825 .addImm(0); // clamp
6826 // multiply by reg size.
6827 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6828 .addImm(0x4);
6829 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MUL_LO_U32_e64),
6830 PermuteByteOffset)
6831 .addReg(WordSizeConst)
6832 .addReg(ShiftedThreadID);
6833 // Permute the lanes
6834 if (is32BitOpc) {
6835 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6836 PermutedValue)
6837 .addReg(PermuteByteOffset) // addr
6838 .addReg(RowBcast15) // data
6839 .addImm(0); // offset
6840 } else {
6841 Register PermutedValuelo =
6842 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6843 Register PermutedValuehi =
6844 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6845 MachineOperand RowBcast15Op =
6846 MachineOperand::CreateReg(RowBcast15, /*isDef=*/false);
6847 auto [RowBcast15Lo, RowBcast15Hi] =
6848 ExtractSubRegs(MI, RowBcast15Op, SrcRegClass, ST, MRI);
6849 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6850 PermutedValuelo)
6851 .addReg(PermuteByteOffset) // addr
6852 .addReg(RowBcast15Lo) // swizzle offset (i16)
6853 .addImm(0x0); // gds (i1)
6854 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6855 PermutedValuehi)
6856 .addReg(PermuteByteOffset) // addr
6857 .addReg(RowBcast15Hi) // swizzle offset (i16)
6858 .addImm(0x0); // gds (i1)
6859 BuildRegSequence(*CurrBB, MI, PermutedValue, PermutedValuelo,
6860 PermutedValuehi);
6861 }
6862 if (NeedsMovDPP)
6863 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6864 else
6865 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6866 }
6867 FinalDPPResult = RowBcast31;
6868 }
6869 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6870 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6871 Register NegatedValVGPR = MRI.createVirtualRegister(SrcRegClass);
6872 // Opc for f32 reduction is V_SUB_F32.
6873 // For f64, there is no equivalent V_SUB_F64 opcode, so use
6874 // V_ADD_F64/V_ADD_F64_pseudo, and negate the second operand.
6875 BuildMI(*CurrBB, MI, DL, TII->get(Opc),
6876 NegatedValVGPR)
6877 .addImm(SISrcMods::NONE) // src0 mods
6878 .addReg(IdentityVGPR) // src0
6879 .addImm(is32BitOpc ? SISrcMods::NONE : SISrcMods::NEG) // src1 mods
6880 .addReg(IsWave32 ? RowBcast15 : RowBcast31) // src1
6881 .addImm(SISrcMods::NONE) // clamp
6882 .addImm(SISrcMods::NONE); // omod
6883 FinalDPPResult = NegatedValVGPR;
6884 }
6885 // The final reduced value is in the last lane.
6886 if (is32BitOpc) {
6887 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6888 ReducedValSGPR)
6889 .addReg(FinalDPPResult)
6890 .addImm(ST.getWavefrontSize() - 1);
6891 } else {
6892 Register LaneValueLoReg =
6893 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6894 Register LaneValueHiReg =
6895 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6896 const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
6897 MachineOperand FinalDPPResultOperand =
6898 MachineOperand::CreateReg(FinalDPPResult, /*isDef=*/false);
6899 auto [Op1L, Op1H] =
6900 ExtractSubRegs(MI, FinalDPPResultOperand, SrcRC, ST, MRI);
6901 // lane value input should be in an sgpr
6902 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6903 LaneValueLoReg)
6904 .addReg(Op1L)
6905 .addImm(ST.getWavefrontSize() - 1);
6906 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6907 LaneValueHiReg)
6908 .addReg(Op1H)
6909 .addImm(ST.getWavefrontSize() - 1);
6910 BuildRegSequence(*CurrBB, MI, ReducedValSGPR, LaneValueLoReg,
6911 LaneValueHiReg);
6912 }
6913 if (Opc == AMDGPU::S_SUB_I32) {
6914 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6915 .addImm(0)
6916 .addReg(ReducedValSGPR)
6917 .setOperandDead(3); // Dead scc
6918 } else if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6919 auto NegatedValInstr =
6920 BuildMI(*CurrBB, MI, DL, TII->get(Opc), NegatedReducedVal)
6921 .addImm(0)
6922 .addReg(ReducedValSGPR)
6923 .setOperandDead(3); // Dead scc
6924 CurrBB = expand64BitScalarArithmetic(*NegatedValInstr, CurrBB);
6925 }
6926 // Mark the final result as a whole-wave-mode calculation.
6927 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::STRICT_WWM), DstReg)
6928 .addReg(Opc == AMDGPU::S_SUB_I32 || Opc == AMDGPU::S_SUB_U64_PSEUDO
6929 ? NegatedReducedVal
6930 : ReducedValSGPR);
6931 RetBB = CurrBB;
6932 }
6933 }
6934 MI.eraseFromParent();
6935 return RetBB;
6936}
6937
6940 MachineBasicBlock *BB) const {
6941 MachineFunction *MF = BB->getParent();
6943 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
6945 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
6947 const DebugLoc &DL = MI.getDebugLoc();
6948
6949 switch (MI.getOpcode()) {
6950 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6951 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_U32);
6952 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6953 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_U64_e64);
6954 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6955 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_I32);
6956 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6957 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_I64_e64);
6958 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6959 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MIN_F32_e64);
6960 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6961 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6962 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6963 ? AMDGPU::V_MIN_NUM_F64_e64
6964 : AMDGPU::V_MIN_F64_e64);
6965 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6966 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_U32);
6967 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6968 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_U64_e64);
6969 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6970 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_I32);
6971 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6972 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_I64_e64);
6973 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6974 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MAX_F32_e64);
6975 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6976 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6977 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6978 ? AMDGPU::V_MAX_NUM_F64_e64
6979 : AMDGPU::V_MAX_F64_e64);
6980 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6981 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_I32);
6982 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6983 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_U64_PSEUDO);
6984 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6985 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_ADD_F32_e64);
6986 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
6987 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6988 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6989 ? AMDGPU::V_ADD_F64_pseudo_e64
6990 : AMDGPU::V_ADD_F64_e64);
6991 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
6992 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_I32);
6993 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
6994 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_U64_PSEUDO);
6995 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
6996 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_SUB_F32_e64);
6997 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
6998 // There is no S/V_SUB_F64 opcode. Double type subtraction is expanded as
6999 // fadd + neg, by setting the NEG bit in the instruction.
7000 return lowerWaveReduce(MI, *BB, *getSubtarget(),
7001 ST.getGeneration() >= AMDGPUSubtarget::GFX12
7002 ? AMDGPU::V_ADD_F64_pseudo_e64
7003 : AMDGPU::V_ADD_F64_e64);
7004 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
7005 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B32);
7006 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
7007 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B64);
7008 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
7009 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B32);
7010 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
7011 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B64);
7012 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
7013 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B32);
7014 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
7015 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B64);
7016 case AMDGPU::S_UADDO_PSEUDO:
7017 case AMDGPU::S_USUBO_PSEUDO: {
7018 MachineOperand &Dest0 = MI.getOperand(0);
7019 MachineOperand &Dest1 = MI.getOperand(1);
7020 MachineOperand &Src0 = MI.getOperand(2);
7021 MachineOperand &Src1 = MI.getOperand(3);
7022
7023 unsigned Opc = (MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
7024 ? AMDGPU::S_ADD_U32
7025 : AMDGPU::S_SUB_U32;
7026 // clang-format off
7027 BuildMI(*BB, MI, DL, TII->get(Opc), Dest0.getReg())
7028 .add(Src0)
7029 .add(Src1);
7030 // clang-format on
7031
7032 unsigned SelOpc =
7033 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7034 BuildMI(*BB, MI, DL, TII->get(SelOpc), Dest1.getReg()).addImm(-1).addImm(0);
7035
7036 MI.eraseFromParent();
7037 return BB;
7038 }
7039 case AMDGPU::S_ADD_U64_PSEUDO:
7040 case AMDGPU::S_SUB_U64_PSEUDO: {
7041 return expand64BitScalarArithmetic(MI, BB);
7042 }
7043 case AMDGPU::V_ADD_U64_PSEUDO:
7044 case AMDGPU::V_SUB_U64_PSEUDO: {
7045 bool IsAdd = (MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
7046
7047 MachineOperand &Dest = MI.getOperand(0);
7048 MachineOperand &Src0 = MI.getOperand(1);
7049 MachineOperand &Src1 = MI.getOperand(2);
7050
7051 if (ST.hasAddSubU64Insts()) {
7052 auto I = BuildMI(*BB, MI, DL,
7053 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
7054 : AMDGPU::V_SUB_U64_e64),
7055 Dest.getReg())
7056 .add(Src0)
7057 .add(Src1)
7058 .addImm(0); // clamp
7059 TII->legalizeOperands(*I);
7060 MI.eraseFromParent();
7061 return BB;
7062 }
7063
7064 if (IsAdd && ST.hasLshlAddU64Inst()) {
7065 auto Add = BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_LSHL_ADD_U64_e64),
7066 Dest.getReg())
7067 .add(Src0)
7068 .addImm(0)
7069 .add(Src1);
7070 TII->legalizeOperands(*Add);
7071 MI.eraseFromParent();
7072 return BB;
7073 }
7074
7075 const auto *CarryRC = TRI->getWaveMaskRegClass();
7076
7077 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7078 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7079
7080 Register CarryReg = MRI.createVirtualRegister(CarryRC);
7081 Register DeadCarryReg = MRI.createVirtualRegister(CarryRC);
7082
7083 const TargetRegisterClass *Src0RC = Src0.isReg()
7084 ? MRI.getRegClass(Src0.getReg())
7085 : &AMDGPU::VReg_64RegClass;
7086 const TargetRegisterClass *Src1RC = Src1.isReg()
7087 ? MRI.getRegClass(Src1.getReg())
7088 : &AMDGPU::VReg_64RegClass;
7089
7090 const TargetRegisterClass *Src0SubRC =
7091 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
7092 const TargetRegisterClass *Src1SubRC =
7093 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
7094
7095 MachineOperand SrcReg0Sub0 = TII->buildExtractSubRegOrImm(
7096 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
7097 MachineOperand SrcReg1Sub0 = TII->buildExtractSubRegOrImm(
7098 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
7099
7100 MachineOperand SrcReg0Sub1 = TII->buildExtractSubRegOrImm(
7101 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
7102 MachineOperand SrcReg1Sub1 = TII->buildExtractSubRegOrImm(
7103 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
7104
7105 unsigned LoOpc =
7106 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7107 MachineInstr *LoHalf = BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0)
7108 .addReg(CarryReg, RegState::Define)
7109 .add(SrcReg0Sub0)
7110 .add(SrcReg1Sub0)
7111 .addImm(0); // clamp bit
7112
7113 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7114 MachineInstr *HiHalf =
7115 BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1)
7116 .addReg(DeadCarryReg, RegState::Define | RegState::Dead)
7117 .add(SrcReg0Sub1)
7118 .add(SrcReg1Sub1)
7119 .addReg(CarryReg)
7120 .addImm(0); // clamp bit
7121
7122 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
7123 .addReg(DestSub0)
7124 .addImm(AMDGPU::sub0)
7125 .addReg(DestSub1)
7126 .addImm(AMDGPU::sub1);
7127 TII->legalizeOperands(*LoHalf);
7128 TII->legalizeOperands(*HiHalf);
7129 MI.eraseFromParent();
7130 return BB;
7131 }
7132 case AMDGPU::S_ADD_CO_PSEUDO:
7133 case AMDGPU::S_SUB_CO_PSEUDO: {
7134 // This pseudo has a chance to be selected
7135 // only from uniform add/subcarry node. All the VGPR operands
7136 // therefore assumed to be splat vectors.
7138 MachineOperand &Dest = MI.getOperand(0);
7139 MachineOperand &CarryDest = MI.getOperand(1);
7140 MachineOperand &Src0 = MI.getOperand(2);
7141 MachineOperand &Src1 = MI.getOperand(3);
7142 MachineOperand &Src2 = MI.getOperand(4);
7143 if (Src0.isReg() && TRI->isVectorRegister(MRI, Src0.getReg())) {
7144 Register RegOp0 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7145 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7146 .addReg(Src0.getReg());
7147 Src0.setReg(RegOp0);
7148 }
7149 if (Src1.isReg() && TRI->isVectorRegister(MRI, Src1.getReg())) {
7150 Register RegOp1 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7151 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7152 .addReg(Src1.getReg());
7153 Src1.setReg(RegOp1);
7154 }
7155 Register RegOp2 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7156 if (TRI->isVectorRegister(MRI, Src2.getReg())) {
7157 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7158 .addReg(Src2.getReg());
7159 Src2.setReg(RegOp2);
7160 }
7161
7162 if (ST.isWave64()) {
7163 if (ST.hasScalarCompareEq64()) {
7164 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U64))
7165 .addReg(Src2.getReg())
7166 .addImm(0);
7167 } else {
7168 const TargetRegisterClass *Src2RC = MRI.getRegClass(Src2.getReg());
7169 const TargetRegisterClass *SubRC =
7170 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7171 MachineOperand Src2Sub0 = TII->buildExtractSubRegOrImm(
7172 MII, MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7173 MachineOperand Src2Sub1 = TII->buildExtractSubRegOrImm(
7174 MII, MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7175 Register Src2_32 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7176
7177 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_OR_B32), Src2_32)
7178 .add(Src2Sub0)
7179 .add(Src2Sub1);
7180
7181 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7182 .addReg(Src2_32)
7183 .addImm(0);
7184 }
7185 } else {
7186 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7187 .addReg(Src2.getReg())
7188 .addImm(0);
7189 }
7190
7191 unsigned Opc = MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7192 ? AMDGPU::S_ADDC_U32
7193 : AMDGPU::S_SUBB_U32;
7194
7195 BuildMI(*BB, MII, DL, TII->get(Opc), Dest.getReg()).add(Src0).add(Src1);
7196
7197 unsigned SelOpc =
7198 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7199
7200 BuildMI(*BB, MII, DL, TII->get(SelOpc), CarryDest.getReg())
7201 .addImm(-1)
7202 .addImm(0);
7203
7204 MI.eraseFromParent();
7205 return BB;
7206 }
7207 case AMDGPU::SI_INIT_M0: {
7208 MachineOperand &M0Init = MI.getOperand(0);
7209 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7210 TII->get(M0Init.isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7211 AMDGPU::M0)
7212 .add(M0Init);
7213 MI.eraseFromParent();
7214 return BB;
7215 }
7216 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7217 // Set SCC to true, in case the barrier instruction gets converted to a NOP.
7218 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7219 TII->get(AMDGPU::S_CMP_EQ_U32))
7220 .addImm(0)
7221 .addImm(0);
7222 return BB;
7223 }
7224 case AMDGPU::GET_GROUPSTATICSIZE: {
7225 assert(getTargetMachine().getTargetTriple().getOS() == Triple::AMDHSA ||
7226 getTargetMachine().getTargetTriple().getOS() == Triple::AMDPAL);
7227 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_MOV_B32))
7228 .add(MI.getOperand(0))
7229 .addImm(MFI->getLDSSize());
7230 MI.eraseFromParent();
7231 return BB;
7232 }
7233 case AMDGPU::GET_SHADERCYCLESHILO: {
7234 assert(MF->getSubtarget<GCNSubtarget>().hasShaderCyclesHiLoRegisters());
7235 // The algorithm is:
7236 //
7237 // hi1 = getreg(SHADER_CYCLES_HI)
7238 // lo1 = getreg(SHADER_CYCLES_LO)
7239 // hi2 = getreg(SHADER_CYCLES_HI)
7240 //
7241 // If hi1 == hi2 then there was no overflow and the result is hi2:lo1.
7242 // Otherwise there was overflow and the result is hi2:0. In both cases the
7243 // result should represent the actual time at some point during the sequence
7244 // of three getregs.
7245 using namespace AMDGPU::Hwreg;
7246 Register RegHi1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7247 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi1)
7248 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7249 Register RegLo1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7250 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegLo1)
7251 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7252 Register RegHi2 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7253 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi2)
7254 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7255 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CMP_EQ_U32))
7256 .addReg(RegHi1)
7257 .addReg(RegHi2);
7258 Register RegLo = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7259 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CSELECT_B32), RegLo)
7260 .addReg(RegLo1)
7261 .addImm(0);
7262 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE))
7263 .add(MI.getOperand(0))
7264 .addReg(RegLo)
7265 .addImm(AMDGPU::sub0)
7266 .addReg(RegHi2)
7267 .addImm(AMDGPU::sub1);
7268 MI.eraseFromParent();
7269 return BB;
7270 }
7271 case AMDGPU::SI_INDIRECT_SRC_V1:
7272 case AMDGPU::SI_INDIRECT_SRC_V2:
7273 case AMDGPU::SI_INDIRECT_SRC_V3:
7274 case AMDGPU::SI_INDIRECT_SRC_V4:
7275 case AMDGPU::SI_INDIRECT_SRC_V5:
7276 case AMDGPU::SI_INDIRECT_SRC_V6:
7277 case AMDGPU::SI_INDIRECT_SRC_V7:
7278 case AMDGPU::SI_INDIRECT_SRC_V8:
7279 case AMDGPU::SI_INDIRECT_SRC_V9:
7280 case AMDGPU::SI_INDIRECT_SRC_V10:
7281 case AMDGPU::SI_INDIRECT_SRC_V11:
7282 case AMDGPU::SI_INDIRECT_SRC_V12:
7283 case AMDGPU::SI_INDIRECT_SRC_V16:
7284 case AMDGPU::SI_INDIRECT_SRC_V32:
7285 return emitIndirectSrc(MI, *BB, *getSubtarget());
7286 case AMDGPU::SI_INDIRECT_DST_V1:
7287 case AMDGPU::SI_INDIRECT_DST_V2:
7288 case AMDGPU::SI_INDIRECT_DST_V3:
7289 case AMDGPU::SI_INDIRECT_DST_V4:
7290 case AMDGPU::SI_INDIRECT_DST_V5:
7291 case AMDGPU::SI_INDIRECT_DST_V6:
7292 case AMDGPU::SI_INDIRECT_DST_V7:
7293 case AMDGPU::SI_INDIRECT_DST_V8:
7294 case AMDGPU::SI_INDIRECT_DST_V9:
7295 case AMDGPU::SI_INDIRECT_DST_V10:
7296 case AMDGPU::SI_INDIRECT_DST_V11:
7297 case AMDGPU::SI_INDIRECT_DST_V12:
7298 case AMDGPU::SI_INDIRECT_DST_V16:
7299 case AMDGPU::SI_INDIRECT_DST_V32:
7300 return emitIndirectDst(MI, *BB, *getSubtarget());
7301 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7302 case AMDGPU::SI_KILL_I1_PSEUDO:
7303 return splitKillBlock(MI, BB);
7304 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7306 return BB;
7307 }
7308 case AMDGPU::SI_BR_UNDEF: {
7309 MachineInstr *Br = BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
7310 .add(MI.getOperand(0));
7311 Br->getOperand(1).setIsUndef(); // read undef SCC
7312 MI.eraseFromParent();
7313 return BB;
7314 }
7315 case AMDGPU::ADJCALLSTACKUP:
7316 case AMDGPU::ADJCALLSTACKDOWN: {
7318 MachineInstrBuilder MIB(*MF, &MI);
7319 MIB.addReg(Info->getStackPtrOffsetReg(), RegState::ImplicitDefine)
7320 .addReg(Info->getStackPtrOffsetReg(), RegState::Implicit);
7321 return BB;
7322 }
7323 case AMDGPU::SI_CALL_ISEL: {
7324 unsigned ReturnAddrReg = TII->getRegisterInfo().getReturnAddressReg(*MF);
7325
7327 MIB = BuildMI(*BB, MI, DL, TII->get(AMDGPU::SI_CALL))
7328 .addDef(ReturnAddrReg, RegState::Dead);
7329
7330 for (const MachineOperand &MO : MI.operands())
7331 MIB.add(MO);
7332
7333 MIB.cloneMemRefs(MI);
7334 MIB.setMIFlags(MI.getFlags());
7335 MI.eraseFromParent();
7336 return BB;
7337 }
7338 case AMDGPU::V_ADDC_U32_e32:
7339 case AMDGPU::V_SUBB_U32_e32:
7340 case AMDGPU::V_SUBBREV_U32_e32:
7341 // These instructions have an implicit use of vcc which counts towards the
7342 // constant bus limit.
7343 TII->legalizeOperands(MI);
7344 return BB;
7345 case AMDGPU::DS_GWS_INIT:
7346 case AMDGPU::DS_GWS_SEMA_BR:
7347 case AMDGPU::DS_GWS_BARRIER:
7348 case AMDGPU::DS_GWS_SEMA_V:
7349 case AMDGPU::DS_GWS_SEMA_P:
7350 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7351 // A s_waitcnt 0 is required to be the instruction immediately following.
7352 if (getSubtarget()->hasGWSAutoReplay()) {
7354 return BB;
7355 }
7356
7357 return emitGWSMemViolTestLoop(MI, BB);
7358 case AMDGPU::S_SETREG_B32: {
7359 // Try to optimize cases that only set the denormal mode or rounding mode.
7360 //
7361 // If the s_setreg_b32 fully sets all of the bits in the rounding mode or
7362 // denormal mode to a constant, we can use s_round_mode or s_denorm_mode
7363 // instead.
7364 //
7365 // FIXME: This could be predicates on the immediate, but tablegen doesn't
7366 // allow you to have a no side effect instruction in the output of a
7367 // sideeffecting pattern.
7368 auto [ID, Offset, Width] =
7369 AMDGPU::Hwreg::HwregEncoding::decode(MI.getOperand(1).getImm());
7370 if (ID != AMDGPU::Hwreg::ID_MODE)
7371 return BB;
7372
7373 const unsigned WidthMask = maskTrailingOnes<unsigned>(Width);
7374 const unsigned SetMask = WidthMask << Offset;
7375
7376 if (getSubtarget()->hasDenormModeInst()) {
7377 unsigned SetDenormOp = 0;
7378 unsigned SetRoundOp = 0;
7379
7380 // The dedicated instructions can only set the whole denorm or round mode
7381 // at once, not a subset of bits in either.
7382 if (SetMask ==
7384 // If this fully sets both the round and denorm mode, emit the two
7385 // dedicated instructions for these.
7386 SetRoundOp = AMDGPU::S_ROUND_MODE;
7387 SetDenormOp = AMDGPU::S_DENORM_MODE;
7388 } else if (SetMask == AMDGPU::Hwreg::FP_ROUND_MASK) {
7389 SetRoundOp = AMDGPU::S_ROUND_MODE;
7390 } else if (SetMask == AMDGPU::Hwreg::FP_DENORM_MASK) {
7391 SetDenormOp = AMDGPU::S_DENORM_MODE;
7392 }
7393
7394 if (SetRoundOp || SetDenormOp) {
7395 MachineInstr *Def = MRI.getVRegDef(MI.getOperand(0).getReg());
7396 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7397 unsigned ImmVal = Def->getOperand(1).getImm();
7398 if (SetRoundOp) {
7399 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetRoundOp))
7400 .addImm(ImmVal & 0xf);
7401
7402 // If we also have the denorm mode, get just the denorm mode bits.
7403 ImmVal >>= 4;
7404 }
7405
7406 if (SetDenormOp) {
7407 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetDenormOp))
7408 .addImm(ImmVal & 0xf);
7409 }
7410
7411 MI.eraseFromParent();
7412 return BB;
7413 }
7414 }
7415 }
7416
7417 // If only FP bits are touched, used the no side effects pseudo.
7418 if ((SetMask & (AMDGPU::Hwreg::FP_ROUND_MASK |
7419 AMDGPU::Hwreg::FP_DENORM_MASK)) == SetMask)
7420 MI.setDesc(TII->get(AMDGPU::S_SETREG_B32_mode));
7421
7422 return BB;
7423 }
7424 case AMDGPU::S_INVERSE_BALLOT_U32:
7425 case AMDGPU::S_INVERSE_BALLOT_U64:
7426 // These opcodes only exist to let SIFixSGPRCopies insert a readfirstlane if
7427 // necessary. After that they are equivalent to a COPY.
7428 MI.setDesc(TII->get(AMDGPU::COPY));
7429 return BB;
7430 case AMDGPU::ENDPGM_TRAP: {
7431 if (BB->succ_empty() && std::next(MI.getIterator()) == BB->end()) {
7432 MI.setDesc(TII->get(AMDGPU::S_ENDPGM));
7433 MI.addOperand(MachineOperand::CreateImm(0));
7434 return BB;
7435 }
7436
7437 // We need a block split to make the real endpgm a terminator. We also don't
7438 // want to break phis in successor blocks, so we can't just delete to the
7439 // end of the block.
7440
7441 MachineBasicBlock *SplitBB = BB->splitAt(MI, false /*UpdateLiveIns*/);
7443 MF->push_back(TrapBB);
7444 // clang-format off
7445 BuildMI(*TrapBB, TrapBB->end(), DL, TII->get(AMDGPU::S_ENDPGM))
7446 .addImm(0);
7447 BuildMI(*BB, &MI, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
7448 .addMBB(TrapBB);
7449 // clang-format on
7450
7451 BB->addSuccessor(TrapBB);
7452 MI.eraseFromParent();
7453 return SplitBB;
7454 }
7455 case AMDGPU::SIMULATED_TRAP: {
7456 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7457 MachineBasicBlock *SplitBB =
7458 TII->insertSimulatedTrap(MRI, *BB, MI, MI.getDebugLoc());
7459 MI.eraseFromParent();
7460 return SplitBB;
7461 }
7462 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7463 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7465
7466 // During ISel, it's difficult to propagate the original EXEC mask to use as
7467 // an input to SI_WHOLE_WAVE_FUNC_RETURN. Set it up here instead.
7468 MachineInstr *Setup = TII->getWholeWaveFunctionSetup(*BB->getParent());
7469 assert(Setup && "Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7470 Register OriginalExec = Setup->getOperand(0).getReg();
7471 MI.getOperand(0).setReg(OriginalExec);
7472 return BB;
7473 }
7474 case AMDGPU::V_DOT2_F32_F16:
7475 case AMDGPU::V_DOT2_F32_BF16: {
7476 // Hint RA to assign dst and src2 the same physical register.
7477 // For targets without VOP2, but with VOPD, variant of the instruction this
7478 // is one of the conditions to attempt converting VOP3P to VOPD.
7479 MRI.setSimpleHint(MI.getOperand(0).getReg(), MI.getOperand(6).getReg());
7480 return BB;
7481 }
7482 case AMDGPU::SCHED_BARRIER:
7483 case AMDGPU::SCHED_GROUP_BARRIER:
7484 MI.getOperand(0).setImm(MI.getOperand(0).getImm() &
7485 static_cast<unsigned>(AMDGPU::SchedGroupMask::ALL));
7486 return BB;
7487 default:
7488 if (TII->isImage(MI) || TII->isMUBUF(MI)) {
7489 if (!MI.mayStore())
7491 return BB;
7492 }
7494 }
7495}
7496
7498 // This currently forces unfolding various combinations of fsub into fma with
7499 // free fneg'd operands. As long as we have fast FMA (controlled by
7500 // isFMAFasterThanFMulAndFAdd), we should perform these.
7501
7502 // When fma is quarter rate, for f64 where add / sub are at best half rate,
7503 // most of these combines appear to be cycle neutral but save on instruction
7504 // count / code size.
7505 return true;
7506}
7507
7509
7511 EVT VT) const {
7512 if (!VT.isVector()) {
7513 return MVT::i1;
7514 }
7515 return EVT::getVectorVT(Ctx, MVT::i1, VT.getVectorNumElements());
7516}
7517
7519 // TODO: Should i16 be used always if legal? For now it would force VALU
7520 // shifts.
7521 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7522}
7523
7525 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7526 ? Ty.changeElementSize(16)
7527 : Ty.changeElementSize(32);
7528}
7529
7530// Answering this is somewhat tricky and depends on the specific device which
7531// have different rates for fma or all f64 operations.
7532//
7533// v_fma_f64 and v_mul_f64 always take the same number of cycles as each other
7534// regardless of which device (although the number of cycles differs between
7535// devices), so it is always profitable for f64.
7536//
7537// v_fma_f32 takes 4 or 16 cycles depending on the device, so it is profitable
7538// only on full rate devices. Normally, we should prefer selecting v_mad_f32
7539// which we can always do even without fused FP ops since it returns the same
7540// result as the separate operations and since it is always full
7541// rate. Therefore, we lie and report that it is not faster for f32. v_mad_f32
7542// however does not support denormals, so we do report fma as faster if we have
7543// a fast fma device and require denormals.
7544//
7546 DenormalFPEnv FPEnv) const {
7547 VT = VT.getScalarType();
7548 if (!VT.isSimple())
7549 return false;
7550
7551 switch (VT.getSimpleVT().SimpleTy) {
7552 case MVT::f32: {
7553 // If mad is not available this depends only on if f32 fma is full rate.
7554 if (!Subtarget->hasMadMacF32Insts())
7555 return Subtarget->hasFastFMAF32();
7556
7557 // Otherwise f32 mad is always full rate and returns the same result as
7558 // the separate operations so should be preferred over fma.
7559 // However does not support denormals.
7561 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7562
7563 // If the subtarget has v_fmac_f32, that's just as good as v_mac_f32.
7564 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7565 }
7566 case MVT::f64:
7567 return true;
7568 case MVT::f16:
7569 case MVT::bf16:
7570 return Subtarget->has16BitInsts() &&
7572 default:
7573 break;
7574 }
7575
7576 return false;
7577}
7578
7583
7585 Type *Ty) const {
7587 getValueType(F.getDataLayout(), Ty, /*AllowUnknown=*/true),
7588 F.getDenormalFPEnv());
7589}
7590
7592 LLT Ty) const {
7593 switch (Ty.getScalarSizeInBits()) {
7594 case 16:
7595 return isFMAFasterThanFMulAndFAdd(MF, MVT::f16);
7596 case 32:
7597 return isFMAFasterThanFMulAndFAdd(MF, MVT::f32);
7598 case 64:
7599 return isFMAFasterThanFMulAndFAdd(MF, MVT::f64);
7600 default:
7601 break;
7602 }
7603
7604 return false;
7605}
7606
7608 // TODO: Check future ftz flag
7609 // v_mad_f32/v_mac_f32 do not support denormals.
7610 if (VT == MVT::f32)
7611 return Subtarget->hasMadMacF32Insts() &&
7613 if (VT == MVT::f16)
7614 return Subtarget->hasMadF16() &&
7616
7617 return false;
7618}
7619
7621 if (!Ty.isScalar())
7622 return false;
7623
7624 DenormalFPEnv FPEnv = getDenormalFPEnv(*MI.getMF());
7625 if (Ty.getScalarSizeInBits() == 16)
7626 return isFMADLegal(MVT::f16, FPEnv);
7627 if (Ty.getScalarSizeInBits() == 32)
7628 return isFMADLegal(MVT::f32, FPEnv);
7629
7630 return false;
7631}
7632
7634 const SDNode *N) const {
7635 return isFMADLegal(N->getValueType(0),
7637}
7638
7640 return isFMADLegal(getValueType(F.getDataLayout(), Ty->getScalarType(),
7641 /*AllowUnknown=*/true),
7642 F.getDenormalFPEnv());
7643}
7644
7645//===----------------------------------------------------------------------===//
7646// Custom DAG Lowering Operations
7647//===----------------------------------------------------------------------===//
7648
7649// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7650// wider vector type is legal.
7652 SelectionDAG &DAG) const {
7653 unsigned Opc = Op.getOpcode();
7654 EVT VT = Op.getValueType();
7656
7657 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
7658 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VT);
7659
7660 SDLoc SL(Op);
7661
7662 // Forward any trailing scalar operands unchanged to both halves.
7663 SmallVector<SDValue, 2> LoOps = {Lo};
7664 SmallVector<SDValue, 2> HiOps = {Hi};
7665 auto TrailingOps = drop_begin(Op->ops());
7666 LoOps.append(TrailingOps.begin(), TrailingOps.end());
7667 HiOps.append(TrailingOps.begin(), TrailingOps.end());
7668
7669 SDValue OpLo = DAG.getNode(Opc, SL, LoVT, LoOps, Op->getFlags());
7670 SDValue OpHi = DAG.getNode(Opc, SL, HiVT, HiOps, Op->getFlags());
7671
7672 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7673}
7674
7675// Enable lowering of ROTR for vxi32 types. This is a workaround for a
7676// regression whereby extra unnecessary instructions were added to codegen
7677// for rotr operations, casued by legalising v2i32 or. This resulted in extra
7678// instructions to extract the result from the vector.
7680 [[maybe_unused]] EVT VT = Op.getValueType();
7681
7682 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7683 VT == MVT::v16i32) &&
7684 "Unexpected ValueType.");
7685
7686 return DAG.UnrollVectorOp(Op.getNode());
7687}
7688
7689// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7690// wider vector type is legal.
7692 SelectionDAG &DAG) const {
7693 unsigned Opc = Op.getOpcode();
7694 EVT VT = Op.getValueType();
7696
7697 auto [Lo0, Hi0] = DAG.SplitVectorOperand(Op.getNode(), 0);
7698 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7699
7700 SDLoc SL(Op);
7701
7702 SDValue OpLo =
7703 DAG.getNode(Opc, SL, Lo0.getValueType(), Lo0, Lo1, Op->getFlags());
7704 SDValue OpHi =
7705 DAG.getNode(Opc, SL, Hi0.getValueType(), Hi0, Hi1, Op->getFlags());
7706
7707 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7708}
7709
7711 SelectionDAG &DAG) const {
7712 unsigned Opc = Op.getOpcode();
7713 EVT VT = Op.getValueType();
7715
7716 SDValue Op0 = Op.getOperand(0);
7717 SDValue Lo0, Hi0;
7718 if (Op0.getValueType().isVector())
7719 std::tie(Lo0, Hi0) = DAG.SplitVectorOperand(Op.getNode(), 0);
7720 else
7721 Lo0 = Hi0 = DAG.getFreeze(Op0);
7722
7723 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7724 auto [Lo2, Hi2] = DAG.SplitVectorOperand(Op.getNode(), 2);
7725
7726 SDLoc SL(Op);
7727 auto ResVT = DAG.GetSplitDestVTs(VT);
7728
7729 SDValue OpLo =
7730 DAG.getNode(Opc, SL, ResVT.first, Lo0, Lo1, Lo2, Op->getFlags());
7731 SDValue OpHi =
7732 DAG.getNode(Opc, SL, ResVT.second, Hi0, Hi1, Hi2, Op->getFlags());
7733
7734 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7735}
7736
7738 switch (Op.getOpcode()) {
7739 default:
7741 case ISD::BRCOND:
7742 return LowerBRCOND(Op, DAG);
7743 case ISD::RETURNADDR:
7744 return LowerRETURNADDR(Op, DAG);
7745 case ISD::SPONENTRY:
7746 return LowerSPONENTRY(Op, DAG);
7747 case ISD::LOAD: {
7748 SDValue Result = LowerLOAD(Op, DAG);
7749 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7750 "Load should return a value and a chain");
7751 return Result;
7752 }
7753 case ISD::FSQRT: {
7754 EVT VT = Op.getValueType();
7755 if (VT == MVT::f32)
7756 return lowerFSQRTF32(Op, DAG);
7757 if (VT == MVT::f64)
7758 return lowerFSQRTF64(Op, DAG);
7759 return SDValue();
7760 }
7761 case ISD::FSIN:
7762 case ISD::FCOS:
7763 return LowerTrig(Op, DAG);
7764 case ISD::SELECT:
7765 return LowerSELECT(Op, DAG);
7766 case ISD::FDIV:
7767 return LowerFDIV(Op, DAG);
7768 case ISD::FFREXP:
7769 return LowerFFREXP(Op, DAG);
7771 return LowerATOMIC_CMP_SWAP(Op, DAG);
7772 case ISD::STORE:
7773 return LowerSTORE(Op, DAG);
7774 case ISD::GlobalAddress: {
7777 return LowerGlobalAddress(MFI, Op, DAG);
7778 }
7779 case ISD::BlockAddress:
7780 return LowerBlockAddress(Op, DAG);
7782 return LowerExternalSymbol(Op, DAG);
7784 return LowerINTRINSIC_WO_CHAIN(Op, DAG);
7786 return LowerCONVERT_FROM_ARBITRARY_FP(Op, DAG);
7788 return LowerCONVERT_TO_ARBITRARY_FP(Op, DAG);
7790 return LowerINTRINSIC_W_CHAIN(Op, DAG);
7792 return LowerINTRINSIC_VOID(Op, DAG);
7793 case ISD::ADDRSPACECAST:
7794 return lowerADDRSPACECAST(Op, DAG);
7796 return lowerINSERT_SUBVECTOR(Op, DAG);
7798 return lowerINSERT_VECTOR_ELT(Op, DAG);
7800 return lowerEXTRACT_VECTOR_ELT(Op, DAG);
7802 return lowerVECTOR_SHUFFLE(Op, DAG);
7804 return lowerSCALAR_TO_VECTOR(Op, DAG);
7805 case ISD::BUILD_VECTOR:
7806 return lowerBUILD_VECTOR(Op, DAG);
7807 case ISD::FP_ROUND:
7809 return lowerFP_ROUND(Op, DAG);
7810 case ISD::TRAP:
7811 return lowerTRAP(Op, DAG);
7812 case ISD::DEBUGTRAP:
7813 return lowerDEBUGTRAP(Op, DAG);
7814 case ISD::ABS:
7815 case ISD::FABS:
7816 case ISD::FNEG:
7817 case ISD::FCANONICALIZE:
7818 case ISD::BSWAP:
7819 return splitUnaryVectorOp(Op, DAG);
7822 if (Op.getValueType().isVector() && Op.getValueType() != MVT::v2i16 &&
7823 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7824 return splitUnaryVectorOp(Op, DAG);
7825 return LowerFP_TO_INT_SAT(Op, DAG);
7826 case ISD::FSUB:
7827 if (Op.getValueType() == MVT::bf16) {
7828 // Custom expansion:
7829 // fsub bf16 %a, %b -> fadd v2bf16(widen %a), fneg v2bf16(widen %b)
7830 // Then extract back to bf16.
7831 //
7832 // We create fneg on v2bf16 (not bf16) so the instruction selector can
7833 // fold the negation into the packed add's neg_lo/neg_hi modifiers,
7834 // generating a single v_pk_add_bf16 instruction. If we negate bf16 first,
7835 // it becomes a separate v_xor instruction before widening.
7836 SDLoc DL(Op);
7837 SDValue Op0 = Op.getOperand(0);
7838 SDValue Op1 = Op.getOperand(1);
7839
7840 // Widen both operands to v2bf16
7841 SDValue Vec0 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op0);
7842 SDValue Vec1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op1);
7843
7844 // Create FNEG v2bf16 for the second operand
7845 SDValue NegVec1 = DAG.getNode(ISD::FNEG, DL, MVT::v2bf16, Vec1);
7846
7847 // Perform FADD v2bf16
7848 SDValue Result = DAG.getNode(ISD::FADD, DL, MVT::v2bf16, Vec0, NegVec1);
7849
7850 // Extract element 0 back to bf16
7851 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::bf16, Result,
7852 DAG.getConstant(0, DL, MVT::i32));
7853 }
7854 return SDValue();
7855 case ISD::FMINNUM:
7856 case ISD::FMAXNUM:
7857 return lowerFMINNUM_FMAXNUM(Op, DAG);
7858 case ISD::FMINIMUMNUM:
7859 case ISD::FMAXIMUMNUM:
7860 return lowerFMINIMUMNUM_FMAXIMUMNUM(Op, DAG);
7861 case ISD::FLDEXP:
7862 case ISD::STRICT_FLDEXP:
7863 return lowerFLDEXP(Op, DAG);
7864 case ISD::FMA:
7865 return splitTernaryVectorOp(Op, DAG);
7866 case ISD::FP_TO_SINT:
7867 case ISD::FP_TO_UINT:
7868 if (Subtarget->hasVCvtPkIU16F32() && Op.getValueType() == MVT::i16 &&
7869 Op.getOperand(0).getValueType() == MVT::f32) {
7870 // Make f32->i16 legal so we can select V_CVT_PK_[IU]16_F32.
7871 return Op;
7872 }
7873 return LowerFP_TO_INT(Op, DAG);
7874 case ISD::SHL:
7875 case ISD::SRA:
7876 case ISD::SRL:
7877 case ISD::ADD:
7878 case ISD::SUB:
7879 case ISD::SMIN:
7880 case ISD::SMAX:
7881 case ISD::UMIN:
7882 case ISD::UMAX:
7883 case ISD::FMINNUM_IEEE:
7884 case ISD::FMAXNUM_IEEE:
7885 case ISD::FMINIMUM:
7886 case ISD::FMAXIMUM:
7887 case ISD::UADDSAT:
7888 case ISD::USUBSAT:
7889 case ISD::SADDSAT:
7890 case ISD::SSUBSAT:
7891 case ISD::FADD:
7892 case ISD::FMUL:
7893 return splitBinaryVectorOp(Op, DAG);
7894 case ISD::FCOPYSIGN:
7895 return lowerFCOPYSIGN(Op, DAG);
7896 case ISD::MUL:
7897 return lowerMUL(Op, DAG);
7898 case ISD::SMULO:
7899 case ISD::UMULO:
7900 return lowerXMULO(Op, DAG);
7901 case ISD::SMUL_LOHI:
7902 case ISD::UMUL_LOHI:
7903 return lowerXMUL_LOHI(Op, DAG);
7905 return LowerDYNAMIC_STACKALLOC(Op, DAG);
7906 case ISD::STACKSAVE:
7907 return LowerSTACKSAVE(Op, DAG);
7908 case ISD::GET_ROUNDING:
7909 return lowerGET_ROUNDING(Op, DAG);
7910 case ISD::SET_ROUNDING:
7911 return lowerSET_ROUNDING(Op, DAG);
7912 case ISD::PREFETCH:
7913 return lowerPREFETCH(Op, DAG);
7914 case ISD::FP_EXTEND:
7916 return lowerFP_EXTEND(Op, DAG);
7917 case ISD::GET_FPENV:
7918 return lowerGET_FPENV(Op, DAG);
7919 case ISD::SET_FPENV:
7920 return lowerSET_FPENV(Op, DAG);
7921 case ISD::ROTR:
7922 return lowerROTR(Op, DAG);
7923 case ISD::INLINEASM:
7924 return LowerINLINEASM(Op, DAG);
7925 }
7926 return SDValue();
7927}
7928
7929// TFE results are dword granular: value dwords followed by one status dword.
7930static std::pair<SDValue, SDValue>
7932 LLVMContext &C = *DAG.getContext();
7933 unsigned NumValueDWords = divideCeil(VT.getSizeInBits(), 32);
7935 DAG.getVectorIdxConstant(NumValueDWords, DL));
7936 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, DL);
7937 SDValue ValueDWords =
7938 NumValueDWords == 1
7939 ? DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op, ZeroIdx)
7941 EVT::getVectorVT(C, MVT::i32, NumValueDWords), Op,
7942 ZeroIdx);
7943 if (!VT.isVector() && VT.getSizeInBits() < 32)
7944 ValueDWords =
7945 DAG.getNode(ISD::TRUNCATE, DL, VT.changeTypeToInteger(), ValueDWords);
7946 return {DAG.getNode(ISD::BITCAST, DL, VT, ValueDWords), Status};
7947}
7948
7949// Used for D16: Casts the result of an instruction into the right vector,
7950// packs values if loads return unpacked values.
7952 const SDLoc &DL, SelectionDAG &DAG,
7953 bool Unpacked) {
7954 if (!LoadVT.isVector())
7955 return Result;
7956
7957 // Cast back to the original packed type or to a larger type that is a
7958 // multiple of 32 bit for D16. Widening the return type is a required for
7959 // legalization.
7960 EVT FittingLoadVT = LoadVT;
7961 if ((LoadVT.getVectorNumElements() % 2) == 1) {
7962 FittingLoadVT =
7964 LoadVT.getVectorNumElements() + 1);
7965 }
7966
7967 if (Unpacked) { // From v2i32/v4i32 back to v2f16/v4f16.
7968 // Truncate to v2i16/v4i16.
7969 EVT IntLoadVT = FittingLoadVT.changeTypeToInteger();
7970
7971 // Workaround legalizer not scalarizing truncate after vector op
7972 // legalization but not creating intermediate vector trunc.
7974 DAG.ExtractVectorElements(Result, Elts);
7975 for (SDValue &Elt : Elts)
7976 Elt = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Elt);
7977
7978 // Pad illegal v1i16/v3fi6 to v4i16
7979 if ((LoadVT.getVectorNumElements() % 2) == 1)
7980 Elts.push_back(DAG.getPOISON(MVT::i16));
7981
7982 Result = DAG.getBuildVector(IntLoadVT, DL, Elts);
7983
7984 // Bitcast to original type (v2f16/v4f16).
7985 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
7986 }
7987
7988 // Cast back to the original packed type.
7989 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
7990}
7991
7992SDValue SITargetLowering::adjustLoadValueType(unsigned Opcode, MemSDNode *M,
7993 SelectionDAG &DAG,
7995 bool IsIntrinsic) const {
7996 SDLoc DL(M);
7997
7998 bool IsTFE = M->getNumValues() == 3;
7999 bool Unpacked = Subtarget->hasUnpackedD16VMem();
8000 EVT LoadVT = M->getValueType(0);
8001
8002 EVT EquivLoadVT = LoadVT;
8003 if (LoadVT.isVector()) {
8004 if (Unpacked) {
8005 EquivLoadVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
8006 LoadVT.getVectorNumElements());
8007 } else if ((LoadVT.getVectorNumElements() % 2) == 1) {
8008 // Widen v3f16 to legal type
8009 EquivLoadVT =
8011 LoadVT.getVectorNumElements() + 1);
8012 }
8013 }
8014
8015 if (IsTFE) {
8016 unsigned NumValueDWords = divideCeil(EquivLoadVT.getSizeInBits(), 32);
8017 EVT LoadDWordsVT =
8018 EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumValueDWords + 1);
8019 SDVTList VTList = DAG.getVTList(LoadDWordsVT, MVT::Other);
8021 Opcode, DL, VTList, Ops, M->getMemoryVT(), M->getMemOperand());
8022 auto [Value, Status] = splitTFEValueAndStatus(Load, EquivLoadVT, DL, DAG);
8023 SDValue Adjusted =
8024 adjustLoadValueTypeImpl(Value, LoadVT, DL, DAG, Unpacked);
8025 return DAG.getMergeValues({Adjusted, Status, Load.getValue(1)}, DL);
8026 }
8027
8028 // Change from v4f16/v2f16 to EquivLoadVT.
8029 SDVTList VTList = DAG.getVTList(EquivLoadVT, MVT::Other);
8030
8032 IsIntrinsic ? (unsigned)ISD::INTRINSIC_W_CHAIN : Opcode, DL, VTList, Ops,
8033 M->getMemoryVT(), M->getMemOperand());
8034
8035 SDValue Adjusted = adjustLoadValueTypeImpl(Load, LoadVT, DL, DAG, Unpacked);
8036
8037 return DAG.getMergeValues({Adjusted, Load.getValue(1)}, DL);
8038}
8039
8040SDValue SITargetLowering::lowerIntrinsicLoad(MemSDNode *M, bool IsFormat,
8041 SelectionDAG &DAG,
8042 ArrayRef<SDValue> Ops) const {
8043 SDLoc DL(M);
8044 EVT LoadVT = M->getValueType(0);
8045 EVT EltType = LoadVT.getScalarType();
8046 EVT IntVT = LoadVT.changeTypeToInteger();
8047
8048 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
8049
8050 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
8051 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
8053 "unsupported sub-dword format buffer load", DL.getDebugLoc()));
8054 return DAG.getMergeValues({DAG.getPOISON(LoadVT), M->getOperand(0)}, DL);
8055 }
8056
8057 assert(M->getNumValues() == 2 || M->getNumValues() == 3);
8058 bool IsTFE = M->getNumValues() == 3;
8059
8060 if (IsD16 && IsTFE && !Subtarget->hasBufferTFEFormatD16()) {
8061 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
8063 "TFE D16 format buffer load is not supported on this GPU",
8064 DL.getDebugLoc()));
8065 return DAG.getErrorMergeValues({M->value_begin(), M->value_end()},
8066 M->getOperand(0), DL);
8067 }
8068
8069 unsigned Opc = IsD16 ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_D16_TFE
8070 : AMDGPUISD::BUFFER_LOAD_FORMAT_D16)
8071 : IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
8072 : AMDGPUISD::BUFFER_LOAD_FORMAT)
8073 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
8074 : AMDGPUISD::BUFFER_LOAD;
8075
8076 if (IsD16)
8077 return adjustLoadValueType(Opc, M, DAG, Ops);
8078
8079 // Handle BUFFER_LOAD_BYTE/UBYTE/SHORT/USHORT overloaded intrinsics
8080 if (!IsD16 && !LoadVT.isVector() && EltType.getSizeInBits() < 32)
8081 return handleByteShortBufferLoads(DAG, LoadVT, DL, Ops, M->getMemOperand(),
8082 IsTFE);
8083
8084 if (isTypeLegal(LoadVT)) {
8085 return getMemIntrinsicNode(Opc, DL, M->getVTList(), Ops, IntVT,
8086 M->getMemOperand(), DAG);
8087 }
8088
8089 EVT CastVT = getEquivalentMemType(*DAG.getContext(), LoadVT);
8090 SDVTList VTList = IsTFE ? DAG.getVTList(CastVT, MVT::i32, MVT::Other)
8091 : DAG.getVTList(CastVT, MVT::Other);
8092 SDValue MemNode = getMemIntrinsicNode(Opc, DL, VTList, Ops, CastVT,
8093 M->getMemOperand(), DAG);
8094 SDValue Data = DAG.getNode(ISD::BITCAST, DL, LoadVT, MemNode);
8095 if (IsTFE)
8096 return DAG.getMergeValues({Data, MemNode.getValue(1), MemNode.getValue(2)},
8097 DL);
8098 return DAG.getMergeValues({Data, MemNode.getValue(1)}, DL);
8099}
8100
8102 SelectionDAG &DAG) {
8103 EVT VT = N->getValueType(0);
8104 SDValue Src = N->getOperand(1);
8105 SDLoc SL(N);
8106
8107 if (Src.getOpcode() == ISD::SETCC) {
8108 SDValue Op0 = Src.getOperand(0);
8109 SDValue Op1 = Src.getOperand(1);
8110 // Need to expand bfloat to float for comparison (setcc).
8111 if (Op0.getValueType() == MVT::bf16) {
8112 Op0 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op0);
8113 Op1 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op1);
8114 }
8115 // (ballot (ISD::SETCC ...)) -> (AMDGPUISD::SETCC ...)
8116 return DAG.getNode(AMDGPUISD::SETCC, SL, VT, Op0, Op1, Src.getOperand(2));
8117 }
8118 if (const ConstantSDNode *Arg = dyn_cast<ConstantSDNode>(Src)) {
8119 // (ballot 0) -> 0
8120 if (Arg->isZero())
8121 return DAG.getConstant(0, SL, VT);
8122
8123 // (ballot 1) -> EXEC/EXEC_LO
8124 if (Arg->isOne()) {
8125 Register Exec;
8126 if (VT.getScalarSizeInBits() == 32)
8127 Exec = AMDGPU::EXEC_LO;
8128 else if (VT.getScalarSizeInBits() == 64)
8129 Exec = AMDGPU::EXEC;
8130 else
8131 return SDValue();
8132
8133 return DAG.getCopyFromReg(DAG.getEntryNode(), SL, Exec, VT);
8134 }
8135 }
8136
8137 // (ballot (i1 $src)) -> (AMDGPUISD::SETCC (i32 (zext $src)) (i32 0)
8138 // ISD::SETNE)
8139 return DAG.getNode(
8140 AMDGPUISD::SETCC, SL, VT, DAG.getZExtOrTrunc(Src, SL, MVT::i32),
8141 DAG.getConstant(0, SL, MVT::i32), DAG.getCondCode(ISD::SETNE));
8142}
8143
8145 Intrinsic::ID IntrinsicID) {
8146 bool Signed = IntrinsicID == Intrinsic::amdgcn_sbfe;
8147 SDLoc DL(Op);
8148 EVT VT = Op.getValueType();
8149 SDValue Src = Op.getOperand(1);
8150 SDValue Offset = Op.getOperand(2);
8151 SDValue Width = Op.getOperand(3);
8152
8153 if (VT != MVT::i32) {
8156 Twine(Intrinsic::getBaseName(IntrinsicID)) + " only supports i32",
8157 DL.getDebugLoc()));
8158 return DAG.getPOISON(VT);
8159 }
8160
8161 return DAG.getNode(Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32, DL, VT,
8162 Src, Offset, Width);
8163}
8164
8166 EVT VT);
8167
8169 SelectionDAG &DAG) {
8170 EVT VT = N->getValueType(0);
8171 unsigned ValSize = VT.getSizeInBits();
8172 unsigned IID = N->getConstantOperandVal(0);
8173 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8174 IID == Intrinsic::amdgcn_permlanex16;
8175 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8176 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8177 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8178 IID == Intrinsic::amdgcn_permlane_up ||
8179 IID == Intrinsic::amdgcn_permlane_down ||
8180 IID == Intrinsic::amdgcn_permlane_xor;
8181 SDLoc SL(N);
8182 MVT IntVT = MVT::getIntegerVT(ValSize);
8183 const GCNSubtarget *ST = TLI.getSubtarget();
8184
8185 unsigned SplitSize = 32;
8186 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8187 ST->hasDPALU_DPP() &&
8188 AMDGPU::isLegalDPALU_DPPControl(*ST, N->getConstantOperandVal(3)))
8189 SplitSize = 64;
8190
8191 auto createLaneOp = [&DAG, &SL, N, IID](SDValue Src0, SDValue Src1,
8192 SDValue Src2, MVT ValT) -> SDValue {
8194 switch (IID) {
8195 case Intrinsic::amdgcn_permlane16:
8196 case Intrinsic::amdgcn_permlanex16:
8197 case Intrinsic::amdgcn_update_dpp:
8198 Operands.push_back(N->getOperand(6));
8199 Operands.push_back(N->getOperand(5));
8200 Operands.push_back(N->getOperand(4));
8201 [[fallthrough]];
8202 case Intrinsic::amdgcn_writelane:
8203 case Intrinsic::amdgcn_permlane_bcast:
8204 case Intrinsic::amdgcn_permlane_up:
8205 case Intrinsic::amdgcn_permlane_down:
8206 case Intrinsic::amdgcn_permlane_xor:
8207 Operands.push_back(Src2);
8208 [[fallthrough]];
8209 case Intrinsic::amdgcn_readlane:
8210 case Intrinsic::amdgcn_set_inactive:
8211 case Intrinsic::amdgcn_set_inactive_chain_arg:
8212 case Intrinsic::amdgcn_mov_dpp8:
8213 Operands.push_back(Src1);
8214 [[fallthrough]];
8215 case Intrinsic::amdgcn_readfirstlane:
8216 case Intrinsic::amdgcn_permlane64:
8217 Operands.push_back(Src0);
8218 break;
8219 default:
8220 llvm_unreachable("unhandled lane op");
8221 }
8222
8223 Operands.push_back(DAG.getTargetConstant(IID, SL, MVT::i32));
8224 std::reverse(Operands.begin(), Operands.end());
8225
8226 if (SDNode *GL = N->getGluedNode()) {
8227 assert(GL->getOpcode() == ISD::CONVERGENCECTRL_GLUE);
8228 GL = GL->getOperand(0).getNode();
8229 Operands.push_back(DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8230 SDValue(GL, 0)));
8231 }
8232
8233 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, ValT, Operands);
8234 };
8235
8236 SDValue Src0 = N->getOperand(1);
8237 SDValue Src1, Src2;
8238 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8239 IID == Intrinsic::amdgcn_mov_dpp8 ||
8240 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8241 IsPermlaneShuffle) {
8242 Src1 = N->getOperand(2);
8243 if (IID == Intrinsic::amdgcn_writelane ||
8244 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8245 IsPermlaneShuffle)
8246 Src2 = N->getOperand(3);
8247 }
8248
8249 if (ValSize == SplitSize) {
8250 // Already legal
8251 return SDValue();
8252 }
8253
8254 if (ValSize < 32) {
8255 bool IsFloat = VT.isFloatingPoint();
8256 Src0 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src0) : Src0,
8257 SL, MVT::i32);
8258
8259 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8260 Src1 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src1) : Src1,
8261 SL, MVT::i32);
8262 }
8263
8264 if (IID == Intrinsic::amdgcn_writelane) {
8265 Src2 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src2) : Src2,
8266 SL, MVT::i32);
8267 }
8268
8269 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8270 SDValue Trunc = DAG.getAnyExtOrTrunc(LaneOp, SL, IntVT);
8271 return IsFloat ? DAG.getBitcast(VT, Trunc) : Trunc;
8272 }
8273
8274 if (ValSize % SplitSize != 0)
8275 return SDValue();
8276
8277 auto unrollLaneOp = [&DAG, &SL](SDNode *N) -> SDValue {
8278 EVT VT = N->getValueType(0);
8279 unsigned NE = VT.getVectorNumElements();
8280 EVT EltVT = VT.getVectorElementType();
8282 unsigned NumOperands = N->getNumOperands();
8283 SmallVector<SDValue, 4> Operands(NumOperands);
8284 SDNode *GL = N->getGluedNode();
8285
8286 // only handle convergencectrl_glue
8288
8289 for (unsigned i = 0; i != NE; ++i) {
8290 for (unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8291 ++j) {
8292 SDValue Operand = N->getOperand(j);
8293 EVT OperandVT = Operand.getValueType();
8294 if (OperandVT.isVector()) {
8295 // A vector operand; extract a single element.
8296 EVT OperandEltVT = OperandVT.getVectorElementType();
8297 Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, OperandEltVT,
8298 Operand, DAG.getVectorIdxConstant(i, SL));
8299 } else {
8300 // A scalar operand; just use it as is.
8301 Operands[j] = Operand;
8302 }
8303 }
8304
8305 if (GL)
8306 Operands[NumOperands - 1] =
8307 DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8308 SDValue(GL->getOperand(0).getNode(), 0));
8309
8310 Scalars.push_back(DAG.getNode(N->getOpcode(), SL, EltVT, Operands));
8311 }
8312
8313 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NE);
8314 return DAG.getBuildVector(VecVT, SL, Scalars);
8315 };
8316
8317 if (VT.isVector()) {
8318 switch (MVT::SimpleValueType EltTy =
8320 case MVT::i32:
8321 case MVT::f32:
8322 if (SplitSize == 32) {
8323 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VT.getSimpleVT());
8324 return unrollLaneOp(LaneOp.getNode());
8325 }
8326 [[fallthrough]];
8327 case MVT::i16:
8328 case MVT::f16:
8329 case MVT::bf16: {
8330 unsigned SubVecNumElt =
8331 SplitSize / VT.getVectorElementType().getSizeInBits();
8332 MVT SubVecVT = MVT::getVectorVT(EltTy, SubVecNumElt);
8334 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8335 for (unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8336 Src0SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src0,
8337 DAG.getConstant(EltIdx, SL, MVT::i32));
8338
8339 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8340 IsPermLane16) {
8341 Src1SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src1,
8342 DAG.getConstant(EltIdx, SL, MVT::i32));
8343
8344 Pieces.push_back(
8345 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8346 } else if (IID == Intrinsic::amdgcn_writelane) {
8347 Src2SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src2,
8348 DAG.getConstant(EltIdx, SL, MVT::i32));
8349 Pieces.push_back(
8350 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8351 } else {
8352 Pieces.push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8353 }
8354
8355 EltIdx += SubVecNumElt;
8356 }
8357 return DAG.getNode(ISD::CONCAT_VECTORS, SL, VT, Pieces);
8358 }
8359 default:
8360 // Handle all other cases by bitcasting to i32 vectors
8361 break;
8362 }
8363 }
8364
8365 MVT VecVT =
8366 MVT::getVectorVT(MVT::getIntegerVT(SplitSize), ValSize / SplitSize);
8367 Src0 = DAG.getBitcast(VecVT, Src0);
8368
8369 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8370 Src1 = DAG.getBitcast(VecVT, Src1);
8371
8372 if (IID == Intrinsic::amdgcn_writelane)
8373 Src2 = DAG.getBitcast(VecVT, Src2);
8374
8375 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8376 SDValue UnrolledLaneOp = unrollLaneOp(LaneOp.getNode());
8377 return DAG.getBitcast(VT, UnrolledLaneOp);
8378}
8379
8381 SelectionDAG &DAG) {
8382 EVT VT = N->getValueType(0);
8383
8384 if (VT.getSizeInBits() != 32)
8385 return SDValue();
8386
8387 SDLoc SL(N);
8388
8389 SDValue Value = N->getOperand(1);
8390 SDValue Index = N->getOperand(2);
8391
8392 // ds_bpermute requires index to be multiplied by 4
8393 SDValue ShiftAmount = DAG.getShiftAmountConstant(2, MVT::i32, SL);
8394 SDValue ShiftedIndex =
8395 DAG.getNode(ISD::SHL, SL, Index.getValueType(), Index, ShiftAmount);
8396
8397 // Intrinsics will require i32 to operate on
8398 SDValue ValueI32 = DAG.getBitcast(MVT::i32, Value);
8399
8400 auto MakeIntrinsic = [&DAG, &SL](unsigned IID, MVT RetVT,
8401 SmallVector<SDValue> IntrinArgs) -> SDValue {
8403 Operands[0] = DAG.getTargetConstant(IID, SL, MVT::i32);
8404 Operands.append(IntrinArgs);
8405 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, RetVT, Operands);
8406 };
8407
8408 // If we can bpermute across the whole wave, then just do that
8409 if (TLI.getSubtarget()->supportsWaveWideBPermute()) {
8410 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8411 {ShiftedIndex, ValueI32});
8412 return DAG.getBitcast(VT, BPermute);
8413 }
8414
8415 assert(TLI.getSubtarget()->isWave64());
8416
8417 // Otherwise, we need to make use of whole wave mode
8418 SDValue PoisonVal = DAG.getPOISON(ValueI32->getValueType(0));
8419
8420 // Set inactive lanes to poison
8421 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8422 {ValueI32, PoisonVal});
8423 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8424 {ShiftedIndex, PoisonVal});
8425
8426 SDValue Swapped =
8427 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8428
8429 // Get permutation of each half, then we'll select which one to use
8430 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8431 {WWMIndex, WWMValue});
8432 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8433 MVT::i32, {WWMIndex, Swapped});
8434 SDValue BPermOtherHalfWWM =
8435 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8436
8437 // Select which side to take the permute from
8438 SDValue ThreadIDMask = DAG.getAllOnesConstant(SL, MVT::i32);
8439 // We can get away with only using mbcnt_lo here since we're only
8440 // trying to detect which side of 32 each lane is on, and mbcnt_lo
8441 // returns 32 for lanes 32-63.
8442 SDValue ThreadID =
8443 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8444 {ThreadIDMask, DAG.getTargetConstant(0, SL, MVT::i32)});
8445
8446 SDValue SameOrOtherHalf =
8447 DAG.getNode(ISD::AND, SL, MVT::i32,
8448 DAG.getNode(ISD::XOR, SL, MVT::i32, ThreadID, Index),
8449 DAG.getTargetConstant(32, SL, MVT::i32));
8450 SDValue UseSameHalf =
8451 DAG.getSetCC(SL, MVT::i1, SameOrOtherHalf,
8452 DAG.getConstant(0, SL, MVT::i32), ISD::SETEQ);
8453 SDValue Result = DAG.getSelect(SL, MVT::i32, UseSameHalf, BPermSameHalf,
8454 BPermOtherHalfWWM);
8455 return DAG.getBitcast(VT, Result);
8456}
8457
8460 SelectionDAG &DAG) const {
8461 switch (N->getOpcode()) {
8463 if (SDValue Res = lowerINSERT_VECTOR_ELT(SDValue(N, 0), DAG))
8464 Results.push_back(Res);
8465 return;
8466 }
8468 if (SDValue Res = lowerEXTRACT_VECTOR_ELT(SDValue(N, 0), DAG))
8469 Results.push_back(Res);
8470 return;
8471 }
8473 if (SDValue Res = LowerCONVERT_TO_ARBITRARY_FP(SDValue(N, 0), DAG))
8474 Results.push_back(Res);
8475 return;
8476 }
8478 unsigned IID = N->getConstantOperandVal(0);
8479 switch (IID) {
8480 case Intrinsic::amdgcn_wave_reduce_min:
8481 case Intrinsic::amdgcn_wave_reduce_umin:
8482 case Intrinsic::amdgcn_wave_reduce_max:
8483 case Intrinsic::amdgcn_wave_reduce_umax:
8484 case Intrinsic::amdgcn_wave_reduce_add:
8485 case Intrinsic::amdgcn_wave_reduce_sub:
8486 case Intrinsic::amdgcn_wave_reduce_and:
8487 case Intrinsic::amdgcn_wave_reduce_or:
8488 case Intrinsic::amdgcn_wave_reduce_xor: {
8489 EVT VT = N->getValueType(0);
8490 if (isTypeLegal(VT))
8491 return;
8492 SDLoc SL(N);
8493 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8494 IID == Intrinsic::amdgcn_wave_reduce_max ||
8495 IID == Intrinsic::amdgcn_wave_reduce_add ||
8496 IID == Intrinsic::amdgcn_wave_reduce_sub;
8497 unsigned ExtOpc = NeedsSignExt ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
8498 SDValue ExtSrc = DAG.getNode(ExtOpc, SL, MVT::i32, N->getOperand(1));
8499 SDValue Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
8500 N->getOperand(0), ExtSrc, N->getOperand(2));
8501 Results.push_back(DAG.getNode(ISD::TRUNCATE, SL, VT, Result));
8502 return;
8503 }
8504 case Intrinsic::amdgcn_make_buffer_rsrc:
8505 Results.push_back(lowerPointerAsRsrcIntrin(N, DAG));
8506 return;
8507 case Intrinsic::amdgcn_cvt_pkrtz: {
8508 SDValue Src0 = N->getOperand(1);
8509 SDValue Src1 = N->getOperand(2);
8510 SDLoc SL(N);
8511 SDValue Cvt =
8512 DAG.getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8513 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Cvt));
8514 return;
8515 }
8516 case Intrinsic::amdgcn_cvt_pknorm_i16:
8517 case Intrinsic::amdgcn_cvt_pknorm_u16:
8518 case Intrinsic::amdgcn_cvt_pk_i16:
8519 case Intrinsic::amdgcn_cvt_pk_u16: {
8520 SDValue Src0 = N->getOperand(1);
8521 SDValue Src1 = N->getOperand(2);
8522 SDLoc SL(N);
8523 unsigned Opcode;
8524
8525 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8526 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8527 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8528 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8529 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8530 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8531 else
8532 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8533
8534 EVT VT = N->getValueType(0);
8535 if (isTypeLegal(VT))
8536 Results.push_back(DAG.getNode(Opcode, SL, VT, Src0, Src1));
8537 else {
8538 SDValue Cvt = DAG.getNode(Opcode, SL, MVT::i32, Src0, Src1);
8539 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, Cvt));
8540 }
8541 return;
8542 }
8543 case Intrinsic::amdgcn_s_buffer_load: {
8544 SDValue Op = SDValue(N, 0);
8545 EVT VT = Op.getValueType();
8546 Results.push_back(lowerSBuffer(VT, VT, SDLoc(Op), DAG.getEntryNode(),
8547 Op.getOperand(1), Op.getOperand(2),
8548 Op.getOperand(3), DAG));
8549 return;
8550 }
8551 case Intrinsic::amdgcn_dead: {
8552 for (unsigned I = 0, E = N->getNumValues(); I < E; ++I)
8553 Results.push_back(DAG.getPOISON(N->getValueType(I)));
8554 return;
8555 }
8556 }
8557 break;
8558 }
8560 if (N->getConstantOperandVal(1) != Intrinsic::amdgcn_ptr_s_buffer_load &&
8561 N->getValueType(0).isSimple() &&
8562 SBufferLoadDiagnosticVTs[N->getSimpleValueType(0).SimpleTy])
8563 break;
8564 if (SDValue Res = LowerINTRINSIC_W_CHAIN(SDValue(N, 0), DAG)) {
8565 if (Res.getOpcode() == ISD::MERGE_VALUES) {
8566 // FIXME: Hacky
8567 for (unsigned I = 0; I < Res.getNumOperands(); I++) {
8568 Results.push_back(Res.getOperand(I));
8569 }
8570 } else {
8571 for (unsigned I = 0; I < N->getNumValues(); ++I)
8572 Results.push_back(Res.getValue(I));
8573 }
8574 return;
8575 }
8576
8577 break;
8578 }
8579 case ISD::SELECT: {
8580 SDLoc SL(N);
8581 EVT VT = N->getValueType(0);
8582 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
8583 SDValue LHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(1));
8584 SDValue RHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(2));
8585
8586 EVT SelectVT = NewVT;
8587 if (NewVT.bitsLT(MVT::i32)) {
8588 LHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, LHS);
8589 RHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, RHS);
8590 SelectVT = MVT::i32;
8591 }
8592
8593 SDValue NewSelect =
8594 DAG.getNode(ISD::SELECT, SL, SelectVT, N->getOperand(0), LHS, RHS);
8595
8596 if (NewVT != SelectVT)
8597 NewSelect = DAG.getNode(ISD::TRUNCATE, SL, NewVT, NewSelect);
8598 Results.push_back(DAG.getNode(ISD::BITCAST, SL, VT, NewSelect));
8599 return;
8600 }
8601 case ISD::FNEG: {
8602 if (N->getValueType(0) != MVT::v2f16)
8603 break;
8604
8605 SDLoc SL(N);
8606 SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::i32, N->getOperand(0));
8607
8608 SDValue Op = DAG.getNode(ISD::XOR, SL, MVT::i32, BC,
8609 DAG.getConstant(0x80008000, SL, MVT::i32));
8610 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8611 return;
8612 }
8613 case ISD::FABS: {
8614 if (N->getValueType(0) != MVT::v2f16)
8615 break;
8616
8617 SDLoc SL(N);
8618 SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::i32, N->getOperand(0));
8619
8620 SDValue Op = DAG.getNode(ISD::AND, SL, MVT::i32, BC,
8621 DAG.getConstant(0x7fff7fff, SL, MVT::i32));
8622 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8623 return;
8624 }
8625 case ISD::FSQRT: {
8626 if (N->getValueType(0) != MVT::f16)
8627 break;
8628 Results.push_back(lowerFSQRTF16(SDValue(N, 0), DAG));
8629 break;
8630 }
8631 default:
8633 break;
8634 }
8635}
8636
8637/// Helper function for LowerBRCOND
8638static SDNode *findUser(SDValue Value, unsigned Opcode) {
8639
8640 for (SDUse &U : Value->uses()) {
8641 if (U.get() != Value)
8642 continue;
8643
8644 if (U.getUser()->getOpcode() == Opcode)
8645 return U.getUser();
8646 }
8647 return nullptr;
8648}
8649
8650unsigned SITargetLowering::isCFIntrinsic(const SDNode *Intr) const {
8651 if (Intr->getOpcode() == ISD::INTRINSIC_W_CHAIN) {
8652 switch (Intr->getConstantOperandVal(1)) {
8653 case Intrinsic::amdgcn_if:
8654 return AMDGPUISD::IF;
8655 case Intrinsic::amdgcn_else:
8656 return AMDGPUISD::ELSE;
8657 case Intrinsic::amdgcn_loop:
8658 return AMDGPUISD::LOOP;
8659 case Intrinsic::amdgcn_end_cf:
8660 llvm_unreachable("should not occur");
8661 default:
8662 return 0;
8663 }
8664 }
8665
8666 // break, if_break, else_break are all only used as inputs to loop, not
8667 // directly as branch conditions.
8668 return 0;
8669}
8670
8677
8679 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8680 return false;
8681
8682 // FIXME: Either avoid relying on address space here or change the default
8683 // address space for functions to avoid the explicit check.
8684 return (GV->getValueType()->isFunctionTy() ||
8687}
8688
8690 return !shouldEmitFixup(GV) && !shouldEmitGOTReloc(GV);
8691}
8692
8694 if (!GV->hasExternalLinkage())
8695 return true;
8696
8697 // With object linking, external LDS declarations need relocations so the
8698 // linker can assign their offsets.
8700 if (const auto *GVar = dyn_cast<GlobalVariable>(GV)) {
8701 if (GVar->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
8702 GVar->getAddressSpace() == AMDGPUAS::BARRIER) {
8703 assert(GVar->isDeclaration() &&
8704 "AS 3 & 13 GVs should be declaration here "
8705 "when object linking is enabled");
8706 return false;
8707 }
8708 }
8709 }
8710
8711 const auto OS = getTargetMachine().getTargetTriple().getOS();
8712 return OS == Triple::AMDHSA || OS == Triple::AMDPAL;
8713}
8714
8715/// This transforms the control flow intrinsics to get the branch destination as
8716/// last parameter, also switches branch target with BR if the need arise
8717SDValue SITargetLowering::LowerBRCOND(SDValue BRCOND, SelectionDAG &DAG) const {
8718 SDLoc DL(BRCOND);
8719
8720 SDNode *Intr = BRCOND.getOperand(1).getNode();
8721 SDValue Target = BRCOND.getOperand(2);
8722 SDNode *BR = nullptr;
8723 SDNode *SetCC = nullptr;
8724
8725 switch (Intr->getOpcode()) {
8726 case ISD::SETCC: {
8727 // As long as we negate the condition everything is fine
8728 SetCC = Intr;
8729 Intr = SetCC->getOperand(0).getNode();
8730 break;
8731 }
8732 case ISD::XOR: {
8733 // Similar to SETCC, if we have (xor c, -1), we will be fine.
8734 SDValue LHS = Intr->getOperand(0);
8735 SDValue RHS = Intr->getOperand(1);
8736 if (auto *C = dyn_cast<ConstantSDNode>(RHS); C && C->getZExtValue()) {
8737 Intr = LHS.getNode();
8738 break;
8739 }
8740 [[fallthrough]];
8741 }
8742 default: {
8743 // Get the target from BR if we don't negate the condition
8744 BR = findUser(BRCOND, ISD::BR);
8745 assert(BR && "brcond missing unconditional branch user");
8746 Target = BR->getOperand(1);
8747 }
8748 }
8749
8750 unsigned CFNode = isCFIntrinsic(Intr);
8751 if (CFNode == 0) {
8752 // This is a uniform branch so we don't need to legalize.
8753 return BRCOND;
8754 }
8755
8756 bool HaveChain = Intr->getOpcode() == ISD::INTRINSIC_VOID ||
8758
8759 assert(!SetCC || (SetCC->getConstantOperandVal(1) == 1 &&
8760 SetCC->getOperandCondCode(2) == ISD::SETNE));
8761
8762 // operands of the new intrinsic call
8764 if (HaveChain)
8765 Ops.push_back(BRCOND.getOperand(0));
8766
8767 Ops.append(Intr->op_begin() + (HaveChain ? 2 : 1), Intr->op_end());
8768 Ops.push_back(Target);
8769
8770 ArrayRef<EVT> Res(Intr->value_begin() + 1, Intr->value_end());
8771
8772 // build the new intrinsic call
8773 SDNode *Result = DAG.getNode(CFNode, DL, DAG.getVTList(Res), Ops).getNode();
8774
8775 if (!HaveChain) {
8776 SDValue Ops[] = {SDValue(Result, 0), BRCOND.getOperand(0)};
8777
8779 }
8780
8781 if (BR) {
8782 // Give the branch instruction our target
8783 SDValue Ops[] = {BR->getOperand(0), BRCOND.getOperand(2)};
8784 SDValue NewBR = DAG.getNode(ISD::BR, DL, BR->getVTList(), Ops);
8785 DAG.ReplaceAllUsesWith(BR, NewBR.getNode());
8786 }
8787
8788 SDValue Chain = SDValue(Result, Result->getNumValues() - 1);
8789
8790 // Copy the intrinsic results to registers
8791 for (unsigned i = 1, e = Intr->getNumValues() - 1; i != e; ++i) {
8792 SDNode *CopyToReg = findUser(SDValue(Intr, i), ISD::CopyToReg);
8793 if (!CopyToReg)
8794 continue;
8795
8796 Chain = DAG.getCopyToReg(Chain, DL, CopyToReg->getOperand(1),
8797 SDValue(Result, i - 1), SDValue());
8798
8799 DAG.ReplaceAllUsesWith(SDValue(CopyToReg, 0), CopyToReg->getOperand(0));
8800 }
8801
8802 // Remove the old intrinsic from the chain
8803 DAG.ReplaceAllUsesOfValueWith(SDValue(Intr, Intr->getNumValues() - 1),
8804 Intr->getOperand(0));
8805
8806 return Chain;
8807}
8808
8809SDValue SITargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
8810 MVT VT = Op.getSimpleValueType();
8811 SDLoc DL(Op);
8812 // Checking the depth
8813 if (Op.getConstantOperandVal(0) != 0)
8814 return DAG.getConstant(0, DL, VT);
8815
8817 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8818 // Check for kernel and shader functions
8819 if (Info->isEntryFunction())
8820 return DAG.getConstant(0, DL, VT);
8821
8822 MachineFrameInfo &MFI = MF.getFrameInfo();
8823 // There is a call to @llvm.returnaddress in this function
8824 MFI.setReturnAddressIsTaken(true);
8825
8826 const SIRegisterInfo *TRI = getSubtarget()->getRegisterInfo();
8827 // Get the return address reg and mark it as an implicit live-in
8828 Register Reg = MF.addLiveIn(TRI->getReturnAddressReg(MF),
8829 getRegClassFor(VT, Op.getNode()->isDivergent()));
8830
8831 return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT);
8832}
8833
8834SDValue SITargetLowering::LowerSPONENTRY(SDValue Op, SelectionDAG &DAG) const {
8836 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
8837
8838 // For functions that set up their own stack, select the GET_STACK_BASE
8839 // pseudo.
8840 if (MFI->isBottomOfStack())
8841 return Op;
8842
8843 // For everything else, create a dummy stack object.
8844 int FI = MF.getFrameInfo().CreateFixedObject(1, 0, /*IsImmutable=*/false);
8845 return DAG.getFrameIndex(FI, Op.getValueType());
8846}
8847
8848SDValue SITargetLowering::getFPExtOrFPRound(SelectionDAG &DAG, SDValue Op,
8849 const SDLoc &DL, EVT VT) const {
8850 return Op.getValueType().bitsLE(VT)
8851 ? DAG.getNode(ISD::FP_EXTEND, DL, VT, Op)
8852 : DAG.getNode(ISD::FP_ROUND, DL, VT, Op,
8853 DAG.getTargetConstant(0, DL, MVT::i32));
8854}
8855
8856SDValue SITargetLowering::splitFP_ROUNDVectorOp(SDValue Op,
8857 SelectionDAG &DAG) const {
8858 EVT DstVT = Op.getValueType();
8859 unsigned NumElts = DstVT.getVectorNumElements();
8860 assert(NumElts > 2 && isPowerOf2_32(NumElts));
8861
8862 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
8863
8864 SDLoc DL(Op);
8865 unsigned Opc = Op.getOpcode();
8866 SDValue Flags = Op.getOperand(1);
8867 EVT HalfDstVT =
8868 EVT::getVectorVT(*DAG.getContext(), DstVT.getScalarType(), NumElts / 2);
8869 SDValue OpLo = DAG.getNode(Opc, DL, HalfDstVT, Lo, Flags);
8870 SDValue OpHi = DAG.getNode(Opc, DL, HalfDstVT, Hi, Flags);
8871
8872 return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, OpLo, OpHi);
8873}
8874
8875SDValue SITargetLowering::lowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const {
8876 bool IsStrict = Op->isStrictFPOpcode();
8877 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
8878 EVT SrcVT = Src.getValueType();
8879 EVT DstVT = Op.getValueType();
8880
8881 if (DstVT.isVectorOf(MVT::f16)) {
8882 assert(Subtarget->hasCvtPkF16F32Inst() && "support v_cvt_pk_f16_f32");
8883 if (SrcVT.getScalarType() != MVT::f32)
8884 return SDValue();
8885 return SrcVT == MVT::v2f32 ? Op : splitFP_ROUNDVectorOp(Op, DAG);
8886 }
8887
8888 if (SrcVT.getScalarType() != MVT::f64)
8889 return Op;
8890
8891 SDLoc DL(Op);
8892 if (DstVT == MVT::f16) {
8893 // TODO: Handle strictfp
8894 if (Op.getOpcode() != ISD::FP_ROUND)
8895 return Op;
8896
8897 if (!Subtarget->has16BitInsts()) {
8898 SDValue FpToFp16 = DAG.getNode(ISD::FP_TO_FP16, DL, MVT::i32, Src);
8899 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8900 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8901 }
8902 if (Op->getFlags().hasApproximateFuncs()) {
8903 SDValue Flags = Op.getOperand(1);
8904 SDValue Src32 = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, Src, Flags);
8905 return DAG.getNode(ISD::FP_ROUND, DL, MVT::f16, Src32, Flags);
8906 }
8907 SDValue FpToFp16 = LowerF64ToF16Safe(Src, DL, DAG);
8908 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8909 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8910 }
8911
8912 assert(DstVT.getScalarType() == MVT::bf16 &&
8913 "custom lower FP_ROUND for f16 or bf16");
8914 assert(Subtarget->hasBF16ConversionInsts() && "f32 -> bf16 is legal");
8915
8916 // Round-inexact-to-odd f64 to f32, then do the final rounding using the
8917 // hardware f32 -> bf16 instruction.
8918 EVT F32VT = SrcVT.changeElementType(*DAG.getContext(), MVT::f32);
8919 SDValue Rod = expandRoundInexactToOdd(F32VT, Src, DL, DAG);
8920 if (IsStrict) {
8921 return DAG.getNode(
8922 ISD::STRICT_FP_ROUND, DL, {DstVT, MVT::Other},
8923 {Op.getOperand(0), Rod, DAG.getTargetConstant(0, DL, MVT::i32)});
8924 }
8925 return DAG.getNode(ISD::FP_ROUND, DL, DstVT, Rod,
8926 DAG.getTargetConstant(0, DL, MVT::i32));
8927}
8928
8929SDValue SITargetLowering::lowerFMINNUM_FMAXNUM(SDValue Op,
8930 SelectionDAG &DAG) const {
8931 EVT VT = Op.getValueType();
8932 const MachineFunction &MF = DAG.getMachineFunction();
8933 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8934 bool IsIEEEMode = Info->getMode().IEEE;
8935
8936 // FIXME: Assert during selection that this is only selected for
8937 // ieee_mode. Currently a combine can produce the ieee version for non-ieee
8938 // mode functions, but this happens to be OK since it's only done in cases
8939 // where there is known no sNaN.
8940 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8941 return expandFMINNUM_FMAXNUM(Op.getNode(), DAG);
8942
8943 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8944 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8945 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8946 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8947 return splitBinaryVectorOp(Op, DAG);
8948 return Op;
8949}
8950
8951SDValue
8952SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(SDValue Op,
8953 SelectionDAG &DAG) const {
8954 EVT VT = Op.getValueType();
8955 const MachineFunction &MF = DAG.getMachineFunction();
8956 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8957 bool IsIEEEMode = Info->getMode().IEEE;
8958
8959 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8960 return expandFMINIMUMNUM_FMAXIMUMNUM(Op.getNode(), DAG);
8961
8962 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8963 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8964 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8965 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8966 return splitBinaryVectorOp(Op, DAG);
8967 return Op;
8968}
8969
8970SDValue SITargetLowering::lowerFLDEXP(SDValue Op, SelectionDAG &DAG) const {
8971 bool IsStrict = Op.getOpcode() == ISD::STRICT_FLDEXP;
8972 EVT VT = Op.getValueType();
8973 assert(VT == MVT::f16);
8974
8975 SDValue Exp = Op.getOperand(IsStrict ? 2 : 1);
8976 EVT ExpVT = Exp.getValueType();
8977 if (ExpVT == MVT::i16)
8978 return Op;
8979
8980 SDLoc DL(Op);
8981
8982 // Correct the exponent type for f16 to i16.
8983 // Clamp the range of the exponent to the instruction's range.
8984
8985 // TODO: This should be a generic narrowing legalization, and can easily be
8986 // for GlobalISel.
8987
8988 SDValue MinExp = DAG.getSignedConstant(minIntN(16), DL, ExpVT);
8989 SDValue ClampMin = DAG.getNode(ISD::SMAX, DL, ExpVT, Exp, MinExp);
8990
8991 SDValue MaxExp = DAG.getSignedConstant(maxIntN(16), DL, ExpVT);
8992 SDValue Clamp = DAG.getNode(ISD::SMIN, DL, ExpVT, ClampMin, MaxExp);
8993
8994 SDValue TruncExp = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Clamp);
8995
8996 if (IsStrict) {
8997 return DAG.getNode(ISD::STRICT_FLDEXP, DL, {VT, MVT::Other},
8998 {Op.getOperand(0), Op.getOperand(1), TruncExp});
8999 }
9000
9001 return DAG.getNode(ISD::FLDEXP, DL, VT, Op.getOperand(0), TruncExp);
9002}
9003
9005 switch (Op->getOpcode()) {
9006 case ISD::ABS:
9007 case ISD::SRA:
9008 case ISD::SMIN:
9009 case ISD::SMAX:
9010 return ISD::SIGN_EXTEND;
9011 case ISD::SRL:
9012 case ISD::UMIN:
9013 case ISD::UMAX:
9014 case ISD::USUBSAT:
9015 case ISD::UADDSAT:
9016 return ISD::ZERO_EXTEND;
9017 case ISD::ADD:
9018 case ISD::SUB:
9019 case ISD::AND:
9020 case ISD::OR:
9021 case ISD::XOR:
9022 case ISD::SHL:
9023 case ISD::SELECT:
9024 case ISD::MUL:
9025 // operation result won't be influenced by garbage high bits.
9026 // TODO: are all of those cases correct, and are there more?
9027 return ISD::ANY_EXTEND;
9028 case ISD::SETCC: {
9029 ISD::CondCode CC = Op.getOperandCondCode(2);
9031 }
9032 default:
9033 llvm_unreachable("unexpected opcode!");
9034 }
9035}
9036
9037SDValue
9038SITargetLowering::promoteUniformUnaryOpToI32(SDValue Op,
9039 DAGCombinerInfo &DCI) const {
9040 EVT OpTy = Op.getValueType();
9041 SelectionDAG &DAG = DCI.DAG;
9042 EVT ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
9043
9044 if (isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
9045 return SDValue();
9046
9047 SDLoc DL(Op);
9048 SDValue Input = Op.getOperand(0);
9049 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
9050 Input = DAG.getNode(ExtOp, DL, ExtTy, Input);
9051
9052 SDValue NewVal = DAG.getNode(Op.getOpcode(), DL, ExtTy, Input);
9053
9054 return DAG.getNode(ISD::TRUNCATE, DL, OpTy, NewVal);
9055}
9056
9057SDValue SITargetLowering::promoteUniformOpToI32(SDValue Op,
9058 DAGCombinerInfo &DCI) const {
9059 const unsigned Opc = Op.getOpcode();
9060 assert(Opc == ISD::ADD || Opc == ISD::SUB || Opc == ISD::SHL ||
9061 Opc == ISD::SRL || Opc == ISD::SRA || Opc == ISD::AND ||
9062 Opc == ISD::OR || Opc == ISD::XOR || Opc == ISD::MUL ||
9063 Opc == ISD::SETCC || Opc == ISD::SELECT || Opc == ISD::SMIN ||
9064 Opc == ISD::SMAX || Opc == ISD::UMIN || Opc == ISD::UMAX ||
9065 Opc == ISD::USUBSAT || Opc == ISD::UADDSAT);
9066
9067 EVT OpTy = (Opc != ISD::SETCC) ? Op.getValueType()
9068 : Op->getOperand(0).getValueType();
9069 auto &DAG = DCI.DAG;
9070 auto ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
9071
9072 if (DCI.isBeforeLegalizeOps() ||
9073 isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
9074 return SDValue();
9075
9076 SDLoc DL(Op);
9077 SDValue LHS;
9078 SDValue RHS;
9079 if (Opc == ISD::SELECT) {
9080 LHS = Op->getOperand(1);
9081 RHS = Op->getOperand(2);
9082 } else {
9083 LHS = Op->getOperand(0);
9084 RHS = Op->getOperand(1);
9085 }
9086
9087 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
9088 LHS = DAG.getNode(ExtOp, DL, ExtTy, {LHS});
9089
9090 // Special case: for shifts, the RHS always needs a zext.
9091 if (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA)
9092 RHS = DAG.getNode(ISD::ZERO_EXTEND, DL, ExtTy, {RHS});
9093 else
9094 RHS = DAG.getNode(ExtOp, DL, ExtTy, {RHS});
9095
9096 // setcc always return i1/i1 vec so no need to truncate after.
9097 if (Opc == ISD::SETCC) {
9098 ISD::CondCode CC = Op.getOperandCondCode(2);
9099 return DAG.getSetCC(DL, Op.getValueType(), LHS, RHS, CC);
9100 }
9101
9102 // For other ops, we extend the operation's return type as well so we need to
9103 // truncate back to the original type.
9104 SDValue NewVal;
9105 if (Opc == ISD::SELECT)
9106 NewVal = DAG.getNode(ISD::SELECT, DL, ExtTy, {Op->getOperand(0), LHS, RHS});
9107 else if (Opc == ISD::UADDSAT) {
9108 SDValue Sum = DAG.getNode(ISD::ADD, DL, ExtTy, LHS, RHS);
9109 SDValue MaxVal = DAG.getConstant(
9110 APInt::getMaxValue(OpTy.getScalarSizeInBits()).zext(32), DL, ExtTy);
9111 NewVal = DAG.getNode(ISD::UMIN, DL, ExtTy, Sum, MaxVal);
9112 } else
9113 NewVal = DAG.getNode(Opc, DL, ExtTy, {LHS, RHS});
9114
9115 return DAG.getZExtOrTrunc(NewVal, DL, OpTy);
9116}
9117
9118SDValue SITargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
9119 SDValue Mag = Op.getOperand(0);
9120 EVT MagVT = Mag.getValueType();
9121
9122 if (MagVT.getVectorNumElements() > 2)
9123 return splitBinaryVectorOp(Op, DAG);
9124
9125 SDValue Sign = Op.getOperand(1);
9126 EVT SignVT = Sign.getValueType();
9127
9128 if (MagVT == SignVT)
9129 return Op;
9130
9131 // fcopysign v2f16:mag, v2f32:sign ->
9132 // fcopysign v2f16:mag,
9133 // bitcast (trunc (srl (bitcast sign to v2i32), 16) to v2i16)
9134
9135 SDLoc SL(Op);
9136 SDValue SignAsInt32 = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Sign);
9137 SDValue ShiftAmt = DAG.getShiftAmountConstant(16, MVT::v2i32, SL);
9138 SDValue SignShifted =
9139 DAG.getNode(ISD::SRL, SL, MVT::v2i32, SignAsInt32, ShiftAmt);
9140 SDValue SignAsInt16 = DAG.getNode(ISD::TRUNCATE, SL, MVT::v2i16, SignShifted);
9141
9142 SDValue SignAsHalf16 = DAG.getNode(ISD::BITCAST, SL, MagVT, SignAsInt16);
9143
9144 return DAG.getNode(ISD::FCOPYSIGN, SL, MagVT, Mag, SignAsHalf16);
9145}
9146
9147// Custom lowering for vector multiplications and s_mul_u64.
9148SDValue SITargetLowering::lowerMUL(SDValue Op, SelectionDAG &DAG) const {
9149 EVT VT = Op.getValueType();
9150
9151 // Split vector operands.
9152 if (VT.isVector())
9153 return splitBinaryVectorOp(Op, DAG);
9154
9155 assert(VT == MVT::i64 && "The following code is a special for s_mul_u64");
9156
9157 // There are four ways to lower s_mul_u64:
9158 //
9159 // 1. If all the operands are uniform, then we lower it as it is.
9160 //
9161 // 2. If the operands are divergent, then we have to split s_mul_u64 in 32-bit
9162 // multiplications because there is not a vector equivalent of s_mul_u64.
9163 //
9164 // 3. If the cost model decides that it is more efficient to use vector
9165 // registers, then we have to split s_mul_u64 in 32-bit multiplications.
9166 // This happens in splitScalarSMULU64() in SIInstrInfo.cpp .
9167 //
9168 // 4. If the cost model decides to use vector registers and both of the
9169 // operands are zero-extended/sign-extended from 32-bits, then we split the
9170 // s_mul_u64 in two 32-bit multiplications. The problem is that it is not
9171 // possible to check if the operands are zero-extended or sign-extended in
9172 // SIInstrInfo.cpp. For this reason, here, we replace s_mul_u64 with
9173 // s_mul_u64_u32_pseudo if both operands are zero-extended and we replace
9174 // s_mul_u64 with s_mul_i64_i32_pseudo if both operands are sign-extended.
9175 // If the cost model decides that we have to use vector registers, then
9176 // splitScalarSMulPseudo() (in SIInstrInfo.cpp) split s_mul_u64_u32/
9177 // s_mul_i64_i32_pseudo in two vector multiplications. If the cost model
9178 // decides that we should use scalar registers, then s_mul_u64_u32_pseudo/
9179 // s_mul_i64_i32_pseudo is lowered as s_mul_u64 in expandPostRAPseudo() in
9180 // SIInstrInfo.cpp .
9181
9182 if (Op->isDivergent())
9183 return SDValue();
9184
9185 SDValue Op0 = Op.getOperand(0);
9186 SDValue Op1 = Op.getOperand(1);
9187 // If all the operands are zero-enteted to 32-bits, then we replace s_mul_u64
9188 // with s_mul_u64_u32_pseudo. If all the operands are sign-extended to
9189 // 32-bits, then we replace s_mul_u64 with s_mul_i64_i32_pseudo.
9190 KnownBits Op0KnownBits = DAG.computeKnownBits(Op0);
9191 unsigned Op0LeadingZeros = Op0KnownBits.countMinLeadingZeros();
9192 KnownBits Op1KnownBits = DAG.computeKnownBits(Op1);
9193 unsigned Op1LeadingZeros = Op1KnownBits.countMinLeadingZeros();
9194 SDLoc SL(Op);
9195 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9196 return SDValue(
9197 DAG.getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9198 unsigned Op0SignBits = DAG.ComputeNumSignBits(Op0);
9199 unsigned Op1SignBits = DAG.ComputeNumSignBits(Op1);
9200 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9201 return SDValue(
9202 DAG.getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9203 // If all the operands are uniform, then we lower s_mul_u64 as it is.
9204 return Op;
9205}
9206
9207SDValue SITargetLowering::lowerXMULO(SDValue Op, SelectionDAG &DAG) const {
9208 EVT VT = Op.getValueType();
9209 SDLoc SL(Op);
9210 SDValue LHS = Op.getOperand(0);
9211 SDValue RHS = Op.getOperand(1);
9212 bool isSigned = Op.getOpcode() == ISD::SMULO;
9213
9214 if (ConstantSDNode *RHSC = isConstOrConstSplat(RHS)) {
9215 const APInt &C = RHSC->getAPIntValue();
9216 // mulo(X, 1 << S) -> { X << S, (X << S) >> S != X }
9217 if (C.isPowerOf2()) {
9218 // smulo(x, signed_min) is same as umulo(x, signed_min).
9219 bool UseArithShift = isSigned && !C.isMinSignedValue();
9220 SDValue ShiftAmt = DAG.getConstant(C.logBase2(), SL, MVT::i32);
9221 SDValue Result = DAG.getNode(ISD::SHL, SL, VT, LHS, ShiftAmt);
9222 SDValue Overflow =
9223 DAG.getSetCC(SL, MVT::i1,
9224 DAG.getNode(UseArithShift ? ISD::SRA : ISD::SRL, SL, VT,
9225 Result, ShiftAmt),
9226 LHS, ISD::SETNE);
9227 return DAG.getMergeValues({Result, Overflow}, SL);
9228 }
9229 }
9230
9231 SDValue Result = DAG.getNode(ISD::MUL, SL, VT, LHS, RHS);
9232 SDValue Top =
9233 DAG.getNode(isSigned ? ISD::MULHS : ISD::MULHU, SL, VT, LHS, RHS);
9234
9236 ? DAG.getNode(ISD::SRA, SL, VT, Result,
9237 DAG.getConstant(VT.getScalarSizeInBits() - 1,
9238 SL, MVT::i32))
9239 : DAG.getConstant(0, SL, VT);
9240 SDValue Overflow = DAG.getSetCC(SL, MVT::i1, Top, Sign, ISD::SETNE);
9241
9242 return DAG.getMergeValues({Result, Overflow}, SL);
9243}
9244
9245SDValue SITargetLowering::lowerXMUL_LOHI(SDValue Op, SelectionDAG &DAG) const {
9246 if (Op->isDivergent()) {
9247 // Select to V_MAD_[IU]64_[IU]32.
9248 return Op;
9249 }
9250 if (Subtarget->hasSMulHi()) {
9251 // Expand to S_MUL_I32 + S_MUL_HI_[IU]32.
9252 return SDValue();
9253 }
9254 // The multiply is uniform but we would have to use V_MUL_HI_[IU]32 to
9255 // calculate the high part, so we might as well do the whole thing with
9256 // V_MAD_[IU]64_[IU]32.
9257 return Op;
9258}
9259
9260SDValue SITargetLowering::lowerTRAP(SDValue Op, SelectionDAG &DAG) const {
9261 if (!Subtarget->hasTrapHandler() ||
9262 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA)
9263 return lowerTrapEndpgm(Op, DAG);
9264
9265 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(Op, DAG)
9266 : lowerTrapHsaQueuePtr(Op, DAG);
9267}
9268
9269SDValue SITargetLowering::lowerTrapEndpgm(SDValue Op, SelectionDAG &DAG) const {
9270 SDLoc SL(Op);
9271 SDValue Chain = Op.getOperand(0);
9272 return DAG.getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9273}
9274
9275SDValue
9276SITargetLowering::loadImplicitKernelArgument(SelectionDAG &DAG, MVT VT,
9277 const SDLoc &DL, Align Alignment,
9278 ImplicitParameter Param) const {
9281 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, DAG.getEntryNode(), Offset);
9282 MachinePointerInfo PtrInfo =
9284 return DAG.getLoad(
9285 VT, DL, DAG.getEntryNode(), Ptr, PtrInfo.getWithOffset(Offset), Alignment,
9287}
9288
9289SDValue SITargetLowering::lowerTrapHsaQueuePtr(SDValue Op,
9290 SelectionDAG &DAG) const {
9291 SDLoc SL(Op);
9292 SDValue Chain = Op.getOperand(0);
9293
9294 SDValue QueuePtr;
9295 // For code object version 5, QueuePtr is passed through implicit kernarg.
9296 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9298 QueuePtr =
9299 loadImplicitKernelArgument(DAG, MVT::i64, SL, Align(8), QUEUE_PTR);
9300 } else {
9302 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9303 Register UserSGPR = Info->getQueuePtrUserSGPR();
9304
9305 if (UserSGPR == AMDGPU::NoRegister) {
9306 // We probably are in a function incorrectly marked with
9307 // amdgpu-no-queue-ptr. This is undefined. We don't want to delete the
9308 // trap, so just use a null pointer.
9309 QueuePtr = DAG.getConstant(0, SL, MVT::i64);
9310 } else {
9311 QueuePtr = CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR,
9312 MVT::i64);
9313 }
9314 }
9315
9316 SDValue SGPR01 = DAG.getRegister(AMDGPU::SGPR0_SGPR1, MVT::i64);
9317 SDValue ToReg = DAG.getCopyToReg(Chain, SL, SGPR01, QueuePtr, SDValue());
9318
9320 SDValue Ops[] = {ToReg, DAG.getTargetConstant(TrapID, SL, MVT::i16), SGPR01,
9321 ToReg.getValue(1)};
9322 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9323}
9324
9325SDValue SITargetLowering::lowerTrapHsa(SDValue Op, SelectionDAG &DAG) const {
9326 SDLoc SL(Op);
9327 SDValue Chain = Op.getOperand(0);
9328
9329 // We need to simulate the 's_trap 2' instruction on targets that run in
9330 // PRIV=1 (where it is treated as a nop).
9331 if (Subtarget->hasPrivEnabledTrap2NopBug())
9332 return DAG.getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9333
9335 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9336 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9337}
9338
9339SDValue SITargetLowering::lowerDEBUGTRAP(SDValue Op, SelectionDAG &DAG) const {
9340 SDLoc SL(Op);
9341 SDValue Chain = Op.getOperand(0);
9343
9344 if (!Subtarget->hasTrapHandler() ||
9345 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA) {
9346 LLVMContext &Ctx = MF.getFunction().getContext();
9347 Ctx.diagnose(DiagnosticInfoUnsupported(MF.getFunction(),
9348 "debugtrap handler not supported",
9349 Op.getDebugLoc(), DS_Warning));
9350 return Chain;
9351 }
9352
9353 uint64_t TrapID =
9355 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9356 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9357}
9358
9359/// When a divergent value (in VGPR) is passed to an inline asm with an SGPR
9360/// constraint ('s'), we need to insert v_readfirstlane to move the value from
9361/// VGPR to SGPR. This is done by modifying the CopyToReg nodes in the glue
9362/// chain that feed into the INLINEASM node.
9363SDValue SITargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
9364 unsigned NumOps = Op.getNumOperands();
9365
9366 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
9367 SmallSet<Register, 8> SGPRInputRegs;
9368
9369 unsigned NumVals = 0;
9370 for (unsigned I = InlineAsm::Op_FirstOperand; I < NumOps - 1;
9371 I += 1 + NumVals) {
9372 const InlineAsm::Flag Flags(Op.getConstantOperandVal(I));
9373 NumVals = Flags.getNumOperandRegisters();
9374
9375 unsigned RCID;
9376 bool IsSGPRInput = Flags.getKind() == InlineAsm::Kind::RegUse &&
9377 NumVals > 0 && Flags.hasRegClassConstraint(RCID) &&
9378 TRI->isSGPRClass(TRI->getRegClass(RCID));
9379
9380 for (unsigned J = 0; J < NumVals; ++J) {
9381 SDValue Val = Op.getOperand(I + 1 + J);
9382 if (const RegisterSDNode *RegNode =
9384 Register Reg = RegNode->getReg();
9385 if (IsSGPRInput || (Reg.isPhysical() && TRI->isSGPRPhysReg(Reg)))
9386 SGPRInputRegs.insert(Reg);
9387 }
9388 }
9389 }
9390
9391 if (SGPRInputRegs.empty())
9392 return Op;
9393
9394 // Walk the glue chain and insert readfirstlane for divergent SGPR inputs.
9395 SDLoc DL(Op);
9396 SDNode *N = Op.getOperand(NumOps - 1).getNode();
9397
9398 while (N && N->getOpcode() == ISD::CopyToReg) {
9399 Register Reg = cast<RegisterSDNode>(N->getOperand(1))->getReg();
9400 SDValue SrcVal = N->getOperand(2);
9401
9402 // Insert readfirstlane if copying a divergent value to an SGPR input.
9403 if (SrcVal->isDivergent() && SGPRInputRegs.count(Reg)) {
9404 SDValue ReadFirstLaneID =
9405 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
9406 SDValue ReadFirstLane =
9408 ReadFirstLaneID, SrcVal);
9409
9410 SmallVector<SDValue, 4> Ops = {N->getOperand(0), N->getOperand(1),
9411 ReadFirstLane};
9412 if (N->getNumOperands() > 3)
9413 Ops.push_back(N->getOperand(3)); // Glue input
9414
9415 DAG.UpdateNodeOperands(N, Ops);
9416 }
9417
9418 // Follow glue chain to next CopyToReg.
9419 SDNode *Next = nullptr;
9420 for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I) {
9421 if (N->getOperand(I).getValueType() == MVT::Glue) {
9422 Next = N->getOperand(I).getNode();
9423 break;
9424 }
9425 }
9426 N = Next;
9427 }
9428
9429 return Op;
9430}
9431
9432SDValue SITargetLowering::getSegmentAperture(unsigned AS, const SDLoc &DL,
9433 SelectionDAG &DAG) const {
9434 unsigned BaseAS = AS;
9435 unsigned SANum = AMDGPU::getSyntheticApertureNumber(AS);
9437 BaseAS = AMDGPUAS::LOCAL_ADDRESS;
9438
9439 SDValue Aperture = getBaseSegmentAperture(BaseAS, DL, DAG);
9440
9441 if (SANum != AMDGPU::SyntheticAperture::None) {
9442 SDValue Tag = DAG.getConstant(SANum, DL, MVT::i32);
9443 return DAG.getNode(ISD::OR, DL, MVT::i32, Aperture, Tag);
9444 }
9445
9446 return Aperture;
9447}
9448
9449SDValue SITargetLowering::getBaseSegmentAperture(unsigned AS, const SDLoc &DL,
9450 SelectionDAG &DAG) const {
9451 const bool IsLDS = (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::BARRIER);
9452
9453 if (Subtarget->hasApertureRegs()) {
9454 const unsigned ApertureRegNo =
9455 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
9456 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9457 !Subtarget->hasGloballyAddressableScratch()) &&
9458 "Cannot use src_private_base with globally addressable scratch!");
9459 // Note: this feature (register) is broken. When used as a 32-bit operand,
9460 // it returns a wrong value (all zeroes?). The real value is in the upper 32
9461 // bits.
9462 //
9463 // To work around the issue, emit a 64 bit copy from this register
9464 // then extract the high bits. Note that this shouldn't even result in a
9465 // shift being emitted and simply become a pair of registers (e.g.):
9466 // s_mov_b64 s[6:7], src_shared_base
9467 // v_mov_b32_e32 v1, s7
9468 SDValue Copy =
9469 DAG.getCopyFromReg(DAG.getEntryNode(), DL, ApertureRegNo, MVT::v2i32);
9470 return DAG.getExtractVectorElt(DL, MVT::i32, Copy, 1);
9471 }
9472
9473 // For code object version 5, private_base and shared_base are passed through
9474 // implicit kernargs.
9475 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9478 return loadImplicitKernelArgument(DAG, MVT::i32, DL, Align(4), Param);
9479 }
9480
9482 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9483 Register UserSGPR = Info->getQueuePtrUserSGPR();
9484 if (UserSGPR == AMDGPU::NoRegister) {
9485 // We probably are in a function incorrectly marked with
9486 // amdgpu-no-queue-ptr. This is undefined.
9487 return DAG.getPOISON(MVT::i32);
9488 }
9489
9490 SDValue QueuePtr =
9491 CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR, MVT::i64);
9492
9493 // Offset into amd_queue_t for group_segment_aperture_base_hi /
9494 // private_segment_aperture_base_hi.
9495 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
9496
9497 SDValue Ptr =
9498 DAG.getObjectPtrOffset(DL, QueuePtr, TypeSize::getFixed(StructOffset));
9499
9500 // TODO: Use custom target PseudoSourceValue.
9501 // TODO: We should use the value from the IR intrinsic call, but it might not
9502 // be available and how do we get it?
9503 MachinePointerInfo PtrInfo(AMDGPUAS::CONSTANT_ADDRESS);
9504 return DAG.getLoad(MVT::i32, DL, QueuePtr.getValue(1), Ptr, PtrInfo,
9505 commonAlignment(Align(64), StructOffset),
9508}
9509
9510/// Return true if the value is a known valid address, such that a null check is
9511/// not necessary.
9513 const AMDGPUTargetMachine &TM, unsigned AddrSpace) {
9515 return true;
9516
9517 if (auto *ConstVal = dyn_cast<ConstantSDNode>(Val))
9518 return ConstVal->getSExtValue() != AMDGPU::getNullPointerValue(AddrSpace);
9519
9520 // TODO: Search through arithmetic, handle arguments and loads
9521 // marked nonnull.
9522 return false;
9523}
9524
9525SDValue SITargetLowering::lowerADDRSPACECAST(SDValue Op,
9526 SelectionDAG &DAG) const {
9527 SDLoc SL(Op);
9528
9529 const AMDGPUTargetMachine &TM =
9530 static_cast<const AMDGPUTargetMachine &>(getTargetMachine());
9531
9532 const auto *ASC = cast<AddrSpaceCastSDNode>(Op);
9533 unsigned SrcAS = ASC->getSrcAddressSpace();
9534 SDValue Src = ASC->getOperand(0);
9535 unsigned DestAS = ASC->getDestAddressSpace();
9536 bool IsNonNull = ASC->getFlags().hasNonNull();
9537
9538 SDValue FlatNullPtr = DAG.getConstant(0, SL, MVT::i64);
9539
9540 // flat -> local/private/barrier
9541 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
9542 if (DestAS == AMDGPUAS::LOCAL_ADDRESS ||
9543 DestAS == AMDGPUAS::PRIVATE_ADDRESS || DestAS == AMDGPUAS::BARRIER) {
9544 SDValue Ptr = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9545
9546 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
9547 Subtarget->hasGloballyAddressableScratch()) {
9548 // flat -> private with globally addressable scratch: subtract
9549 // src_flat_scratch_base_lo.
9550 SDValue FlatScratchBaseLo(
9551 DAG.getMachineNode(
9552 AMDGPU::S_MOV_B32, SL, MVT::i32,
9553 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9554 0);
9555 Ptr = DAG.getNode(ISD::SUB, SL, MVT::i32, Ptr, FlatScratchBaseLo);
9556 }
9557
9558 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9559 return Ptr;
9560
9561 unsigned NullVal = AMDGPU::getNullPointerValue(DestAS);
9562 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9563 SDValue NonNull = DAG.getSetCC(SL, MVT::i1, Src, FlatNullPtr, ISD::SETNE);
9564
9565 return DAG.getNode(ISD::SELECT, SL, MVT::i32, NonNull, Ptr,
9566 SegmentNullPtr);
9567 }
9568 }
9569
9570 // local/private/barrier -> flat
9571 if (DestAS == AMDGPUAS::FLAT_ADDRESS) {
9572 if (SrcAS == AMDGPUAS::LOCAL_ADDRESS ||
9573 SrcAS == AMDGPUAS::PRIVATE_ADDRESS || SrcAS == AMDGPUAS::BARRIER) {
9574 SDValue CvtPtr;
9575 if (SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
9576 Subtarget->hasGloballyAddressableScratch()) {
9577 // For wave32: Addr = (TID[4:0] << 52) + FLAT_SCRATCH_BASE + privateAddr
9578 // For wave64: Addr = (TID[5:0] << 51) + FLAT_SCRATCH_BASE + privateAddr
9579 SDValue AllOnes = DAG.getSignedTargetConstant(-1, SL, MVT::i32);
9580 SDValue ThreadID = DAG.getConstant(0, SL, MVT::i32);
9581 ThreadID = DAG.getNode(
9582 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9583 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_lo, SL, MVT::i32),
9584 AllOnes, ThreadID);
9585 if (Subtarget->isWave64())
9586 ThreadID = DAG.getNode(
9587 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9588 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_hi, SL, MVT::i32),
9589 AllOnes, ThreadID);
9590 SDValue ShAmt = DAG.getShiftAmountConstant(
9591 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9592 SDValue SrcHi = DAG.getNode(ISD::SHL, SL, MVT::i32, ThreadID, ShAmt);
9593 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, SrcHi);
9594 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9595 // Accessing src_flat_scratch_base_lo as a 64-bit operand gives the full
9596 // 64-bit hi:lo value.
9597 SDValue FlatScratchBase = {
9598 DAG.getMachineNode(
9599 AMDGPU::S_MOV_B64, SL, MVT::i64,
9600 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9601 0};
9602 CvtPtr = DAG.getNode(ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9603 } else {
9604 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9605
9606 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Aperture);
9607 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9608 }
9609
9610 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9611 return CvtPtr;
9612
9613 unsigned NullVal = AMDGPU::getNullPointerValue(SrcAS);
9614 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9615
9616 SDValue NonNull =
9617 DAG.getSetCC(SL, MVT::i1, Src, SegmentNullPtr, ISD::SETNE);
9618
9619 return DAG.getNode(ISD::SELECT, SL, MVT::i64, NonNull, CvtPtr,
9620 FlatNullPtr);
9621 }
9622 }
9623
9624 if (SrcAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9625 Op.getValueType() == MVT::i64) {
9626 const SIMachineFunctionInfo *Info =
9627 DAG.getMachineFunction().getInfo<SIMachineFunctionInfo>();
9628 if (Info->get32BitAddressHighBits() == 0)
9629 return DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i64, Src);
9630
9631 SDValue Hi = DAG.getConstant(Info->get32BitAddressHighBits(), SL, MVT::i32);
9632 SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Hi);
9633 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
9634 }
9635
9636 if (DestAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9637 Src.getValueType() == MVT::i64)
9638 return DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9639
9640 // global <-> flat are no-ops and never emitted.
9641
9642 // Invalid casts are poison.
9643 return DAG.getPOISON(Op->getValueType(0));
9644}
9645
9646// This lowers an INSERT_SUBVECTOR by extracting the individual elements from
9647// the small vector and inserting them into the big vector. That is better than
9648// the default expansion of doing it via a stack slot. Even though the use of
9649// the stack slot would be optimized away afterwards, the stack slot itself
9650// remains.
9651SDValue SITargetLowering::lowerINSERT_SUBVECTOR(SDValue Op,
9652 SelectionDAG &DAG) const {
9653 SDValue Vec = Op.getOperand(0);
9654 SDValue Ins = Op.getOperand(1);
9655 SDValue Idx = Op.getOperand(2);
9656 EVT VecVT = Vec.getValueType();
9657 EVT InsVT = Ins.getValueType();
9658 EVT EltVT = VecVT.getVectorElementType();
9659 unsigned InsNumElts = InsVT.getVectorNumElements();
9660 unsigned IdxVal = Idx->getAsZExtVal();
9661 SDLoc SL(Op);
9662
9663 if (EltVT.getScalarSizeInBits() == 16 && IdxVal % 2 == 0) {
9664 // Insert 32-bit registers at a time.
9665 assert(InsNumElts % 2 == 0 && "expect legal vector types");
9666
9667 unsigned VecNumElts = VecVT.getVectorNumElements();
9668 EVT NewVecVT =
9669 EVT::getVectorVT(*DAG.getContext(), MVT::i32, VecNumElts / 2);
9670 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9672 MVT::i32, InsNumElts / 2);
9673
9674 Vec = DAG.getNode(ISD::BITCAST, SL, NewVecVT, Vec);
9675 Ins = DAG.getNode(ISD::BITCAST, SL, NewInsVT, Ins);
9676
9677 for (unsigned I = 0; I != InsNumElts / 2; ++I) {
9678 SDValue Elt;
9679 if (InsNumElts == 2) {
9680 Elt = Ins;
9681 } else {
9682 Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Ins,
9683 DAG.getConstant(I, SL, MVT::i32));
9684 }
9685 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, NewVecVT, Vec, Elt,
9686 DAG.getConstant(IdxVal / 2 + I, SL, MVT::i32));
9687 }
9688
9689 return DAG.getNode(ISD::BITCAST, SL, VecVT, Vec);
9690 }
9691
9692 for (unsigned I = 0; I != InsNumElts; ++I) {
9693 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Ins,
9694 DAG.getConstant(I, SL, MVT::i32));
9695 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, VecVT, Vec, Elt,
9696 DAG.getConstant(IdxVal + I, SL, MVT::i32));
9697 }
9698 return Vec;
9699}
9700
9701SDValue SITargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,
9702 SelectionDAG &DAG) const {
9703 SDValue Vec = Op.getOperand(0);
9704 SDValue InsVal = Op.getOperand(1);
9705 SDValue Idx = Op.getOperand(2);
9706 EVT VecVT = Vec.getValueType();
9707 EVT EltVT = VecVT.getVectorElementType();
9708 unsigned VecSize = VecVT.getSizeInBits();
9709 unsigned EltSize = EltVT.getSizeInBits();
9710 SDLoc SL(Op);
9711
9712 // Specially handle the case of v4i16 with static indexing.
9713 unsigned NumElts = VecVT.getVectorNumElements();
9714 auto *KIdx = dyn_cast<ConstantSDNode>(Idx);
9715 if (NumElts == 4 && EltSize == 16 && KIdx) {
9716 SDValue BCVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Vec);
9717
9718 SDValue LoHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9719 DAG.getConstant(0, SL, MVT::i32));
9720 SDValue HiHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9721 DAG.getConstant(1, SL, MVT::i32));
9722
9723 SDValue LoVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, LoHalf);
9724 SDValue HiVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, HiHalf);
9725
9726 unsigned Idx = KIdx->getZExtValue();
9727 bool InsertLo = Idx < 2;
9728 SDValue InsHalf = DAG.getNode(
9729 ISD::INSERT_VECTOR_ELT, SL, MVT::v2i16, InsertLo ? LoVec : HiVec,
9730 DAG.getNode(ISD::BITCAST, SL, MVT::i16, InsVal),
9731 DAG.getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9732
9733 InsHalf = DAG.getNode(ISD::BITCAST, SL, MVT::i32, InsHalf);
9734
9735 SDValue Concat =
9736 InsertLo ? DAG.getBuildVector(MVT::v2i32, SL, {InsHalf, HiHalf})
9737 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9738
9739 return DAG.getNode(ISD::BITCAST, SL, VecVT, Concat);
9740 }
9741
9742 // Static indexing does not lower to stack access, and hence there is no need
9743 // for special custom lowering to avoid stack access.
9744 if (isa<ConstantSDNode>(Idx))
9745 return SDValue();
9746
9747 // Avoid stack access for dynamic indexing by custom lowering to
9748 // v_bfi_b32 (v_bfm_b32 16, (shl idx, 16)), val, vec
9749 // Vectors wider than 64 bits do this on each 64-bit piece.
9750 assert(isPowerOf2_32(EltSize));
9751 unsigned PieceSize = std::min(VecSize, 64u);
9752 unsigned NumPieces = VecSize / PieceSize;
9753 unsigned EltsPerPiece = PieceSize / EltSize;
9754 MVT IntVT = MVT::getIntegerVT(PieceSize);
9755 EVT PieceVT = EVT::getVectorVT(*DAG.getContext(), EltVT, EltsPerPiece);
9756
9757 // Convert vector index to bit-index within its piece and get the required
9758 // bit mask. Using the index within the piece keeps the shift below 64.
9759 SDValue PieceIdx = Idx;
9760 if (NumPieces > 1)
9761 PieceIdx = DAG.getNode(ISD::AND, SL, MVT::i32, Idx,
9762 DAG.getConstant(EltsPerPiece - 1, SL, MVT::i32));
9763 const auto EltMask = maskTrailingOnes<uint64_t>(EltSize);
9764 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9765 SDValue ScaledIdx =
9766 DAG.getNode(ISD::SHL, SL, MVT::i32, PieceIdx, ScaleFactor);
9767 SDValue BFM = DAG.getNode(ISD::SHL, SL, IntVT,
9768 DAG.getConstant(EltMask, SL, IntVT), ScaledIdx);
9769
9770 // 1. Create a congruent vector with the target value in each element.
9771 SDValue ExtVal =
9772 DAG.getBitcast(IntVT, DAG.getSplatBuildVector(PieceVT, SL, InsVal));
9773
9774 auto InsertIntoPiece = [&](SDValue Piece, SDValue Mask) {
9775 // 2. Mask off all other indices except the required index within (1).
9776 SDValue LHS = DAG.getNode(ISD::AND, SL, IntVT, Mask, ExtVal);
9777
9778 // 3. Mask off the required index within the target vector.
9779 SDValue RHS =
9780 DAG.getNode(ISD::AND, SL, IntVT, DAG.getNOT(SL, Mask, IntVT), Piece);
9781
9782 // 4. Get (2) and (3) ORed into the target vector.
9783 return DAG.getNode(ISD::OR, SL, IntVT, LHS, RHS, SDNodeFlags::Disjoint);
9784 };
9785
9786 if (NumPieces == 1)
9787 return DAG.getBitcast(VecVT,
9788 InsertIntoPiece(DAG.getBitcast(IntVT, Vec), BFM));
9789
9790 // 5. Apply (2)-(4) to each 64-bit piece, with the mask cleared in every
9791 // piece except the one that holds the index, and rebuild the vector.
9792 MVT PiecesVT = MVT::getVectorVT(IntVT, NumPieces);
9793 SDValue BCVec = DAG.getBitcast(PiecesVT, Vec);
9794 SDValue PieceNo =
9795 DAG.getNode(ISD::SRL, SL, MVT::i32, Idx,
9796 DAG.getConstant(Log2_32(EltsPerPiece), SL, MVT::i32));
9797 SDValue Zero = DAG.getConstant(0, SL, IntVT);
9799 Pieces.reserve(NumPieces);
9800 for (unsigned I = 0; I != NumPieces; ++I) {
9801 SDValue CurPieceNo = DAG.getConstant(I, SL, MVT::i32);
9802 SDValue Piece =
9803 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, IntVT, BCVec, CurPieceNo);
9804 SDValue Mask =
9805 DAG.getSelectCC(SL, PieceNo, CurPieceNo, BFM, Zero, ISD::SETEQ);
9806 Pieces.push_back(InsertIntoPiece(Piece, Mask));
9807 }
9808
9809 return DAG.getBitcast(VecVT, DAG.getBuildVector(PiecesVT, SL, Pieces));
9810}
9811
9812SDValue SITargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op,
9813 SelectionDAG &DAG) const {
9814 SDLoc SL(Op);
9815
9816 EVT ResultVT = Op.getValueType();
9817 SDValue Vec = Op.getOperand(0);
9818 SDValue Idx = Op.getOperand(1);
9819 EVT VecVT = Vec.getValueType();
9820 unsigned VecSize = VecVT.getSizeInBits();
9821 EVT EltVT = VecVT.getVectorElementType();
9822
9823 DAGCombinerInfo DCI(DAG, AfterLegalizeVectorOps, true, nullptr);
9824
9825 // Make sure we do any optimizations that will make it easier to fold
9826 // source modifiers before obscuring it with bit operations.
9827
9828 // XXX - Why doesn't this get called when vector_shuffle is expanded?
9829 if (SDValue Combined = performExtractVectorEltCombine(Op.getNode(), DCI))
9830 return Combined;
9831
9832 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9833 SDValue Lo, Hi;
9834 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VecVT);
9835
9836 if (VecSize == 128) {
9837 SDValue V2 = DAG.getBitcast(MVT::v2i64, Vec);
9838 Lo = DAG.getBitcast(LoVT,
9839 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9840 DAG.getConstant(0, SL, MVT::i32)));
9841 Hi = DAG.getBitcast(HiVT,
9842 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9843 DAG.getConstant(1, SL, MVT::i32)));
9844 } else if (VecSize == 256) {
9845 SDValue V2 = DAG.getBitcast(MVT::v4i64, Vec);
9846 SDValue Parts[4];
9847 for (unsigned P = 0; P < 4; ++P) {
9848 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9849 DAG.getConstant(P, SL, MVT::i32));
9850 }
9851
9852 Lo = DAG.getBitcast(LoVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9853 Parts[0], Parts[1]));
9854 Hi = DAG.getBitcast(HiVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9855 Parts[2], Parts[3]));
9856 } else {
9857 assert(VecSize == 512);
9858
9859 SDValue V2 = DAG.getBitcast(MVT::v8i64, Vec);
9860 SDValue Parts[8];
9861 for (unsigned P = 0; P < 8; ++P) {
9862 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9863 DAG.getConstant(P, SL, MVT::i32));
9864 }
9865
9866 Lo = DAG.getBitcast(LoVT,
9867 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9868 Parts[0], Parts[1], Parts[2], Parts[3]));
9869 Hi = DAG.getBitcast(HiVT,
9870 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9871 Parts[4], Parts[5], Parts[6], Parts[7]));
9872 }
9873
9874 EVT IdxVT = Idx.getValueType();
9875 unsigned NElem = VecVT.getVectorNumElements();
9876 assert(isPowerOf2_32(NElem));
9877 SDValue IdxMask = DAG.getConstant(NElem / 2 - 1, SL, IdxVT);
9878 SDValue NewIdx = DAG.getNode(ISD::AND, SL, IdxVT, Idx, IdxMask);
9879 SDValue Half = DAG.getSelectCC(SL, Idx, IdxMask, Hi, Lo, ISD::SETUGT);
9880 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Half, NewIdx);
9881 }
9882
9883 assert(VecSize <= 64);
9884
9885 MVT IntVT = MVT::getIntegerVT(VecSize);
9886
9887 // If Vec is just a SCALAR_TO_VECTOR, then use the scalar integer directly.
9888 SDValue VecBC = peekThroughBitcasts(Vec);
9889 if (VecBC.getOpcode() == ISD::SCALAR_TO_VECTOR) {
9890 SDValue Src = VecBC.getOperand(0);
9891 Src = DAG.getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9892 Vec = DAG.getAnyExtOrTrunc(Src, SL, IntVT);
9893 }
9894
9895 unsigned EltSize = EltVT.getSizeInBits();
9896 assert(isPowerOf2_32(EltSize));
9897
9898 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9899
9900 // Convert vector index to bit-index (* EltSize)
9901 SDValue ScaledIdx = DAG.getNode(ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9902
9903 SDValue BC = DAG.getNode(ISD::BITCAST, SL, IntVT, Vec);
9904 SDValue Elt = DAG.getNode(ISD::SRL, SL, IntVT, BC, ScaledIdx);
9905
9906 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9907 SDValue Result = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Elt);
9908 return DAG.getNode(ISD::BITCAST, SL, ResultVT, Result);
9909 }
9910
9911 return DAG.getAnyExtOrTrunc(Elt, SL, ResultVT);
9912}
9913
9914static bool elementPairIsContiguous(ArrayRef<int> Mask, int Elt) {
9915 assert(Elt % 2 == 0);
9916 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9917}
9918
9919static bool elementPairIsOddToEven(ArrayRef<int> Mask, int Elt) {
9920 assert(Elt % 2 == 0);
9921 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9922 !(Mask[Elt + 1] & 1);
9923}
9924
9925SDValue SITargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
9926 SelectionDAG &DAG) const {
9927 SDLoc SL(Op);
9928 EVT ResultVT = Op.getValueType();
9929 ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
9930 MVT EltVT = ResultVT.getVectorElementType().getSimpleVT();
9931 const int NewSrcNumElts = 2;
9932 MVT PackVT = MVT::getVectorVT(EltVT, NewSrcNumElts);
9933 int SrcNumElts = Op.getOperand(0).getValueType().getVectorNumElements();
9934
9935 // Break up the shuffle into registers sized pieces.
9936 //
9937 // We're trying to form sub-shuffles that the register allocation pipeline
9938 // won't be able to figure out, like how to use v_pk_mov_b32 to do a register
9939 // blend or 16-bit op_sel. It should be able to figure out how to reassemble a
9940 // pair of copies into a consecutive register copy, so use the ordinary
9941 // extract_vector_elt lowering unless we can use the shuffle.
9942 //
9943 // TODO: This is a bit of hack, and we should probably always use
9944 // extract_subvector for the largest possible subvector we can (or at least
9945 // use it for PackVT aligned pieces). However we have worse support for
9946 // combines on them don't directly treat extract_subvector / insert_subvector
9947 // as legal. The DAG scheduler also ends up doing a worse job with the
9948 // extract_subvectors.
9949 const bool ShouldUseConsecutiveExtract = EltVT.getSizeInBits() == 16;
9950
9951 // vector_shuffle <0,1,6,7> lhs, rhs
9952 // -> concat_vectors (extract_subvector lhs, 0), (extract_subvector rhs, 2)
9953 //
9954 // vector_shuffle <6,7,2,3> lhs, rhs
9955 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 2)
9956 //
9957 // vector_shuffle <6,7,0,1> lhs, rhs
9958 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 0)
9959
9960 // Avoid scalarizing when both halves are reading from consecutive elements.
9961
9962 // If we're treating 2 element shuffles as legal, also create odd-to-even
9963 // shuffles of neighboring pairs.
9964 //
9965 // vector_shuffle <3,2,7,6> lhs, rhs
9966 // -> concat_vectors vector_shuffle <1, 0> (extract_subvector lhs, 0)
9967 // vector_shuffle <1, 0> (extract_subvector rhs, 2)
9968
9970 for (int I = 0, N = ResultVT.getVectorNumElements(); I != N; I += 2) {
9971 if (ShouldUseConsecutiveExtract &&
9973 const int Idx = SVN->getMaskElt(I);
9974 int VecIdx = Idx < SrcNumElts ? 0 : 1;
9975 int EltIdx = Idx < SrcNumElts ? Idx : Idx - SrcNumElts;
9976 SDValue SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT,
9977 SVN->getOperand(VecIdx),
9978 DAG.getConstant(EltIdx, SL, MVT::i32));
9979 Pieces.push_back(SubVec);
9980 } else if (elementPairIsOddToEven(SVN->getMask(), I) &&
9982 int Idx0 = SVN->getMaskElt(I);
9983 int Idx1 = SVN->getMaskElt(I + 1);
9984
9985 SDValue SrcOp0 = SVN->getOperand(0);
9986 SDValue SrcOp1 = SrcOp0;
9987 if (Idx0 >= SrcNumElts) {
9988 SrcOp0 = SVN->getOperand(1);
9989 Idx0 -= SrcNumElts;
9990 }
9991
9992 if (Idx1 >= SrcNumElts) {
9993 SrcOp1 = SVN->getOperand(1);
9994 Idx1 -= SrcNumElts;
9995 }
9996
9997 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
9998 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
9999
10000 // Extract nearest even aligned piece.
10001 SDValue SubVec0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp0,
10002 DAG.getConstant(AlignedIdx0, SL, MVT::i32));
10003 SDValue SubVec1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp1,
10004 DAG.getConstant(AlignedIdx1, SL, MVT::i32));
10005
10006 int NewMaskIdx0 = Idx0 - AlignedIdx0;
10007 int NewMaskIdx1 = Idx1 - AlignedIdx1;
10008
10009 SDValue Result0 = SubVec0;
10010 SDValue Result1 = SubVec0;
10011
10012 if (SubVec0 != SubVec1) {
10013 NewMaskIdx1 += NewSrcNumElts;
10014 Result1 = SubVec1;
10015 } else {
10016 Result1 = DAG.getPOISON(PackVT);
10017 }
10018
10019 SDValue Shuf = DAG.getVectorShuffle(PackVT, SL, Result0, Result1,
10020 {NewMaskIdx0, NewMaskIdx1});
10021 Pieces.push_back(Shuf);
10022 } else {
10023 const int Idx0 = SVN->getMaskElt(I);
10024 const int Idx1 = SVN->getMaskElt(I + 1);
10025 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
10026 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
10027 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
10028 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
10029
10030 SDValue Vec0 = SVN->getOperand(VecIdx0);
10031 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec0,
10032 DAG.getSignedConstant(EltIdx0, SL, MVT::i32));
10033
10034 SDValue Vec1 = SVN->getOperand(VecIdx1);
10035 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec1,
10036 DAG.getSignedConstant(EltIdx1, SL, MVT::i32));
10037 Pieces.push_back(DAG.getBuildVector(PackVT, SL, {Elt0, Elt1}));
10038 }
10039 }
10040
10041 return DAG.getNode(ISD::CONCAT_VECTORS, SL, ResultVT, Pieces);
10042}
10043
10044SDValue SITargetLowering::lowerSCALAR_TO_VECTOR(SDValue Op,
10045 SelectionDAG &DAG) const {
10046 SDValue SVal = Op.getOperand(0);
10047 EVT ResultVT = Op.getValueType();
10048 EVT SValVT = SVal.getValueType();
10049 SDValue UndefVal = DAG.getPOISON(SValVT);
10050 SDLoc SL(Op);
10051
10053 VElts.push_back(SVal);
10054 for (int I = 1, E = ResultVT.getVectorNumElements(); I < E; ++I)
10055 VElts.push_back(UndefVal);
10056
10057 return DAG.getBuildVector(ResultVT, SL, VElts);
10058}
10059
10060SDValue SITargetLowering::lowerBUILD_VECTOR(SDValue Op,
10061 SelectionDAG &DAG) const {
10062 SDLoc SL(Op);
10063 EVT VT = Op.getValueType();
10064
10065 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
10066 assert(!Subtarget->hasVOP3PInsts() && "this should be legal");
10067
10068 SDValue Lo = Op.getOperand(0);
10069 SDValue Hi = Op.getOperand(1);
10070
10071 // Avoid adding defined bits with the zero_extend.
10072 if (Hi.isUndef()) {
10073 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
10074 SDValue ExtLo = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Lo);
10075 return DAG.getNode(ISD::BITCAST, SL, VT, ExtLo);
10076 }
10077
10078 Hi = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Hi);
10079 Hi = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Hi);
10080
10081 SDValue ShlHi = DAG.getNode(ISD::SHL, SL, MVT::i32, Hi,
10082 DAG.getConstant(16, SL, MVT::i32));
10083 if (Lo.isUndef())
10084 return DAG.getNode(ISD::BITCAST, SL, VT, ShlHi);
10085
10086 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
10087 Lo = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Lo);
10088
10089 SDValue Or =
10090 DAG.getNode(ISD::OR, SL, MVT::i32, Lo, ShlHi, SDNodeFlags::Disjoint);
10091 return DAG.getNode(ISD::BITCAST, SL, VT, Or);
10092 }
10093
10094 // Split into 2-element chunks.
10095 const unsigned NumParts = VT.getVectorNumElements() / 2;
10096 EVT PartVT = MVT::getVectorVT(VT.getVectorElementType().getSimpleVT(), 2);
10097 MVT PartIntVT = MVT::getIntegerVT(PartVT.getSizeInBits());
10098
10100 for (unsigned P = 0; P < NumParts; ++P) {
10101 SDValue Vec = DAG.getBuildVector(
10102 PartVT, SL, {Op.getOperand(P * 2), Op.getOperand(P * 2 + 1)});
10103 Casts.push_back(DAG.getNode(ISD::BITCAST, SL, PartIntVT, Vec));
10104 }
10105
10106 SDValue Blend =
10107 DAG.getBuildVector(MVT::getVectorVT(PartIntVT, NumParts), SL, Casts);
10108 return DAG.getNode(ISD::BITCAST, SL, VT, Blend);
10109}
10110
10112 const GlobalAddressSDNode *GA) const {
10113 // Named barriers have fixed, non-relocated LDS addresses, so a constant
10114 // offset into an array of them can be folded into the address.
10116 const auto *GV = dyn_cast<GlobalVariable>(GA->getGlobal());
10117 return GV && AMDGPU::isNamedBarrier(*GV);
10118 }
10119
10120 // OSes that use ELF REL relocations (instead of RELA) can only store a
10121 // 32-bit addend in the instruction, so it is not safe to allow offset folding
10122 // which can create arbitrary 64-bit addends. (This is only a problem for
10123 // R_AMDGPU_*32_HI relocations since other relocation types are unaffected by
10124 // the high 32 bits of the addend.)
10125 //
10126 // This should be kept in sync with how HasRelocationAddend is initialized in
10127 // the constructor of ELFAMDGPUAsmBackend.
10128 if (!Subtarget->isAmdHsaOS())
10129 return false;
10130
10131 // We can fold offsets for anything that doesn't require a GOT relocation.
10132 return (GA->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS ||
10136}
10137
10138static SDValue
10140 const SDLoc &DL, int64_t Offset, EVT PtrVT,
10141 unsigned GAFlags = SIInstrInfo::MO_NONE) {
10142 assert(isInt<32>(Offset + 4) && "32-bit offset is expected!");
10143 // In order to support pc-relative addressing, the PC_ADD_REL_OFFSET SDNode is
10144 // lowered to the following code sequence:
10145 //
10146 // For constant address space:
10147 // s_getpc_b64 s[0:1]
10148 // s_add_u32 s0, s0, $symbol
10149 // s_addc_u32 s1, s1, 0
10150 //
10151 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10152 // a fixup or relocation is emitted to replace $symbol with a literal
10153 // constant, which is a pc-relative offset from the encoding of the $symbol
10154 // operand to the global variable.
10155 //
10156 // For global address space:
10157 // s_getpc_b64 s[0:1]
10158 // s_add_u32 s0, s0, $symbol@{gotpc}rel32@lo
10159 // s_addc_u32 s1, s1, $symbol@{gotpc}rel32@hi
10160 //
10161 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10162 // fixups or relocations are emitted to replace $symbol@*@lo and
10163 // $symbol@*@hi with lower 32 bits and higher 32 bits of a literal constant,
10164 // which is a 64-bit pc-relative offset from the encoding of the $symbol
10165 // operand to the global variable.
10166 if (((const GCNSubtarget &)DAG.getSubtarget()).has64BitLiterals()) {
10167 assert(GAFlags != SIInstrInfo::MO_NONE);
10168
10169 SDValue Ptr =
10170 DAG.getTargetGlobalAddress(GV, DL, MVT::i64, Offset, GAFlags + 2);
10171 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET64, DL, PtrVT, Ptr);
10172 }
10173
10174 SDValue PtrLo = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags);
10175 SDValue PtrHi;
10176 if (GAFlags == SIInstrInfo::MO_NONE)
10177 PtrHi = DAG.getTargetConstant(0, DL, MVT::i32);
10178 else
10179 PtrHi = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags + 1);
10180 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET, DL, PtrVT, PtrLo, PtrHi);
10181}
10182
10183SDValue SITargetLowering::LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI,
10184 SDValue Op,
10185 SelectionDAG &DAG) const {
10186 GlobalAddressSDNode *GSD = cast<GlobalAddressSDNode>(Op);
10187 SDLoc DL(GSD);
10188 EVT PtrVT = Op.getValueType();
10189
10190 const GlobalValue *GV = GSD->getGlobal();
10191 const unsigned AS = GSD->getAddressSpace();
10192 if (((AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::BARRIER) &&
10195 if (AS == AMDGPUAS::LOCAL_ADDRESS && GV->hasExternalLinkage()) {
10196 const GlobalVariable &GVar = *cast<GlobalVariable>(GV);
10197 // HIP uses an unsized array `extern __shared__ T s[]` or similar
10198 // zero-sized type in other languages to declare the dynamic shared
10199 // memory which size is not known at the compile time. They will be
10200 // allocated by the runtime and placed directly after the static
10201 // allocated ones. They all share the same offset.
10202 if (GVar.getGlobalSize(GVar.getDataLayout()) == 0) {
10203 assert(PtrVT == MVT::i32 && "32-bit pointer is expected.");
10204 // Adjust alignment for that dynamic shared memory array.
10206 MFI->setDynLDSAlign(F, GVar);
10207 MFI->setUsesDynamicLDS(true);
10208 return SDValue(
10209 DAG.getMachineNode(AMDGPU::GET_GROUPSTATICSIZE, DL, PtrVT), 0);
10210 }
10211 }
10213 }
10214
10215 if (AS == AMDGPUAS::BARRIER) {
10216 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, GSD->getOffset(),
10218 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0);
10219 }
10220
10221 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
10222 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, GSD->getOffset(),
10224 return DAG.getNode(AMDGPUISD::LDS, DL, MVT::i32, GA);
10225 }
10226
10227 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10228 if (Subtarget->has64BitLiterals()) {
10230 GV, DL, MVT::i64, GSD->getOffset(), SIInstrInfo::MO_ABS64);
10231 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B64, DL, MVT::i64, Addr),
10232 0);
10233 }
10234
10235 SDValue AddrLo = DAG.getTargetGlobalAddress(
10236 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_LO);
10237 AddrLo = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrLo), 0};
10238
10239 SDValue AddrHi = DAG.getTargetGlobalAddress(
10240 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_HI);
10241 AddrHi = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrHi), 0};
10242
10243 return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, AddrLo, AddrHi);
10244 }
10245
10246 if (shouldEmitFixup(GV))
10247 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT);
10248
10249 if (shouldEmitPCReloc(GV))
10250 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT,
10252
10253 SDValue GOTAddr = buildPCRelGlobalAddress(DAG, GV, DL, 0, PtrVT,
10255 PointerType *PtrTy =
10257 const DataLayout &DataLayout = DAG.getDataLayout();
10258 Align Alignment = DataLayout.getABITypeAlign(PtrTy);
10259 MachinePointerInfo PtrInfo =
10261
10262 return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), GOTAddr, PtrInfo, Alignment,
10265}
10266
10267SDValue SITargetLowering::LowerExternalSymbol(SDValue Op,
10268 SelectionDAG &DAG) const {
10269 // TODO: Handle this. It should be mostly the same as LowerGlobalAddress.
10270 const Function &Fn = DAG.getMachineFunction().getFunction();
10271 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10272 Fn, "unsupported external symbol", Op.getDebugLoc()));
10273 return DAG.getPOISON(Op.getValueType());
10274}
10275
10277 const SDLoc &DL, SDValue V) const {
10278 // We can't use S_MOV_B32 directly, because there is no way to specify m0 as
10279 // the destination register.
10280 //
10281 // We can't use CopyToReg, because MachineCSE won't combine COPY instructions,
10282 // so we will end up with redundant moves to m0.
10283 //
10284 // We use a pseudo to ensure we emit s_mov_b32 with m0 as the direct result.
10285
10286 // A Null SDValue creates a glue result.
10287 SDNode *M0 = DAG.getMachineNode(AMDGPU::SI_INIT_M0, DL, MVT::Other, MVT::Glue,
10288 V, Chain);
10289 return SDValue(M0, 0);
10290}
10291
10292SDValue SITargetLowering::lowerImplicitZextParam(SelectionDAG &DAG, SDValue Op,
10293 MVT VT,
10294 unsigned Offset) const {
10295 SDLoc SL(Op);
10296 SDValue Param = lowerKernargMemParameter(
10297 DAG, MVT::i32, MVT::i32, SL, DAG.getEntryNode(), Offset, Align(4), false);
10298 // The local size values will have the hi 16-bits as zero.
10299 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Param,
10300 DAG.getValueType(VT));
10301}
10302
10304 EVT VT) {
10307 "non-hsa intrinsic with hsa target", DL.getDebugLoc()));
10308 return DAG.getPOISON(VT);
10309}
10310
10312 EVT VT) {
10315 "intrinsic not supported on subtarget", DL.getDebugLoc()));
10316 return DAG.getPOISON(VT);
10317}
10318
10320 ArrayRef<SDValue> Elts) {
10321 assert(!Elts.empty());
10322 MVT Type;
10323 unsigned NumElts = Elts.size();
10324
10325 if (NumElts <= 12) {
10326 Type = MVT::getVectorVT(MVT::f32, NumElts);
10327 } else {
10328 assert(Elts.size() <= 16);
10329 Type = MVT::v16f32;
10330 NumElts = 16;
10331 }
10332
10333 SmallVector<SDValue, 16> VecElts(NumElts);
10334 for (unsigned i = 0; i < Elts.size(); ++i) {
10335 SDValue Elt = Elts[i];
10336 if (Elt.getValueType() != MVT::f32)
10337 Elt = DAG.getBitcast(MVT::f32, Elt);
10338 VecElts[i] = Elt;
10339 }
10340 for (unsigned i = Elts.size(); i < NumElts; ++i)
10341 VecElts[i] = DAG.getPOISON(MVT::f32);
10342
10343 if (NumElts == 1)
10344 return VecElts[0];
10345 return DAG.getBuildVector(Type, DL, VecElts);
10346}
10347
10348static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT,
10349 SDValue Src, int ExtraElts) {
10350 EVT SrcVT = Src.getValueType();
10351
10353
10354 if (SrcVT.isVector())
10355 DAG.ExtractVectorElements(Src, Elts);
10356 else
10357 Elts.push_back(Src);
10358
10359 SDValue Undef = DAG.getPOISON(SrcVT.getScalarType());
10360 while (ExtraElts--)
10361 Elts.push_back(Undef);
10362
10363 return DAG.getBuildVector(CastVT, DL, Elts);
10364}
10365
10366// Re-construct the required return value for a image load intrinsic.
10367// This is more complicated due to the optional use TexFailCtrl which means the
10368// required return type is an aggregate
10370 ArrayRef<EVT> ResultTypes, bool IsTexFail,
10371 bool Unpacked, bool IsD16, int DMaskPop,
10372 int NumVDataDwords, bool IsAtomicPacked16Bit,
10373 const SDLoc &DL) {
10374 // Determine the required return type. This is the same regardless of
10375 // IsTexFail flag
10376 EVT ReqRetVT = ResultTypes[0];
10377 int ReqRetNumElts = ReqRetVT.isVector() ? ReqRetVT.getVectorNumElements() : 1;
10378 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10379 ? (ReqRetNumElts + 1) / 2
10380 : ReqRetNumElts;
10381
10382 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10383
10384 MVT DataDwordVT =
10385 NumDataDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, NumDataDwords);
10386
10387 MVT MaskPopVT =
10388 MaskPopDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, MaskPopDwords);
10389
10390 SDValue Data(Result, 0);
10391 SDValue TexFail;
10392
10393 if (DMaskPop > 0 && Data.getValueType() != MaskPopVT) {
10394 SDValue ZeroIdx = DAG.getConstant(0, DL, MVT::i32);
10395 if (MaskPopVT.isVector()) {
10396 Data = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, MaskPopVT,
10397 SDValue(Result, 0), ZeroIdx);
10398 } else {
10399 Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MaskPopVT,
10400 SDValue(Result, 0), ZeroIdx);
10401 }
10402 }
10403
10404 if (DataDwordVT.isVector() && !IsAtomicPacked16Bit)
10405 Data = padEltsToUndef(DAG, DL, DataDwordVT, Data,
10406 NumDataDwords - MaskPopDwords);
10407
10408 if (IsD16)
10409 Data = adjustLoadValueTypeImpl(Data, ReqRetVT, DL, DAG, Unpacked);
10410
10411 EVT LegalReqRetVT = ReqRetVT;
10412 if (!ReqRetVT.isVector()) {
10413 if (!Data.getValueType().isInteger())
10414 Data = DAG.getNode(ISD::BITCAST, DL,
10415 Data.getValueType().changeTypeToInteger(), Data);
10416 Data = DAG.getNode(ISD::TRUNCATE, DL, ReqRetVT.changeTypeToInteger(), Data);
10417 } else {
10418 // We need to widen the return vector to a legal type
10419 if ((ReqRetVT.getVectorNumElements() % 2) == 1 &&
10420 ReqRetVT.getVectorElementType().getSizeInBits() == 16) {
10421 LegalReqRetVT =
10423 ReqRetVT.getVectorNumElements() + 1);
10424 }
10425 }
10426 Data = DAG.getNode(ISD::BITCAST, DL, LegalReqRetVT, Data);
10427
10428 if (IsTexFail) {
10429 TexFail =
10430 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, SDValue(Result, 0),
10431 DAG.getConstant(MaskPopDwords, DL, MVT::i32));
10432
10433 return DAG.getMergeValues({Data, TexFail, SDValue(Result, 1)}, DL);
10434 }
10435
10436 if (Result->getNumValues() == 1)
10437 return Data;
10438
10439 return DAG.getMergeValues({Data, SDValue(Result, 1)}, DL);
10440}
10441
10442static bool parseTexFail(SDValue TexFailCtrl, SelectionDAG &DAG, SDValue *TFE,
10443 SDValue *LWE, bool &IsTexFail) {
10444 auto *TexFailCtrlConst = cast<ConstantSDNode>(TexFailCtrl.getNode());
10445
10446 uint64_t Value = TexFailCtrlConst->getZExtValue();
10447 if (Value) {
10448 IsTexFail = true;
10449 }
10450
10451 SDLoc DL(TexFailCtrlConst);
10452 *TFE = DAG.getTargetConstant((Value & 0x1) ? 1 : 0, DL, MVT::i32);
10453 Value &= ~(uint64_t)0x1;
10454 *LWE = DAG.getTargetConstant((Value & 0x2) ? 1 : 0, DL, MVT::i32);
10455 Value &= ~(uint64_t)0x2;
10456
10457 return Value == 0;
10458}
10459
10461 MVT PackVectorVT,
10462 SmallVectorImpl<SDValue> &PackedAddrs,
10463 unsigned DimIdx, unsigned EndIdx,
10464 unsigned NumGradients) {
10465 SDLoc DL(Op);
10466 for (unsigned I = DimIdx; I < EndIdx; I++) {
10467 SDValue Addr = Op.getOperand(I);
10468
10469 // Gradients are packed with undef for each coordinate.
10470 // In <hi 16 bit>,<lo 16 bit> notation, the registers look like this:
10471 // 1D: undef,dx/dh; undef,dx/dv
10472 // 2D: dy/dh,dx/dh; dy/dv,dx/dv
10473 // 3D: dy/dh,dx/dh; undef,dz/dh; dy/dv,dx/dv; undef,dz/dv
10474 if (((I + 1) >= EndIdx) ||
10475 ((NumGradients / 2) % 2 == 1 && (I == DimIdx + (NumGradients / 2) - 1 ||
10476 I == DimIdx + NumGradients - 1))) {
10477 if (Addr.getValueType() != MVT::i16)
10478 Addr = DAG.getBitcast(MVT::i16, Addr);
10479 Addr = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Addr);
10480 } else {
10481 Addr = DAG.getBuildVector(PackVectorVT, DL, {Addr, Op.getOperand(I + 1)});
10482 I++;
10483 }
10484 Addr = DAG.getBitcast(MVT::f32, Addr);
10485 PackedAddrs.push_back(Addr);
10486 }
10487}
10488
10489/// Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and
10490/// return poison values of \p ResultTypes, preserving the chain if present.
10492 ArrayRef<EVT> ResultTypes,
10493 const SDLoc &DL, const Twine &Msg) {
10495 DAG.getMachineFunction().getFunction(), Msg, DL.getDebugLoc()));
10496 return DAG.getErrorMergeValues(ResultTypes, Op.getOperand(0), DL);
10497}
10498
10499SDValue SITargetLowering::lowerImage(SDValue Op,
10501 SelectionDAG &DAG, bool WithChain) const {
10502 SDLoc DL(Op);
10504 const GCNSubtarget *ST = &MF.getSubtarget<GCNSubtarget>();
10505 unsigned IntrOpcode = Intr->BaseOpcode;
10506 // For image atomic: use no-return opcode if result is unused.
10507 if (Intr->AtomicNoRetBaseOpcode != Intr->BaseOpcode &&
10508 !Op.getNode()->hasAnyUseOfValue(0))
10509 IntrOpcode = Intr->AtomicNoRetBaseOpcode;
10510 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10512 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfo(Intr->Dim);
10513 bool IsGFX10Plus = AMDGPU::isGFX10Plus(*Subtarget);
10514 bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
10515 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
10516 bool IsGFX13 = AMDGPU::isGFX13(*Subtarget);
10517
10518 SmallVector<EVT, 3> ResultTypes(Op->values());
10519 SmallVector<EVT, 3> OrigResultTypes(Op->values());
10520 if (BaseOpcode->NoReturn && BaseOpcode->Atomic)
10521 ResultTypes.erase(&ResultTypes[0]);
10522
10523 bool IsD16 = false;
10524 bool IsG16 = false;
10525 bool IsA16 = false;
10526 SDValue VData;
10527 int NumVDataDwords = 0;
10528 bool AdjustRetType = false;
10529 bool IsAtomicPacked16Bit = false;
10530
10531 // Offset of intrinsic arguments
10532 const unsigned ArgOffset = WithChain ? 2 : 1;
10533
10534 unsigned DMask;
10535 unsigned DMaskLanes = 0;
10536
10537 if (BaseOpcode->Atomic) {
10538 VData = Op.getOperand(2);
10539
10540 IsAtomicPacked16Bit =
10541 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10542 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10543 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10544 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10545
10546 if (!IsAtomicPacked16Bit && VData.getValueSizeInBits() != 32 &&
10547 VData.getValueSizeInBits() != 64) {
10548 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10549 "unsupported image atomic data type");
10550 }
10551
10552 bool Is64Bit = VData.getValueSizeInBits() == 64;
10553 if (BaseOpcode->AtomicX2) {
10554 SDValue VData2 = Op.getOperand(3);
10555 VData = DAG.getBuildVector(Is64Bit ? MVT::v2i64 : MVT::v2i32, DL,
10556 {VData, VData2});
10557 if (Is64Bit)
10558 VData = DAG.getBitcast(MVT::v4i32, VData);
10559
10560 if (!BaseOpcode->NoReturn)
10561 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10562
10563 DMask = Is64Bit ? 0xf : 0x3;
10564 NumVDataDwords = Is64Bit ? 4 : 2;
10565 } else {
10566 DMask = Is64Bit ? 0x3 : 0x1;
10567 NumVDataDwords = Is64Bit ? 2 : 1;
10568 }
10569 } else {
10570 DMask = Op->getConstantOperandVal(ArgOffset + Intr->DMaskIndex);
10571 DMaskLanes = BaseOpcode->Gather4 ? 4 : llvm::popcount(DMask);
10572
10573 if (BaseOpcode->Store) {
10574 VData = Op.getOperand(2);
10575
10576 MVT StoreVT = VData.getSimpleValueType();
10577 MVT StoreScalarVT = StoreVT.getScalarType();
10578 if (StoreScalarVT != MVT::f16 && StoreScalarVT.getSizeInBits() != 32 &&
10579 StoreScalarVT.getSizeInBits() != 64) {
10580 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10581 "unsupported image store data type");
10582 }
10583 if (StoreScalarVT == MVT::f16) {
10584 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10585 return Op; // D16 is unsupported for this instruction
10586
10587 IsD16 = true;
10588 VData = handleD16VData(VData, DAG, true);
10589 }
10590
10591 NumVDataDwords = (VData.getValueType().getSizeInBits() + 31) / 32;
10592 } else if (!BaseOpcode->NoReturn) {
10593 // Work out the num dwords based on the dmask popcount and underlying type
10594 // and whether packing is supported.
10595 MVT LoadVT = ResultTypes[0].getSimpleVT();
10596 MVT LoadScalarVT = LoadVT.getScalarType();
10597 if (LoadScalarVT != MVT::f16 && LoadScalarVT.getSizeInBits() != 32 &&
10598 LoadScalarVT.getSizeInBits() != 64) {
10599 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10600 "unsupported image load data type");
10601 }
10602 if (LoadScalarVT == MVT::f16) {
10603 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10604 return Op; // D16 is unsupported for this instruction
10605
10606 IsD16 = true;
10607 }
10608
10609 // Confirm that the return type is large enough for the dmask specified
10610 if ((LoadVT.isVector() && LoadVT.getVectorNumElements() < DMaskLanes) ||
10611 (!LoadVT.isVector() && DMaskLanes > 1))
10612 return Op;
10613
10614 // The sq block of gfx8 and gfx9 do not estimate register use correctly
10615 // for d16 image_gather4, image_gather4_l, and image_gather4_lz
10616 // instructions.
10617 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10618 !(BaseOpcode->Gather4 && Subtarget->hasImageGather4D16Bug()))
10619 NumVDataDwords = (DMaskLanes + 1) / 2;
10620 else
10621 NumVDataDwords = DMaskLanes;
10622
10623 AdjustRetType = true;
10624 }
10625 }
10626
10627 unsigned VAddrEnd = ArgOffset + Intr->VAddrEnd;
10629
10630 // Check for 16 bit addresses or derivatives and pack if true.
10631 MVT VAddrVT =
10632 Op.getOperand(ArgOffset + Intr->GradientStart).getSimpleValueType();
10633 MVT VAddrScalarVT = VAddrVT.getScalarType();
10634 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10635 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10636
10637 VAddrVT = Op.getOperand(ArgOffset + Intr->CoordStart).getSimpleValueType();
10638 VAddrScalarVT = VAddrVT.getScalarType();
10639 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10640 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10641
10642 // Push back extra arguments.
10643 for (unsigned I = Intr->VAddrStart; I < Intr->GradientStart; I++) {
10644 if (IsA16 && (Op.getOperand(ArgOffset + I).getValueType() == MVT::f16)) {
10645 assert(I == Intr->BiasIndex && "Got unexpected 16-bit extra argument");
10646 // Special handling of bias when A16 is on. Bias is of type half but
10647 // occupies full 32-bit.
10648 SDValue Bias = DAG.getBuildVector(
10649 MVT::v2f16, DL,
10650 {Op.getOperand(ArgOffset + I), DAG.getPOISON(MVT::f16)});
10651 VAddrs.push_back(Bias);
10652 } else {
10653 assert((!IsA16 || Intr->NumBiasArgs == 0 || I != Intr->BiasIndex) &&
10654 "Bias needs to be converted to 16 bit in A16 mode");
10655 VAddrs.push_back(Op.getOperand(ArgOffset + I));
10656 }
10657 }
10658
10659 if (BaseOpcode->Gradients && !ST->hasG16() && (IsA16 != IsG16)) {
10660 // 16 bit gradients are supported, but are tied to the A16 control
10661 // so both gradients and addresses must be 16 bit
10662 LLVM_DEBUG(
10663 dbgs() << "Failed to lower image intrinsic: 16 bit addresses "
10664 "require 16 bit args for both gradients and addresses");
10665 return Op;
10666 }
10667
10668 if (IsA16) {
10669 if (!ST->hasA16()) {
10670 LLVM_DEBUG(dbgs() << "Failed to lower image intrinsic: Target does not "
10671 "support 16 bit addresses\n");
10672 return Op;
10673 }
10674 }
10675
10676 // We've dealt with incorrect input so we know that if IsA16, IsG16
10677 // are set then we have to compress/pack operands (either address,
10678 // gradient or both)
10679 // In the case where a16 and gradients are tied (no G16 support) then we
10680 // have already verified that both IsA16 and IsG16 are true
10681 if (BaseOpcode->Gradients && IsG16 && ST->hasG16()) {
10682 // Activate g16
10683 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10685 IntrOpcode = G16MappingInfo->G16; // set new opcode to variant with _g16
10686 }
10687
10688 // Add gradients (packed or unpacked)
10689 if (IsG16) {
10690 // Pack the gradients
10691 // const int PackEndIdx = IsA16 ? VAddrEnd : (ArgOffset + Intr->CoordStart);
10692 packImage16bitOpsToDwords(DAG, Op, GradPackVectorVT, VAddrs,
10693 ArgOffset + Intr->GradientStart,
10694 ArgOffset + Intr->CoordStart, Intr->NumGradients);
10695 } else {
10696 for (unsigned I = ArgOffset + Intr->GradientStart;
10697 I < ArgOffset + Intr->CoordStart; I++)
10698 VAddrs.push_back(Op.getOperand(I));
10699 }
10700
10701 // Add addresses (packed or unpacked)
10702 if (IsA16) {
10703 packImage16bitOpsToDwords(DAG, Op, AddrPackVectorVT, VAddrs,
10704 ArgOffset + Intr->CoordStart, VAddrEnd,
10705 0 /* No gradients */);
10706 } else {
10707 // Add uncompressed address
10708 for (unsigned I = ArgOffset + Intr->CoordStart; I < VAddrEnd; I++)
10709 VAddrs.push_back(Op.getOperand(I));
10710 }
10711
10712 // If the register allocator cannot place the address registers contiguously
10713 // without introducing moves, then using the non-sequential address encoding
10714 // is always preferable, since it saves VALU instructions and is usually a
10715 // wash in terms of code size or even better.
10716 //
10717 // However, we currently have no way of hinting to the register allocator that
10718 // MIMG addresses should be placed contiguously when it is possible to do so,
10719 // so force non-NSA for the common 2-address case as a heuristic.
10720 //
10721 // SIShrinkInstructions will convert NSA encodings to non-NSA after register
10722 // allocation when possible.
10723 //
10724 // Partial NSA is allowed on GFX11+ where the final register is a contiguous
10725 // set of the remaining addresses.
10726 const unsigned NSAMaxSize = ST->getNSAMaxSize(BaseOpcode->Sampler);
10727 const bool HasPartialNSAEncoding = ST->hasPartialNSAEncoding();
10728 const bool UseNSA = ST->hasNSAEncoding() &&
10729 VAddrs.size() >= ST->getNSAThreshold(MF) &&
10730 (VAddrs.size() <= NSAMaxSize || HasPartialNSAEncoding);
10731 const bool UsePartialNSA =
10732 UseNSA && HasPartialNSAEncoding && VAddrs.size() > NSAMaxSize;
10733
10734 SDValue VAddr;
10735 if (UsePartialNSA) {
10736 VAddr = getBuildDwordsVector(DAG, DL,
10737 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10738 } else if (!UseNSA) {
10739 VAddr = getBuildDwordsVector(DAG, DL, VAddrs);
10740 }
10741
10742 SDValue True = DAG.getTargetConstant(1, DL, MVT::i1);
10743 SDValue False = DAG.getTargetConstant(0, DL, MVT::i1);
10744 SDValue Unorm;
10745 if (!BaseOpcode->Sampler) {
10746 Unorm = True;
10747 } else {
10748 uint64_t UnormConst =
10749 Op.getConstantOperandVal(ArgOffset + Intr->UnormIndex);
10750
10751 Unorm = UnormConst ? True : False;
10752 }
10753
10754 SDValue TFE;
10755 SDValue LWE;
10756 SDValue TexFail = Op.getOperand(ArgOffset + Intr->TexFailCtrlIndex);
10757 bool IsTexFail = false;
10758 if (!parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10759 return Op;
10760
10761 if (IsTexFail) {
10762 if (!DMaskLanes) {
10763 // Expecting to get an error flag since TFC is on - and dmask is 0
10764 // Force dmask to be at least 1 otherwise the instruction will fail
10765 DMask = 0x1;
10766 DMaskLanes = 1;
10767 NumVDataDwords = 1;
10768 }
10769 NumVDataDwords += 1;
10770 AdjustRetType = true;
10771 }
10772
10773 // Has something earlier tagged that the return type needs adjusting
10774 // This happens if the instruction is a load or has set TexFailCtrl flags
10775 if (AdjustRetType) {
10776 // NumVDataDwords reflects the true number of dwords required in the return
10777 // type
10778 if (DMaskLanes == 0 && !BaseOpcode->Store) {
10779 // This is a no-op load. This can be eliminated
10780 SDValue Undef = DAG.getPOISON(Op.getValueType());
10781 if (isa<MemSDNode>(Op))
10782 return DAG.getMergeValues({Undef, Op.getOperand(0)}, DL);
10783 return Undef;
10784 }
10785
10786 EVT NewVT = NumVDataDwords > 1 ? EVT::getVectorVT(*DAG.getContext(),
10787 MVT::i32, NumVDataDwords)
10788 : MVT::i32;
10789
10790 ResultTypes[0] = NewVT;
10791 if (ResultTypes.size() == 3) {
10792 // Original result was aggregate type used for TexFailCtrl results
10793 // The actual instruction returns as a vector type which has now been
10794 // created. Remove the aggregate result.
10795 ResultTypes.erase(&ResultTypes[1]);
10796 }
10797 }
10798
10799 unsigned CPol = Op.getConstantOperandVal(ArgOffset + Intr->CachePolicyIndex);
10800 // Keep GLC only when the atomic's result is actually used.
10801 if (BaseOpcode->Atomic && !BaseOpcode->NoReturn)
10803 if (CPol & ~((IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12) |
10805 return Op;
10806
10808 if (BaseOpcode->Store || BaseOpcode->Atomic)
10809 Ops.push_back(VData); // vdata
10810 if (UsePartialNSA) {
10811 append_range(Ops, ArrayRef(VAddrs).take_front(NSAMaxSize - 1));
10812 Ops.push_back(VAddr);
10813 } else if (UseNSA)
10814 append_range(Ops, VAddrs);
10815 else
10816 Ops.push_back(VAddr);
10817 SDValue Rsrc = Op.getOperand(ArgOffset + Intr->RsrcIndex);
10818 EVT RsrcVT = Rsrc.getValueType();
10819 bool IndexedRsrc = IsGFX13 && RsrcVT == MVT::i32;
10820 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32 && !IndexedRsrc)
10821 return Op;
10822 Ops.push_back(Rsrc);
10823 bool IsSampIndexed = false;
10824 if (BaseOpcode->Sampler) {
10825 SDValue Samp = Op.getOperand(ArgOffset + Intr->SampIndex);
10826 EVT SampVT = Samp.getValueType();
10827 IsSampIndexed = IsGFX13 && SampVT == MVT::i32;
10828 if (SampVT != MVT::v4i32 && !IsSampIndexed)
10829 return Op;
10830 Ops.push_back(Samp);
10831 }
10832 Ops.push_back(DAG.getTargetConstant(DMask, DL, MVT::i32));
10833 if (IsGFX10Plus)
10834 Ops.push_back(DAG.getTargetConstant(DimInfo->Encoding, DL, MVT::i32));
10835 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10836 Ops.push_back(Unorm);
10837 Ops.push_back(DAG.getTargetConstant(CPol, DL, MVT::i32));
10838 Ops.push_back(IsA16 && // r128, a16 for gfx9
10839 ST->hasFeature(AMDGPU::FeatureR128A16)
10840 ? True
10841 : False);
10842 if (IsGFX10Plus)
10843 Ops.push_back(IsA16 ? True : False);
10844
10845 if (!Subtarget->hasGFX90AInsts())
10846 Ops.push_back(TFE); // tfe
10847 else if (TFE->getAsZExtVal()) {
10848 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10850 "TFE is not supported on this GPU", DL.getDebugLoc()));
10851 }
10852
10853 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10854 Ops.push_back(LWE); // lwe
10855 if (!IsGFX10Plus)
10856 Ops.push_back(DimInfo->DA ? True : False);
10857 if (BaseOpcode->HasD16)
10858 Ops.push_back(IsD16 ? True : False);
10859 if (isa<MemSDNode>(Op))
10860 Ops.push_back(Op.getOperand(0)); // chain
10861
10862 int NumVAddrDwords =
10863 UseNSA ? VAddrs.size() : VAddr.getValueType().getSizeInBits() / 32;
10864 int Opcode = -1;
10865
10866 if (IsGFX13) {
10867 Opcode =
10868 AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx13, NumVDataDwords,
10869 NumVAddrDwords, IndexedRsrc, IsSampIndexed);
10870 } else if (IsGFX12Plus) {
10871 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx12,
10872 NumVDataDwords, NumVAddrDwords);
10873 } else if (IsGFX11Plus) {
10874 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10875 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10876 : AMDGPU::MIMGEncGfx11Default,
10877 NumVDataDwords, NumVAddrDwords);
10878 } else if (IsGFX10Plus) {
10879 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10880 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10881 : AMDGPU::MIMGEncGfx10Default,
10882 NumVDataDwords, NumVAddrDwords);
10883 } else {
10884 if (Subtarget->hasGFX90AInsts()) {
10885 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx90a,
10886 NumVDataDwords, NumVAddrDwords);
10887 if (Opcode == -1) {
10889 DAG, Op, OrigResultTypes, DL,
10890 "requested image instruction is not supported on this GPU");
10891 }
10892 }
10893 if (Opcode == -1 &&
10894 Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10895 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx8,
10896 NumVDataDwords, NumVAddrDwords);
10897 if (Opcode == -1)
10898 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx6,
10899 NumVDataDwords, NumVAddrDwords);
10900 }
10901 if (Opcode == -1)
10902 return Op;
10903
10904 MachineSDNode *NewNode = DAG.getMachineNode(Opcode, DL, ResultTypes, Ops);
10905 if (auto *MemOp = dyn_cast<MemSDNode>(Op)) {
10906 MachineMemOperand *MemRef = MemOp->getMemOperand();
10907 DAG.setNodeMemRefs(NewNode, {MemRef});
10908 }
10909
10910 if (BaseOpcode->NoReturn) {
10911 if (BaseOpcode->Atomic)
10912 return DAG.getMergeValues(
10913 {DAG.getPOISON(OrigResultTypes[0]), SDValue(NewNode, 0)}, DL);
10914
10915 return SDValue(NewNode, 0);
10916 }
10917
10918 if (BaseOpcode->AtomicX2) {
10920 DAG.ExtractVectorElements(SDValue(NewNode, 0), Elt, 0, 1);
10921 return DAG.getMergeValues({Elt[0], SDValue(NewNode, 1)}, DL);
10922 }
10923
10924 return constructRetValue(DAG, NewNode, OrigResultTypes, IsTexFail,
10925 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10926 NumVDataDwords, IsAtomicPacked16Bit, DL);
10927}
10928
10929SDValue SITargetLowering::lowerSBuffer(EVT VT, EVT MemVT, SDLoc DL,
10930 SDValue Chain, SDValue Rsrc,
10931 SDValue Offset, SDValue CachePolicy,
10932 SelectionDAG &DAG,
10933 MachineMemOperand *MMO) const {
10935 bool HasChainResult = MMO != nullptr;
10936
10937 // SBUFFER_LOAD only produces values that fill whole SGPRs, apart from the
10938 // subword loads below.
10939 bool IsSubwordLoad = (MemVT == MVT::i8 || MemVT == MVT::i16) &&
10940 Subtarget->hasScalarSubwordLoads();
10941 if ((!isTypeLegal(VT) || VT.getSizeInBits() % 32 != 0) && !IsSubwordLoad) {
10942 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10943 MF.getFunction(), "unsupported s_buffer_load result type",
10944 DL.getDebugLoc()));
10945 EVT ResultTypes[] = {VT, MVT::Other};
10946 return DAG.getErrorMergeValues(
10947 ArrayRef(ResultTypes, HasChainResult ? 2 : 1), Chain, DL);
10948 }
10949
10950 if (!HasChainResult) {
10951 const DataLayout &DataLayout = DAG.getDataLayout();
10953 DataLayout.getABITypeAlign(MemVT.getTypeForEVT(*DAG.getContext()));
10954
10955 MMO = MF.getMachineMemOperand(MachinePointerInfo(),
10959 MemVT.getStoreSize(), Alignment);
10960 }
10961
10962 if (!Offset->isDivergent()) {
10963 SDValue Ops[] = {Chain, Rsrc, Offset, CachePolicy};
10964
10965 // Lower llvm.amdgcn.*s.buffer.load.{i,u}N intrinsics. First, generate
10966 // s_buffer_load_u* for signed and unsigned load instructions. Next, DAG
10967 // combiner tries to merge the s_buffer_load_uN with a sext instruction
10968 // (performSignExtendInRegCombine()) and it replaces s_buffer_load_uN with
10969 // s_buffer_load_iN.
10970 auto HandleScalarSubwordLoads = [&](unsigned Opcode) -> SDValue {
10971 SDValue BufferLoad = DAG.getMemIntrinsicNode(
10972 Opcode, DL, DAG.getVTList(MVT::i32, MVT::Other), Ops, MemVT, MMO);
10973 SDValue LoadVal = DAG.getAnyExtOrTrunc(
10974 DAG.getNode(ISD::TRUNCATE, DL, MemVT, BufferLoad), DL, VT);
10975 if (HasChainResult)
10976 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
10977 return LoadVal;
10978 };
10979 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10980 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10981
10982 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10983 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10984
10985 // Widen vec3 load to vec4. Only 32-bit elements have a vec4 pattern.
10986 if (VT.isVector() && VT.getVectorNumElements() == 3 &&
10987 VT.getVectorElementType().getSizeInBits() == 32 &&
10988 !Subtarget->hasScalarDwordx3Loads()) {
10989 EVT WidenedVT =
10991 auto WidenedOp = DAG.getMemIntrinsicNode(
10992 AMDGPUISD::SBUFFER_LOAD, DL, DAG.getVTList(WidenedVT, MVT::Other),
10993 Ops, WidenedVT,
10994 MF.getMachineMemOperand(MMO, 0, WidenedVT.getStoreSize()));
10995 auto Subvector = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, WidenedOp,
10996 DAG.getVectorIdxConstant(0, DL));
10997 if (HasChainResult)
10998 return DAG.getMergeValues({Subvector, WidenedOp.getValue(1)}, DL);
10999 return Subvector;
11000 }
11001
11002 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_LOAD, DL,
11003 DAG.getVTList(VT, MVT::Other), Ops, MemVT,
11004 MMO);
11005 }
11006
11007 // We have a divergent offset. Emit a MUBUF buffer load instead. We can
11008 // assume that the buffer is unswizzled.
11009 SDValue Ops[] = {
11010 Chain, // Chain
11011 Rsrc, // rsrc
11012 DAG.getConstant(0, DL, MVT::i32), // vindex
11013 {}, // voffset
11014 {}, // soffset
11015 {}, // offset
11016 CachePolicy, // cachepolicy
11017 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11018 };
11019 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
11020 Subtarget->hasScalarSubwordLoads()) {
11021 setBufferOffsets(Offset, DAG, &Ops[3], Align(4));
11022 SDValue Load = handleByteShortBufferLoads(DAG, MemVT, DL, Ops, MMO);
11023 SDValue LoadVal = DAG.getAnyExtOrTrunc(Load.getOperand(0), DL, VT);
11024 if (HasChainResult)
11025 return DAG.getMergeValues({LoadVal, Load.getOperand(1)}, DL);
11026 return LoadVal;
11027 }
11028
11030 unsigned NumLoads = 1;
11031 MVT LoadVT = VT.getSimpleVT();
11032 unsigned NumElts = LoadVT.isVector() ? LoadVT.getVectorNumElements() : 1;
11033 assert((LoadVT.getScalarType() == MVT::i32 ||
11034 LoadVT.getScalarType() == MVT::f32));
11035
11036 if (NumElts == 8 || NumElts == 16) {
11037 NumLoads = NumElts / 4;
11038 LoadVT = MVT::getVectorVT(LoadVT.getScalarType(), 4);
11039 }
11040
11041 SDVTList VTList = DAG.getVTList({LoadVT, MVT::Other});
11042
11043 // Use the alignment to ensure that the required offsets will fit into the
11044 // immediate offsets.
11045 setBufferOffsets(Offset, DAG, &Ops[3],
11046 NumLoads > 1 ? Align(16 * NumLoads) : Align(4));
11047
11048 uint64_t InstOffset = Ops[5]->getAsZExtVal();
11049 unsigned LoadSize = LoadVT.getStoreSize();
11050 for (unsigned i = 0; i < NumLoads; ++i) {
11051 Ops[5] = DAG.getTargetConstant(InstOffset + 16 * i, DL, MVT::i32);
11052 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(MMO, 16 * i, LoadSize);
11053 Loads.push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD, DL, VTList, Ops,
11054 LoadVT, LoadMMO, DAG));
11055 }
11056
11057 if (NumElts == 8 || NumElts == 16) {
11058 SDValue LoadVal = DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Loads);
11059 if (HasChainResult) {
11060 SmallVector<SDValue, 4> LoadChains;
11061 for (SDValue Load : Loads)
11062 LoadChains.push_back(Load.getValue(1));
11063 SDValue Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, LoadChains);
11064 return DAG.getMergeValues({LoadVal, Chain}, DL);
11065 }
11066 return LoadVal;
11067 }
11068
11069 return Loads[0];
11070}
11071
11072SDValue SITargetLowering::lowerWaveID(SelectionDAG &DAG, SDValue Op) const {
11073 // With architected SGPRs, waveIDinGroup is in TTMP8[29:25].
11074 if (!Subtarget->hasArchitectedSGPRs())
11075 return {};
11076 SDLoc SL(Op);
11077 MVT VT = MVT::i32;
11078 SDValue TTMP8 = DAG.getCopyFromReg(DAG.getEntryNode(), SL, AMDGPU::TTMP8, VT);
11079 return DAG.getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
11080 DAG.getConstant(25, SL, VT), DAG.getConstant(5, SL, VT));
11081}
11082
11083SDValue SITargetLowering::lowerConstHwRegRead(SelectionDAG &DAG, SDValue Op,
11084 AMDGPU::Hwreg::Id HwReg,
11085 unsigned LowBit,
11086 unsigned Width) const {
11087 SDLoc SL(Op);
11088 using namespace AMDGPU::Hwreg;
11089 return {DAG.getMachineNode(
11090 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
11091 DAG.getTargetConstant(HwregEncoding::encode(HwReg, LowBit, Width),
11092 SL, MVT::i32)),
11093 0};
11094}
11095
11096SDValue SITargetLowering::lowerWorkitemID(SelectionDAG &DAG, SDValue Op,
11097 unsigned Dim,
11098 const ArgDescriptor &Arg) const {
11099 SDLoc SL(Op);
11101 unsigned MaxID = Subtarget->getMaxWorkitemID(MF.getFunction(), Dim);
11102 if (MaxID == 0)
11103 return DAG.getConstant(0, SL, MVT::i32);
11104
11105 // It's undefined behavior if a function marked with the amdgpu-no-*
11106 // attributes uses the corresponding intrinsic.
11107 if (!Arg)
11108 return DAG.getPOISON(Op->getValueType(0));
11109
11110 SDValue Val = loadInputValue(DAG, &AMDGPU::VGPR_32RegClass, MVT::i32,
11111 SDLoc(DAG.getEntryNode()), Arg);
11112
11113 // Don't bother inserting AssertZext for packed IDs since we're emitting the
11114 // masking operations anyway.
11115 //
11116 // TODO: We could assert the top bit is 0 for the source copy.
11117 if (Arg.isMasked())
11118 return Val;
11119
11120 // Preserve the known bits after expansion to a copy.
11121 EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), llvm::bit_width(MaxID));
11122 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Val,
11123 DAG.getValueType(SmallVT));
11124}
11125
11126SDValue SITargetLowering::lowerFromFP8(SDValue Op, bool IsBF8,
11127 SelectionDAG &DAG) const {
11128 SDLoc SL(Op);
11129 SDValue Src = Op.getOperand(0);
11130 EVT DstVT = Op.getValueType();
11131 bool IsF16 = DstVT.getVectorElementType() == MVT::f16;
11132 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
11133 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11134
11135 unsigned Opc;
11136 if (IsF16)
11137 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11138 else
11139 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11140
11141 // Pack the two i8 lanes into the integer type the packed HW node reads. The
11142 // f16 form takes i16 and the f32 form takes i32. v2i8 bitcasts to i16
11143 // directly and the f32 node reads the low half of an any-extended i32.
11144 EVT PackedVT =
11146 SDValue AsI16 = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
11147 SDValue Packed = DAG.getAnyExtOrTrunc(AsI16, SL, PackedVT);
11148 return DAG.getNode(Opc, SL, DstVT, Packed);
11149}
11150
11151SDValue
11152SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(SDValue Op,
11153 SelectionDAG &DAG) const {
11154 // Handle the OCP FP8 formats (E4M3FN, E5M2) and unsigned E5M3 on subtargets
11155 // with matching HW conversions. Other formats use the generic expansion.
11156 APFloatBase::Semantics FPSemantic =
11157 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11158 const bool IsFP8 = FPSemantic == APFloatBase::S_Float8E4M3FN;
11159 const bool IsBF8 = FPSemantic == APFloatBase::S_Float8E5M2;
11160 const bool IsE5M3 = FPSemantic == APFloatBase::S_Float8E5M3FNU;
11161 const bool HasE5M3ConversionInsts =
11162 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11163 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11164 if (!IsSupported)
11165 return SDValue();
11166
11167 EVT DstVT = Op.getValueType();
11168 // The custom action for a v2i8 source also reaches half conversions on
11169 // targets which only have FP8-to-f32 instructions.
11170 if (DstVT.getScalarType() == MVT::f16 &&
11171 !Subtarget->hasFP8F16ConversionInsts())
11172 return SDValue();
11173
11174 if (IsE5M3) {
11175 if (DstVT.getScalarType() != MVT::f32)
11176 return SDValue();
11177
11178 SDLoc SL(Op);
11179 SDValue Src = Op.getOperand(0);
11180 assert((!DstVT.isVector() || DstVT == MVT::v2f32) &&
11181 "only the v2f32 vector result is custom lowered");
11182
11183 if (DstVT.isVector())
11184 Src = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
11185 Src = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
11186
11187 auto ConvertByte = [&](unsigned ByteSel) {
11188 return DAG.getNode(AMDGPUISD::CVT_F32_FP8_E5M3, SL, MVT::f32, Src,
11189 DAG.getTargetConstant(ByteSel, SL, MVT::i32));
11190 };
11191
11192 if (!DstVT.isVector())
11193 return ConvertByte(0);
11194 return DAG.getBuildVector(DstVT, SL, {ConvertByte(0), ConvertByte(1)});
11195 }
11196
11197 if (!DstVT.isVector()) {
11198 SDValue Src = Op.getOperand(0);
11199 if (Src.getValueType() != MVT::i32) {
11200 SDLoc SL(Op);
11201 SDValue SrcI32 = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
11202 return DAG.getNode(ISD::CONVERT_FROM_ARBITRARY_FP, SL, DstVT, SrcI32,
11203 Op.getOperand(1));
11204 }
11205 return Op;
11206 }
11207
11208 EVT EltVT = DstVT.getVectorElementType();
11209 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11210 return lowerFromFP8(Op, IsBF8, DAG);
11211 return SDValue();
11212}
11213
11214SDValue SITargetLowering::lowerToFP8(SDValue Op, bool IsBF8, bool IsE5M3,
11215 SelectionDAG &DAG) const {
11216 SDLoc SL(Op);
11217 SDValue Src = Op.getOperand(0);
11218 EVT ResVT = Op.getValueType();
11219 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11220 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11221 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11222 assert((!ResVT.isVector() || ResVT == MVT::v2i8) &&
11223 "only the v2i8 vector result is custom lowered");
11224
11225 if (IsF16) {
11226 unsigned Opc =
11227 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11228 SDValue Bytes = DAG.getNode(Opc, SL, MVT::i16, Src);
11229 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11230 }
11231
11232 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32
11233 : IsE5M3 ? AMDGPUISD::CVT_PK_FP8_F32_E5M3
11234 : AMDGPUISD::CVT_PK_FP8_F32;
11235 SDValue PoisonI32 = DAG.getPOISON(MVT::i32);
11236 SDValue WordSel = DAG.getTargetConstant(0, SL, MVT::i1);
11237
11238 if (!ResVT.isVector()) {
11239 // Convert one lane, the second is unused. Feed it the same source so the
11240 // instruction does not read an undefined register.
11241 SDValue Packed =
11242 DAG.getNode(Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11243 return DAG.getAnyExtOrTrunc(Packed, SL, ResVT);
11244 }
11245
11246 SDValue A = DAG.getExtractVectorElt(SL, MVT::f32, Src, 0);
11247 SDValue B = DAG.getExtractVectorElt(SL, MVT::f32, Src, 1);
11248 SDValue Packed = DAG.getNode(Opc, SL, MVT::i32, A, B, PoisonI32, WordSel);
11249 SDValue Bytes = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Packed);
11250 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11251}
11252
11253SDValue
11254SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(SDValue Op,
11255 SelectionDAG &DAG) const {
11256 // The OCP FP8 formats (E4M3FN, E5M2) and unsigned E5M3 map to HW conversions
11257 // on subtargets that support them. Everything else uses generic expansion.
11259 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11260 const bool IsFP8 = Sem == APFloatBase::S_Float8E4M3FN;
11261 const bool IsBF8 = Sem == APFloatBase::S_Float8E5M2;
11262 const bool IsE5M3 = Sem == APFloatBase::S_Float8E5M3FNU;
11263 const bool HasE5M3ConversionInsts =
11264 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11265 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11266 if (!IsSupported)
11267 return SDValue();
11268
11269 // The HW conversions only support nearest-even. The OCP conversions do not
11270 // saturate. The unsigned E5M3 conversion always clamps out-of-range inputs,
11271 // which also refines the non-saturating form where those inputs are poison.
11272 if (static_cast<RoundingMode>(Op.getConstantOperandVal(2)) !=
11274 return SDValue();
11275 if (!IsE5M3 && Op.getConstantOperandVal(3) != 0)
11276 return SDValue();
11277
11278 EVT SrcEltVT = Op.getOperand(0).getValueType().getScalarType();
11279 // The f32 form is built here rather than by a tablegen pattern because the
11280 // HW result is i32 while the node result is i16 after the i8 promotion.
11281 if (SrcEltVT == MVT::f32)
11282 return lowerToFP8(Op, IsBF8, IsE5M3, DAG);
11283 if (!IsE5M3 && SrcEltVT == MVT::f16 &&
11284 Subtarget->hasF16FP8ConversionInsts()) {
11285 // A scalar conversion is selected from the generic node by tablegen, only
11286 // the illegal v2i8 result type needs lowering here.
11287 if (!Op.getValueType().isVector())
11288 return Op;
11289 return lowerToFP8(Op, IsBF8, false, DAG);
11290 }
11291 return SDValue();
11292}
11293
11294SDValue SITargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
11295 SelectionDAG &DAG) const {
11297 auto *MFI = MF.getInfo<SIMachineFunctionInfo>();
11298
11299 EVT VT = Op.getValueType();
11300 SDLoc DL(Op);
11301 unsigned IntrinsicID = Op.getConstantOperandVal(0);
11302
11303 // TODO: Should this propagate fast-math-flags?
11304
11305 switch (IntrinsicID) {
11306 case Intrinsic::amdgcn_wave_reduce_min:
11307 case Intrinsic::amdgcn_wave_reduce_umin:
11308 case Intrinsic::amdgcn_wave_reduce_fmin:
11309 case Intrinsic::amdgcn_wave_reduce_max:
11310 case Intrinsic::amdgcn_wave_reduce_umax:
11311 case Intrinsic::amdgcn_wave_reduce_fmax:
11312 case Intrinsic::amdgcn_wave_reduce_add:
11313 case Intrinsic::amdgcn_wave_reduce_fadd:
11314 case Intrinsic::amdgcn_wave_reduce_sub:
11315 case Intrinsic::amdgcn_wave_reduce_fsub:
11316 case Intrinsic::amdgcn_wave_reduce_and:
11317 case Intrinsic::amdgcn_wave_reduce_or:
11318 case Intrinsic::amdgcn_wave_reduce_xor: {
11319 EVT SrcVT = Op.getOperand(1).getValueType();
11320 if (SrcVT.getFixedSizeInBits() == 16) {
11321 bool IsFPOp = SrcVT.isFloatingPoint();
11322 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11323 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11324 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11325 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11326 unsigned ExtOpc = IsFPOp ? ISD::FP_EXTEND
11327 : NeedsSignExt ? ISD::SIGN_EXTEND
11329 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11330 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11331 SDValue ExtendedSrc = DAG.getNode(ExtOpc, DL, ExtType, Op.getOperand(1));
11332 SDValue Strategy = Op.getOperand(2);
11334 Op.getOperand(0), ExtendedSrc, Strategy);
11335 if (IsFPOp)
11336 return DAG.getNode(ISD::FP_ROUND, DL, SrcType, Result,
11337 DAG.getTargetConstant(1, DL, MVT::i32));
11338 else
11339 return DAG.getNode(ISD::TRUNCATE, DL, SrcType, Result);
11340 }
11341 return SDValue();
11342 }
11343 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11344 if (!MFI->getUserSGPRInfo().hasImplicitBufferPtr()) {
11345 const char *Error =
11346 Subtarget->hasArchitectedFlatScratch()
11347 ? "intrinsic not supported on subtarget"
11348 : !Subtarget->isMesa3DOS()
11349 ? "intrinsic not supported for OS"
11350 : "intrinsic not supported for calling convention";
11351 DAG.getContext()->diagnose(
11352 DiagnosticInfoUnsupported(MF.getFunction(), Error, DL.getDebugLoc()));
11353 return DAG.getPOISON(VT);
11354 }
11355
11356 return getPreloadedValue(DAG, *MFI, VT,
11358 }
11359 case Intrinsic::amdgcn_dispatch_ptr:
11360 case Intrinsic::amdgcn_queue_ptr: {
11361 if (!Subtarget->isAmdHsaOrMesa(MF.getFunction())) {
11362 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11363 MF.getFunction(), "unsupported hsa intrinsic without hsa target",
11364 DL.getDebugLoc()));
11365 return DAG.getPOISON(VT);
11366 }
11367
11368 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11371 return getPreloadedValue(DAG, *MFI, VT, RegID);
11372 }
11373 case Intrinsic::amdgcn_implicitarg_ptr: {
11374 if (MFI->isEntryFunction())
11375 return getImplicitArgPtr(DAG, DL);
11376 return getPreloadedValue(DAG, *MFI, VT,
11378 }
11379 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11380 if (!AMDGPU::isKernel(MF.getFunction())) {
11381 // This only makes sense to call in a kernel, so just lower to null.
11382 return DAG.getConstant(0, DL, VT);
11383 }
11384
11385 return getPreloadedValue(DAG, *MFI, VT,
11387 }
11388 case Intrinsic::amdgcn_dispatch_id: {
11389 return getPreloadedValue(DAG, *MFI, VT, AMDGPUFunctionArgInfo::DISPATCH_ID);
11390 }
11391 case Intrinsic::amdgcn_rcp:
11392 return DAG.getNode(AMDGPUISD::RCP, DL, VT, Op.getOperand(1));
11393 case Intrinsic::amdgcn_rsq:
11394 return DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11395 case Intrinsic::amdgcn_rsq_legacy:
11396 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11397 return emitRemovedIntrinsicError(DAG, DL, VT);
11398 return SDValue();
11399 case Intrinsic::amdgcn_rcp_legacy:
11400 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11401 return emitRemovedIntrinsicError(DAG, DL, VT);
11402 return DAG.getNode(AMDGPUISD::RCP_LEGACY, DL, VT, Op.getOperand(1));
11403 case Intrinsic::amdgcn_fma_legacy:
11404 case Intrinsic::amdgcn_sudot4:
11405 case Intrinsic::amdgcn_sudot8:
11406 case Intrinsic::amdgcn_tanh:
11407 return SDValue();
11408 case Intrinsic::amdgcn_rsq_clamp: {
11409 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11410 return DAG.getNode(AMDGPUISD::RSQ_CLAMP, DL, VT, Op.getOperand(1));
11411
11412 Type *Type = VT.getTypeForEVT(*DAG.getContext());
11413 APFloat Max = APFloat::getLargest(Type->getFltSemantics());
11414 APFloat Min = APFloat::getLargest(Type->getFltSemantics(), true);
11415
11416 SDValue Rsq = DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11417 SDValue Tmp =
11418 DAG.getNode(ISD::FMINNUM, DL, VT, Rsq, DAG.getConstantFP(Max, DL, VT));
11419 return DAG.getNode(ISD::FMAXNUM, DL, VT, Tmp,
11420 DAG.getConstantFP(Min, DL, VT));
11421 }
11422 case Intrinsic::r600_read_ngroups_x:
11423 if (Subtarget->isAmdHsaOS())
11424 return emitNonHSAIntrinsicError(DAG, DL, VT);
11425
11426 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11428 false);
11429 case Intrinsic::r600_read_ngroups_y:
11430 if (Subtarget->isAmdHsaOS())
11431 return emitNonHSAIntrinsicError(DAG, DL, VT);
11432
11433 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11435 false);
11436 case Intrinsic::r600_read_ngroups_z:
11437 if (Subtarget->isAmdHsaOS())
11438 return emitNonHSAIntrinsicError(DAG, DL, VT);
11439
11440 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11442 false);
11443 case Intrinsic::r600_read_local_size_x:
11444 if (Subtarget->isAmdHsaOS())
11445 return emitNonHSAIntrinsicError(DAG, DL, VT);
11446
11447 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11449 case Intrinsic::r600_read_local_size_y:
11450 if (Subtarget->isAmdHsaOS())
11451 return emitNonHSAIntrinsicError(DAG, DL, VT);
11452
11453 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11455 case Intrinsic::r600_read_local_size_z:
11456 if (Subtarget->isAmdHsaOS())
11457 return emitNonHSAIntrinsicError(DAG, DL, VT);
11458
11459 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11461 case Intrinsic::amdgcn_workgroup_id_x:
11462 return lowerWorkGroupId(DAG, *MFI, VT,
11466 case Intrinsic::amdgcn_workgroup_id_y:
11467 return lowerWorkGroupId(DAG, *MFI, VT,
11471 case Intrinsic::amdgcn_workgroup_id_z:
11472 return lowerWorkGroupId(DAG, *MFI, VT,
11476 case Intrinsic::amdgcn_cluster_id_x:
11477 return Subtarget->hasClusters()
11478 ? getPreloadedValue(DAG, *MFI, VT,
11480 : DAG.getPOISON(VT);
11481 case Intrinsic::amdgcn_cluster_id_y:
11482 return Subtarget->hasClusters()
11483 ? getPreloadedValue(DAG, *MFI, VT,
11485 : DAG.getPOISON(VT);
11486 case Intrinsic::amdgcn_cluster_id_z:
11487 return Subtarget->hasClusters()
11488 ? getPreloadedValue(DAG, *MFI, VT,
11490 : DAG.getPOISON(VT);
11491 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11492 return Subtarget->hasClusters()
11493 ? getPreloadedValue(
11494 DAG, *MFI, VT,
11496 : DAG.getPOISON(VT);
11497 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11498 return Subtarget->hasClusters()
11499 ? getPreloadedValue(
11500 DAG, *MFI, VT,
11502 : DAG.getPOISON(VT);
11503 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11504 return Subtarget->hasClusters()
11505 ? getPreloadedValue(
11506 DAG, *MFI, VT,
11508 : DAG.getPOISON(VT);
11509 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11510 return Subtarget->hasClusters()
11511 ? lowerConstHwRegRead(DAG, Op, AMDGPU::Hwreg::ID_IB_STS2, 21, 4)
11512 : SDValue();
11513 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11514 return Subtarget->hasClusters()
11515 ? getPreloadedValue(
11516 DAG, *MFI, VT,
11518 : DAG.getPOISON(VT);
11519 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11520 return Subtarget->hasClusters()
11521 ? getPreloadedValue(
11522 DAG, *MFI, VT,
11524 : DAG.getPOISON(VT);
11525 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11526 return Subtarget->hasClusters()
11527 ? getPreloadedValue(
11528 DAG, *MFI, VT,
11530 : DAG.getPOISON(VT);
11531 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11532 return Subtarget->hasClusters()
11533 ? getPreloadedValue(
11534 DAG, *MFI, VT,
11536 : DAG.getPOISON(VT);
11537 case Intrinsic::amdgcn_wave_id:
11538 return lowerWaveID(DAG, Op);
11539 case Intrinsic::amdgcn_lds_kernel_id: {
11540 if (MFI->isEntryFunction())
11541 return getLDSKernelId(DAG, DL);
11542 return getPreloadedValue(DAG, *MFI, VT,
11544 }
11545 case Intrinsic::amdgcn_workitem_id_x:
11546 return lowerWorkitemID(DAG, Op, 0, MFI->getArgInfo().WorkItemIDX);
11547 case Intrinsic::amdgcn_workitem_id_y:
11548 return lowerWorkitemID(DAG, Op, 1, MFI->getArgInfo().WorkItemIDY);
11549 case Intrinsic::amdgcn_workitem_id_z:
11550 return lowerWorkitemID(DAG, Op, 2, MFI->getArgInfo().WorkItemIDZ);
11551 case Intrinsic::amdgcn_wavefrontsize:
11552 return DAG.getConstant(MF.getSubtarget<GCNSubtarget>().getWavefrontSize(),
11553 SDLoc(Op), MVT::i32);
11554 case Intrinsic::amdgcn_s_buffer_load: {
11555 unsigned CPol = Op.getConstantOperandVal(3);
11556 // s_buffer_load, because of how it's optimized, can't be volatile
11557 // so reject ones with the volatile bit set.
11558 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
11561 return Op;
11562 return lowerSBuffer(VT, VT, DL, DAG.getEntryNode(), Op.getOperand(1),
11563 Op.getOperand(2), Op.getOperand(3), DAG);
11564 }
11565 case Intrinsic::amdgcn_fdiv_fast:
11566 return lowerFDIV_FAST(Op, DAG);
11567 case Intrinsic::amdgcn_sin:
11568 return DAG.getNode(AMDGPUISD::SIN_HW, DL, VT, Op.getOperand(1));
11569
11570 case Intrinsic::amdgcn_cos:
11571 return DAG.getNode(AMDGPUISD::COS_HW, DL, VT, Op.getOperand(1));
11572
11573 case Intrinsic::amdgcn_mul_u24:
11574 return DAG.getNode(AMDGPUISD::MUL_U24, DL, VT, Op.getOperand(1),
11575 Op.getOperand(2));
11576 case Intrinsic::amdgcn_mul_i24:
11577 return DAG.getNode(AMDGPUISD::MUL_I24, DL, VT, Op.getOperand(1),
11578 Op.getOperand(2));
11579
11580 case Intrinsic::amdgcn_log_clamp: {
11581 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11582 return SDValue();
11583
11584 return emitRemovedIntrinsicError(DAG, DL, VT);
11585 }
11586 case Intrinsic::amdgcn_fract:
11587 return DAG.getNode(AMDGPUISD::FRACT, DL, VT, Op.getOperand(1));
11588
11589 case Intrinsic::amdgcn_class: {
11590 SDValue Src = Op.getOperand(1);
11591 EVT SrcVT = Src.getValueType();
11592 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11593 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11594 if (!IsLegal) {
11595 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11597 "llvm.amdgcn.class only supports f16, f32, and f64",
11598 DL.getDebugLoc()));
11599 return DAG.getPOISON(VT);
11600 }
11601 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, VT, Src, Op.getOperand(2));
11602 }
11603 case Intrinsic::amdgcn_div_fmas:
11604 return DAG.getNode(AMDGPUISD::DIV_FMAS, DL, VT, Op.getOperand(1),
11605 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11606
11607 case Intrinsic::amdgcn_div_fixup:
11608 return DAG.getNode(AMDGPUISD::DIV_FIXUP, DL, VT, Op.getOperand(1),
11609 Op.getOperand(2), Op.getOperand(3));
11610
11611 case Intrinsic::amdgcn_div_scale: {
11612 const ConstantSDNode *Param = cast<ConstantSDNode>(Op.getOperand(3));
11613
11614 // Translate to the operands expected by the machine instruction. The
11615 // first parameter must be the same as the first instruction.
11616 SDValue Numerator = Op.getOperand(1);
11617 SDValue Denominator = Op.getOperand(2);
11618
11619 // Note this order is opposite of the machine instruction's operations,
11620 // which is s0.f = Quotient, s1.f = Denominator, s2.f = Numerator. The
11621 // intrinsic has the numerator as the first operand to match a normal
11622 // division operation.
11623
11624 SDValue Src0 = Param->isAllOnes() ? Numerator : Denominator;
11625
11626 return DAG.getNode(AMDGPUISD::DIV_SCALE, DL, Op->getVTList(), Src0,
11627 Denominator, Numerator);
11628 }
11629 case Intrinsic::amdgcn_ballot:
11630 return lowerBALLOTIntrinsic(*this, Op.getNode(), DAG);
11631 case Intrinsic::amdgcn_fmed3:
11632 return DAG.getNode(AMDGPUISD::FMED3, DL, VT, Op.getOperand(1),
11633 Op.getOperand(2), Op.getOperand(3), Op->getFlags());
11634 case Intrinsic::amdgcn_fdot2:
11635 return DAG.getNode(AMDGPUISD::FDOT2, DL, VT, Op.getOperand(1),
11636 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11637 case Intrinsic::amdgcn_fmul_legacy:
11638 return DAG.getNode(AMDGPUISD::FMUL_LEGACY, DL, VT, Op.getOperand(1),
11639 Op.getOperand(2));
11640 case Intrinsic::amdgcn_sbfe:
11641 case Intrinsic::amdgcn_ubfe:
11642 return lowerBFEIntrinsic(Op, DAG, IntrinsicID);
11643 case Intrinsic::amdgcn_cvt_pkrtz:
11644 case Intrinsic::amdgcn_cvt_pknorm_i16:
11645 case Intrinsic::amdgcn_cvt_pknorm_u16:
11646 case Intrinsic::amdgcn_cvt_pk_i16:
11647 case Intrinsic::amdgcn_cvt_pk_u16: {
11648 // FIXME: Stop adding cast if v2f16/v2i16 are legal.
11649 EVT VT = Op.getValueType();
11650 unsigned Opcode;
11651
11652 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11653 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11654 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11655 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11656 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11657 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11658 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11659 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11660 else
11661 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11662
11663 if (isTypeLegal(VT))
11664 return DAG.getNode(Opcode, DL, VT, Op.getOperand(1), Op.getOperand(2));
11665
11666 SDValue Node =
11667 DAG.getNode(Opcode, DL, MVT::i32, Op.getOperand(1), Op.getOperand(2));
11668 return DAG.getNode(ISD::BITCAST, DL, VT, Node);
11669 }
11670 case Intrinsic::amdgcn_fmad_ftz:
11671 return DAG.getNode(AMDGPUISD::FMAD_FTZ, DL, VT, Op.getOperand(1),
11672 Op.getOperand(2), Op.getOperand(3));
11673
11674 case Intrinsic::amdgcn_if_break:
11675 return SDValue(DAG.getMachineNode(AMDGPU::SI_IF_BREAK, DL, VT,
11676 Op->getOperand(1), Op->getOperand(2)),
11677 0);
11678
11679 case Intrinsic::amdgcn_groupstaticsize: {
11681 if (OS == Triple::AMDHSA || OS == Triple::AMDPAL)
11682 return Op;
11683
11684 const Module *M = MF.getFunction().getParent();
11685 const GlobalValue *GV =
11686 Intrinsic::getDeclarationIfExists(M, Intrinsic::amdgcn_groupstaticsize);
11687 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, 0,
11689 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11690 }
11691 case Intrinsic::amdgcn_is_shared:
11692 case Intrinsic::amdgcn_is_private: {
11693 SDLoc SL(Op);
11694 SDValue SrcVec =
11695 DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
11696 SDValue SrcHi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, SrcVec,
11697 DAG.getConstant(1, SL, MVT::i32));
11698
11699 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11701 : AMDGPUAS::PRIVATE_ADDRESS;
11702 if (AS == AMDGPUAS::PRIVATE_ADDRESS &&
11703 Subtarget->hasGloballyAddressableScratch()) {
11704 SDValue FlatScratchBaseHi(
11705 DAG.getMachineNode(
11706 AMDGPU::S_MOV_B32, DL, MVT::i32,
11707 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11708 0);
11709 // Test bits 63..58 against the aperture address.
11710 return DAG.getSetCC(
11711 SL, MVT::i1,
11712 DAG.getNode(ISD::XOR, SL, MVT::i32, SrcHi, FlatScratchBaseHi),
11713 DAG.getConstant(1u << 26, SL, MVT::i32), ISD::SETULT);
11714 }
11715
11716 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11717 return DAG.getSetCC(SL, MVT::i1, SrcHi, Aperture, ISD::SETEQ);
11718 }
11719 case Intrinsic::amdgcn_perm:
11720 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op.getOperand(1),
11721 Op.getOperand(2), Op.getOperand(3));
11722 case Intrinsic::amdgcn_reloc_constant: {
11723 Module *M = MF.getFunction().getParent();
11724 const MDNode *Metadata = cast<MDNodeSDNode>(Op.getOperand(1))->getMD();
11725 auto SymbolName = cast<MDString>(Metadata->getOperand(0))->getString();
11726 auto *RelocSymbol = cast<GlobalVariable>(
11727 M->getOrInsertGlobal(SymbolName, Type::getInt32Ty(M->getContext())));
11728 SDValue GA = DAG.getTargetGlobalAddress(RelocSymbol, DL, MVT::i32, 0,
11730 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11731 }
11732 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11733 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11734 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11735 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11736 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11737 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11738 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11739 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11740 if (Op.getOperand(4).getValueType() == MVT::i32)
11741 return SDValue();
11742
11743 SDLoc SL(Op);
11744 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i32);
11745 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11746 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11747 Op.getOperand(3), IndexKeyi32);
11748 }
11749 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11750 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11751 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11752 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11753 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11754 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11755 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11756 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11757 if (Op.getOperand(4).getValueType() == MVT::i64)
11758 return SDValue();
11759
11760 SDLoc SL(Op);
11761 auto IndexKeyi64 =
11762 Op.getOperand(4).getValueType() == MVT::v2i32
11763 ? DAG.getBitcast(MVT::i64, Op.getOperand(4))
11764 : DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i64);
11765 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11766 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11767 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11768 Op.getOperand(6)});
11769 }
11770 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11771 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11772 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11773 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11774 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11775 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11776 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11777 ? MVT::i64
11778 : MVT::i32;
11779 if (Op.getOperand(6).getValueType() == IndexKeyTy)
11780 return SDValue();
11781
11782 SDLoc SL(Op);
11783 auto IndexKey =
11784 Op.getOperand(6).getValueType().isVector()
11785 ? DAG.getBitcast(IndexKeyTy, Op.getOperand(6))
11786 : DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, IndexKeyTy);
11788 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11789 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11790 IndexKey, Op.getOperand(7), Op.getOperand(8)};
11791 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11792 Args.push_back(Op.getOperand(9));
11793 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(), Args);
11794 }
11795 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11796 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11797 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11798 if (Op.getOperand(6).getValueType() == MVT::i32)
11799 return SDValue();
11800
11801 SDLoc SL(Op);
11802 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, MVT::i32);
11803 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11804 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11805 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11806 IndexKeyi32, Op.getOperand(7)});
11807 }
11808 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11809 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11810 unsigned AFmt = (unsigned)Op.getConstantOperandVal(1);
11811 unsigned BFmt = (unsigned)Op.getConstantOperandVal(3);
11812 unsigned AScaleFmt = (unsigned)Op.getConstantOperandVal(8);
11813 unsigned BScaleFmt = (unsigned)Op.getConstantOperandVal(11);
11814 if (!AMDGPU::isValidWMMAScaleFmtCombination(AFmt, AScaleFmt, BFmt,
11815 BScaleFmt)) {
11817 "invalid matrix and scale format combination in wmma call");
11818 Op->print(errs());
11819 errs() << '\n';
11820 }
11821 return SDValue();
11822 }
11823 case Intrinsic::amdgcn_readlane:
11824 case Intrinsic::amdgcn_readfirstlane:
11825 case Intrinsic::amdgcn_writelane:
11826 case Intrinsic::amdgcn_permlane16:
11827 case Intrinsic::amdgcn_permlanex16:
11828 case Intrinsic::amdgcn_permlane64:
11829 case Intrinsic::amdgcn_set_inactive:
11830 case Intrinsic::amdgcn_set_inactive_chain_arg:
11831 case Intrinsic::amdgcn_mov_dpp8:
11832 case Intrinsic::amdgcn_update_dpp:
11833 case Intrinsic::amdgcn_permlane_bcast:
11834 case Intrinsic::amdgcn_permlane_up:
11835 case Intrinsic::amdgcn_permlane_down:
11836 case Intrinsic::amdgcn_permlane_xor:
11837 return lowerLaneOp(*this, Op.getNode(), DAG);
11838 case Intrinsic::amdgcn_dead: {
11840 for (const EVT ValTy : Op.getNode()->values())
11841 Poisons.push_back(DAG.getPOISON(ValTy));
11842 return DAG.getMergeValues(Poisons, SDLoc(Op));
11843 }
11844 case Intrinsic::amdgcn_wave_shuffle:
11845 return lowerWaveShuffle(*this, Op.getNode(), DAG);
11846 default:
11847 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11849 return lowerImage(Op, ImageDimIntr, DAG, false);
11850
11851 return Op;
11852 }
11853}
11854
11855// On targets not supporting constant in soffset field, turn zero to
11856// SGPR_NULL to avoid generating an extra s_mov with zero.
11858 const GCNSubtarget *Subtarget) {
11859 if (Subtarget->hasRestrictedSOffset() && isNullConstant(SOffset))
11860 return DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11861 return SOffset;
11862}
11863
11864SDValue SITargetLowering::lowerRawBufferAtomicIntrin(SDValue Op,
11865 SelectionDAG &DAG,
11866 unsigned NewOpcode) const {
11867 SDLoc DL(Op);
11868
11869 SDValue VData = Op.getOperand(2);
11870 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11871 SmallVector<EVT, 2> ResultTypes(Op->values());
11872 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11873 "unsupported buffer atomic data type");
11874 }
11875 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11876 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
11877 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
11878 SDValue Ops[] = {
11879 Op.getOperand(0), // Chain
11880 VData, // vdata
11881 Rsrc, // rsrc
11882 DAG.getConstant(0, DL, MVT::i32), // vindex
11883 VOffset, // voffset
11884 SOffset, // soffset
11885 Offset, // offset
11886 Op.getOperand(6), // cachepolicy
11887 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11888 };
11889
11890 auto *M = cast<MemSDNode>(Op);
11891
11892 EVT MemVT = VData.getValueType();
11893 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11894 M->getMemOperand());
11895}
11896
11897SDValue
11898SITargetLowering::lowerStructBufferAtomicIntrin(SDValue Op, SelectionDAG &DAG,
11899 unsigned NewOpcode) const {
11900 SDLoc DL(Op);
11901
11902 SDValue VData = Op.getOperand(2);
11903 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11904 SmallVector<EVT, 2> ResultTypes(Op->values());
11905 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11906 "unsupported buffer atomic data type");
11907 }
11908 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11909 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
11910 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
11911 SDValue Ops[] = {
11912 Op.getOperand(0), // Chain
11913 VData, // vdata
11914 Rsrc, // rsrc
11915 Op.getOperand(4), // vindex
11916 VOffset, // voffset
11917 SOffset, // soffset
11918 Offset, // offset
11919 Op.getOperand(7), // cachepolicy
11920 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
11921 };
11922
11923 auto *M = cast<MemSDNode>(Op);
11924
11925 EVT MemVT = VData.getValueType();
11926 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11927 M->getMemOperand());
11928}
11929
11931 SDLoc DL) {
11932 SDNode *N = Op.getNode();
11933 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
11934 unsigned NumOperands = N->getNumOperands();
11935 if (N->getOperand(NumOperands - 1) == Zero)
11936 return;
11938 Ops[NumOperands - 1] = Zero; // M0 = 0
11939 DAG.UpdateNodeOperands(N, Ops);
11940}
11941
11942SDValue SITargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
11943 SelectionDAG &DAG) const {
11944 unsigned IntrID = Op.getConstantOperandVal(1);
11945 SDLoc DL(Op);
11946
11947 switch (IntrID) {
11948 case Intrinsic::amdgcn_cluster_load_b32:
11949 case Intrinsic::amdgcn_cluster_load_b64:
11950 case Intrinsic::amdgcn_cluster_load_b128: {
11951 if (Subtarget->hasGFX1250_STRICT())
11953 return SDValue();
11954 }
11955 case Intrinsic::amdgcn_ds_ordered_add:
11956 case Intrinsic::amdgcn_ds_ordered_swap: {
11957 MemSDNode *M = cast<MemSDNode>(Op);
11958 SDValue Chain = M->getOperand(0);
11959 SDValue M0 = M->getOperand(2);
11960 SDValue Value = M->getOperand(3);
11961 unsigned IndexOperand = M->getConstantOperandVal(7);
11962 unsigned WaveRelease = M->getConstantOperandVal(8);
11963 unsigned WaveDone = M->getConstantOperandVal(9);
11964
11965 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11966 IndexOperand &= ~0x3f;
11967 unsigned CountDw = 0;
11968
11969 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10) {
11970 CountDw = (IndexOperand >> 24) & 0xf;
11971 IndexOperand &= ~(0xf << 24);
11972
11973 if (CountDw < 1 || CountDw > 4) {
11974 const Function &Fn = DAG.getMachineFunction().getFunction();
11975 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11976 Fn, "ds_ordered_count: dword count must be between 1 and 4",
11977 DL.getDebugLoc()));
11978 CountDw = 1;
11979 }
11980 }
11981
11982 if (IndexOperand) {
11983 const Function &Fn = DAG.getMachineFunction().getFunction();
11984 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11985 Fn, "ds_ordered_count: bad index operand", DL.getDebugLoc()));
11986 }
11987
11988 if (WaveDone && !WaveRelease) {
11989 // TODO: Move this to IR verifier
11990 const Function &Fn = DAG.getMachineFunction().getFunction();
11991 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11992 Fn, "ds_ordered_count: wave_done requires wave_release",
11993 DL.getDebugLoc()));
11994 }
11995
11996 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
11997 unsigned ShaderType =
11999 unsigned Offset0 = OrderedCountIndex << 2;
12000 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
12001
12002 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10)
12003 Offset1 |= (CountDw - 1) << 6;
12004
12005 if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX11)
12006 Offset1 |= ShaderType << 2;
12007
12008 unsigned Offset = Offset0 | (Offset1 << 8);
12009
12010 SDValue Ops[] = {
12011 Chain, Value, DAG.getTargetConstant(Offset, DL, MVT::i16),
12012 copyToM0(DAG, Chain, DL, M0).getValue(1), // Glue
12013 };
12014 return DAG.getMemIntrinsicNode(AMDGPUISD::DS_ORDERED_COUNT, DL,
12015 M->getVTList(), Ops, M->getMemoryVT(),
12016 M->getMemOperand());
12017 }
12018 case Intrinsic::amdgcn_ptr_s_buffer_load: {
12019 unsigned CPol = Op.getConstantOperandVal(4);
12020 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
12023 return Op;
12024
12025 MemSDNode *M = cast<MemSDNode>(Op);
12026 return lowerSBuffer(
12027 Op.getValueType(), M->getMemoryVT(), DL, Op.getOperand(0),
12028 bufferRsrcPtrToVector(Op.getOperand(2), DAG), Op.getOperand(3),
12029 Op.getOperand(4), DAG, M->getMemOperand());
12030 }
12031 case Intrinsic::amdgcn_raw_buffer_load:
12032 case Intrinsic::amdgcn_raw_ptr_buffer_load:
12033 case Intrinsic::amdgcn_raw_atomic_buffer_load:
12034 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
12035 case Intrinsic::amdgcn_raw_buffer_load_format:
12036 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
12037 const bool IsFormat =
12038 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
12039 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
12040
12041 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12042 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
12043 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
12044 SDValue Ops[] = {
12045 Op.getOperand(0), // Chain
12046 Rsrc, // rsrc
12047 DAG.getConstant(0, DL, MVT::i32), // vindex
12048 VOffset, // voffset
12049 SOffset, // soffset
12050 Offset, // offset
12051 Op.getOperand(5), // cachepolicy, swizzled buffer
12052 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12053 };
12054
12055 auto *M = cast<MemSDNode>(Op);
12056 return lowerIntrinsicLoad(M, IsFormat, DAG, Ops);
12057 }
12058 case Intrinsic::amdgcn_struct_buffer_load:
12059 case Intrinsic::amdgcn_struct_ptr_buffer_load:
12060 case Intrinsic::amdgcn_struct_buffer_load_format:
12061 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
12062 case Intrinsic::amdgcn_struct_atomic_buffer_load:
12063 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
12064 const bool IsFormat =
12065 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
12066 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
12067
12068 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12069 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12070 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12071 SDValue Ops[] = {
12072 Op.getOperand(0), // Chain
12073 Rsrc, // rsrc
12074 Op.getOperand(3), // vindex
12075 VOffset, // voffset
12076 SOffset, // soffset
12077 Offset, // offset
12078 Op.getOperand(6), // cachepolicy, swizzled buffer
12079 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12080 };
12081
12082 return lowerIntrinsicLoad(cast<MemSDNode>(Op), IsFormat, DAG, Ops);
12083 }
12084 case Intrinsic::amdgcn_raw_tbuffer_load:
12085 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
12086 MemSDNode *M = cast<MemSDNode>(Op);
12087 EVT LoadVT = Op.getValueType();
12088 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12089 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
12090 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
12091
12092 SDValue Ops[] = {
12093 Op.getOperand(0), // Chain
12094 Rsrc, // rsrc
12095 DAG.getConstant(0, DL, MVT::i32), // vindex
12096 VOffset, // voffset
12097 SOffset, // soffset
12098 Offset, // offset
12099 Op.getOperand(5), // format
12100 Op.getOperand(6), // cachepolicy, swizzled buffer
12101 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12102 };
12103
12104 if (LoadVT.getScalarSizeInBits() == 16)
12105 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12106 Ops);
12107 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
12108 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
12109 DAG);
12110 }
12111 case Intrinsic::amdgcn_struct_tbuffer_load:
12112 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
12113 MemSDNode *M = cast<MemSDNode>(Op);
12114 EVT LoadVT = Op.getValueType();
12115 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12116 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12117 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12118
12119 SDValue Ops[] = {
12120 Op.getOperand(0), // Chain
12121 Rsrc, // rsrc
12122 Op.getOperand(3), // vindex
12123 VOffset, // voffset
12124 SOffset, // soffset
12125 Offset, // offset
12126 Op.getOperand(6), // format
12127 Op.getOperand(7), // cachepolicy, swizzled buffer
12128 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12129 };
12130
12131 if (LoadVT.getScalarSizeInBits() == 16)
12132 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12133 Ops);
12134 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
12135 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
12136 DAG);
12137 }
12138 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
12139 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
12140 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
12141 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
12142 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
12143 return lowerStructBufferAtomicIntrin(Op, DAG,
12144 AMDGPUISD::BUFFER_ATOMIC_FADD);
12145 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
12146 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
12147 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
12148 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
12149 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
12150 return lowerStructBufferAtomicIntrin(Op, DAG,
12151 AMDGPUISD::BUFFER_ATOMIC_FMIN);
12152 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
12153 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
12154 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
12155 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
12156 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
12157 return lowerStructBufferAtomicIntrin(Op, DAG,
12158 AMDGPUISD::BUFFER_ATOMIC_FMAX);
12159 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
12160 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
12161 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
12162 case Intrinsic::amdgcn_raw_buffer_atomic_add:
12163 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
12164 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12165 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
12166 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
12167 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12168 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
12169 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
12170 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
12171 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
12172 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
12173 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
12174 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
12175 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
12176 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
12177 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
12178 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
12179 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
12180 case Intrinsic::amdgcn_raw_buffer_atomic_and:
12181 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
12182 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12183 case Intrinsic::amdgcn_raw_buffer_atomic_or:
12184 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
12185 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12186 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
12187 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
12188 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12189 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
12190 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
12191 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12192 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12193 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12194 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12195 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12196 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12197 return lowerStructBufferAtomicIntrin(Op, DAG,
12198 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12199 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12200 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12201 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12202 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12203 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12204 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12205 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12206 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12207 return lowerStructBufferAtomicIntrin(Op, DAG,
12208 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12209 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12210 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12211 return lowerStructBufferAtomicIntrin(Op, DAG,
12212 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12213 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12214 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12215 return lowerStructBufferAtomicIntrin(Op, DAG,
12216 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12217 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12218 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12219 return lowerStructBufferAtomicIntrin(Op, DAG,
12220 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12221 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12222 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12223 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12224 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12225 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12226 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12227 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12228 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12229 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12230 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12231 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12232 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12233 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12234 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12235 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12236 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12237 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12238 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12239 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12240 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12241 return lowerStructBufferAtomicIntrin(Op, DAG,
12242 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12243 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12244 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12245 return lowerRawBufferAtomicIntrin(Op, DAG,
12246 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12247 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12248 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12249 return lowerStructBufferAtomicIntrin(Op, DAG,
12250 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12251 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12252 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12253 SDValue Src = Op.getOperand(2);
12254 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12255 SmallVector<EVT, 2> ResultTypes(Op->values());
12256 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12257 "unsupported buffer atomic data type");
12258 }
12259 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(4), DAG);
12260 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12261 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12262 SDValue Ops[] = {
12263 Op.getOperand(0), // Chain
12264 Op.getOperand(2), // src
12265 Op.getOperand(3), // cmp
12266 Rsrc, // rsrc
12267 DAG.getConstant(0, DL, MVT::i32), // vindex
12268 VOffset, // voffset
12269 SOffset, // soffset
12270 Offset, // offset
12271 Op.getOperand(7), // cachepolicy
12272 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12273 };
12274 EVT VT = Op.getValueType();
12275 auto *M = cast<MemSDNode>(Op);
12276
12277 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12278 Op->getVTList(), Ops, VT,
12279 M->getMemOperand());
12280 }
12281 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12282 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12283 SDValue Src = Op.getOperand(2);
12284 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12285 SmallVector<EVT, 2> ResultTypes(Op->values());
12286 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12287 "unsupported buffer atomic data type");
12288 }
12289 SDValue Rsrc = bufferRsrcPtrToVector(Op->getOperand(4), DAG);
12290 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(6), DAG);
12291 auto SOffset = selectSOffset(Op.getOperand(7), DAG, Subtarget);
12292 SDValue Ops[] = {
12293 Op.getOperand(0), // Chain
12294 Op.getOperand(2), // src
12295 Op.getOperand(3), // cmp
12296 Rsrc, // rsrc
12297 Op.getOperand(5), // vindex
12298 VOffset, // voffset
12299 SOffset, // soffset
12300 Offset, // offset
12301 Op.getOperand(8), // cachepolicy
12302 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12303 };
12304 EVT VT = Op.getValueType();
12305 auto *M = cast<MemSDNode>(Op);
12306
12307 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12308 Op->getVTList(), Ops, VT,
12309 M->getMemOperand());
12310 }
12311 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12312 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12313 MemSDNode *M = cast<MemSDNode>(Op);
12314 SDValue NodePtr = M->getOperand(2);
12315 SDValue RayExtent = M->getOperand(3);
12316 SDValue InstanceMask = M->getOperand(4);
12317 SDValue RayOrigin = M->getOperand(5);
12318 SDValue RayDir = M->getOperand(6);
12319 SDValue Offsets = M->getOperand(7);
12320 SDValue TDescr = M->getOperand(8);
12321
12322 assert(NodePtr.getValueType() == MVT::i64);
12323 assert(RayDir.getValueType() == MVT::v3f32);
12324
12325 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12326 const unsigned NumVDataDwords = 10;
12327 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12328 int Opcode = AMDGPU::getMIMGOpcode(
12329 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12330 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12331 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12332 assert(Opcode != -1);
12333
12335 Ops.push_back(NodePtr);
12336 Ops.push_back(DAG.getBuildVector(
12337 MVT::v2i32, DL,
12338 {DAG.getBitcast(MVT::i32, RayExtent),
12339 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12340 Ops.push_back(RayOrigin);
12341 Ops.push_back(RayDir);
12342 Ops.push_back(Offsets);
12343 Ops.push_back(TDescr);
12344 Ops.push_back(M->getChain());
12345
12346 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12347 MachineMemOperand *MemRef = M->getMemOperand();
12348 DAG.setNodeMemRefs(NewNode, {MemRef});
12349 return SDValue(NewNode, 0);
12350 }
12351 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12352 MemSDNode *M = cast<MemSDNode>(Op);
12353 SDValue NodePtr = M->getOperand(2);
12354 SDValue RayExtent = M->getOperand(3);
12355 SDValue RayOrigin = M->getOperand(4);
12356 SDValue RayDir = M->getOperand(5);
12357 SDValue RayInvDir = M->getOperand(6);
12358 SDValue TDescr = M->getOperand(7);
12359
12360 assert(NodePtr.getValueType() == MVT::i32 ||
12361 NodePtr.getValueType() == MVT::i64);
12362 assert(RayDir.getValueType() == MVT::v3f16 ||
12363 RayDir.getValueType() == MVT::v3f32);
12364
12365 const bool IsGFX11 = AMDGPU::isGFX11(*Subtarget);
12366 const bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
12367 const bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
12368 const bool IsA16 = RayDir.getValueType().getVectorElementType() == MVT::f16;
12369 const bool Is64 = NodePtr.getValueType() == MVT::i64;
12370 const unsigned NumVDataDwords = 4;
12371 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12372 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12373 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12374 NumVAddrs <= Subtarget->getNSAMaxSize()) ||
12375 IsGFX12Plus;
12376 const unsigned BaseOpcodes[2][2] = {
12377 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12378 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12379 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12380 int Opcode;
12381 if (UseNSA) {
12382 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12383 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12384 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12385 : AMDGPU::MIMGEncGfx10NSA,
12386 NumVDataDwords, NumVAddrDwords);
12387 } else {
12388 assert(!IsGFX12Plus);
12389 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12390 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12391 : AMDGPU::MIMGEncGfx10Default,
12392 NumVDataDwords, NumVAddrDwords);
12393 }
12394 assert(Opcode != -1);
12395
12397
12398 auto packLanes = [&DAG, &Ops, &DL](SDValue Op, bool IsAligned) {
12400 DAG.ExtractVectorElements(Op, Lanes, 0, 3);
12401 if (Lanes[0].getValueSizeInBits() == 32) {
12402 for (unsigned I = 0; I < 3; ++I)
12403 Ops.push_back(DAG.getBitcast(MVT::i32, Lanes[I]));
12404 } else {
12405 if (IsAligned) {
12406 Ops.push_back(DAG.getBitcast(
12407 MVT::i32,
12408 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[0], Lanes[1]})));
12409 Ops.push_back(Lanes[2]);
12410 } else {
12411 SDValue Elt0 = Ops.pop_back_val();
12412 Ops.push_back(DAG.getBitcast(
12413 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL, {Elt0, Lanes[0]})));
12414 Ops.push_back(DAG.getBitcast(
12415 MVT::i32,
12416 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[1], Lanes[2]})));
12417 }
12418 }
12419 };
12420
12421 if (UseNSA && IsGFX11Plus) {
12422 Ops.push_back(NodePtr);
12423 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12424 Ops.push_back(RayOrigin);
12425 if (IsA16) {
12426 SmallVector<SDValue, 3> DirLanes, InvDirLanes, MergedLanes;
12427 DAG.ExtractVectorElements(RayDir, DirLanes, 0, 3);
12428 DAG.ExtractVectorElements(RayInvDir, InvDirLanes, 0, 3);
12429 for (unsigned I = 0; I < 3; ++I) {
12430 MergedLanes.push_back(DAG.getBitcast(
12431 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL,
12432 {DirLanes[I], InvDirLanes[I]})));
12433 }
12434 Ops.push_back(DAG.getBuildVector(MVT::v3i32, DL, MergedLanes));
12435 } else {
12436 Ops.push_back(RayDir);
12437 Ops.push_back(RayInvDir);
12438 }
12439 } else {
12440 if (Is64)
12441 DAG.ExtractVectorElements(DAG.getBitcast(MVT::v2i32, NodePtr), Ops, 0,
12442 2);
12443 else
12444 Ops.push_back(NodePtr);
12445
12446 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12447 packLanes(RayOrigin, true);
12448 packLanes(RayDir, true);
12449 packLanes(RayInvDir, false);
12450 }
12451
12452 if (!UseNSA) {
12453 // Build a single vector containing all the operands so far prepared.
12454 if (NumVAddrDwords > 12) {
12455 SDValue Undef = DAG.getPOISON(MVT::i32);
12456 Ops.append(16 - Ops.size(), Undef);
12457 }
12458 assert(Ops.size() >= 8 && Ops.size() <= 12);
12459 SDValue MergedOps =
12460 DAG.getBuildVector(MVT::getVectorVT(MVT::i32, Ops.size()), DL, Ops);
12461 Ops.clear();
12462 Ops.push_back(MergedOps);
12463 }
12464
12465 Ops.push_back(TDescr);
12466 Ops.push_back(DAG.getTargetConstant(IsA16, DL, MVT::i1));
12467 Ops.push_back(M->getChain());
12468
12469 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12470 MachineMemOperand *MemRef = M->getMemOperand();
12471 DAG.setNodeMemRefs(NewNode, {MemRef});
12472 return SDValue(NewNode, 0);
12473 }
12474 case Intrinsic::amdgcn_global_atomic_fmin_num:
12475 case Intrinsic::amdgcn_global_atomic_fmax_num:
12476 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12477 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12478 MemSDNode *M = cast<MemSDNode>(Op);
12479 SDValue Ops[] = {
12480 M->getOperand(0), // Chain
12481 M->getOperand(2), // Ptr
12482 M->getOperand(3) // Value
12483 };
12484 unsigned Opcode = 0;
12485 switch (IntrID) {
12486 case Intrinsic::amdgcn_global_atomic_fmin_num:
12487 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12488 Opcode = ISD::ATOMIC_LOAD_FMIN;
12489 break;
12490 }
12491 case Intrinsic::amdgcn_global_atomic_fmax_num:
12492 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12493 Opcode = ISD::ATOMIC_LOAD_FMAX;
12494 break;
12495 }
12496 default:
12497 llvm_unreachable("unhandled atomic opcode");
12498 }
12499 return DAG.getAtomic(Opcode, SDLoc(Op), M->getMemoryVT(), M->getVTList(),
12500 Ops, M->getMemOperand());
12501 }
12502 case Intrinsic::amdgcn_s_alloc_vgpr: {
12503 SDValue NumVGPRs = Op.getOperand(2);
12504 if (!NumVGPRs->isDivergent())
12505 return Op;
12506
12507 SDValue ReadFirstLaneID =
12508 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
12509 NumVGPRs = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
12510 ReadFirstLaneID, NumVGPRs);
12511
12512 return DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, Op->getVTList(),
12513 Op.getOperand(0), Op.getOperand(1), NumVGPRs);
12514 }
12515 case Intrinsic::amdgcn_s_get_barrier_state:
12516 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12517 SDValue Chain = Op->getOperand(0);
12519 unsigned Opc;
12520
12521 if (isa<ConstantSDNode>(Op->getOperand(2))) {
12522 uint64_t BarID = cast<ConstantSDNode>(Op->getOperand(2))->getZExtValue();
12523 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12524 BarID = BarID & 0x3F;
12525 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12526 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
12527 Ops.push_back(K);
12528 Ops.push_back(Chain);
12529 } else {
12530 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12531 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12532 SDValue M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, Op->getOperand(2),
12533 DAG.getConstant(0x3F, DL, MVT::i32));
12534 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
12535 } else
12536 Ops.push_back(copyToM0(DAG, Chain, DL, Op->getOperand(2)).getValue(0));
12537 }
12538
12539 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
12540 return SDValue(NewMI, 0);
12541 }
12542 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12543 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12544 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12545 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12546 SDValue Chain = Op->getOperand(0);
12547 SDValue Ptr = Op->getOperand(2);
12548 EVT VT = Op->getValueType(0);
12549 return DAG.getAtomicLoad(ISD::NON_EXTLOAD, DL, MII->getMemoryVT(), VT,
12550 Chain, Ptr, MII->getMemOperand());
12551 }
12552 case Intrinsic::amdgcn_av_load_b8:
12553 case Intrinsic::amdgcn_av_load_b16:
12554 case Intrinsic::amdgcn_av_load_b32:
12555 case Intrinsic::amdgcn_av_load_b64:
12556 case Intrinsic::amdgcn_av_load_b128: {
12557 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12558 SDValue Chain = Op->getOperand(0);
12559 SDValue Ptr = Op->getOperand(2);
12560 EVT VT = Op->getValueType(0);
12561 // Lower to a regular ISD::LOAD. The MachineMemOperand carries Monotonic
12562 // ordering and syncscope so that SIMemoryLegalizer sets cache policy bits.
12563 // Address space filtering in the load_global/load_flat PatFrags selects
12564 // the correct GLOBAL vs FLAT instruction.
12565 return DAG.getLoad(VT, DL, Chain, Ptr, MII->getMemOperand());
12566 }
12567 case Intrinsic::amdgcn_flat_load_monitor_b32:
12568 case Intrinsic::amdgcn_flat_load_monitor_b64:
12569 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12570 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12571 SDValue Chain = Op->getOperand(0);
12572 SDValue Ptr = Op->getOperand(2);
12573 return DAG.getMemIntrinsicNode(AMDGPUISD::FLAT_LOAD_MONITOR, DL,
12574 Op->getVTList(), {Chain, Ptr},
12575 MII->getMemoryVT(), MII->getMemOperand());
12576 }
12577 case Intrinsic::amdgcn_global_load_monitor_b32:
12578 case Intrinsic::amdgcn_global_load_monitor_b64:
12579 case Intrinsic::amdgcn_global_load_monitor_b128: {
12580 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12581 SDValue Chain = Op->getOperand(0);
12582 SDValue Ptr = Op->getOperand(2);
12583 return DAG.getMemIntrinsicNode(AMDGPUISD::GLOBAL_LOAD_MONITOR, DL,
12584 Op->getVTList(), {Chain, Ptr},
12585 MII->getMemoryVT(), MII->getMemOperand());
12586 }
12587 default:
12588
12589 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12591 return lowerImage(Op, ImageDimIntr, DAG, true);
12592
12593 return SDValue();
12594 }
12595}
12596
12597// Call DAG.getMemIntrinsicNode for a load, but first widen a dwordx3 type to
12598// dwordx4 if on SI and handle TFE loads.
12599SDValue SITargetLowering::getMemIntrinsicNode(unsigned Opcode, const SDLoc &DL,
12600 SDVTList VTList,
12601 ArrayRef<SDValue> Ops, EVT MemVT,
12602 MachineMemOperand *MMO,
12603 SelectionDAG &DAG) const {
12604 LLVMContext &C = *DAG.getContext();
12606 EVT VT = VTList.VTs[0];
12607
12608 assert(VTList.NumVTs == 2 || VTList.NumVTs == 3);
12609 bool IsTFE = VTList.NumVTs == 3;
12610 if (IsTFE) {
12611 unsigned NumValueDWords = divideCeil(VT.getSizeInBits(), 32);
12612 unsigned NumOpDWords = NumValueDWords + 1;
12613 EVT OpDWordsVT = EVT::getVectorVT(C, MVT::i32, NumOpDWords);
12614 SDVTList OpDWordsVTList = DAG.getVTList(OpDWordsVT, VTList.VTs[2]);
12615 MachineMemOperand *OpDWordsMMO =
12616 MF.getMachineMemOperand(MMO, 0, NumOpDWords * 4);
12617 SDValue Op = getMemIntrinsicNode(Opcode, DL, OpDWordsVTList, Ops,
12618 OpDWordsVT, OpDWordsMMO, DAG);
12619 auto [Value, Status] = splitTFEValueAndStatus(Op, VT, DL, DAG);
12620 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
12621 }
12622
12623 if (!Subtarget->hasDwordx3LoadStores() &&
12624 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12625 EVT WidenedVT = EVT::getVectorVT(C, VT.getVectorElementType(), 4);
12626 EVT WidenedMemVT = EVT::getVectorVT(C, MemVT.getVectorElementType(), 4);
12627 MachineMemOperand *WidenedMMO = MF.getMachineMemOperand(MMO, 0, 16);
12628 SDVTList WidenedVTList = DAG.getVTList(WidenedVT, VTList.VTs[1]);
12629 SDValue Op = DAG.getMemIntrinsicNode(Opcode, DL, WidenedVTList, Ops,
12630 WidenedMemVT, WidenedMMO);
12632 DAG.getVectorIdxConstant(0, DL));
12633 return DAG.getMergeValues({Value, SDValue(Op.getNode(), 1)}, DL);
12634 }
12635
12636 return DAG.getMemIntrinsicNode(Opcode, DL, VTList, Ops, MemVT, MMO);
12637}
12638
12639SDValue SITargetLowering::handleD16VData(SDValue VData, SelectionDAG &DAG,
12640 bool ImageStore) const {
12641 EVT StoreVT = VData.getValueType();
12642
12643 // No change for f16 and legal vector D16 types.
12644 if (!StoreVT.isVector())
12645 return VData;
12646
12647 SDLoc DL(VData);
12648 unsigned NumElements = StoreVT.getVectorNumElements();
12649
12650 if (Subtarget->hasUnpackedD16VMem()) {
12651 // We need to unpack the packed data to store.
12652 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12653 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12654
12655 EVT EquivStoreVT =
12656 EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumElements);
12657 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, EquivStoreVT, IntVData);
12658 return DAG.UnrollVectorOp(ZExt.getNode());
12659 }
12660
12661 // The sq block of gfx8.1 does not estimate register use correctly for d16
12662 // image store instructions. The data operand is computed as if it were not a
12663 // d16 image instruction.
12664 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12665 // Bitcast to i16
12666 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12667 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12668
12669 // Decompose into scalars
12671 DAG.ExtractVectorElements(IntVData, Elts);
12672
12673 // Group pairs of i16 into v2i16 and bitcast to i32
12674 SmallVector<SDValue, 4> PackedElts;
12675 for (unsigned I = 0; I < Elts.size() / 2; I += 1) {
12676 SDValue Pair =
12677 DAG.getBuildVector(MVT::v2i16, DL, {Elts[I * 2], Elts[I * 2 + 1]});
12678 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12679 PackedElts.push_back(IntPair);
12680 }
12681 if ((NumElements % 2) == 1) {
12682 // Handle v3i16
12683 unsigned I = Elts.size() / 2;
12684 SDValue Pair = DAG.getBuildVector(MVT::v2i16, DL,
12685 {Elts[I * 2], DAG.getPOISON(MVT::i16)});
12686 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12687 PackedElts.push_back(IntPair);
12688 }
12689
12690 // Pad using UNDEF
12691 PackedElts.resize(Elts.size(), DAG.getPOISON(MVT::i32));
12692
12693 // Build final vector
12694 EVT VecVT =
12695 EVT::getVectorVT(*DAG.getContext(), MVT::i32, PackedElts.size());
12696 return DAG.getBuildVector(VecVT, DL, PackedElts);
12697 }
12698
12699 if (NumElements == 3) {
12700 EVT IntStoreVT =
12702 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12703
12704 EVT WidenedStoreVT = EVT::getVectorVT(
12705 *DAG.getContext(), StoreVT.getVectorElementType(), NumElements + 1);
12706 EVT WidenedIntVT = EVT::getIntegerVT(*DAG.getContext(),
12707 WidenedStoreVT.getStoreSizeInBits());
12708 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenedIntVT, IntVData);
12709 return DAG.getNode(ISD::BITCAST, DL, WidenedStoreVT, ZExt);
12710 }
12711
12712 assert(isTypeLegal(StoreVT));
12713 return VData;
12714}
12715
12716static bool isAsyncLDSDMA(Intrinsic::ID Intr) {
12717 switch (Intr) {
12718 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12719 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12720 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12721 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12722 case Intrinsic::amdgcn_load_async_to_lds:
12723 case Intrinsic::amdgcn_global_load_async_lds:
12724 return true;
12725 }
12726 return false;
12727}
12728
12729SDValue SITargetLowering::LowerINTRINSIC_VOID(SDValue Op,
12730 SelectionDAG &DAG) const {
12731 SDLoc DL(Op);
12732 SDValue Chain = Op.getOperand(0);
12733 unsigned IntrinsicID = Op.getConstantOperandVal(1);
12734
12735 switch (IntrinsicID) {
12736 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
12737 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
12738 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
12739 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
12740 if (Subtarget->hasGFX1250_STRICT())
12742 return SDValue();
12743 }
12744 case Intrinsic::amdgcn_exp_compr: {
12745 SDValue Src0 = Op.getOperand(4);
12746 SDValue Src1 = Op.getOperand(5);
12747 // Hack around illegal type on SI by directly selecting it.
12748 if (isTypeLegal(Src0.getValueType()))
12749 return SDValue();
12750
12751 const ConstantSDNode *Done = cast<ConstantSDNode>(Op.getOperand(6));
12752 SDValue Undef = DAG.getPOISON(MVT::f32);
12753 const SDValue Ops[] = {
12754 Op.getOperand(2), // tgt
12755 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src0), // src0
12756 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src1), // src1
12757 Undef, // src2
12758 Undef, // src3
12759 Op.getOperand(7), // vm
12760 DAG.getTargetConstant(1, DL, MVT::i1), // compr
12761 Op.getOperand(3), // en
12762 Op.getOperand(0) // Chain
12763 };
12764
12765 unsigned Opc = Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12766 return SDValue(DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops), 0);
12767 }
12768
12769 case Intrinsic::amdgcn_struct_tbuffer_store:
12770 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12771 SDValue VData = Op.getOperand(2);
12772 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12773 if (IsD16)
12774 VData = handleD16VData(VData, DAG);
12775 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12776 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12777 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12778 SDValue Ops[] = {
12779 Chain,
12780 VData, // vdata
12781 Rsrc, // rsrc
12782 Op.getOperand(4), // vindex
12783 VOffset, // voffset
12784 SOffset, // soffset
12785 Offset, // offset
12786 Op.getOperand(7), // format
12787 Op.getOperand(8), // cachepolicy, swizzled buffer
12788 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12789 };
12790 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12791 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12792 MemSDNode *M = cast<MemSDNode>(Op);
12793 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12794 M->getMemoryVT(), M->getMemOperand());
12795 }
12796
12797 case Intrinsic::amdgcn_raw_tbuffer_store:
12798 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12799 SDValue VData = Op.getOperand(2);
12800 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12801 if (IsD16)
12802 VData = handleD16VData(VData, DAG);
12803 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12804 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12805 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12806 SDValue Ops[] = {
12807 Chain,
12808 VData, // vdata
12809 Rsrc, // rsrc
12810 DAG.getConstant(0, DL, MVT::i32), // vindex
12811 VOffset, // voffset
12812 SOffset, // soffset
12813 Offset, // offset
12814 Op.getOperand(6), // format
12815 Op.getOperand(7), // cachepolicy, swizzled buffer
12816 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12817 };
12818 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12819 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12820 MemSDNode *M = cast<MemSDNode>(Op);
12821 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12822 M->getMemoryVT(), M->getMemOperand());
12823 }
12824
12825 case Intrinsic::amdgcn_raw_buffer_store:
12826 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12827 case Intrinsic::amdgcn_raw_buffer_store_format:
12828 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12829 const bool IsFormat =
12830 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12831 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12832
12833 SDValue VData = Op.getOperand(2);
12834 EVT VDataVT = VData.getValueType();
12835 EVT EltType = VDataVT.getScalarType();
12836 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12837
12838 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12839 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12841 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12842 return Chain;
12843 }
12844
12845 if (IsD16) {
12846 VData = handleD16VData(VData, DAG);
12847 VDataVT = VData.getValueType();
12848 }
12849
12850 if (!isTypeLegal(VDataVT)) {
12851 VData =
12852 DAG.getNode(ISD::BITCAST, DL,
12853 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12854 }
12855
12856 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12857 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12858 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12859 SDValue Ops[] = {
12860 Chain,
12861 VData,
12862 Rsrc,
12863 DAG.getConstant(0, DL, MVT::i32), // vindex
12864 VOffset, // voffset
12865 SOffset, // soffset
12866 Offset, // offset
12867 Op.getOperand(6), // cachepolicy, swizzled buffer
12868 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12869 };
12870 unsigned Opc =
12871 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12872 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12873 MemSDNode *M = cast<MemSDNode>(Op);
12874
12875 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12876 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12877 return handleByteShortBufferStores(DAG, VDataVT, DL, Ops, M);
12878
12879 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12880 M->getMemoryVT(), M->getMemOperand());
12881 }
12882
12883 case Intrinsic::amdgcn_struct_buffer_store:
12884 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12885 case Intrinsic::amdgcn_struct_buffer_store_format:
12886 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12887 const bool IsFormat =
12888 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12889 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12890
12891 SDValue VData = Op.getOperand(2);
12892 EVT VDataVT = VData.getValueType();
12893 EVT EltType = VDataVT.getScalarType();
12894 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12895
12896 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12897 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12899 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12900 return Chain;
12901 }
12902
12903 if (IsD16) {
12904 VData = handleD16VData(VData, DAG);
12905 VDataVT = VData.getValueType();
12906 }
12907
12908 if (!isTypeLegal(VDataVT)) {
12909 VData =
12910 DAG.getNode(ISD::BITCAST, DL,
12911 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12912 }
12913
12914 auto Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12915 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12916 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12917 SDValue Ops[] = {
12918 Chain,
12919 VData,
12920 Rsrc,
12921 Op.getOperand(4), // vindex
12922 VOffset, // voffset
12923 SOffset, // soffset
12924 Offset, // offset
12925 Op.getOperand(7), // cachepolicy, swizzled buffer
12926 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12927 };
12928 unsigned Opc =
12929 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12930 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12931 MemSDNode *M = cast<MemSDNode>(Op);
12932
12933 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12934 EVT VDataType = VData.getValueType().getScalarType();
12935 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12936 return handleByteShortBufferStores(DAG, VDataType, DL, Ops, M);
12937
12938 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12939 M->getMemoryVT(), M->getMemOperand());
12940 }
12941 case Intrinsic::amdgcn_raw_buffer_load_lds:
12942 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12943 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12944 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12945 case Intrinsic::amdgcn_struct_buffer_load_lds:
12946 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12947 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12948 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12949 unsigned Opc;
12950 bool HasVIndex =
12951 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12952 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12953 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12954 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12955 unsigned OpOffset = HasVIndex ? 1 : 0;
12956 SDValue VOffset = Op.getOperand(5 + OpOffset);
12957 bool HasVOffset = !isNullConstant(VOffset);
12958 unsigned Size = Op->getConstantOperandVal(4);
12959
12960 switch (Size) {
12961 default:
12962 return SDValue();
12963 case 1:
12964 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12965 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12966 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12967 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12968 break;
12969 case 2:
12970 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12971 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12972 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12973 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12974 break;
12975 case 4:
12976 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12977 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12978 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12979 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12980 break;
12981 case 12:
12982 if (!Subtarget->hasLDSLoadB96_B128())
12983 return SDValue();
12984 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
12985 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
12986 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
12987 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
12988 break;
12989 case 16:
12990 if (!Subtarget->hasLDSLoadB96_B128())
12991 return SDValue();
12992 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
12993 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
12994 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
12995 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
12996 break;
12997 }
12998
12999 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
13000
13002
13003 if (HasVIndex && HasVOffset)
13004 Ops.push_back(DAG.getBuildVector(MVT::v2i32, DL,
13005 {Op.getOperand(5), // VIndex
13006 VOffset}));
13007 else if (HasVIndex)
13008 Ops.push_back(Op.getOperand(5));
13009 else if (HasVOffset)
13010 Ops.push_back(VOffset);
13011
13012 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
13013 Ops.push_back(Rsrc);
13014 Ops.push_back(Op.getOperand(6 + OpOffset)); // soffset
13015 Ops.push_back(Op.getOperand(7 + OpOffset)); // imm offset
13016 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
13017 unsigned Aux = Op.getConstantOperandVal(8 + OpOffset);
13018 Ops.push_back(DAG.getTargetConstant(
13019 Aux & (IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12),
13020 DL, MVT::i16)); // cpol
13021 Ops.push_back(DAG.getTargetConstant(
13022 Aux & (IsGFX12Plus ? AMDGPU::CPol::SWZ : AMDGPU::CPol::SWZ_pregfx12)
13023 ? 1
13024 : 0,
13025 DL, MVT::i8)); // swz
13026 Ops.push_back(
13027 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
13028 Ops.push_back(M0Val.getValue(0)); // Chain
13029 Ops.push_back(M0Val.getValue(1)); // Glue
13030
13031 auto *M = cast<MemSDNode>(Op);
13032 auto *Load = DAG.getMachineNode(Opc, DL, M->getVTList(), Ops);
13033 DAG.setNodeMemRefs(Load, M->memoperands());
13034
13035 return SDValue(Load, 0);
13036 }
13037 // Buffers are handled by LowerBufferFatPointers, and we're going to go
13038 // for "trust me" that the remaining cases are global pointers until
13039 // such time as we can put two mem operands on an intrinsic.
13040 case Intrinsic::amdgcn_load_to_lds:
13041 case Intrinsic::amdgcn_load_async_to_lds:
13042 case Intrinsic::amdgcn_global_load_lds:
13043 case Intrinsic::amdgcn_global_load_async_lds: {
13044 if (!Subtarget->hasVMemToLDSLoad())
13045 return SDValue();
13046
13047 unsigned Opc;
13048 unsigned Size = Op->getConstantOperandVal(4);
13049 switch (Size) {
13050 default:
13051 return SDValue();
13052 case 1:
13053 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
13054 break;
13055 case 2:
13056 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
13057 break;
13058 case 4:
13059 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
13060 break;
13061 case 12:
13062 if (!Subtarget->hasLDSLoadB96_B128())
13063 return SDValue();
13064 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
13065 break;
13066 case 16:
13067 if (!Subtarget->hasLDSLoadB96_B128())
13068 return SDValue();
13069 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
13070 break;
13071 }
13072
13073 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
13074
13076
13077 SDValue Addr = Op.getOperand(2); // Global ptr
13078 SDValue VOffset;
13079 // Try to split SAddr and VOffset. Global and LDS pointers share the same
13080 // immediate offset, so we cannot use a regular SelectGlobalSAddr().
13081 if (Addr->isDivergent() && Addr->isAnyAdd()) {
13082 SDValue LHS = Addr.getOperand(0);
13083 SDValue RHS = Addr.getOperand(1);
13084
13085 if (LHS->isDivergent())
13086 std::swap(LHS, RHS);
13087
13088 if (!LHS->isDivergent() && RHS.getOpcode() == ISD::ZERO_EXTEND &&
13089 RHS.getOperand(0).getValueType() == MVT::i32) {
13090 // add (i64 sgpr), (zero_extend (i32 vgpr))
13091 Addr = LHS;
13092 VOffset = RHS.getOperand(0);
13093 }
13094 }
13095
13096 Ops.push_back(Addr);
13097 if (!Addr->isDivergent()) {
13099 if (!VOffset)
13100 VOffset =
13101 SDValue(DAG.getMachineNode(AMDGPU::V_MOV_B32_e32, DL, MVT::i32,
13102 DAG.getTargetConstant(0, DL, MVT::i32)),
13103 0);
13104 Ops.push_back(VOffset);
13105 }
13106
13107 Ops.push_back(Op.getOperand(5)); // Offset
13108
13109 unsigned Aux = Op.getConstantOperandVal(6);
13110 Ops.push_back(DAG.getTargetConstant(Aux & ~AMDGPU::CPol::VIRTUAL_BITS, DL,
13111 MVT::i32)); // CPol
13112 Ops.push_back(
13113 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
13114
13115 Ops.push_back(M0Val.getValue(0)); // Chain
13116 Ops.push_back(M0Val.getValue(1)); // Glue
13117
13118 auto *M = cast<MemSDNode>(Op);
13119 auto *Load = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13120 DAG.setNodeMemRefs(Load, M->memoperands());
13121
13122 return SDValue(Load, 0);
13123 }
13124 case Intrinsic::amdgcn_end_cf:
13125 return SDValue(DAG.getMachineNode(AMDGPU::SI_END_CF, DL, MVT::Other,
13126 Op->getOperand(2), Chain),
13127 0);
13128 case Intrinsic::amdgcn_s_barrier_signal_var: {
13129 // Member count of 0 means to re-use a previous member count,
13130 // which, if the named barrier is statically chosen, means we can use
13131 // the immarg form. Otherwisee, fall through to constructiong M0 as for
13132 // s_barrier_init.
13133 SDValue CntOp = Op->getOperand(3);
13134 auto *CntC = dyn_cast<ConstantSDNode>(CntOp);
13135 if (CntC && CntC->isZero()) {
13136 SDValue Chain = Op->getOperand(0);
13137 SDValue BarOp = Op->getOperand(2);
13139
13140 std::optional<uint64_t> BarVal;
13141 if (auto *C = dyn_cast<ConstantSDNode>(BarOp))
13142 BarVal = C->getZExtValue();
13143 else if (auto *GA = dyn_cast<GlobalAddressSDNode>(BarOp))
13145 *GA->getGlobal(), AMDGPUAS::BARRIER))
13146 BarVal = *Addr + GA->getOffset();
13147
13148 if (BarVal) {
13149 unsigned BarID = *BarVal & 0x3F;
13150 Ops.push_back(DAG.getTargetConstant(BarID, DL, MVT::i32));
13151 Ops.push_back(Chain);
13152 auto *NewMI = DAG.getMachineNode(AMDGPU::S_BARRIER_SIGNAL_IMM, DL,
13153 Op->getVTList(), Ops);
13154 return SDValue(NewMI, 0);
13155 }
13156 }
13157 [[fallthrough]];
13158 }
13159 case Intrinsic::amdgcn_s_barrier_init: {
13160 // these two intrinsics have two operands: barrier pointer and member count
13161 SDValue Chain = Op->getOperand(0);
13163 SDValue BarOp = Op->getOperand(2);
13164 SDValue CntOp = Op->getOperand(3);
13165 SDValue M0Val;
13166 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
13167 ? AMDGPU::S_BARRIER_INIT_M0
13168 : AMDGPU::S_BARRIER_SIGNAL_M0;
13169 // extract the BarrierID from bits 0-5 of BarOp
13170 SDValue BarID = DAG.getNode(ISD::AND, DL, MVT::i32, BarOp,
13171 DAG.getConstant(0x3F, DL, MVT::i32));
13172 // Member count should be put into M0[ShAmt:+CntMask width]
13173 // Barrier ID should be put into M0[5:0]
13174 unsigned CntMask = AMDGPU::getBarrierMemberCountBitMask(
13175 AMDGPU::getIsaVersion(Subtarget->getCPU()));
13176 SDValue MemberCnt = DAG.getNode(ISD::AND, DL, MVT::i32, CntOp,
13177 DAG.getConstant(CntMask, DL, MVT::i32));
13178 constexpr unsigned ShAmt = 16;
13179 M0Val = DAG.getNode(ISD::SHL, DL, MVT::i32, MemberCnt,
13180 DAG.getShiftAmountConstant(ShAmt, MVT::i32, DL));
13181
13182 M0Val = DAG.getNode(ISD::OR, DL, MVT::i32, M0Val, BarID);
13183
13184 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
13185
13186 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13187 return SDValue(NewMI, 0);
13188 }
13189 case Intrinsic::amdgcn_s_wakeup_barrier: {
13190 if (!Subtarget->hasSWakeupBarrier())
13191 return SDValue();
13192 [[fallthrough]];
13193 }
13194 case Intrinsic::amdgcn_s_barrier_join: {
13195 // these three intrinsics have one operand: barrier pointer
13196 SDValue Chain = Op->getOperand(0);
13198 SDValue BarOp = Op->getOperand(2);
13199 unsigned Opc;
13200
13201 if (isa<ConstantSDNode>(BarOp)) {
13202 uint64_t BarVal = cast<ConstantSDNode>(BarOp)->getZExtValue();
13203 switch (IntrinsicID) {
13204 default:
13205 return SDValue();
13206 case Intrinsic::amdgcn_s_barrier_join:
13207 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13208 break;
13209 case Intrinsic::amdgcn_s_wakeup_barrier:
13210 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13211 break;
13212 }
13213 // extract the BarrierID from bits 0-5 of the immediate
13214 unsigned BarID = BarVal & 0x3F;
13215 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
13216 Ops.push_back(K);
13217 Ops.push_back(Chain);
13218 } else {
13219 switch (IntrinsicID) {
13220 default:
13221 return SDValue();
13222 case Intrinsic::amdgcn_s_barrier_join:
13223 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13224 break;
13225 case Intrinsic::amdgcn_s_wakeup_barrier:
13226 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13227 break;
13228 }
13229 // extract the BarrierID from bits 0-5 of BarOp, copy to M0[5:0]
13230 SDValue M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, BarOp,
13231 DAG.getConstant(0x3F, DL, MVT::i32));
13232 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
13233 }
13234
13235 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13236 return SDValue(NewMI, 0);
13237 }
13238 case Intrinsic::amdgcn_s_prefetch_data:
13239 case Intrinsic::amdgcn_s_prefetch_inst: {
13240 // For non-global address space preserve the chain and remove the call.
13242 return Op.getOperand(0);
13243 return Op;
13244 }
13245 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13246 SDValue Ops[] = {
13247 Chain, bufferRsrcPtrToVector(Op.getOperand(2), DAG),
13248 Op.getOperand(3), // offset
13249 Op.getOperand(4), // length
13250 };
13251
13252 MemSDNode *M = cast<MemSDNode>(Op);
13253 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_PREFETCH_DATA, DL,
13254 Op->getVTList(), Ops, M->getMemoryVT(),
13255 M->getMemOperand());
13256 }
13257 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13258 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13259 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13260 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13261 SDValue Chain = Op->getOperand(0);
13262 SDValue Ptr = Op->getOperand(2);
13263 SDValue Val = Op->getOperand(3);
13264 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MII->getMemoryVT(), Chain, Val,
13265 Ptr, MII->getMemOperand());
13266 }
13267 case Intrinsic::amdgcn_av_store_b8:
13268 case Intrinsic::amdgcn_av_store_b16:
13269 case Intrinsic::amdgcn_av_store_b32:
13270 case Intrinsic::amdgcn_av_store_b64:
13271 case Intrinsic::amdgcn_av_store_b128: {
13272 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13273 SDValue Chain = Op->getOperand(0);
13274 SDValue Ptr = Op->getOperand(2);
13275 SDValue Val = Op->getOperand(3);
13276 return DAG.getStore(Chain, DL, Val, Ptr, MII->getMemOperand());
13277 }
13278 default: {
13279 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13281 return lowerImage(Op, ImageDimIntr, DAG, true);
13282
13283 return Op;
13284 }
13285 }
13286}
13287
13288// Return whether the operation has NoUnsignedWrap property.
13289static bool isNoUnsignedWrap(SDValue Addr) {
13290 return (Addr.getOpcode() == ISD::ADD &&
13291 Addr->getFlags().hasNoUnsignedWrap()) ||
13292 Addr->getOpcode() == ISD::OR;
13293}
13294
13296 EVT PtrVT) const {
13297 return PtrVT == MVT::i64;
13298}
13299
13301 EVT PtrVT) const {
13302 return true;
13303}
13304
13305// The raw.(t)buffer and struct.(t)buffer intrinsics have two offset args:
13306// offset (the offset that is included in bounds checking and swizzling, to be
13307// split between the instruction's voffset and immoffset fields) and soffset
13308// (the offset that is excluded from bounds checking and swizzling, to go in
13309// the instruction's soffset field). This function takes the first kind of
13310// offset and figures out how to split it between voffset and immoffset.
13311std::pair<SDValue, SDValue>
13312SITargetLowering::splitBufferOffsets(SDValue Offset, SelectionDAG &DAG) const {
13313 SDLoc DL(Offset);
13314 const unsigned MaxImm = SIInstrInfo::getMaxMUBUFImmOffset(*Subtarget);
13315 SDValue N0 = Offset;
13316 ConstantSDNode *C1 = nullptr;
13317
13318 if ((C1 = dyn_cast<ConstantSDNode>(N0)))
13319 N0 = SDValue();
13320 else if (DAG.isBaseWithConstantOffset(N0)) {
13321 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13322 // being added, so we can only safely match a 32-bit addition with no
13323 // unsigned overflow.
13324 bool CheckNUW = Subtarget->hasGFX1250Insts();
13325 if (!CheckNUW || isNoUnsignedWrap(N0)) {
13327 N0 = N0.getOperand(0);
13328 }
13329 }
13330
13331 if (C1) {
13332 unsigned ImmOffset = C1->getZExtValue();
13333 // If the immediate value is too big for the immoffset field, put only bits
13334 // that would normally fit in the immoffset field. The remaining value that
13335 // is copied/added for the voffset field is a large power of 2, and it
13336 // stands more chance of being CSEd with the copy/add for another similar
13337 // load/store.
13338 // However, do not do that rounding down if that is a negative
13339 // number, as it appears to be illegal to have a negative offset in the
13340 // vgpr, even if adding the immediate offset makes it positive.
13341 unsigned Overflow = ImmOffset & ~MaxImm;
13342 ImmOffset -= Overflow;
13343 if ((int32_t)Overflow < 0) {
13344 Overflow += ImmOffset;
13345 ImmOffset = 0;
13346 }
13347 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(ImmOffset, DL, MVT::i32));
13348 if (Overflow) {
13349 auto OverflowVal = DAG.getConstant(Overflow, DL, MVT::i32);
13350 if (!N0)
13351 N0 = OverflowVal;
13352 else {
13353 SDValue Ops[] = {N0, OverflowVal};
13354 N0 = DAG.getNode(ISD::ADD, DL, MVT::i32, Ops);
13355 }
13356 }
13357 }
13358 if (!N0)
13359 N0 = DAG.getConstant(0, DL, MVT::i32);
13360 if (!C1)
13361 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(0, DL, MVT::i32));
13362 return {N0, SDValue(C1, 0)};
13363}
13364
13365// Analyze a combined offset from an amdgcn_s_buffer_load intrinsic and store
13366// the three offsets (voffset, soffset and instoffset) into the SDValue[3] array
13367// pointed to by Offsets.
13368void SITargetLowering::setBufferOffsets(SDValue CombinedOffset,
13369 SelectionDAG &DAG, SDValue *Offsets,
13370 Align Alignment) const {
13371 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
13372 SDLoc DL(CombinedOffset);
13373 if (auto *C = dyn_cast<ConstantSDNode>(CombinedOffset)) {
13374 uint32_t Imm = C->getZExtValue();
13375 uint32_t SOffset, ImmOffset;
13376 if (TII->splitMUBUFOffset(Imm, SOffset, ImmOffset, Alignment)) {
13377 Offsets[0] = DAG.getConstant(0, DL, MVT::i32);
13378 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13379 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13380 return;
13381 }
13382 }
13383 if (DAG.isBaseWithConstantOffset(CombinedOffset)) {
13384 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13385 // being added, so we can only safely match a 32-bit addition with no
13386 // unsigned overflow.
13387 bool CheckNUW = Subtarget->hasGFX1250Insts();
13388 SDValue N0 = CombinedOffset.getOperand(0);
13389 SDValue N1 = CombinedOffset.getOperand(1);
13390 uint32_t SOffset, ImmOffset;
13391 int Offset = cast<ConstantSDNode>(N1)->getSExtValue();
13392 if (Offset >= 0 && (!CheckNUW || isNoUnsignedWrap(CombinedOffset)) &&
13393 TII->splitMUBUFOffset(Offset, SOffset, ImmOffset, Alignment)) {
13394 Offsets[0] = N0;
13395 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13396 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13397 return;
13398 }
13399 }
13400
13401 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13402 ? DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32)
13403 : DAG.getConstant(0, DL, MVT::i32);
13404
13405 Offsets[0] = CombinedOffset;
13406 Offsets[1] = SOffsetZero;
13407 Offsets[2] = DAG.getTargetConstant(0, DL, MVT::i32);
13408}
13409
13410SDValue SITargetLowering::bufferRsrcPtrToVector(SDValue MaybePointer,
13411 SelectionDAG &DAG) const {
13412 if (!MaybePointer.getValueType().isScalarInteger())
13413 return MaybePointer;
13414
13415 SDValue Rsrc = DAG.getBitcast(MVT::v4i32, MaybePointer);
13416 return Rsrc;
13417}
13418
13419// Wrap a global or flat pointer into a buffer intrinsic using the flags
13420// specified in the intrinsic.
13421SDValue SITargetLowering::lowerPointerAsRsrcIntrin(SDNode *Op,
13422 SelectionDAG &DAG) const {
13423 SDLoc Loc(Op);
13424
13425 SDValue Pointer = Op->getOperand(1);
13426 SDValue Stride = Op->getOperand(2);
13427 SDValue NumRecords = Op->getOperand(3);
13428 SDValue Flags = Op->getOperand(4);
13429
13430 SDValue ExtStride = DAG.getAnyExtOrTrunc(Stride, Loc, MVT::i32);
13431 SDValue Rsrc;
13432
13433 if (Subtarget->getBufferResourceNumRecordsWidth() == 45) {
13434 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i64);
13435 NumRecords = DAG.getNode(ISD::AND, Loc, MVT::i64, NumRecords,
13436 DAG.getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13437 SDValue Zero = DAG.getConstant(0, Loc, MVT::i32);
13438 // Build the lower 64-bit value, which has a 57-bit base and the lower 7-bit
13439 // num_records.
13440 SDValue ExtPointer = DAG.getAnyExtOrTrunc(Pointer, Loc, MVT::i64);
13441 SDValue NumRecordsLHS =
13442 DAG.getNode(ISD::SHL, Loc, MVT::i64, NumRecords,
13443 DAG.getShiftAmountConstant(57, MVT::i32, Loc));
13444 SDValue LowHalf =
13445 DAG.getNode(ISD::OR, Loc, MVT::i64, ExtPointer, NumRecordsLHS);
13446
13447 // Build the higher 64-bit value, which has the higher 38-bit num_records,
13448 // 6-bit zero (omit), 16-bit stride and scale and 4-bit flag.
13449 SDValue NumRecordsRHS =
13450 DAG.getNode(ISD::SRL, Loc, MVT::i64, NumRecords,
13451 DAG.getShiftAmountConstant(7, MVT::i32, Loc));
13452 SDValue ShiftedStride =
13453 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13454 DAG.getShiftAmountConstant(12, MVT::i32, Loc));
13455 SDValue ExtShiftedStrideVec =
13456 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedStride);
13457 SDValue ExtShiftedStride =
13458 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedStrideVec);
13459 SDValue ShiftedFlags =
13460 DAG.getNode(ISD::SHL, Loc, MVT::i32, Flags,
13461 DAG.getShiftAmountConstant(28, MVT::i32, Loc));
13462 SDValue ExtShiftedFlagsVec =
13463 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedFlags);
13464 SDValue ExtShiftedFlags =
13465 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedFlagsVec);
13466 SDValue CombinedFields =
13467 DAG.getNode(ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13468 SDValue HighHalf =
13469 DAG.getNode(ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13470
13471 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i64, LowHalf, HighHalf);
13472 } else {
13473 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i32);
13474 auto [LowHalf, HighHalf] =
13475 DAG.SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13476 SDValue Mask = DAG.getConstant(0x0000ffff, Loc, MVT::i32);
13477 SDValue Masked = DAG.getNode(ISD::AND, Loc, MVT::i32, HighHalf, Mask);
13478 SDValue ShiftedStride =
13479 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13480 DAG.getShiftAmountConstant(16, MVT::i32, Loc));
13481 SDValue NewHighHalf =
13482 DAG.getNode(ISD::OR, Loc, MVT::i32, Masked, ShiftedStride);
13483
13484 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v4i32, LowHalf, NewHighHalf,
13485 NumRecords, Flags);
13486 }
13487
13488 SDValue RsrcPtr = DAG.getNode(ISD::BITCAST, Loc, MVT::i128, Rsrc);
13489 return RsrcPtr;
13490}
13491
13492// Handle 8 bit and 16 bit buffer loads
13493SDValue SITargetLowering::handleByteShortBufferLoads(SelectionDAG &DAG,
13494 EVT LoadVT, SDLoc DL,
13496 MachineMemOperand *MMO,
13497 bool IsTFE) const {
13498 EVT IntVT = LoadVT.changeTypeToInteger();
13499
13500 if (IsTFE) {
13501 unsigned Opc = (LoadVT.getScalarType() == MVT::i8)
13502 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13503 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13505 MachineMemOperand *OpMMO = MF.getMachineMemOperand(MMO, 0, 8);
13506 SDVTList VTs = DAG.getVTList(MVT::v2i32, MVT::Other);
13507 SDValue Op = getMemIntrinsicNode(Opc, DL, VTs, Ops, MVT::v2i32, OpMMO, DAG);
13508 SDValue Status = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13509 DAG.getConstant(1, DL, MVT::i32));
13510 SDValue Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13511 DAG.getConstant(0, DL, MVT::i32));
13512 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Data);
13513 SDValue Value = DAG.getNode(ISD::BITCAST, DL, LoadVT, Trunc);
13514 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
13515 }
13516
13517 unsigned Opc = LoadVT.getScalarType() == MVT::i8
13518 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13519 : AMDGPUISD::BUFFER_LOAD_USHORT;
13520
13521 SDVTList ResList = DAG.getVTList(MVT::i32, MVT::Other);
13522 SDValue BufferLoad =
13523 DAG.getMemIntrinsicNode(Opc, DL, ResList, Ops, IntVT, MMO);
13524 SDValue LoadVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, BufferLoad);
13525 LoadVal = DAG.getNode(ISD::BITCAST, DL, LoadVT, LoadVal);
13526
13527 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
13528}
13529
13530// Handle 8 bit and 16 bit buffer stores
13531SDValue SITargetLowering::handleByteShortBufferStores(SelectionDAG &DAG,
13532 EVT VDataType, SDLoc DL,
13533 SDValue Ops[],
13534 MemSDNode *M) const {
13535 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13536 Ops[1] = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Ops[1]);
13537
13538 SDValue BufferStoreExt = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Ops[1]);
13539 Ops[1] = BufferStoreExt;
13540 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13541 : AMDGPUISD::BUFFER_STORE_SHORT;
13542 ArrayRef<SDValue> OpsRef = ArrayRef(&Ops[0], 9);
13543 return DAG.getMemIntrinsicNode(Opc, DL, M->getVTList(), OpsRef, VDataType,
13544 M->getMemOperand());
13545}
13546
13548 SDValue Op, const SDLoc &SL, EVT VT) {
13549 if (VT.bitsLT(Op.getValueType()))
13550 return DAG.getNode(ISD::TRUNCATE, SL, VT, Op);
13551
13552 switch (ExtType) {
13553 case ISD::SEXTLOAD:
13554 return DAG.getNode(ISD::SIGN_EXTEND, SL, VT, Op);
13555 case ISD::ZEXTLOAD:
13556 return DAG.getNode(ISD::ZERO_EXTEND, SL, VT, Op);
13557 case ISD::EXTLOAD:
13558 return DAG.getNode(ISD::ANY_EXTEND, SL, VT, Op);
13559 case ISD::NON_EXTLOAD:
13560 return Op;
13561 }
13562
13563 llvm_unreachable("invalid ext type");
13564}
13565
13566// Try to turn 8 and 16-bit scalar loads into SMEM eligible 32-bit loads.
13567// TODO: Skip this on GFX12 which does have scalar sub-dword loads.
13568SDValue SITargetLowering::widenLoad(LoadSDNode *Ld,
13569 DAGCombinerInfo &DCI) const {
13570 SelectionDAG &DAG = DCI.DAG;
13571 if (Ld->getAlign() < Align(4) || Ld->isDivergent())
13572 return SDValue();
13573
13574 // FIXME: Constant loads should all be marked invariant.
13575 unsigned AS = Ld->getAddressSpace();
13576 if (AS != AMDGPUAS::CONSTANT_ADDRESS &&
13578 (AS != AMDGPUAS::GLOBAL_ADDRESS || !Ld->isInvariant()))
13579 return SDValue();
13580
13581 // Don't do this early, since it may interfere with adjacent load merging for
13582 // illegal types. We can avoid losing alignment information for exotic types
13583 // pre-legalize.
13584 EVT MemVT = Ld->getMemoryVT();
13585 if ((MemVT.isSimple() && !DCI.isAfterLegalizeDAG()) ||
13586 MemVT.getSizeInBits() >= 32)
13587 return SDValue();
13588
13589 SDLoc SL(Ld);
13590
13591 assert((!MemVT.isVector() || Ld->getExtensionType() == ISD::NON_EXTLOAD) &&
13592 "unexpected vector extload");
13593
13594 // TODO: Drop only high part of range.
13595 SDValue Ptr = Ld->getBasePtr();
13596 SDValue NewLoad = DAG.getLoad(
13597 ISD::UNINDEXED, ISD::NON_EXTLOAD, MVT::i32, SL, Ld->getChain(), Ptr,
13598 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13599 Ld->getMemOperand()->getFlags(), Ld->getAAInfo()); // Drop ranges
13600
13601 EVT TruncVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
13602 if (MemVT.isFloatingPoint()) {
13603 assert(Ld->getExtensionType() == ISD::NON_EXTLOAD &&
13604 "unexpected fp extload");
13605 TruncVT = MemVT.changeTypeToInteger();
13606 }
13607
13608 SDValue Cvt = NewLoad;
13609 if (Ld->getExtensionType() == ISD::SEXTLOAD) {
13610 Cvt = DAG.getNode(ISD::SIGN_EXTEND_INREG, SL, MVT::i32, NewLoad,
13611 DAG.getValueType(TruncVT));
13612 } else if (Ld->getExtensionType() == ISD::ZEXTLOAD ||
13613 Ld->getExtensionType() == ISD::NON_EXTLOAD) {
13614 Cvt = DAG.getZeroExtendInReg(NewLoad, SL, TruncVT);
13615 } else {
13616 assert(Ld->getExtensionType() == ISD::EXTLOAD);
13617 }
13618
13619 EVT VT = Ld->getValueType(0);
13620 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
13621
13622 DCI.AddToWorklist(Cvt.getNode());
13623
13624 // We may need to handle exotic cases, such as i16->i64 extloads, so insert
13625 // the appropriate extension from the 32-bit load.
13626 Cvt = getLoadExtOrTrunc(DAG, Ld->getExtensionType(), Cvt, SL, IntVT);
13627 DCI.AddToWorklist(Cvt.getNode());
13628
13629 // Handle conversion back to floating point if necessary.
13630 Cvt = DAG.getNode(ISD::BITCAST, SL, VT, Cvt);
13631
13632 return DAG.getMergeValues({Cvt, NewLoad.getValue(1)}, SL);
13633}
13634
13636 const SIMachineFunctionInfo &Info) {
13637 // TODO: Should check if the address can definitely not access stack.
13638 if (Info.isEntryFunction())
13639 return Info.getUserSGPRInfo().hasFlatScratchInit();
13640 return true;
13641}
13642
13643SDValue SITargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
13644 SDLoc DL(Op);
13645 LoadSDNode *Load = cast<LoadSDNode>(Op);
13646 ISD::LoadExtType ExtType = Load->getExtensionType();
13647 EVT MemVT = Load->getMemoryVT();
13648 MachineMemOperand *MMO = Load->getMemOperand();
13649
13650 if (ExtType == ISD::NON_EXTLOAD && MemVT.getSizeInBits() < 32) {
13651 // Legalize uniform 16-bit loads to i16 = trunc (zextload i16->i32)
13652 // to match subword load patterns.
13653 // Only do this for loads that can use scalar subword load instructions.
13654 if (!MemVT.isVector() && MemVT.getSizeInBits() == 16 &&
13655 isTypeLegal(MemVT) && Subtarget->hasScalarSubwordLoads() &&
13657 SDValue Chain = Load->getChain();
13658 SDValue BasePtr = Load->getBasePtr();
13659
13660 // Load as i16 and zero-extend to i32 (matches S_LOAD_U16 behavior)
13661 SDValue NewLD = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain,
13662 BasePtr, MVT::i16, MMO);
13663
13664 // Truncate back to i16
13665 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, NewLD);
13666
13667 // For f16/bf16, bitcast from i16 to the original fp type
13668 SDValue Result = (MemVT == MVT::i16)
13669 ? Trunc
13670 : DAG.getNode(ISD::BITCAST, DL, MemVT, Trunc);
13671
13672 SDValue Ops[] = {Result, NewLD.getValue(1)};
13673 return DAG.getMergeValues(Ops, DL);
13674 }
13675
13676 if (MemVT == MVT::i16 && isTypeLegal(MVT::i16))
13677 return SDValue();
13678
13679 // FIXME: Copied from PPC
13680 // First, load into 32 bits, then truncate to 1 bit.
13681
13682 SDValue Chain = Load->getChain();
13683 SDValue BasePtr = Load->getBasePtr();
13684
13685 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13686
13687 SDValue NewLD = DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, BasePtr,
13688 RealMemVT, MMO);
13689
13690 if (!MemVT.isVector()) {
13691 SDValue Ops[] = {DAG.getNode(ISD::TRUNCATE, DL, MemVT, NewLD),
13692 NewLD.getValue(1)};
13693
13694 return DAG.getMergeValues(Ops, DL);
13695 }
13696
13698 for (unsigned I = 0, N = MemVT.getVectorNumElements(); I != N; ++I) {
13699 SDValue Elt = DAG.getNode(ISD::SRL, DL, MVT::i32, NewLD,
13700 DAG.getConstant(I, DL, MVT::i32));
13701
13702 Elts.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Elt));
13703 }
13704
13705 SDValue Ops[] = {DAG.getBuildVector(MemVT, DL, Elts), NewLD.getValue(1)};
13706
13707 return DAG.getMergeValues(Ops, DL);
13708 }
13709
13710 if (!MemVT.isVector())
13711 return SDValue();
13712
13713 assert(Op.getValueType().getVectorElementType() == MVT::i32 &&
13714 "Custom lowering for non-i32 vectors hasn't been implemented.");
13715
13716 Align Alignment = Load->getAlign();
13717 unsigned AS = Load->getAddressSpace();
13718 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13719 AS == AMDGPUAS::FLAT_ADDRESS &&
13720 Alignment.value() < MemVT.getStoreSize() && MemVT.getSizeInBits() > 32) {
13721 return SplitVectorLoad(Op, DAG);
13722 }
13723
13725 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
13726 // If there is a possibility that flat instruction access scratch memory
13727 // then we need to use the same legalization rules we use for private.
13728 if (AS == AMDGPUAS::FLAT_ADDRESS &&
13729 !Subtarget->hasMultiDwordFlatScratchAddressing())
13730 AS = addressMayBeAccessedAsPrivate(Load->getMemOperand(), *MFI)
13733
13734 unsigned NumElements = MemVT.getVectorNumElements();
13735
13736 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13738 (AS == AMDGPUAS::GLOBAL_ADDRESS && Load->isSimple() &&
13739 (Load->isInvariant() || isMemOpHasNoClobberedMemOperand(Load)))) {
13740 if ((!Op->isDivergent() || AMDGPU::isUniformMMO(MMO)) &&
13741 Alignment >= Align(4) && NumElements < 32) {
13742 if (MemVT.isPow2VectorType() ||
13743 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13744 return SDValue();
13745 return WidenOrSplitVectorLoad(Op, DAG);
13746 }
13747 // Non-uniform loads will be selected to MUBUF instructions, so they
13748 // have the same legalization requirements as global and private
13749 // loads.
13750 //
13751 }
13752 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13755 if (NumElements > 4)
13756 return SplitVectorLoad(Op, DAG);
13757 // v3 loads not supported on SI.
13758 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13759 return WidenOrSplitVectorLoad(Op, DAG);
13760
13761 // v3 and v4 loads are supported for private and global memory.
13762 return SDValue();
13763 }
13764 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
13765 // Depending on the setting of the private_element_size field in the
13766 // resource descriptor, we can only make private accesses up to a certain
13767 // size.
13768 switch (Subtarget->getMaxPrivateElementSize()) {
13769 case 4: {
13770 auto [Op0, Op1] = scalarizeVectorLoad(Load, DAG);
13771 return DAG.getMergeValues({Op0, Op1}, DL);
13772 }
13773 case 8:
13774 if (NumElements > 2)
13775 return SplitVectorLoad(Op, DAG);
13776 return SDValue();
13777 case 16:
13778 // Same as global/flat
13779 if (NumElements > 4)
13780 return SplitVectorLoad(Op, DAG);
13781 // v3 loads not supported on SI.
13782 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13783 return WidenOrSplitVectorLoad(Op, DAG);
13784
13785 return SDValue();
13786 default:
13787 llvm_unreachable("unsupported private_element_size");
13788 }
13789 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
13790 unsigned Fast = 0;
13791 auto Flags = Load->getMemOperand()->getFlags();
13793 Load->getAlign(), Flags, &Fast) &&
13794 Fast > 1)
13795 return SDValue();
13796
13797 if (MemVT.isVector())
13798 return SplitVectorLoad(Op, DAG);
13799 }
13800
13802 MemVT, *Load->getMemOperand())) {
13803 auto [Op0, Op1] = expandUnalignedLoad(Load, DAG);
13804 return DAG.getMergeValues({Op0, Op1}, DL);
13805 }
13806
13807 return SDValue();
13808}
13809
13810SDValue SITargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
13811 EVT VT = Op.getValueType();
13812 if (VT.getSizeInBits() == 128 || VT.getSizeInBits() == 256 ||
13813 VT.getSizeInBits() == 512)
13814 return splitTernaryVectorOp(Op, DAG);
13815
13816 assert(VT.getSizeInBits() == 64);
13817
13818 SDLoc DL(Op);
13819 SDValue Cond = DAG.getFreeze(Op.getOperand(0));
13820
13821 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
13822 SDValue One = DAG.getConstant(1, DL, MVT::i32);
13823
13824 SDValue LHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
13825 SDValue RHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(2));
13826
13827 SDValue Lo0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, Zero);
13828 SDValue Lo1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, Zero);
13829
13830 SDValue Lo = DAG.getSelect(DL, MVT::i32, Cond, Lo0, Lo1);
13831
13832 SDValue Hi0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, One);
13833 SDValue Hi1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, One);
13834
13835 SDValue Hi = DAG.getSelect(DL, MVT::i32, Cond, Hi0, Hi1);
13836
13837 SDValue Res = DAG.getBuildVector(MVT::v2i32, DL, {Lo, Hi});
13838 return DAG.getNode(ISD::BITCAST, DL, VT, Res);
13839}
13840
13841// Catch division cases where we can use shortcuts with rcp and rsq
13842// instructions.
13843SDValue SITargetLowering::lowerFastUnsafeFDIV(SDValue Op,
13844 SelectionDAG &DAG) const {
13845 SDLoc SL(Op);
13846 SDValue LHS = Op.getOperand(0);
13847 SDValue RHS = Op.getOperand(1);
13848 EVT VT = Op.getValueType();
13849 const SDNodeFlags Flags = Op->getFlags();
13850
13851 bool AllowInaccurateRcp = Flags.hasApproximateFuncs();
13852
13853 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
13854 // Without !fpmath accuracy information, we can't do more because we don't
13855 // know exactly whether rcp is accurate enough to meet !fpmath requirement.
13856 // f16 is always accurate enough
13857 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13858 return SDValue();
13859
13860 if (CLHS->isOne()) {
13861 // v_rcp_f32 and v_rsq_f32 do not support denormals, and according to
13862 // the CI documentation has a worst case error of 1 ulp.
13863 // OpenCL requires <= 2.5 ulp for 1.0 / x, so it should always be OK to
13864 // use it as long as we aren't trying to use denormals.
13865 //
13866 // v_rcp_f16 and v_rsq_f16 DO support denormals and 0.51ulp.
13867
13868 // 1.0 / sqrt(x) -> rsq(x)
13869
13870 // XXX - Is afn sufficient to do this for f64? The maximum ULP
13871 // error seems really high at 2^29 ULP.
13872 // 1.0 / x -> rcp(x)
13873 return DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13874 }
13875
13876 // Same as for 1.0, but expand the sign out of the constant.
13877 if (CLHS->isMinusOne()) {
13878 // -1.0 / x -> rcp (fneg x)
13879 SDValue FNegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
13880 return DAG.getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13881 }
13882 }
13883
13884 // For f16 and bf16 require afn or arcp.
13885 // For f32 require afn.
13886 if (!AllowInaccurateRcp &&
13887 ((VT != MVT::f16 && VT != MVT::bf16) || !Flags.hasAllowReciprocal()))
13888 return SDValue();
13889
13890 // Turn into multiply by the reciprocal.
13891 // x / y -> x * (1.0 / y)
13892 SDValue Recip = DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13893 return DAG.getNode(ISD::FMUL, SL, VT, LHS, Recip, Flags);
13894}
13895
13896SDValue SITargetLowering::lowerFastUnsafeFDIV64(SDValue Op,
13897 SelectionDAG &DAG) const {
13898 SDLoc SL(Op);
13899 SDValue X = Op.getOperand(0);
13900 SDValue Y = Op.getOperand(1);
13901 EVT VT = Op.getValueType();
13902 const SDNodeFlags Flags = Op->getFlags();
13903
13904 bool AllowInaccurateDiv = Flags.hasApproximateFuncs();
13905 if (!AllowInaccurateDiv)
13906 return SDValue();
13907
13908 const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(X);
13909 bool IsNegRcp = CLHS && CLHS->isMinusOne();
13910
13911 // Pull out the negation so it folds for free into the source modifiers.
13912 if (IsNegRcp)
13913 X = DAG.getConstantFP(1.0, SL, VT);
13914
13915 SDValue NegY = IsNegRcp ? Y : DAG.getNode(ISD::FNEG, SL, VT, Y);
13916 SDValue One = DAG.getConstantFP(1.0, SL, VT);
13917
13918 SDValue R = DAG.getNode(AMDGPUISD::RCP, SL, VT, Y);
13919 if (IsNegRcp)
13920 R = DAG.getNode(ISD::FNEG, SL, VT, R);
13921
13922 SDValue Tmp0 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13923
13924 R = DAG.getNode(ISD::FMA, SL, VT, Tmp0, R, R);
13925 SDValue Tmp1 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13926 R = DAG.getNode(ISD::FMA, SL, VT, Tmp1, R, R);
13927
13928 // Skip the last 2 correction terms for reciprocal.
13929 if (IsNegRcp || (CLHS && CLHS->isOne()))
13930 return R;
13931
13932 SDValue Ret = DAG.getNode(ISD::FMUL, SL, VT, X, R);
13933 SDValue Tmp2 = DAG.getNode(ISD::FMA, SL, VT, NegY, Ret, X);
13934 return DAG.getNode(ISD::FMA, SL, VT, Tmp2, R, Ret);
13935}
13936
13937static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13938 EVT VT, SDValue A, SDValue B, SDValue GlueChain,
13939 SDNodeFlags Flags) {
13940 if (GlueChain->getNumValues() <= 1) {
13941 return DAG.getNode(Opcode, SL, VT, A, B, Flags);
13942 }
13943
13944 assert(GlueChain->getNumValues() == 3);
13945
13946 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13947 switch (Opcode) {
13948 default:
13949 llvm_unreachable("no chain equivalent for opcode");
13950 case ISD::FMUL:
13951 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13952 break;
13953 }
13954
13955 return DAG.getNode(Opcode, SL, VTList,
13956 {GlueChain.getValue(1), A, B, GlueChain.getValue(2)},
13957 Flags);
13958}
13959
13960static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13961 EVT VT, SDValue A, SDValue B, SDValue C,
13962 SDValue GlueChain, SDNodeFlags Flags) {
13963 if (GlueChain->getNumValues() <= 1) {
13964 return DAG.getNode(Opcode, SL, VT, {A, B, C}, Flags);
13965 }
13966
13967 assert(GlueChain->getNumValues() == 3);
13968
13969 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13970 switch (Opcode) {
13971 default:
13972 llvm_unreachable("no chain equivalent for opcode");
13973 case ISD::FMA:
13974 Opcode = AMDGPUISD::FMA_W_CHAIN;
13975 break;
13976 }
13977
13978 return DAG.getNode(Opcode, SL, VTList,
13979 {GlueChain.getValue(1), A, B, C, GlueChain.getValue(2)},
13980 Flags);
13981}
13982
13983SDValue SITargetLowering::LowerFDIV16(SDValue Op, SelectionDAG &DAG) const {
13984 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
13985 return FastLowered;
13986
13987 SDLoc SL(Op);
13988 EVT VT = Op.getValueType();
13989 SDValue LHS = Op.getOperand(0);
13990 SDValue RHS = Op.getOperand(1);
13991
13992 SDValue LHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, LHS);
13993 SDValue RHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, RHS);
13994
13995 if (VT == MVT::bf16) {
13996 SDValue ExtDiv =
13997 DAG.getNode(ISD::FDIV, SL, MVT::f32, LHSExt, RHSExt, Op->getFlags());
13998 return DAG.getNode(ISD::FP_ROUND, SL, MVT::bf16, ExtDiv,
13999 DAG.getTargetConstant(0, SL, MVT::i32));
14000 }
14001
14002 assert(VT == MVT::f16);
14003
14004 // a32.u = opx(V_CVT_F32_F16, a.u); // CVT to F32
14005 // b32.u = opx(V_CVT_F32_F16, b.u); // CVT to F32
14006 // r32.u = opx(V_RCP_F32, b32.u); // rcp = 1 / d
14007 // q32.u = opx(V_MUL_F32, a32.u, r32.u); // q = n * rcp
14008 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
14009 // q32.u = opx(V_MAD_F32, e32.u, r32.u, q32.u); // q = n * rcp
14010 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
14011 // tmp.u = opx(V_MUL_F32, e32.u, r32.u);
14012 // tmp.u = opx(V_AND_B32, tmp.u, 0xff800000)
14013 // q32.u = opx(V_ADD_F32, tmp.u, q32.u);
14014 // q16.u = opx(V_CVT_F16_F32, q32.u);
14015 // q16.u = opx(V_DIV_FIXUP_F16, q16.u, b.u, a.u); // q = touchup(q, d, n)
14016
14017 // We will use ISD::FMA on targets that don't support ISD::FMAD.
14018 unsigned FMADOpCode =
14020 SDValue NegRHSExt = DAG.getNode(ISD::FNEG, SL, MVT::f32, RHSExt);
14021 SDValue Rcp =
14022 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt, Op->getFlags());
14023 SDValue Quot =
14024 DAG.getNode(ISD::FMUL, SL, MVT::f32, LHSExt, Rcp, Op->getFlags());
14025 SDValue Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
14026 Op->getFlags());
14027 Quot = DAG.getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot, Op->getFlags());
14028 Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
14029 Op->getFlags());
14030 SDValue Tmp = DAG.getNode(ISD::FMUL, SL, MVT::f32, Err, Rcp, Op->getFlags());
14031 SDValue TmpCast = DAG.getNode(ISD::BITCAST, SL, MVT::i32, Tmp);
14032 TmpCast = DAG.getNode(ISD::AND, SL, MVT::i32, TmpCast,
14033 DAG.getConstant(0xff800000, SL, MVT::i32));
14034 Tmp = DAG.getNode(ISD::BITCAST, SL, MVT::f32, TmpCast);
14035 Quot = DAG.getNode(ISD::FADD, SL, MVT::f32, Tmp, Quot, Op->getFlags());
14036 SDValue RDst = DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Quot,
14037 DAG.getTargetConstant(0, SL, MVT::i32));
14038 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst, RHS, LHS,
14039 Op->getFlags());
14040}
14041
14042// Faster 2.5 ULP division that does not support denormals.
14043SDValue SITargetLowering::lowerFDIV_FAST(SDValue Op, SelectionDAG &DAG) const {
14044 SDNodeFlags Flags = Op->getFlags();
14045 SDLoc SL(Op);
14046 SDValue LHS = Op.getOperand(1);
14047 SDValue RHS = Op.getOperand(2);
14048
14049 // TODO: The combiner should probably handle elimination of redundant fabs.
14051 ? RHS
14052 : DAG.getNode(ISD::FABS, SL, MVT::f32, RHS, Flags);
14053
14054 const APFloat K0Val(0x1p+96f);
14055 const SDValue K0 = DAG.getConstantFP(K0Val, SL, MVT::f32);
14056
14057 const APFloat K1Val(0x1p-32f);
14058 const SDValue K1 = DAG.getConstantFP(K1Val, SL, MVT::f32);
14059
14060 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
14061
14062 EVT SetCCVT =
14063 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
14064
14065 SDValue r2 = DAG.getSetCC(SL, SetCCVT, r1, K0, ISD::SETOGT);
14066
14067 SDValue r3 = DAG.getNode(ISD::SELECT, SL, MVT::f32, r2, K1, One, Flags);
14068
14069 r1 = DAG.getNode(ISD::FMUL, SL, MVT::f32, RHS, r3, Flags);
14070
14071 // rcp does not support denormals.
14072 SDValue r0 = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, r1, Flags);
14073
14074 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f32, LHS, r0, Flags);
14075
14076 return DAG.getNode(ISD::FMUL, SL, MVT::f32, r3, Mul, Flags);
14077}
14078
14079// Returns immediate value for setting the F32 denorm mode when using the
14080// S_DENORM_MODE instruction.
14082 const SIMachineFunctionInfo *Info,
14083 const GCNSubtarget *ST) {
14084 assert(ST->hasDenormModeInst() && "Requires S_DENORM_MODE");
14085 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
14086 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
14087 return DAG.getTargetConstant(Mode, SDLoc(), MVT::i32);
14088}
14089
14090SDValue SITargetLowering::LowerFDIV32(SDValue Op, SelectionDAG &DAG) const {
14091 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
14092 return FastLowered;
14093
14094 // The selection matcher assumes anything with a chain selecting to a
14095 // mayRaiseFPException machine instruction. Since we're introducing a chain
14096 // here, we need to explicitly report nofpexcept for the regular fdiv
14097 // lowering.
14098 SDNodeFlags Flags = Op->getFlags();
14099 Flags.setNoFPExcept(true);
14100
14101 SDLoc SL(Op);
14102 SDValue LHS = Op.getOperand(0);
14103 SDValue RHS = Op.getOperand(1);
14104
14105 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
14106
14107 SDVTList ScaleVT = DAG.getVTList(MVT::f32, MVT::i1);
14108
14109 SDValue DenominatorScaled =
14110 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {RHS, RHS, LHS}, Flags);
14111 SDValue NumeratorScaled =
14112 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {LHS, RHS, LHS}, Flags);
14113
14114 // Denominator is scaled to not be denormal, so using rcp is ok.
14115 SDValue ApproxRcp =
14116 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
14117 SDValue NegDivScale0 =
14118 DAG.getNode(ISD::FNEG, SL, MVT::f32, DenominatorScaled, Flags);
14119
14120 using namespace AMDGPU::Hwreg;
14121 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
14122 const SDValue BitField = DAG.getTargetConstant(Denorm32Reg, SL, MVT::i32);
14123
14124 const MachineFunction &MF = DAG.getMachineFunction();
14125 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
14126 const DenormalMode DenormMode = Info->getMode().FP32Denormals;
14127
14128 const bool PreservesDenormals = DenormMode == DenormalMode::getIEEE();
14129 const bool HasDynamicDenormals =
14130 (DenormMode.Input == DenormalMode::Dynamic) ||
14131 (DenormMode.Output == DenormalMode::Dynamic);
14132
14133 SDValue SavedDenormMode;
14134
14135 if (!PreservesDenormals) {
14136 // Note we can't use the STRICT_FMA/STRICT_FMUL for the non-strict FDIV
14137 // lowering. The chain dependence is insufficient, and we need glue. We do
14138 // not need the glue variants in a strictfp function.
14139
14140 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
14141
14142 SDValue Glue = DAG.getEntryNode();
14143 if (HasDynamicDenormals) {
14144 SDNode *GetReg = DAG.getMachineNode(AMDGPU::S_GETREG_B32, SL,
14145 DAG.getVTList(MVT::i32, MVT::Glue),
14146 {BitField, Glue});
14147 SavedDenormMode = SDValue(GetReg, 0);
14148
14149 Glue = DAG.getMergeValues(
14150 {DAG.getEntryNode(), SDValue(GetReg, 0), SDValue(GetReg, 1)}, SL);
14151 }
14152
14153 SDNode *EnableDenorm;
14154 if (Subtarget->hasDenormModeInst()) {
14155 const SDValue EnableDenormValue =
14156 getSPDenormModeValue(FP_DENORM_FLUSH_NONE, DAG, Info, Subtarget);
14157
14158 EnableDenorm = DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
14159 EnableDenormValue)
14160 .getNode();
14161 } else {
14162 const SDValue EnableDenormValue =
14163 DAG.getConstant(FP_DENORM_FLUSH_NONE, SL, MVT::i32);
14164 EnableDenorm = DAG.getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
14165 {EnableDenormValue, BitField, Glue});
14166 }
14167
14168 SDValue Ops[3] = {NegDivScale0, SDValue(EnableDenorm, 0),
14169 SDValue(EnableDenorm, 1)};
14170
14171 NegDivScale0 = DAG.getMergeValues(Ops, SL);
14172 }
14173
14174 SDValue Fma0 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0,
14175 ApproxRcp, One, NegDivScale0, Flags);
14176
14177 SDValue Fma1 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma0, ApproxRcp,
14178 ApproxRcp, Fma0, Flags);
14179
14180 SDValue Mul = getFPBinOp(DAG, ISD::FMUL, SL, MVT::f32, NumeratorScaled, Fma1,
14181 Fma1, Flags);
14182
14183 SDValue Fma2 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Mul,
14184 NumeratorScaled, Mul, Flags);
14185
14186 SDValue Fma3 =
14187 getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma2, Fma1, Mul, Fma2, Flags);
14188
14189 SDValue Fma4 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Fma3,
14190 NumeratorScaled, Fma3, Flags);
14191
14192 if (!PreservesDenormals) {
14193 SDNode *DisableDenorm;
14194 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
14195 const SDValue DisableDenormValue = getSPDenormModeValue(
14196 FP_DENORM_FLUSH_IN_FLUSH_OUT, DAG, Info, Subtarget);
14197
14198 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
14199 DisableDenorm =
14200 DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
14201 Fma4.getValue(1), DisableDenormValue, Fma4.getValue(2))
14202 .getNode();
14203 } else {
14204 assert(HasDynamicDenormals == (bool)SavedDenormMode);
14205 const SDValue DisableDenormValue =
14206 HasDynamicDenormals
14207 ? SavedDenormMode
14208 : DAG.getConstant(FP_DENORM_FLUSH_IN_FLUSH_OUT, SL, MVT::i32);
14209
14210 DisableDenorm = DAG.getMachineNode(
14211 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14212 {DisableDenormValue, BitField, Fma4.getValue(1), Fma4.getValue(2)});
14213 }
14214
14215 SDValue OutputChain = DAG.getNode(ISD::TokenFactor, SL, MVT::Other,
14216 SDValue(DisableDenorm, 0), DAG.getRoot());
14217 DAG.setRoot(OutputChain);
14218 }
14219
14220 SDValue Scale = NumeratorScaled.getValue(1);
14221 SDValue Fmas = DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f32,
14222 {Fma4, Fma1, Fma3, Scale}, Flags);
14223
14224 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas, RHS, LHS, Flags);
14225}
14226
14227SDValue SITargetLowering::LowerFDIV64(SDValue Op, SelectionDAG &DAG) const {
14228 if (SDValue FastLowered = lowerFastUnsafeFDIV64(Op, DAG))
14229 return FastLowered;
14230
14231 SDLoc SL(Op);
14232 SDValue X = Op.getOperand(0);
14233 SDValue Y = Op.getOperand(1);
14234
14235 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f64);
14236
14237 SDVTList ScaleVT = DAG.getVTList(MVT::f64, MVT::i1);
14238
14239 SDValue DivScale0 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, Y, Y, X);
14240
14241 SDValue NegDivScale0 = DAG.getNode(ISD::FNEG, SL, MVT::f64, DivScale0);
14242
14243 SDValue Rcp = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14244
14245 SDValue Fma0 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Rcp, One);
14246
14247 SDValue Fma1 = DAG.getNode(ISD::FMA, SL, MVT::f64, Rcp, Fma0, Rcp);
14248
14249 SDValue Fma2 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Fma1, One);
14250
14251 SDValue DivScale1 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, X, Y, X);
14252
14253 SDValue Fma3 = DAG.getNode(ISD::FMA, SL, MVT::f64, Fma1, Fma2, Fma1);
14254 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f64, DivScale1, Fma3);
14255
14256 SDValue Fma4 =
14257 DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Mul, DivScale1);
14258
14259 SDValue Scale;
14260
14261 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14262 // Workaround a hardware bug on SI where the condition output from div_scale
14263 // is not usable.
14264
14265 const SDValue Hi = DAG.getConstant(1, SL, MVT::i32);
14266
14267 // Figure out if the scale to use for div_fmas.
14268 SDValue NumBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, X);
14269 SDValue DenBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Y);
14270 SDValue Scale0BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale0);
14271 SDValue Scale1BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale1);
14272
14273 SDValue NumHi =
14274 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, NumBC, Hi);
14275 SDValue DenHi =
14276 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, DenBC, Hi);
14277
14278 SDValue Scale0Hi =
14279 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale0BC, Hi);
14280 SDValue Scale1Hi =
14281 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale1BC, Hi);
14282
14283 SDValue CmpDen = DAG.getSetCC(SL, MVT::i1, DenHi, Scale0Hi, ISD::SETEQ);
14284 SDValue CmpNum = DAG.getSetCC(SL, MVT::i1, NumHi, Scale1Hi, ISD::SETEQ);
14285 Scale = DAG.getNode(ISD::XOR, SL, MVT::i1, CmpNum, CmpDen);
14286 } else {
14287 Scale = DivScale1.getValue(1);
14288 }
14289
14290 SDValue Fmas =
14291 DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3, Mul, Scale);
14292
14293 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas, Y, X);
14294}
14295
14296SDValue SITargetLowering::LowerFDIV(SDValue Op, SelectionDAG &DAG) const {
14297 EVT VT = Op.getValueType();
14298
14299 if (VT == MVT::f32)
14300 return LowerFDIV32(Op, DAG);
14301
14302 if (VT == MVT::f64)
14303 return LowerFDIV64(Op, DAG);
14304
14305 if (VT == MVT::f16 || VT == MVT::bf16)
14306 return LowerFDIV16(Op, DAG);
14307
14308 llvm_unreachable("Unexpected type for fdiv");
14309}
14310
14311SDValue SITargetLowering::LowerFFREXP(SDValue Op, SelectionDAG &DAG) const {
14312 SDLoc dl(Op);
14313 SDValue Val = Op.getOperand(0);
14314 EVT VT = Val.getValueType();
14315 EVT ResultExpVT = Op->getValueType(1);
14316 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14317
14318 SDValue Mant = DAG.getNode(
14320 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_mant, dl, MVT::i32), Val);
14321
14322 SDValue Exp = DAG.getNode(
14323 ISD::INTRINSIC_WO_CHAIN, dl, InstrExpVT,
14324 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_exp, dl, MVT::i32), Val);
14325
14326 if (Subtarget->hasFractBug()) {
14327 SDValue Fabs = DAG.getNode(ISD::FABS, dl, VT, Val);
14328 SDValue Inf =
14330
14331 SDValue IsFinite = DAG.getSetCC(dl, MVT::i1, Fabs, Inf, ISD::SETOLT);
14332 SDValue Zero = DAG.getConstant(0, dl, InstrExpVT);
14333 Exp = DAG.getNode(ISD::SELECT, dl, InstrExpVT, IsFinite, Exp, Zero);
14334 Mant = DAG.getNode(ISD::SELECT, dl, VT, IsFinite, Mant, Val);
14335 }
14336
14337 SDValue CastExp = DAG.getSExtOrTrunc(Exp, dl, ResultExpVT);
14338 return DAG.getMergeValues({Mant, CastExp}, dl);
14339}
14340
14341SDValue SITargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const {
14342 SDLoc DL(Op);
14343 StoreSDNode *Store = cast<StoreSDNode>(Op);
14344 EVT VT = Store->getMemoryVT();
14345
14346 if (VT == MVT::i1) {
14347 return DAG.getTruncStore(
14348 Store->getChain(), DL,
14349 DAG.getSExtOrTrunc(Store->getValue(), DL, MVT::i32),
14350 Store->getBasePtr(), MVT::i1, Store->getMemOperand());
14351 }
14352
14353 assert(VT.isVector() &&
14354 Store->getValue().getValueType().getScalarType() == MVT::i32);
14355
14356 unsigned AS = Store->getAddressSpace();
14357 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14358 AS == AMDGPUAS::FLAT_ADDRESS &&
14359 Store->getAlign().value() < VT.getStoreSize() &&
14360 VT.getSizeInBits() > 32) {
14361 return SplitVectorStore(Op, DAG);
14362 }
14363
14365 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
14366 // If there is a possibility that flat instruction access scratch memory
14367 // then we need to use the same legalization rules we use for private.
14368 if (AS == AMDGPUAS::FLAT_ADDRESS &&
14369 !Subtarget->hasMultiDwordFlatScratchAddressing())
14370 AS = addressMayBeAccessedAsPrivate(Store->getMemOperand(), *MFI)
14373
14374 unsigned NumElements = VT.getVectorNumElements();
14376 if (NumElements > 4)
14377 return SplitVectorStore(Op, DAG);
14378 // v3 stores not supported on SI.
14379 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14380 return SplitVectorStore(Op, DAG);
14381
14383 VT, *Store->getMemOperand()))
14384 return expandUnalignedStore(Store, DAG);
14385
14386 return SDValue();
14387 }
14388 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
14389 switch (Subtarget->getMaxPrivateElementSize()) {
14390 case 4:
14391 return scalarizeVectorStore(Store, DAG);
14392 case 8:
14393 if (NumElements > 2)
14394 return SplitVectorStore(Op, DAG);
14395 return SDValue();
14396 case 16:
14397 if (NumElements > 4 ||
14398 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14399 return SplitVectorStore(Op, DAG);
14400 return SDValue();
14401 default:
14402 llvm_unreachable("unsupported private_element_size");
14403 }
14404 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
14405 unsigned Fast = 0;
14406 auto Flags = Store->getMemOperand()->getFlags();
14408 Store->getAlign(), Flags, &Fast) &&
14409 Fast > 1)
14410 return SDValue();
14411
14412 if (VT.isVector())
14413 return SplitVectorStore(Op, DAG);
14414
14415 return expandUnalignedStore(Store, DAG);
14416 }
14417
14418 // Probably an invalid store. If so we'll end up emitting a selection error.
14419 return SDValue();
14420}
14421
14422// Avoid the full correct expansion for f32 sqrt when promoting from f16.
14423SDValue SITargetLowering::lowerFSQRTF16(SDValue Op, SelectionDAG &DAG) const {
14424 SDLoc SL(Op);
14425 assert(!Subtarget->has16BitInsts());
14426 SDNodeFlags Flags = Op->getFlags();
14427 SDValue Ext =
14428 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op.getOperand(0), Flags);
14429
14430 SDValue SqrtID = DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, SL, MVT::i32);
14431 SDValue Sqrt =
14432 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::f32, SqrtID, Ext, Flags);
14433
14434 return DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Sqrt,
14435 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
14436}
14437
14438SDValue SITargetLowering::lowerFSQRTF32(SDValue Op, SelectionDAG &DAG) const {
14439 SDLoc DL(Op);
14440 SDNodeFlags Flags = Op->getFlags();
14441 MVT VT = Op.getValueType().getSimpleVT();
14442 const SDValue X = Op.getOperand(0);
14443
14444 if (allowApproxFunc(DAG, Flags)) {
14445 // Instruction is 1ulp but ignores denormals.
14446 return DAG.getNode(
14448 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32), X, Flags);
14449 }
14450
14451 SDValue ScaleThreshold = DAG.getConstantFP(0x1.0p-96f, DL, VT);
14452 SDValue NeedScale = DAG.getSetCC(DL, MVT::i1, X, ScaleThreshold, ISD::SETOLT);
14453
14454 SDValue ScaleUpFactor = DAG.getConstantFP(0x1.0p+32f, DL, VT);
14455
14456 SDValue ScaledX = DAG.getNode(ISD::FMUL, DL, VT, X, ScaleUpFactor, Flags);
14457
14458 SDValue SqrtX =
14459 DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledX, X, Flags);
14460
14461 SDValue SqrtS;
14462 if (needsDenormHandlingF32(DAG, X, Flags)) {
14463 SDValue SqrtID =
14464 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32);
14465 SqrtS = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, SqrtID, SqrtX, Flags);
14466
14467 SDValue SqrtSAsInt = DAG.getNode(ISD::BITCAST, DL, MVT::i32, SqrtS);
14468 SDValue SqrtSNextDownInt =
14469 DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14470 DAG.getAllOnesConstant(DL, MVT::i32));
14471 SDValue SqrtSNextDown = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextDownInt);
14472
14473 SDValue NegSqrtSNextDown =
14474 DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextDown, Flags);
14475
14476 SDValue SqrtVP =
14477 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
14478
14479 SDValue SqrtSNextUpInt = DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14480 DAG.getConstant(1, DL, MVT::i32));
14481 SDValue SqrtSNextUp = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextUpInt);
14482
14483 SDValue NegSqrtSNextUp = DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextUp, Flags);
14484 SDValue SqrtVS =
14485 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
14486
14487 SDValue Zero = DAG.getConstantFP(0.0f, DL, VT);
14488 SDValue SqrtVPLE0 = DAG.getSetCC(DL, MVT::i1, SqrtVP, Zero, ISD::SETOLE);
14489
14490 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPLE0, SqrtSNextDown, SqrtS,
14491 Flags);
14492
14493 SDValue SqrtVPVSGT0 = DAG.getSetCC(DL, MVT::i1, SqrtVS, Zero, ISD::SETOGT);
14494 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPVSGT0, SqrtSNextUp, SqrtS,
14495 Flags);
14496 } else {
14497 SDValue SqrtR = DAG.getNode(AMDGPUISD::RSQ, DL, VT, SqrtX, Flags);
14498
14499 SqrtS = DAG.getNode(ISD::FMUL, DL, VT, SqrtX, SqrtR, Flags);
14500
14501 SDValue Half = DAG.getConstantFP(0.5f, DL, VT);
14502 SDValue SqrtH = DAG.getNode(ISD::FMUL, DL, VT, SqrtR, Half, Flags);
14503 SDValue NegSqrtH = DAG.getNode(ISD::FNEG, DL, VT, SqrtH, Flags);
14504
14505 SDValue SqrtE = DAG.getNode(ISD::FMA, DL, VT, NegSqrtH, SqrtS, Half, Flags);
14506 SqrtH = DAG.getNode(ISD::FMA, DL, VT, SqrtH, SqrtE, SqrtH, Flags);
14507 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtS, SqrtE, SqrtS, Flags);
14508
14509 SDValue NegSqrtS = DAG.getNode(ISD::FNEG, DL, VT, SqrtS, Flags);
14510 SDValue SqrtD =
14511 DAG.getNode(ISD::FMA, DL, VT, NegSqrtS, SqrtS, SqrtX, Flags);
14512 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtD, SqrtH, SqrtS, Flags);
14513 }
14514
14515 SDValue ScaleDownFactor = DAG.getConstantFP(0x1.0p-16f, DL, VT);
14516
14517 SDValue ScaledDown =
14518 DAG.getNode(ISD::FMUL, DL, VT, SqrtS, ScaleDownFactor, Flags);
14519
14520 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledDown, SqrtS, Flags);
14521 SDValue IsZeroOrInf =
14522 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14523 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14524
14525 return DAG.getNode(ISD::SELECT, DL, VT, IsZeroOrInf, SqrtX, SqrtS, Flags);
14526}
14527
14528SDValue SITargetLowering::lowerFSQRTF64(SDValue Op, SelectionDAG &DAG) const {
14529 // For double type, the SQRT and RSQ instructions don't have required
14530 // precision, we apply Goldschmidt's algorithm to improve the result:
14531 //
14532 // y0 = rsq(x)
14533 // g0 = x * y0
14534 // h0 = 0.5 * y0
14535 //
14536 // r0 = 0.5 - h0 * g0
14537 // g1 = g0 * r0 + g0
14538 // h1 = h0 * r0 + h0
14539 //
14540 // r1 = 0.5 - h1 * g1 => d0 = x - g1 * g1
14541 // g2 = g1 * r1 + g1 g2 = d0 * h1 + g1
14542 // h2 = h1 * r1 + h1
14543 //
14544 // r2 = 0.5 - h2 * g2 => d1 = x - g2 * g2
14545 // g3 = g2 * r2 + g2 g3 = d1 * h1 + g2
14546 //
14547 // sqrt(x) = g3
14548
14549 SDNodeFlags Flags = Op->getFlags();
14550
14551 SDLoc DL(Op);
14552
14553 SDValue X = Op.getOperand(0);
14554 SDValue ZeroInt = DAG.getConstant(0, DL, MVT::i32);
14555
14556 SDValue SqrtX = X;
14557 SDValue Scaling;
14558 if (!Flags.hasApproximateFuncs()) {
14559 SDValue ScaleConstant = DAG.getConstantFP(0x1.0p-767, DL, MVT::f64);
14560 Scaling = DAG.getSetCC(DL, MVT::i1, X, ScaleConstant, ISD::SETOLT);
14561
14562 // Scale up input if it is too small.
14563 SDValue ScaleUpFactor = DAG.getConstant(256, DL, MVT::i32);
14564 SDValue ScaleUp =
14565 DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling, ScaleUpFactor, ZeroInt);
14566 SqrtX = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, X, ScaleUp, Flags);
14567 }
14568
14569 SDValue SqrtY = DAG.getNode(AMDGPUISD::RSQ, DL, MVT::f64, SqrtX);
14570
14571 SDValue SqrtS0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtX, SqrtY);
14572
14573 SDValue Half = DAG.getConstantFP(0.5, DL, MVT::f64);
14574 SDValue SqrtH0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtY, Half);
14575
14576 SDValue NegSqrtH0 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtH0);
14577 SDValue SqrtR0 = DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtH0, SqrtS0, Half);
14578
14579 SDValue SqrtH1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtH0, SqrtR0, SqrtH0);
14580
14581 SDValue SqrtS1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtS0, SqrtR0, SqrtS0);
14582
14583 SDValue NegSqrtS1 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS1);
14584 SDValue SqrtD0 =
14585 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS1, SqrtS1, SqrtX);
14586
14587 SDValue SqrtS2 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD0, SqrtH1, SqrtS1);
14588
14589 SDValue SqrtRet = SqrtS2;
14590 if (!Flags.hasApproximateFuncs()) {
14591 SDValue NegSqrtS2 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS2);
14592 SDValue SqrtD1 =
14593 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS2, SqrtS2, SqrtX);
14594
14595 SqrtRet = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD1, SqrtH1, SqrtS2);
14596
14597 SDValue ScaleDownFactor = DAG.getSignedConstant(-128, DL, MVT::i32);
14598 SDValue ScaleDown = DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling,
14599 ScaleDownFactor, ZeroInt);
14600 SqrtRet = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, SqrtRet, ScaleDown, Flags);
14601 }
14602
14603 // TODO: Check for DAZ and expand to subnormals
14604
14605 SDValue IsZeroOrInf;
14606 if (Flags.hasNoInfs()) {
14607 SDValue Zero = DAG.getConstantFP(0.0, DL, MVT::f64);
14608 IsZeroOrInf = DAG.getSetCC(DL, MVT::i1, SqrtX, Zero, ISD::SETOEQ);
14609 } else {
14610 IsZeroOrInf =
14611 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14612 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14613 }
14614
14615 // If x is +INF, +0, or -0, use its original value
14616 return DAG.getNode(ISD::SELECT, DL, MVT::f64, IsZeroOrInf, SqrtX, SqrtRet,
14617 Flags);
14618}
14619
14620SDValue SITargetLowering::LowerTrig(SDValue Op, SelectionDAG &DAG) const {
14621 SDLoc DL(Op);
14622 EVT VT = Op.getValueType();
14623 SDValue Arg = Op.getOperand(0);
14624 SDValue TrigVal;
14625
14626 // Propagate fast-math flags so that the multiply we introduce can be folded
14627 // if Arg is already the result of a multiply by constant.
14628 auto Flags = Op->getFlags();
14629
14630 // AMDGPUISD nodes of vector type must be unrolled here since
14631 // they will not be expanded elsewhere.
14632 auto UnrollIfVec = [&DAG](SDValue V) -> SDValue {
14633 if (!V.getValueType().isVector())
14634 return V;
14635
14636 return DAG.UnrollVectorOp(cast<SDNode>(V));
14637 };
14638
14639 SDValue OneOver2Pi = DAG.getConstantFP(0.5 * numbers::inv_pi, DL, VT);
14640
14641 if (Subtarget->hasTrigReducedRange()) {
14642 SDValue MulVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14643 TrigVal = UnrollIfVec(DAG.getNode(AMDGPUISD::FRACT, DL, VT, MulVal, Flags));
14644 } else {
14645 TrigVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14646 }
14647
14648 switch (Op.getOpcode()) {
14649 case ISD::FCOS:
14650 TrigVal = DAG.getNode(AMDGPUISD::COS_HW, SDLoc(Op), VT, TrigVal, Flags);
14651 break;
14652 case ISD::FSIN:
14653 TrigVal = DAG.getNode(AMDGPUISD::SIN_HW, SDLoc(Op), VT, TrigVal, Flags);
14654 break;
14655 default:
14656 llvm_unreachable("Wrong trig opcode");
14657 }
14658
14659 return UnrollIfVec(TrigVal);
14660}
14661
14662SDValue SITargetLowering::LowerATOMIC_CMP_SWAP(SDValue Op,
14663 SelectionDAG &DAG) const {
14664 AtomicSDNode *AtomicNode = cast<AtomicSDNode>(Op);
14665 assert(AtomicNode->isCompareAndSwap());
14666 unsigned AS = AtomicNode->getAddressSpace();
14667
14668 // No custom lowering required for local address space
14670 return Op;
14671
14672 // Non-local address space requires custom lowering for atomic compare
14673 // and swap; cmp and swap should be in a v2i32 or v2i64 in case of _X2
14674 SDLoc DL(Op);
14675 SDValue ChainIn = Op.getOperand(0);
14676 SDValue Addr = Op.getOperand(1);
14677 SDValue Old = Op.getOperand(2);
14678 SDValue New = Op.getOperand(3);
14679 EVT VT = Op.getValueType();
14680 MVT SimpleVT = VT.getSimpleVT();
14681 MVT VecType = MVT::getVectorVT(SimpleVT, 2);
14682
14683 SDValue NewOld = DAG.getBuildVector(VecType, DL, {New, Old});
14684 SDValue Ops[] = {ChainIn, Addr, NewOld};
14685
14686 return DAG.getMemIntrinsicNode(AMDGPUISD::ATOMIC_CMP_SWAP, DL,
14687 Op->getVTList(), Ops, VT,
14688 AtomicNode->getMemOperand());
14689}
14690
14691//===----------------------------------------------------------------------===//
14692// Custom DAG optimizations
14693//===----------------------------------------------------------------------===//
14694
14695SDValue
14696SITargetLowering::performUCharToFloatCombine(SDNode *N,
14697 DAGCombinerInfo &DCI) const {
14698 EVT VT = N->getValueType(0);
14699 EVT ScalarVT = VT.getScalarType();
14700 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14701 return SDValue();
14702
14703 SelectionDAG &DAG = DCI.DAG;
14704 SDLoc DL(N);
14705
14706 SDValue Src = N->getOperand(0);
14707 EVT SrcVT = Src.getValueType();
14708
14709 // TODO: We could try to match extracting the higher bytes, which would be
14710 // easier if i8 vectors weren't promoted to i32 vectors, particularly after
14711 // types are legalized. v4i8 -> v4f32 is probably the only case to worry
14712 // about in practice.
14713 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14714 if (DAG.MaskedValueIsZero(Src, APInt::getHighBitsSet(32, 24))) {
14715 SDValue Cvt = DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0, DL, MVT::f32, Src);
14716 DCI.AddToWorklist(Cvt.getNode());
14717
14718 // For the f16 case, fold to a cast to f32 and then cast back to f16.
14719 if (ScalarVT != MVT::f32) {
14720 Cvt = DAG.getNode(ISD::FP_ROUND, DL, VT, Cvt,
14721 DAG.getTargetConstant(0, DL, MVT::i32));
14722 }
14723 return Cvt;
14724 }
14725 }
14726
14727 return SDValue();
14728}
14729
14730SDValue SITargetLowering::performFCopySignCombine(SDNode *N,
14731 DAGCombinerInfo &DCI) const {
14732 SDValue MagnitudeOp = N->getOperand(0);
14733 SDValue SignOp = N->getOperand(1);
14734
14735 // The generic combine for fcopysign + fp cast is too conservative with
14736 // vectors, and also gets confused by the splitting we will perform here, so
14737 // peek through FP casts.
14738 if (SignOp.getOpcode() == ISD::FP_EXTEND ||
14739 SignOp.getOpcode() == ISD::FP_ROUND)
14740 SignOp = SignOp.getOperand(0);
14741
14742 SelectionDAG &DAG = DCI.DAG;
14743 SDLoc DL(N);
14744 EVT SignVT = SignOp.getValueType();
14745
14746 // f64 fcopysign is really an f32 copysign on the high bits, so replace the
14747 // lower half with a copy.
14748 // fcopysign f64:x, _:y -> x.lo32, (fcopysign (f32 x.hi32), _:y)
14749 EVT MagVT = MagnitudeOp.getValueType();
14750
14751 unsigned NumElts = MagVT.isVector() ? MagVT.getVectorNumElements() : 1;
14752
14753 if (MagVT.getScalarType() == MVT::f64) {
14754 EVT F32VT = MagVT.isVector()
14755 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14756 : MVT::v2f32;
14757
14758 SDValue MagAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, MagnitudeOp);
14759
14761 for (unsigned I = 0; I != NumElts; ++I) {
14762 SDValue MagLo =
14763 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14764 DAG.getConstant(2 * I, DL, MVT::i32));
14765 SDValue MagHi =
14766 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14767 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14768
14769 SDValue SignOpElt =
14770 MagVT.isVector()
14772 SignOp, DAG.getConstant(I, DL, MVT::i32))
14773 : SignOp;
14774
14775 SDValue HiOp =
14776 DAG.getNode(ISD::FCOPYSIGN, DL, MVT::f32, MagHi, SignOpElt);
14777
14778 SDValue Vector =
14779 DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v2f32, MagLo, HiOp);
14780
14781 SDValue NewElt = DAG.getNode(ISD::BITCAST, DL, MVT::f64, Vector);
14782 NewElts.push_back(NewElt);
14783 }
14784
14785 if (NewElts.size() == 1)
14786 return NewElts[0];
14787
14788 return DAG.getNode(ISD::BUILD_VECTOR, DL, MagVT, NewElts);
14789 }
14790
14791 if (SignVT.getScalarType() != MVT::f64)
14792 return SDValue();
14793
14794 // Reduce width of sign operand, we only need the highest bit.
14795 //
14796 // fcopysign f64:x, f64:y ->
14797 // fcopysign f64:x, (extract_vector_elt (bitcast f64:y to v2f32), 1)
14798 // TODO: In some cases it might make sense to go all the way to f16.
14799
14800 EVT F32VT = MagVT.isVector()
14801 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14802 : MVT::v2f32;
14803
14804 SDValue SignAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, SignOp);
14805
14806 SmallVector<SDValue, 8> F32Signs;
14807 for (unsigned I = 0; I != NumElts; ++I) {
14808 // Take sign from odd elements of cast vector
14809 SDValue SignAsF32 =
14810 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, SignAsVector,
14811 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14812 F32Signs.push_back(SignAsF32);
14813 }
14814
14815 SDValue NewSign =
14816 NumElts == 1
14817 ? F32Signs.back()
14819 EVT::getVectorVT(*DAG.getContext(), MVT::f32, NumElts),
14820 F32Signs);
14821
14822 return DAG.getNode(ISD::FCOPYSIGN, DL, N->getValueType(0), N->getOperand(0),
14823 NewSign);
14824}
14825
14826// (shl (add x, c1), c2) -> add (shl x, c2), (shl c1, c2)
14827// (shl (or x, c1), c2) -> add (shl x, c2), (shl c1, c2) iff x and c1 share no
14828// bits
14829
14830// This is a variant of
14831// (mul (add x, c1), c2) -> add (mul x, c2), (mul c1, c2),
14832//
14833// The normal DAG combiner will do this, but only if the add has one use since
14834// that would increase the number of instructions.
14835//
14836// This prevents us from seeing a constant offset that can be folded into a
14837// memory instruction's addressing mode. If we know the resulting add offset of
14838// a pointer can be folded into an addressing offset, we can replace the pointer
14839// operand with the add of new constant offset. This eliminates one of the uses,
14840// and may allow the remaining use to also be simplified.
14841//
14842SDValue SITargetLowering::performSHLPtrCombine(SDNode *N, unsigned AddrSpace,
14843 EVT MemVT,
14844 DAGCombinerInfo &DCI) const {
14845 SDValue N0 = N->getOperand(0);
14846 SDValue N1 = N->getOperand(1);
14847
14848 // We only do this to handle cases where it's profitable when there are
14849 // multiple uses of the add, so defer to the standard combine.
14850 if ((!N0->isAnyAdd() && N0.getOpcode() != ISD::OR) || N0->hasOneUse())
14851 return SDValue();
14852
14853 const ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(N1);
14854 if (!CN1)
14855 return SDValue();
14856
14857 const ConstantSDNode *CAdd = dyn_cast<ConstantSDNode>(N0.getOperand(1));
14858 if (!CAdd)
14859 return SDValue();
14860
14861 SelectionDAG &DAG = DCI.DAG;
14862
14863 if (N0->getOpcode() == ISD::OR &&
14864 !DAG.haveNoCommonBitsSet(N0.getOperand(0), N0.getOperand(1)))
14865 return SDValue();
14866
14867 // If the resulting offset is too large, we can't fold it into the
14868 // addressing mode offset.
14869 APInt Offset = CAdd->getAPIntValue() << CN1->getAPIntValue();
14870 Type *Ty = MemVT.getTypeForEVT(*DCI.DAG.getContext());
14871
14872 AddrMode AM;
14873 AM.HasBaseReg = true;
14874 AM.BaseOffs = Offset.getSExtValue();
14875 if (!isLegalAddressingMode(DCI.DAG.getDataLayout(), AM, Ty, AddrSpace))
14876 return SDValue();
14877
14878 SDLoc SL(N);
14879 EVT VT = N->getValueType(0);
14880
14881 SDValue ShlX = DAG.getNode(ISD::SHL, SL, VT, N0.getOperand(0), N1);
14882 SDValue COffset = DAG.getConstant(Offset, SL, VT);
14883
14884 SDNodeFlags Flags;
14885 Flags.setNoUnsignedWrap(
14886 N->getFlags().hasNoUnsignedWrap() &&
14887 (N0.getOpcode() == ISD::OR || N0->getFlags().hasNoUnsignedWrap()));
14888
14889 // Use ISD::ADD even if the original operation was ISD::PTRADD, since we can't
14890 // be sure that the new left operand is a proper base pointer.
14891 return DAG.getNode(ISD::ADD, SL, VT, ShlX, COffset, Flags);
14892}
14893
14894/// MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset
14895/// by the chain and intrinsic ID. Theoretically we would also need to check the
14896/// specific intrinsic, but they all place the pointer operand first.
14897static unsigned getBasePtrIndex(const MemSDNode *N) {
14898 switch (N->getOpcode()) {
14899 case ISD::STORE:
14902 return 2;
14903 default:
14904 return 1;
14905 }
14906}
14907
14908SDValue SITargetLowering::performMemSDNodeCombine(MemSDNode *N,
14909 DAGCombinerInfo &DCI) const {
14910 SelectionDAG &DAG = DCI.DAG;
14911
14912 unsigned PtrIdx = getBasePtrIndex(N);
14913 SDValue Ptr = N->getOperand(PtrIdx);
14914
14915 // TODO: We could also do this for multiplies.
14916 if (Ptr.getOpcode() == ISD::SHL) {
14917 SDValue NewPtr = performSHLPtrCombine(Ptr.getNode(), N->getAddressSpace(),
14918 N->getMemoryVT(), DCI);
14919 if (NewPtr) {
14920 SmallVector<SDValue, 8> NewOps(N->ops());
14921
14922 NewOps[PtrIdx] = NewPtr;
14923 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
14924 }
14925 }
14926
14927 return SDValue();
14928}
14929
14930static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val) {
14931 return (Opc == ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14932 (Opc == ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14933 (Opc == ISD::XOR && Val == 0);
14934}
14935
14936// Break up 64-bit bit operation of a constant into two 32-bit and/or/xor. This
14937// will typically happen anyway for a VALU 64-bit and. This exposes other 32-bit
14938// integer combine opportunities since most 64-bit operations are decomposed
14939// this way. TODO: We won't want this for SALU especially if it is an inline
14940// immediate.
14941SDValue SITargetLowering::splitBinaryBitConstantOp(
14942 DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS,
14943 const ConstantSDNode *CRHS) const {
14944 uint64_t Val = CRHS->getZExtValue();
14945 uint32_t ValLo = Lo_32(Val);
14946 uint32_t ValHi = Hi_32(Val);
14947 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
14948
14949 if ((bitOpWithConstantIsReducible(Opc, ValLo) ||
14951 (CRHS->hasOneUse() && !TII->isInlineConstant(CRHS->getAPIntValue()))) {
14952 // We have 64-bit scalar and/or/xor, but do not have vector forms.
14953 if (Subtarget->has64BitLiterals() && CRHS->hasOneUse() &&
14954 !CRHS->user_begin()->isDivergent())
14955 return SDValue();
14956
14957 // If we need to materialize a 64-bit immediate, it will be split up later
14958 // anyway. Avoid creating the harder to understand 64-bit immediate
14959 // materialization.
14960 return splitBinaryBitConstantOpImpl(DCI, SL, Opc, LHS, ValLo, ValHi);
14961 }
14962
14963 return SDValue();
14964}
14965
14967 if (V.getValueType() != MVT::i1)
14968 return false;
14969 switch (V.getOpcode()) {
14970 default:
14971 break;
14972 case ISD::SETCC:
14973 case ISD::IS_FPCLASS:
14974 case AMDGPUISD::FP_CLASS:
14975 return true;
14976 case ISD::AND:
14977 case ISD::OR:
14978 case ISD::XOR:
14979 return isBoolSGPR(V.getOperand(0)) && isBoolSGPR(V.getOperand(1));
14980 case ISD::SADDO:
14981 case ISD::UADDO:
14982 case ISD::SSUBO:
14983 case ISD::USUBO:
14984 case ISD::SMULO:
14985 case ISD::UMULO:
14986 return V.getResNo() == 1;
14988 unsigned IntrinsicID = V.getConstantOperandVal(0);
14989 switch (IntrinsicID) {
14990 case Intrinsic::amdgcn_is_shared:
14991 case Intrinsic::amdgcn_is_private:
14992 return true;
14993 default:
14994 return false;
14995 }
14996
14997 return false;
14998 }
14999 }
15000 return false;
15001}
15002
15003// If a constant has all zeroes or all ones within each byte return it.
15004// Otherwise return 0.
15006 // 0xff for any zero byte in the mask
15007 uint32_t ZeroByteMask = 0;
15008 if (!(C & 0x000000ff))
15009 ZeroByteMask |= 0x000000ff;
15010 if (!(C & 0x0000ff00))
15011 ZeroByteMask |= 0x0000ff00;
15012 if (!(C & 0x00ff0000))
15013 ZeroByteMask |= 0x00ff0000;
15014 if (!(C & 0xff000000))
15015 ZeroByteMask |= 0xff000000;
15016 uint32_t NonZeroByteMask = ~ZeroByteMask; // 0xff for any non-zero byte
15017 if ((NonZeroByteMask & C) != NonZeroByteMask)
15018 return 0; // Partial bytes selected.
15019 return C;
15020}
15021
15022// Check if a node selects whole bytes from its operand 0 starting at a byte
15023// boundary while masking the rest. Returns select mask as in the v_perm_b32
15024// or -1 if not succeeded.
15025// Note byte select encoding:
15026// value 0-3 selects corresponding source byte;
15027// value 0xc selects zero;
15028// value 0xff selects 0xff.
15030 assert(V.getValueSizeInBits() == 32);
15031
15032 if (V.getNumOperands() != 2)
15033 return ~0;
15034
15035 ConstantSDNode *N1 = dyn_cast<ConstantSDNode>(V.getOperand(1));
15036 if (!N1)
15037 return ~0;
15038
15039 uint32_t C = N1->getZExtValue();
15040
15041 switch (V.getOpcode()) {
15042 default:
15043 break;
15044 case ISD::AND:
15045 if (uint32_t ConstMask = getConstantPermuteMask(C))
15046 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
15047 break;
15048
15049 case ISD::OR:
15050 if (uint32_t ConstMask = getConstantPermuteMask(C))
15051 return (0x03020100 & ~ConstMask) | ConstMask;
15052 break;
15053
15054 case ISD::SHL:
15055 if (C % 8)
15056 return ~0;
15057
15058 return uint32_t((0x030201000c0c0c0cull << C) >> 32);
15059
15060 case ISD::SRL:
15061 if (C % 8)
15062 return ~0;
15063
15064 return uint32_t(0x0c0c0c0c03020100ull >> C);
15065 }
15066
15067 return ~0;
15068}
15069
15070SDValue SITargetLowering::performAndCombine(SDNode *N,
15071 DAGCombinerInfo &DCI) const {
15072 if (DCI.isBeforeLegalize())
15073 return SDValue();
15074
15075 SelectionDAG &DAG = DCI.DAG;
15076 EVT VT = N->getValueType(0);
15077 SDValue LHS = N->getOperand(0);
15078 SDValue RHS = N->getOperand(1);
15079
15080 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS);
15081 if (VT == MVT::i64 && CRHS) {
15082 if (SDValue Split =
15083 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::AND, LHS, CRHS))
15084 return Split;
15085 }
15086
15087 if (CRHS && VT == MVT::i32) {
15088 // and (srl x, c), mask => shl (bfe x, nb + c, mask >> nb), nb
15089 // nb = number of trailing zeroes in mask
15090 // It can be optimized out using SDWA for GFX8+ in the SDWA peephole pass,
15091 // given that we are selecting 8 or 16 bit fields starting at byte boundary.
15092 uint64_t Mask = CRHS->getZExtValue();
15093 unsigned Bits = llvm::popcount(Mask);
15094 if (getSubtarget()->hasSDWA() && LHS->getOpcode() == ISD::SRL &&
15095 (Bits == 8 || Bits == 16) && isShiftedMask_64(Mask) && !(Mask & 1)) {
15096 if (auto *CShift = dyn_cast<ConstantSDNode>(LHS->getOperand(1))) {
15097 unsigned Shift = CShift->getZExtValue();
15098 unsigned NB = CRHS->getAPIntValue().countr_zero();
15099 unsigned Offset = NB + Shift;
15100 if ((Offset & (Bits - 1)) == 0) { // Starts at a byte or word boundary.
15101 SDLoc SL(N);
15102 SDValue BFE =
15103 DAG.getNode(AMDGPUISD::BFE_U32, SL, MVT::i32, LHS->getOperand(0),
15104 DAG.getConstant(Offset, SL, MVT::i32),
15105 DAG.getConstant(Bits, SL, MVT::i32));
15106 EVT NarrowVT = EVT::getIntegerVT(*DAG.getContext(), Bits);
15107 SDValue Ext = DAG.getNode(ISD::AssertZext, SL, VT, BFE,
15108 DAG.getValueType(NarrowVT));
15109 SDValue Shl = DAG.getNode(ISD::SHL, SDLoc(LHS), VT, Ext,
15110 DAG.getConstant(NB, SDLoc(CRHS), MVT::i32));
15111 return Shl;
15112 }
15113 }
15114 }
15115
15116 // and (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
15117 if (LHS.hasOneUse() && LHS.getOpcode() == AMDGPUISD::PERM &&
15118 isa<ConstantSDNode>(LHS.getOperand(2))) {
15119 uint32_t Sel = getConstantPermuteMask(Mask);
15120 if (!Sel)
15121 return SDValue();
15122
15123 // Select 0xc for all zero bytes
15124 Sel = (LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
15125 SDLoc DL(N);
15126 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15127 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
15128 }
15129 }
15130
15131 // and (trunc (srl x, c)), mask => srl (trunc x), c
15132 // if mask keeps exactly the bits that srl leaves in the low half
15133 if (CRHS && VT == MVT::i16 && LHS.getOpcode() == ISD::TRUNCATE &&
15134 LHS.hasOneUse() && LHS.getOperand(0).getOpcode() == ISD::SRL) {
15135 auto *Shift = dyn_cast<ConstantSDNode>(LHS.getOperand(0).getOperand(1));
15136 if (Shift && Shift->getZExtValue() < 16 &&
15137 CRHS->getAPIntValue().isMask(16 - Shift->getZExtValue())) {
15138 SDLoc SL(N);
15139 SDValue Trunc =
15140 DAG.getNode(ISD::TRUNCATE, SL, VT, LHS.getOperand(0).getOperand(0));
15141 return DAG.getNode(
15142 ISD::SRL, SL, VT, Trunc,
15143 DAG.getShiftAmountConstant(Shift->getZExtValue(), VT, SL));
15144 }
15145 }
15146
15147 // (and (fcmp ord x, x), (fcmp une (fabs x), inf)) ->
15148 // fp_class x, ~(s_nan | q_nan | n_infinity | p_infinity)
15149 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == ISD::SETCC) {
15150 ISD::CondCode LCC = LHS.getOperandCondCode(2);
15151 ISD::CondCode RCC = RHS.getOperandCondCode(2);
15152
15153 SDValue X = LHS.getOperand(0);
15154 SDValue Y = RHS.getOperand(0);
15155 if (Y.getOpcode() != ISD::FABS || Y.getOperand(0) != X ||
15156 !isTypeLegal(X.getValueType()))
15157 return SDValue();
15158
15159 if (LCC == ISD::SETO) {
15160 if (X != LHS.getOperand(1))
15161 return SDValue();
15162
15163 if (RCC == ISD::SETUNE) {
15164 const ConstantFPSDNode *C1 =
15165 dyn_cast<ConstantFPSDNode>(RHS.getOperand(1));
15166 if (!C1 || !C1->isInfinity() || C1->isNegative())
15167 return SDValue();
15168
15169 const uint32_t Mask = SIInstrFlags::N_NORMAL |
15173
15174 static_assert(
15177 0x3ff) == Mask,
15178 "mask not equal");
15179
15180 SDLoc DL(N);
15181 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, X,
15182 DAG.getConstant(Mask, DL, MVT::i32));
15183 }
15184 }
15185 }
15186
15187 if (RHS.getOpcode() == ISD::SETCC && LHS.getOpcode() == AMDGPUISD::FP_CLASS)
15188 std::swap(LHS, RHS);
15189
15190 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15191 RHS.hasOneUse()) {
15192 ISD::CondCode LCC = LHS.getOperandCondCode(2);
15193 // and (fcmp seto), (fp_class x, mask) -> fp_class x, mask & ~(p_nan |
15194 // n_nan) and (fcmp setuo), (fp_class x, mask) -> fp_class x, mask & (p_nan
15195 // | n_nan)
15196 const ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
15197 if ((LCC == ISD::SETO || LCC == ISD::SETUO) && Mask &&
15198 (RHS.getOperand(0) == LHS.getOperand(0) &&
15199 LHS.getOperand(0) == LHS.getOperand(1))) {
15200 const unsigned OrdMask = SIInstrFlags::S_NAN | SIInstrFlags::Q_NAN;
15201 unsigned NewMask = LCC == ISD::SETO ? Mask->getZExtValue() & ~OrdMask
15202 : Mask->getZExtValue() & OrdMask;
15203
15204 SDLoc DL(N);
15205 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, RHS.getOperand(0),
15206 DAG.getConstant(NewMask, DL, MVT::i32));
15207 }
15208 }
15209
15210 if (VT == MVT::i32 && (RHS.getOpcode() == ISD::SIGN_EXTEND ||
15211 LHS.getOpcode() == ISD::SIGN_EXTEND)) {
15212 // and x, (sext cc from i1) => select cc, x, 0
15213 if (RHS.getOpcode() != ISD::SIGN_EXTEND)
15214 std::swap(LHS, RHS);
15215 if (isBoolSGPR(RHS.getOperand(0)))
15216 return DAG.getSelect(SDLoc(N), MVT::i32, RHS.getOperand(0), LHS,
15217 DAG.getConstant(0, SDLoc(N), MVT::i32));
15218 }
15219
15220 // and (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
15221 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
15222 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
15223 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15224 uint32_t LHSMask = getPermuteMask(LHS);
15225 uint32_t RHSMask = getPermuteMask(RHS);
15226 if (LHSMask != ~0u && RHSMask != ~0u) {
15227 // Canonicalize the expression in an attempt to have fewer unique masks
15228 // and therefore fewer registers used to hold the masks.
15229 if (LHSMask > RHSMask) {
15230 std::swap(LHSMask, RHSMask);
15231 std::swap(LHS, RHS);
15232 }
15233
15234 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15235 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15236 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15237 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15238
15239 // Check of we need to combine values from two sources within a byte.
15240 if (!(LHSUsedLanes & RHSUsedLanes) &&
15241 // If we select high and lower word keep it for SDWA.
15242 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15243 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15244 // Each byte in each mask is either selector mask 0-3, or has higher
15245 // bits set in either of masks, which can be 0xff for 0xff or 0x0c for
15246 // zero. If 0x0c is in either mask it shall always be 0x0c. Otherwise
15247 // mask which is not 0xff wins. By anding both masks we have a correct
15248 // result except that 0x0c shall be corrected to give 0x0c only.
15249 uint32_t Mask = LHSMask & RHSMask;
15250 for (unsigned I = 0; I < 32; I += 8) {
15251 uint32_t ByteSel = 0xff << I;
15252 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15253 Mask &= (0x0c << I) & 0xffffffff;
15254 }
15255
15256 // Add 4 to each active LHS lane. It will not affect any existing 0xff
15257 // or 0x0c.
15258 uint32_t Sel = Mask | (LHSUsedLanes & 0x04040404);
15259 SDLoc DL(N);
15260
15261 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15262 RHS.getOperand(0),
15263 DAG.getConstant(Sel, DL, MVT::i32));
15264 }
15265 }
15266 }
15267
15268 return SDValue();
15269}
15270
15271// A key component of v_perm is a mapping between byte position of the src
15272// operands, and the byte position of the dest. To provide such, we need: 1. the
15273// node that provides x byte of the dest of the OR, and 2. the byte of the node
15274// used to provide that x byte. calculateByteProvider finds which node provides
15275// a certain byte of the dest of the OR, and calculateSrcByte takes that node,
15276// and finds an ultimate src and byte position For example: The supported
15277// LoadCombine pattern for vector loads is as follows
15278// t1
15279// or
15280// / \
15281// t2 t3
15282// zext shl
15283// | | \
15284// t4 t5 16
15285// or anyext
15286// / \ |
15287// t6 t7 t8
15288// srl shl or
15289// / | / \ / \
15290// t9 t10 t11 t12 t13 t14
15291// trunc* 8 trunc* 8 and and
15292// | | / | | \
15293// t15 t16 t17 t18 t19 t20
15294// trunc* 255 srl -256
15295// | / \
15296// t15 t15 16
15297//
15298// *In this example, the truncs are from i32->i16
15299//
15300// calculateByteProvider would find t6, t7, t13, and t14 for bytes 0-3
15301// respectively. calculateSrcByte would find (given node) -> ultimate src &
15302// byteposition: t6 -> t15 & 1, t7 -> t16 & 0, t13 -> t15 & 0, t14 -> t15 & 3.
15303// After finding the mapping, we can combine the tree into vperm t15, t16,
15304// 0x05000407
15305
15306// Find the source and byte position from a node.
15307// \p DestByte is the byte position of the dest of the or that the src
15308// ultimately provides. \p SrcIndex is the byte of the src that maps to this
15309// dest of the or byte. \p Depth tracks how many recursive iterations we have
15310// performed.
15311static const std::optional<ByteProvider<SDValue>>
15312calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex = 0,
15313 unsigned Depth = 0) {
15314 // We may need to recursively traverse a series of SRLs
15315 if (Depth >= 6)
15316 return std::nullopt;
15317
15318 if (Op.getValueSizeInBits() < 8)
15319 return std::nullopt;
15320
15321 if (Op.getValueType().isVector())
15322 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15323
15324 switch (Op->getOpcode()) {
15325 case ISD::TRUNCATE: {
15326 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15327 }
15328
15329 case ISD::ANY_EXTEND:
15330 case ISD::SIGN_EXTEND:
15331 case ISD::ZERO_EXTEND:
15333 SDValue NarrowOp = Op->getOperand(0);
15334 auto NarrowVT = NarrowOp.getValueType();
15335 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG) {
15336 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15337 NarrowVT = VTSign->getVT();
15338 }
15339 if (!NarrowVT.isByteSized())
15340 return std::nullopt;
15341 uint64_t NarrowByteWidth = NarrowVT.getStoreSize();
15342
15343 if (SrcIndex >= NarrowByteWidth)
15344 return std::nullopt;
15345 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15346 }
15347
15348 case ISD::SRA:
15349 case ISD::SRL: {
15350 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15351 if (!ShiftOp)
15352 return std::nullopt;
15353
15354 uint64_t BitShift = ShiftOp->getZExtValue();
15355
15356 if (BitShift % 8 != 0)
15357 return std::nullopt;
15358
15359 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15360 if (NewSrcIndex >= Op.getScalarValueSizeInBits() / 8)
15361 return std::nullopt;
15362
15363 return calculateSrcByte(Op->getOperand(0), DestByte, NewSrcIndex,
15364 Depth + 1);
15365 }
15366
15367 default: {
15368 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15369 }
15370 }
15371 llvm_unreachable("fully handled switch");
15372}
15373
15374// For a byte position in the result of an Or, traverse the tree and find the
15375// node (and the byte of the node) which ultimately provides this {Or,
15376// BytePosition}. \p Op is the operand we are currently examining. \p Index is
15377// the byte position of the Op that corresponds with the originally requested
15378// byte of the Or \p Depth tracks how many recursive iterations we have
15379// performed. \p StartingIndex is the originally requested byte of the Or
15380static const std::optional<ByteProvider<SDValue>>
15381calculateByteProvider(const SDValue &Op, unsigned Index, unsigned Depth,
15382 unsigned StartingIndex = 0) {
15383 // Finding Src tree of RHS of or typically requires at least 1 additional
15384 // depth
15385 if (Depth > 6)
15386 return std::nullopt;
15387
15388 unsigned BitWidth = Op.getScalarValueSizeInBits();
15389 if (BitWidth % 8 != 0)
15390 return std::nullopt;
15391 if (Index > BitWidth / 8 - 1)
15392 return std::nullopt;
15393
15394 bool IsVec = Op.getValueType().isVector();
15395 switch (Op.getOpcode()) {
15396 case ISD::OR: {
15397 if (IsVec)
15398 return std::nullopt;
15399
15400 auto RHS = calculateByteProvider(Op.getOperand(1), Index, Depth + 1,
15401 StartingIndex);
15402 if (!RHS)
15403 return std::nullopt;
15404 auto LHS = calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15405 StartingIndex);
15406 if (!LHS)
15407 return std::nullopt;
15408 // A well formed Or will have two ByteProviders for each byte, one of which
15409 // is constant zero
15410 if (!LHS->isConstantZero() && !RHS->isConstantZero())
15411 return std::nullopt;
15412 if (!LHS || LHS->isConstantZero())
15413 return RHS;
15414 if (!RHS || RHS->isConstantZero())
15415 return LHS;
15416 return std::nullopt;
15417 }
15418
15419 case ISD::AND: {
15420 if (IsVec)
15421 return std::nullopt;
15422
15423 auto *BitMaskOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15424 if (!BitMaskOp)
15425 return std::nullopt;
15426
15427 uint32_t BitMask = BitMaskOp->getZExtValue();
15428 // Bits we expect for our StartingIndex
15429 uint32_t IndexMask = 0xFF << (Index * 8);
15430
15431 if ((IndexMask & BitMask) != IndexMask) {
15432 // If the result of the and partially provides the byte, then it
15433 // is not well formatted
15434 if (IndexMask & BitMask)
15435 return std::nullopt;
15437 }
15438
15439 return calculateSrcByte(Op->getOperand(0), StartingIndex, Index);
15440 }
15441
15442 case ISD::FSHR: {
15443 if (IsVec)
15444 return std::nullopt;
15445
15446 // fshr(X,Y,Z): (X << (BW - (Z % BW))) | (Y >> (Z % BW))
15447 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15448 if (!ShiftOp || Op.getValueType().isVector())
15449 return std::nullopt;
15450
15451 uint64_t BitsProvided = Op.getValueSizeInBits();
15452 if (BitsProvided % 8 != 0)
15453 return std::nullopt;
15454
15455 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15456 if (BitShift % 8)
15457 return std::nullopt;
15458
15459 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15460 uint64_t ByteShift = BitShift / 8;
15461
15462 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15463 uint64_t BytesProvided = BitsProvided / 8;
15464 SDValue NextOp = Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15465 NewIndex %= BytesProvided;
15466 return calculateByteProvider(NextOp, NewIndex, Depth + 1, StartingIndex);
15467 }
15468
15469 case ISD::SRA:
15470 case ISD::SRL: {
15471 if (IsVec)
15472 return std::nullopt;
15473
15474 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15475 if (!ShiftOp)
15476 return std::nullopt;
15477
15478 uint64_t BitShift = ShiftOp->getZExtValue();
15479 if (BitShift % 8)
15480 return std::nullopt;
15481
15482 auto BitsProvided = Op.getScalarValueSizeInBits();
15483 if (BitsProvided % 8 != 0)
15484 return std::nullopt;
15485
15486 uint64_t BytesProvided = BitsProvided / 8;
15487 uint64_t ByteShift = BitShift / 8;
15488 if (Index + ByteShift < BytesProvided)
15489 return calculateSrcByte(Op->getOperand(0), StartingIndex,
15490 Index + ByteShift);
15491 // SRA's out-of-range bytes are sign bits, not constant zero.
15492 if (Op.getOpcode() == ISD::SRA)
15493 return std::nullopt;
15495 }
15496
15497 case ISD::SHL: {
15498 if (IsVec)
15499 return std::nullopt;
15500
15501 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15502 if (!ShiftOp)
15503 return std::nullopt;
15504
15505 uint64_t BitShift = ShiftOp->getZExtValue();
15506 if (BitShift % 8 != 0)
15507 return std::nullopt;
15508 uint64_t ByteShift = BitShift / 8;
15509
15510 // If we are shifting by an amount greater than (or equal to)
15511 // the index we are trying to provide, then it provides 0s. If not,
15512 // then this bytes are not definitively 0s, and the corresponding byte
15513 // of interest is Index - ByteShift of the src
15514 return Index < ByteShift
15516 : calculateByteProvider(Op.getOperand(0), Index - ByteShift,
15517 Depth + 1, StartingIndex);
15518 }
15519 case ISD::ANY_EXTEND:
15520 case ISD::SIGN_EXTEND:
15521 case ISD::ZERO_EXTEND:
15523 case ISD::AssertZext:
15524 case ISD::AssertSext: {
15525 if (IsVec)
15526 return std::nullopt;
15527
15528 SDValue NarrowOp = Op->getOperand(0);
15529 unsigned NarrowBitWidth = NarrowOp.getValueSizeInBits();
15530 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG ||
15531 Op->getOpcode() == ISD::AssertZext ||
15532 Op->getOpcode() == ISD::AssertSext) {
15533 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15534 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15535 }
15536 if (NarrowBitWidth % 8 != 0)
15537 return std::nullopt;
15538 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15539
15540 if (Index >= NarrowByteWidth)
15541 return Op.getOpcode() == ISD::ZERO_EXTEND
15542 ? std::optional<ByteProvider<SDValue>>(
15544 : std::nullopt;
15545 return calculateByteProvider(NarrowOp, Index, Depth + 1, StartingIndex);
15546 }
15547
15548 case ISD::TRUNCATE: {
15549 if (IsVec)
15550 return std::nullopt;
15551
15552 uint64_t NarrowByteWidth = BitWidth / 8;
15553
15554 if (NarrowByteWidth >= Index) {
15555 return calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15556 StartingIndex);
15557 }
15558
15559 return std::nullopt;
15560 }
15561
15562 case ISD::CopyFromReg: {
15563 if (BitWidth / 8 > Index)
15564 return calculateSrcByte(Op, StartingIndex, Index);
15565
15566 return std::nullopt;
15567 }
15568
15569 case ISD::LOAD: {
15570 auto *L = cast<LoadSDNode>(Op.getNode());
15571
15572 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15573 if (NarrowBitWidth % 8 != 0)
15574 return std::nullopt;
15575 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15576
15577 // If the width of the load does not reach byte we are trying to provide for
15578 // and it is not a ZEXTLOAD, then the load does not provide for the byte in
15579 // question
15580 if (Index >= NarrowByteWidth) {
15581 return L->getExtensionType() == ISD::ZEXTLOAD
15582 ? std::optional<ByteProvider<SDValue>>(
15584 : std::nullopt;
15585 }
15586
15587 if (NarrowByteWidth > Index) {
15588 return calculateSrcByte(Op, StartingIndex, Index);
15589 }
15590
15591 return std::nullopt;
15592 }
15593
15594 case ISD::BSWAP: {
15595 if (IsVec)
15596 return std::nullopt;
15597
15598 return calculateByteProvider(Op->getOperand(0), BitWidth / 8 - Index - 1,
15599 Depth + 1, StartingIndex);
15600 }
15601
15603 auto *IdxOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15604 if (!IdxOp)
15605 return std::nullopt;
15606 auto VecIdx = IdxOp->getZExtValue();
15607 auto ScalarSize = Op.getScalarValueSizeInBits();
15608 if (ScalarSize < 32)
15609 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15610 return calculateSrcByte(ScalarSize >= 32 ? Op : Op.getOperand(0),
15611 StartingIndex, Index);
15612 }
15613
15614 case AMDGPUISD::PERM: {
15615 if (IsVec)
15616 return std::nullopt;
15617
15618 auto *PermMask = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15619 if (!PermMask)
15620 return std::nullopt;
15621
15622 auto IdxMask =
15623 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15624 if (IdxMask > 0x07 && IdxMask != 0x0c)
15625 return std::nullopt;
15626
15627 auto NextOp = Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15628 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15629
15630 return IdxMask != 0x0c ? calculateSrcByte(NextOp, StartingIndex, NextIndex)
15633 }
15634
15635 default: {
15636 return std::nullopt;
15637 }
15638 }
15639
15640 llvm_unreachable("fully handled switch");
15641}
15642
15643// Returns true if the Operand is a scalar and is 16 bits
15644static bool isExtendedFrom16Bits(SDValue &Operand) {
15645
15646 switch (Operand.getOpcode()) {
15647 case ISD::ANY_EXTEND:
15648 case ISD::SIGN_EXTEND:
15649 case ISD::ZERO_EXTEND: {
15650 auto OpVT = Operand.getOperand(0).getValueType();
15651 return !OpVT.isVector() && OpVT.getSizeInBits() == 16;
15652 }
15653 case ISD::LOAD: {
15654 LoadSDNode *L = cast<LoadSDNode>(Operand.getNode());
15655 auto ExtType = cast<LoadSDNode>(L)->getExtensionType();
15656 if (ExtType == ISD::ZEXTLOAD || ExtType == ISD::SEXTLOAD ||
15657 ExtType == ISD::EXTLOAD) {
15658 auto MemVT = L->getMemoryVT();
15659 return !MemVT.isVector() && MemVT.getSizeInBits() == 16;
15660 }
15661 return L->getMemoryVT().getSizeInBits() == 16;
15662 }
15663 default:
15664 return false;
15665 }
15666}
15667
15668// Returns true if the mask matches consecutive bytes, and the first byte
15669// begins at a power of 2 byte offset from 0th byte
15670static bool addresses16Bits(int Mask) {
15671 int Low8 = Mask & 0xff;
15672 int Hi8 = (Mask & 0xff00) >> 8;
15673
15674 assert(Low8 < 8 && Hi8 < 8);
15675 // Are the bytes contiguous in the order of increasing addresses.
15676 bool IsConsecutive = (Hi8 - Low8 == 1);
15677 // Is the first byte at location that is aligned for 16 bit instructions.
15678 // A counter example is taking 2 consecutive bytes starting at the 8th bit.
15679 // In this case, we still need code to extract the 16 bit operand, so it
15680 // is better to use i8 v_perm
15681 bool Is16Aligned = !(Low8 % 2);
15682
15683 return IsConsecutive && Is16Aligned;
15684}
15685
15686// Do not lower into v_perm if the operands are actually 16 bit
15687// and the selected bits (based on PermMask) correspond with two
15688// easily addressable 16 bit operands.
15690 SDValue &OtherOp) {
15691 int Low16 = PermMask & 0xffff;
15692 int Hi16 = (PermMask & 0xffff0000) >> 16;
15693
15694 auto TempOp = peekThroughBitcasts(Op);
15695 auto TempOtherOp = peekThroughBitcasts(OtherOp);
15696
15697 auto OpIs16Bit =
15698 TempOp.getValueSizeInBits() == 16 || isExtendedFrom16Bits(TempOp);
15699 if (!OpIs16Bit)
15700 return true;
15701
15702 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15703 isExtendedFrom16Bits(TempOtherOp);
15704 if (!OtherOpIs16Bit)
15705 return true;
15706
15707 // Do we cleanly address both
15708 return !addresses16Bits(Low16) || !addresses16Bits(Hi16);
15709}
15710
15712 unsigned DWordOffset) {
15713 SDValue Ret;
15714
15715 auto TypeSize = Src.getValueSizeInBits().getFixedValue();
15716 // ByteProvider must be at least 8 bits
15717 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15718
15719 if (TypeSize <= 32)
15720 return DAG.getBitcastedAnyExtOrTrunc(Src, SL, MVT::i32);
15721
15722 if (Src.getValueType().isVector()) {
15723 auto ScalarTySize = Src.getScalarValueSizeInBits();
15724 auto ScalarTy = Src.getValueType().getScalarType();
15725 if (ScalarTySize == 32) {
15726 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Src,
15727 DAG.getConstant(DWordOffset, SL, MVT::i32));
15728 }
15729 if (ScalarTySize > 32) {
15730 Ret = DAG.getNode(
15731 ISD::EXTRACT_VECTOR_ELT, SL, ScalarTy, Src,
15732 DAG.getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15733 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15734 if (ShiftVal)
15735 Ret = DAG.getNode(ISD::SRL, SL, Ret.getValueType(), Ret,
15736 DAG.getConstant(ShiftVal, SL, MVT::i32));
15737 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15738 }
15739
15740 assert(ScalarTySize < 32);
15741 if (TypeSize % 32 == 0) {
15742 assert(DWordOffset < TypeSize / 32);
15743 SDValue Cast = DAG.getBitcast(
15744 EVT::getVectorVT(*DAG.getContext(), MVT::i32, TypeSize / 32), Src);
15745 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Cast,
15746 DAG.getConstant(DWordOffset, SL, MVT::i32));
15747 }
15748
15749 auto NumElements = TypeSize / ScalarTySize;
15750 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15751 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15752 auto NumElementsIn32 = 32 / ScalarTySize;
15753 auto NumAvailElements = DWordOffset < Trunc32Elements
15754 ? NumElementsIn32
15755 : NumElements - NormalizedTrunc;
15756
15758 DAG.ExtractVectorElements(Src, VecSrcs, DWordOffset * NumElementsIn32,
15759 NumAvailElements);
15760
15761 Ret = DAG.getBuildVector(
15762 MVT::getVectorVT(MVT::getIntegerVT(ScalarTySize), NumAvailElements), SL,
15763 VecSrcs);
15764 return Ret = DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15765 }
15766
15767 /// Scalar Type
15768 auto ShiftVal = 32 * DWordOffset;
15769 Ret = DAG.getNode(ISD::SRL, SL, Src.getValueType(), Src,
15770 DAG.getConstant(ShiftVal, SL, MVT::i32));
15771 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15772}
15773
15775 SelectionDAG &DAG = DCI.DAG;
15776 [[maybe_unused]] EVT VT = N->getValueType(0);
15778
15779 // VT is known to be MVT::i32, so we need to provide 4 bytes.
15780 assert(VT == MVT::i32);
15781 for (int i = 0; i < 4; i++) {
15782 // Find the ByteProvider that provides the ith byte of the result of OR
15783 std::optional<ByteProvider<SDValue>> P =
15784 calculateByteProvider(SDValue(N, 0), i, 0, /*StartingIndex = */ i);
15785 // TODO support constantZero
15786 if (!P || P->isConstantZero())
15787 return SDValue();
15788
15789 PermNodes.push_back(*P);
15790 }
15791 if (PermNodes.size() != 4)
15792 return SDValue();
15793
15794 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15795 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15796 uint64_t PermMask = 0x00000000;
15797 for (size_t i = 0; i < PermNodes.size(); i++) {
15798 auto PermOp = PermNodes[i];
15799 // Since the mask is applied to Src1:Src2, Src1 bytes must be offset
15800 // by sizeof(Src2) = 4
15801 int SrcByteAdjust = 4;
15802
15803 // If the Src uses a byte from a different DWORD, then it corresponds
15804 // with a difference source
15805 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15806 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15807 if (SecondSrc)
15808 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15809 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15810 return SDValue();
15811
15812 // Set the index of the second distinct Src node
15813 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15814 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15815 SrcByteAdjust = 0;
15816 }
15817 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15819 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15820 }
15821 SDLoc DL(N);
15822 SDValue Op = *PermNodes[FirstSrc.first].Src;
15823 Op = getDWordFromOffset(DAG, DL, Op, FirstSrc.second);
15824 assert(Op.getValueSizeInBits() == 32);
15825
15826 // Check that we are not just extracting the bytes in order from an op
15827 if (!SecondSrc) {
15828 int Low16 = PermMask & 0xffff;
15829 int Hi16 = (PermMask & 0xffff0000) >> 16;
15830
15831 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15832 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15833
15834 // The perm op would really just produce Op. So combine into Op
15835 if (WellFormedLow && WellFormedHi)
15836 return DAG.getBitcast(MVT::getIntegerVT(32), Op);
15837 }
15838
15839 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src : Op;
15840
15841 if (SecondSrc) {
15842 OtherOp = getDWordFromOffset(DAG, DL, OtherOp, SecondSrc->second);
15843 assert(OtherOp.getValueSizeInBits() == 32);
15844 }
15845
15846 // Check that we haven't just recreated the same FSHR node.
15847 if (N->getOpcode() == ISD::FSHR &&
15848 (N->getOperand(0) == Op || N->getOperand(0) == OtherOp) &&
15849 (N->getOperand(1) == Op || N->getOperand(1) == OtherOp))
15850 return SDValue();
15851
15852 if (hasNon16BitAccesses(PermMask, Op, OtherOp)) {
15853
15854 assert(Op.getValueType().isByteSized() &&
15855 OtherOp.getValueType().isByteSized());
15856
15857 // If the ultimate src is less than 32 bits, then we will only be
15858 // using bytes 0: Op.getValueSizeInBytes() - 1 in the or.
15859 // CalculateByteProvider would not have returned Op as source if we
15860 // used a byte that is outside its ValueType. Thus, we are free to
15861 // ANY_EXTEND as the extended bits are dont-cares.
15862 Op = DAG.getBitcastedAnyExtOrTrunc(Op, DL, MVT::i32);
15863 OtherOp = DAG.getBitcastedAnyExtOrTrunc(OtherOp, DL, MVT::i32);
15864
15865 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op, OtherOp,
15866 DAG.getConstant(PermMask, DL, MVT::i32));
15867 }
15868 return SDValue();
15869}
15870
15871SDValue SITargetLowering::performOrCombine(SDNode *N,
15872 DAGCombinerInfo &DCI) const {
15873 SelectionDAG &DAG = DCI.DAG;
15874 SDValue LHS = N->getOperand(0);
15875 SDValue RHS = N->getOperand(1);
15876
15877 EVT VT = N->getValueType(0);
15878 if (VT == MVT::i1) {
15879 // or (fp_class x, c1), (fp_class x, c2) -> fp_class x, (c1 | c2)
15880 if (LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15881 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15882 SDValue Src = LHS.getOperand(0);
15883 if (Src != RHS.getOperand(0))
15884 return SDValue();
15885
15886 const ConstantSDNode *CLHS = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
15887 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
15888 if (!CLHS || !CRHS)
15889 return SDValue();
15890
15891 // Only 10 bits are used.
15892 static const uint32_t MaxMask = 0x3ff;
15893
15894 uint32_t NewMask =
15895 (CLHS->getZExtValue() | CRHS->getZExtValue()) & MaxMask;
15896 SDLoc DL(N);
15897 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, Src,
15898 DAG.getConstant(NewMask, DL, MVT::i32));
15899 }
15900
15901 return SDValue();
15902 }
15903
15904 // or (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
15906 LHS.getOpcode() == AMDGPUISD::PERM &&
15907 isa<ConstantSDNode>(LHS.getOperand(2))) {
15908 uint32_t Sel = getConstantPermuteMask(N->getConstantOperandVal(1));
15909 if (!Sel)
15910 return SDValue();
15911
15912 Sel |= LHS.getConstantOperandVal(2);
15913 SDLoc DL(N);
15914 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15915 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
15916 }
15917
15918 // or (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
15919 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
15920 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
15921 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15922
15923 // If all the uses of an or need to extract the individual elements, do not
15924 // attempt to lower into v_perm
15925 auto usesCombinedOperand = [](SDNode *OrUse) {
15926 // If we have any non-vectorized use, then it is a candidate for v_perm
15927 if (OrUse->getOpcode() != ISD::BITCAST ||
15928 !OrUse->getValueType(0).isVector())
15929 return true;
15930
15931 // If we have any non-vectorized use, then it is a candidate for v_perm
15932 for (auto *VUser : OrUse->users()) {
15933 if (!VUser->getValueType(0).isVector())
15934 return true;
15935
15936 // If the use of a vector is a store, then combining via a v_perm
15937 // is beneficial.
15938 // TODO -- whitelist more uses
15939 for (auto VectorwiseOp : {ISD::STORE, ISD::CopyToReg, ISD::CopyFromReg})
15940 if (VUser->getOpcode() == VectorwiseOp)
15941 return true;
15942 }
15943 return false;
15944 };
15945
15946 if (!any_of(N->users(), usesCombinedOperand))
15947 return SDValue();
15948
15949 uint32_t LHSMask = getPermuteMask(LHS);
15950 uint32_t RHSMask = getPermuteMask(RHS);
15951
15952 if (LHSMask != ~0u && RHSMask != ~0u) {
15953 // Canonicalize the expression in an attempt to have fewer unique masks
15954 // and therefore fewer registers used to hold the masks.
15955 if (LHSMask > RHSMask) {
15956 std::swap(LHSMask, RHSMask);
15957 std::swap(LHS, RHS);
15958 }
15959
15960 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15961 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15962 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15963 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15964
15965 // Check of we need to combine values from two sources within a byte.
15966 if (!(LHSUsedLanes & RHSUsedLanes) &&
15967 // If we select high and lower word keep it for SDWA.
15968 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15969 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15970 // Kill zero bytes selected by other mask. Zero value is 0xc.
15971 LHSMask &= ~RHSUsedLanes;
15972 RHSMask &= ~LHSUsedLanes;
15973 // Add 4 to each active LHS lane
15974 LHSMask |= LHSUsedLanes & 0x04040404;
15975 // Combine masks
15976 uint32_t Sel = LHSMask | RHSMask;
15977 SDLoc DL(N);
15978
15979 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15980 RHS.getOperand(0),
15981 DAG.getConstant(Sel, DL, MVT::i32));
15982 }
15983 }
15984 if (LHSMask == ~0u || RHSMask == ~0u) {
15985 if (SDValue Perm = matchPERM(N, DCI))
15986 return Perm;
15987 }
15988 }
15989
15990 // Detect identity v2i32 OR and replace with identity source node.
15991 // Specifically an Or that has operands constructed from the same source node
15992 // via extract_vector_elt and build_vector. I.E.
15993 // v2i32 or(
15994 // v2i32 build_vector(
15995 // i32 extract_elt(%IdentitySrc, 0),
15996 // i32 0
15997 // ),
15998 // v2i32 build_vector(
15999 // i32 0,
16000 // i32 extract_elt(%IdentitySrc, 1)
16001 // ) )
16002 // =>
16003 // v2i32 %IdentitySrc
16004
16005 if (VT == MVT::v2i32 && LHS->getOpcode() == ISD::BUILD_VECTOR &&
16006 RHS->getOpcode() == ISD::BUILD_VECTOR) {
16007
16008 ConstantSDNode *LC = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
16009 ConstantSDNode *RC = dyn_cast<ConstantSDNode>(RHS->getOperand(0));
16010
16011 // Test for and normalise build vectors.
16012 if (LC && RC && LC->getZExtValue() == 0 && RC->getZExtValue() == 0) {
16013
16014 // Get the extract_vector_element operands.
16015 SDValue LEVE = LHS->getOperand(0);
16016 SDValue REVE = RHS->getOperand(1);
16017
16018 if (LEVE->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
16020 // Check that different elements from the same vector are
16021 // extracted.
16022 if (LEVE->getOperand(0) == REVE->getOperand(0) &&
16023 LEVE->getOperand(1) != REVE->getOperand(1)) {
16024 SDValue IdentitySrc = LEVE.getOperand(0);
16025 return IdentitySrc;
16026 }
16027 }
16028 }
16029 }
16030
16031 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
16032 return SDValue();
16033
16034 // TODO: This could be a generic combine with a predicate for extracting the
16035 // high half of an integer being free.
16036
16037 // (or i64:x, (zero_extend i32:y)) ->
16038 // i64 (bitcast (v2i32 build_vector (or i32:y, lo_32(x)), hi_32(x)))
16039 if (LHS.getOpcode() == ISD::ZERO_EXTEND &&
16040 RHS.getOpcode() != ISD::ZERO_EXTEND)
16041 std::swap(LHS, RHS);
16042
16043 if (RHS.getOpcode() == ISD::ZERO_EXTEND) {
16044 SDValue ExtSrc = RHS.getOperand(0);
16045 EVT SrcVT = ExtSrc.getValueType();
16046 if (SrcVT == MVT::i32) {
16047 SDLoc SL(N);
16048 auto [LowLHS, HiBits] = split64BitValue(LHS, DAG);
16049 SDValue LowOr = DAG.getNode(ISD::OR, SL, MVT::i32, LowLHS, ExtSrc);
16050
16051 DCI.AddToWorklist(LowOr.getNode());
16052 DCI.AddToWorklist(HiBits.getNode());
16053
16054 SDValue Vec =
16055 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, LowOr, HiBits);
16056 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
16057 }
16058 }
16059
16060 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
16061 if (CRHS) {
16062 if (SDValue Split = splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::OR,
16063 N->getOperand(0), CRHS))
16064 return Split;
16065 }
16066
16067 return SDValue();
16068}
16069
16070SDValue SITargetLowering::performXorCombine(SDNode *N,
16071 DAGCombinerInfo &DCI) const {
16072 if (SDValue RV = reassociateScalarOps(N, DCI.DAG))
16073 return RV;
16074
16075 SDValue LHS = N->getOperand(0);
16076 SDValue RHS = N->getOperand(1);
16077
16078 const ConstantSDNode *CRHS = isConstOrConstSplat(RHS);
16079 SelectionDAG &DAG = DCI.DAG;
16080
16081 EVT VT = N->getValueType(0);
16082 if (CRHS && VT == MVT::i64) {
16083 if (SDValue Split =
16084 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::XOR, LHS, CRHS))
16085 return Split;
16086 }
16087
16088 // v2i32 (xor (vselect cc, x, y), K) ->
16089 // (v2i32 svelect cc, (xor x, K), (xor y, K)) This enables the xor to be
16090 // replaced with source modifiers when the select is lowered to CNDMASK.
16091 unsigned Opc = LHS.getOpcode();
16092 if (((Opc == ISD::VSELECT && VT == MVT::v2i32) ||
16093 (Opc == ISD::SELECT && VT == MVT::i64)) &&
16094 CRHS && CRHS->getAPIntValue().isSignMask()) {
16095 SDValue CC = LHS->getOperand(0);
16096 SDValue TRUE = LHS->getOperand(1);
16097 SDValue FALSE = LHS->getOperand(2);
16098 SDValue XTrue = DAG.getNode(ISD::XOR, SDLoc(N), VT, TRUE, RHS);
16099 SDValue XFalse = DAG.getNode(ISD::XOR, SDLoc(N), VT, FALSE, RHS);
16100 SDValue XSelect =
16101 DAG.getNode(ISD::VSELECT, SDLoc(N), VT, CC, XTrue, XFalse);
16102 return XSelect;
16103 }
16104
16105 // Make sure to apply the 64-bit constant splitting fold before trying to fold
16106 // fneg-like xors into 64-bit select.
16107 if (LHS.getOpcode() == ISD::SELECT && VT == MVT::i32) {
16108 // This looks like an fneg, try to fold as a source modifier.
16109 if (CRHS && CRHS->getAPIntValue().isSignMask() &&
16111 // xor (select c, a, b), 0x80000000 ->
16112 // bitcast (select c, (fneg (bitcast a)), (fneg (bitcast b)))
16113 SDLoc DL(N);
16114 SDValue CastLHS =
16115 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(1));
16116 SDValue CastRHS =
16117 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(2));
16118 SDValue FNegLHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastLHS);
16119 SDValue FNegRHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastRHS);
16120 SDValue NewSelect = DAG.getNode(ISD::SELECT, DL, MVT::f32,
16121 LHS->getOperand(0), FNegLHS, FNegRHS);
16122 return DAG.getNode(ISD::BITCAST, DL, VT, NewSelect);
16123 }
16124 }
16125
16126 return SDValue();
16127}
16128
16129SDValue
16130SITargetLowering::performZeroOrAnyExtendCombine(SDNode *N,
16131 DAGCombinerInfo &DCI) const {
16132 if (!Subtarget->has16BitInsts() ||
16133 DCI.getDAGCombineLevel() < AfterLegalizeTypes)
16134 return SDValue();
16135
16136 EVT VT = N->getValueType(0);
16137 if (VT != MVT::i32)
16138 return SDValue();
16139
16140 SDValue Src = N->getOperand(0);
16141 if (Src.getValueType() != MVT::i16)
16142 return SDValue();
16143
16144 if (!Src->hasOneUse())
16145 return SDValue();
16146
16147 if (SDValue Ext = performExtendTruncShiftCombine(N, DCI))
16148 return Ext;
16149
16150 // TODO: We bail out below if SrcOffset is not in the first dword (>= 4). It's
16151 // possible we're missing out on some combine opportunities, but we'd need to
16152 // weigh the cost of extracting the byte from the upper dwords.
16153
16154 std::optional<ByteProvider<SDValue>> BP0 =
16155 calculateByteProvider(SDValue(N, 0), 0, 0, 0);
16156 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
16157 return SDValue();
16158 SDValue V0 = *BP0->Src;
16159
16160 std::optional<ByteProvider<SDValue>> BP1 =
16161 calculateByteProvider(SDValue(N, 0), 1, 0, 1);
16162 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
16163 return SDValue();
16164
16165 SDValue V1 = *BP1->Src;
16166
16167 if (V0 == V1)
16168 return SDValue();
16169
16170 SelectionDAG &DAG = DCI.DAG;
16171 SDLoc DL(N);
16172 uint32_t PermMask = 0x0c0c0c0c;
16173 if (V0) {
16174 V0 = getDWordFromOffset(DAG, DL, V0, /*DWordOffset=*/0);
16175 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
16176 }
16177
16178 if (V1) {
16179 V1 = getDWordFromOffset(DAG, DL, V1, /*DWordOffset=*/0);
16180 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
16181 }
16182
16183 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, V0, V1,
16184 DAG.getConstant(PermMask, DL, MVT::i32));
16185}
16186
16187// zext (srl (trunc x), c) => and (srl x, c), lowbits
16188// aext (srl (trunc x), c) => and (srl x, c), lowbits
16189// sext (sra (trunc x), 8) => sext_inreg (srl x, 8), i8
16190SDValue
16191SITargetLowering::performExtendTruncShiftCombine(SDNode *N,
16192 DAGCombinerInfo &DCI) const {
16193 if (DCI.getDAGCombineLevel() < AfterLegalizeTypes)
16194 return SDValue();
16195
16196 const unsigned Opc = N->getOpcode();
16197 const bool IsSigned = Opc == ISD::SIGN_EXTEND;
16198 SDValue Src = N->getOperand(0);
16199 if (N->getValueType(0) != MVT::i32 || Src.getValueType() != MVT::i16 ||
16200 Src.getOpcode() != (IsSigned ? ISD::SRA : ISD::SRL) || !Src.hasOneUse() ||
16201 Src.getOperand(0).getOpcode() != ISD::TRUNCATE)
16202 return SDValue();
16203
16204 // A uniform i16 srl is promoted to i32 later and yields the same nodes.
16205 // Skip it so that the node order, and with it the schedule, stays the same.
16206 if (!IsSigned && !Src->isDivergent())
16207 return SDValue();
16208
16209 SDValue X = Src.getOperand(0).getOperand(0);
16210 auto *Shift = dyn_cast<ConstantSDNode>(Src.getOperand(1));
16211 if (X.getValueType() != MVT::i32 || !Shift || Shift->getZExtValue() == 0 ||
16212 Shift->getZExtValue() >= 16 || (IsSigned && Shift->getZExtValue() != 8))
16213 return SDValue();
16214
16215 SelectionDAG &DAG = DCI.DAG;
16216 SDLoc SL(N);
16217 const unsigned Width = 16 - Shift->getZExtValue();
16218 SDValue Srl = DAG.getNode(
16219 ISD::SRL, SL, MVT::i32, X,
16220 DAG.getShiftAmountConstant(Shift->getZExtValue(), MVT::i32, SL));
16221 if (IsSigned)
16222 return DAG.getNode(ISD::SIGN_EXTEND_INREG, SL, MVT::i32, Srl,
16223 DAG.getValueType(MVT::i8));
16224 return DAG.getNode(
16225 ISD::AND, SL, MVT::i32, Srl,
16226 DAG.getConstant(maskTrailingOnes<uint32_t>(Width), SL, MVT::i32));
16227}
16228
16229SDValue
16230SITargetLowering::performSignExtendInRegCombine(SDNode *N,
16231 DAGCombinerInfo &DCI) const {
16232 SDValue Src = N->getOperand(0);
16233 auto *VTSign = cast<VTSDNode>(N->getOperand(1));
16234
16235 // Combine s_buffer_load_u8 or s_buffer_load_u16 with sext and replace them
16236 // with s_buffer_load_i8 and s_buffer_load_i16 respectively.
16237 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
16238 VTSign->getVT() == MVT::i8) ||
16239 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
16240 VTSign->getVT() == MVT::i16))) {
16241 assert(Subtarget->hasScalarSubwordLoads() &&
16242 "s_buffer_load_{u8, i8} are supported "
16243 "in GFX12 (or newer) architectures.");
16244 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
16245 ? AMDGPUISD::SBUFFER_LOAD_BYTE
16246 : AMDGPUISD::SBUFFER_LOAD_SHORT;
16247 SDLoc DL(N);
16248 SDVTList ResList =
16249 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16250 SDValue Ops[] = {
16251 Src.getOperand(0), // Chain
16252 Src.getOperand(1), // source register
16253 Src.getOperand(2), // offset
16254 Src.getOperand(3) // cachePolicy
16255 };
16256 auto *M = cast<MemSDNode>(Src);
16257 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
16258 Opc, DL, ResList, Ops, M->getMemoryVT(), M->getMemOperand());
16259 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.getValue(1)}, DL);
16260 }
16261 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
16262 VTSign->getVT() == MVT::i8) ||
16263 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
16264 VTSign->getVT() == MVT::i16)) &&
16265 Src.hasOneUse()) {
16266 auto *M = cast<MemSDNode>(Src);
16267 SDValue Ops[] = {Src.getOperand(0), // Chain
16268 Src.getOperand(1), // rsrc
16269 Src.getOperand(2), // vindex
16270 Src.getOperand(3), // voffset
16271 Src.getOperand(4), // soffset
16272 Src.getOperand(5), // offset
16273 Src.getOperand(6), Src.getOperand(7)};
16274 // replace with BUFFER_LOAD_BYTE/SHORT
16275 SDVTList ResList =
16276 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16277 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
16278 ? AMDGPUISD::BUFFER_LOAD_BYTE
16279 : AMDGPUISD::BUFFER_LOAD_SHORT;
16280 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
16281 Opc, SDLoc(N), ResList, Ops, M->getMemoryVT(), M->getMemOperand());
16282 return DCI.DAG.getMergeValues(
16283 {BufferLoadSignExt, BufferLoadSignExt.getValue(1)}, SDLoc(N));
16284 }
16285 return SDValue();
16286}
16287
16288SDValue SITargetLowering::performClassCombine(SDNode *N,
16289 DAGCombinerInfo &DCI) const {
16290 SelectionDAG &DAG = DCI.DAG;
16291 SDValue Mask = N->getOperand(1);
16292
16293 // fp_class x, 0 -> false
16294 if (isNullConstant(Mask))
16295 return DAG.getConstant(0, SDLoc(N), MVT::i1);
16296
16297 if (N->getOperand(0).isUndef())
16298 return DAG.getUNDEF(MVT::i1);
16299
16300 return SDValue();
16301}
16302
16303SDValue SITargetLowering::performRcpCombine(SDNode *N,
16304 DAGCombinerInfo &DCI) const {
16305 EVT VT = N->getValueType(0);
16306 SDValue N0 = N->getOperand(0);
16307
16308 if (N0.isUndef()) {
16309 return DCI.DAG.getConstantFP(APFloat::getQNaN(VT.getFltSemantics()),
16310 SDLoc(N), VT);
16311 }
16312
16313 // TODO: Could handle f32 + amdgcn.sqrt but probably never reaches here.
16314 if ((VT == MVT::f16 && N0.getOpcode() == ISD::FSQRT) &&
16315 N->getFlags().hasAllowContract() && N0->getFlags().hasAllowContract()) {
16316 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(N), VT, N0.getOperand(0),
16317 N->getFlags());
16318 }
16319
16321}
16322
16324 SDNodeFlags UserFlags,
16325 unsigned MaxDepth) const {
16326 EVT VT = Op.getValueType();
16327 assert(VT.isFloatingPoint() &&
16328 "expected a floating-point value to query canonicality of");
16329 return isCanonicalized(DAG, Op, VT.getScalarType(), UserFlags, MaxDepth);
16330}
16331
16333 EVT QueryVT, SDNodeFlags UserFlags,
16334 unsigned MaxDepth) const {
16335 assert(QueryVT.isFloatingPoint() && !QueryVT.isVector() &&
16336 "QueryVT must be a floating-point scalar type");
16337 EVT VT = Op.getValueType();
16338 if (VT.isFloatingPoint() && VT.getScalarType() != QueryVT)
16339 return false;
16340
16341 unsigned Opcode = Op.getOpcode();
16342 if (Opcode == ISD::FCANONICALIZE)
16343 return true;
16344
16345 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16346 const auto &F = CFP->getValueAPF();
16347 if (F.isNaN() && F.isSignaling())
16348 return false;
16349 if (!F.isDenormal())
16350 return true;
16351
16352 DenormalMode Mode =
16353 DAG.getMachineFunction().getDenormalMode(F.getSemantics());
16354 return Mode == DenormalMode::getIEEE();
16355 }
16356
16357 // If source is a result of another standard FP operation it is already in
16358 // canonical form.
16359 if (MaxDepth == 0)
16360 return false;
16361
16362 switch (Opcode) {
16363 // These will flush denorms if required.
16364 case ISD::FADD:
16365 case ISD::FSUB:
16366 case ISD::FMUL:
16367 case ISD::FCEIL:
16368 case ISD::FFLOOR:
16369 case ISD::FMA:
16370 case ISD::FMAD:
16371 case ISD::FSQRT:
16372 case ISD::FDIV:
16373 case ISD::FREM:
16374 case ISD::FP_ROUND:
16375 case ISD::FP_EXTEND:
16376 case ISD::FP16_TO_FP:
16377 case ISD::FP_TO_FP16:
16378 case ISD::BF16_TO_FP:
16379 case ISD::FP_TO_BF16:
16380 case ISD::FLDEXP:
16381 case AMDGPUISD::FMUL_LEGACY:
16382 case AMDGPUISD::FMAD_FTZ:
16383 case AMDGPUISD::RCP:
16384 case AMDGPUISD::RSQ:
16385 case AMDGPUISD::RSQ_CLAMP:
16386 case AMDGPUISD::RCP_LEGACY:
16387 case AMDGPUISD::RCP_IFLAG:
16388 case AMDGPUISD::LOG:
16389 case AMDGPUISD::EXP:
16390 case AMDGPUISD::DIV_SCALE:
16391 case AMDGPUISD::DIV_FMAS:
16392 case AMDGPUISD::DIV_FIXUP:
16393 case AMDGPUISD::FRACT:
16394 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16395 case AMDGPUISD::CVT_F32_UBYTE0:
16396 case AMDGPUISD::CVT_F32_UBYTE1:
16397 case AMDGPUISD::CVT_F32_UBYTE2:
16398 case AMDGPUISD::CVT_F32_UBYTE3:
16399 case AMDGPUISD::FP_TO_FP16:
16400 case AMDGPUISD::SIN_HW:
16401 case AMDGPUISD::COS_HW:
16402 return true;
16403
16404 // It can/will be lowered or combined as a bit operation.
16405 // Need to check their input recursively to handle.
16406 case ISD::FNEG:
16407 case ISD::FABS:
16408 case ISD::FCOPYSIGN:
16409 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16410 MaxDepth - 1);
16411
16412 case ISD::AND:
16413 if (Op.getValueType() == MVT::i32) {
16414 // Be careful as we only know it is a bitcast floating point type. It
16415 // could be f32, v2f16, we have no way of knowing. Luckily the constant
16416 // value that we optimize for, which comes up in fp32 to bf16 conversions,
16417 // is valid to optimize for all types.
16418 if (auto *RHS = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
16419 if (RHS->getZExtValue() == 0xffff0000) {
16420 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16421 MaxDepth - 1);
16422 }
16423 }
16424 }
16425 break;
16426
16427 case ISD::FSIN:
16428 case ISD::FCOS:
16429 case ISD::FSINCOS:
16430 return Op.getValueType().getScalarType() != MVT::f16;
16431
16432 case ISD::FMINNUM:
16433 case ISD::FMAXNUM:
16434 case ISD::FMINNUM_IEEE:
16435 case ISD::FMAXNUM_IEEE:
16436 case ISD::FMINIMUM:
16437 case ISD::FMAXIMUM:
16438 case ISD::FMINIMUMNUM:
16439 case ISD::FMAXIMUMNUM:
16440 case AMDGPUISD::CLAMP:
16441 case AMDGPUISD::FMED3:
16442 case AMDGPUISD::FMAX3:
16443 case AMDGPUISD::FMIN3:
16444 case AMDGPUISD::FMAXIMUM3:
16445 case AMDGPUISD::FMINIMUM3: {
16446 // FIXME: Shouldn't treat the generic operations different based these.
16447 // However, we aren't really required to flush the result from
16448 // minnum/maxnum..
16449
16450 // snans will be quieted, so we only need to worry about denormals.
16451 if (Subtarget->supportsMinMaxDenormModes() ||
16452 // FIXME: denormalsEnabledForType is broken for dynamic
16453 denormalsEnabledForType(DAG, Op.getValueType()))
16454 return true;
16455
16456 // Flushing may be required.
16457 // In pre-GFX9 targets V_MIN_F32 and others do not flush denorms. For such
16458 // targets need to check their input recursively.
16459
16460 // FIXME: Does this apply with clamp? It's implemented with max.
16461 for (unsigned I = 0, E = Op.getNumOperands(); I != E; ++I) {
16462 if (!isCanonicalized(DAG, Op.getOperand(I), QueryVT, UserFlags,
16463 MaxDepth - 1))
16464 return false;
16465 }
16466
16467 return true;
16468 }
16469 case ISD::SELECT: {
16470 return isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16471 MaxDepth - 1) &&
16472 isCanonicalized(DAG, Op.getOperand(2), QueryVT, UserFlags,
16473 MaxDepth - 1);
16474 }
16475 case ISD::BUILD_VECTOR: {
16476 for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
16477 SDValue SrcOp = Op.getOperand(i);
16478 if (!isCanonicalized(DAG, SrcOp, QueryVT, UserFlags, MaxDepth - 1))
16479 return false;
16480 }
16481
16482 return true;
16483 }
16486 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16487 MaxDepth - 1);
16488 }
16490 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16491 MaxDepth - 1) &&
16492 isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16493 MaxDepth - 1);
16494 }
16495 case ISD::POISON:
16496 return true;
16497 case ISD::UNDEF:
16498 // Could be anything.
16499 return false;
16500
16501 case ISD::BITCAST: {
16502 // Carry QueryVT through the bitcast unchanged. The top-of-function guard
16503 // rejects a source whose FP format differs from the consumed type, so a
16504 // value canonical in one FP format is not assumed canonical in another.
16505 SDValue Src = peekThroughBitcasts(Op.getOperand(0));
16506 return isCanonicalized(DAG, Src, QueryVT, UserFlags, MaxDepth - 1);
16507 }
16508 case ISD::TRUNCATE: {
16509 // Hack round the mess we make when legalizing extract_vector_elt
16510 if (Op.getValueType() == MVT::i16) {
16511 SDValue TruncSrc = Op.getOperand(0);
16512 if (TruncSrc.getValueType() == MVT::i32 &&
16513 TruncSrc.getOpcode() == ISD::BITCAST &&
16514 TruncSrc.getOperand(0).getValueType() == MVT::v2f16) {
16515 return isCanonicalized(DAG, TruncSrc.getOperand(0), QueryVT, UserFlags,
16516 MaxDepth - 1);
16517 }
16518 }
16519 return false;
16520 }
16522 unsigned IntrinsicID = Op.getConstantOperandVal(0);
16523 // TODO: Handle more intrinsics
16524 switch (IntrinsicID) {
16525 case Intrinsic::amdgcn_update_dpp: {
16526 enum UpdateDPPOperand {
16527 Src = 2,
16528 RowMask = 4,
16529 BankMask = 5,
16530 BoundCtrl = 6,
16531 };
16532
16533 if (QueryVT == MVT::f32 && (VT == MVT::i32 || VT == MVT::f32) &&
16534 Op.getConstantOperandVal(RowMask) == 0xf && // Enable all rows.
16535 Op.getConstantOperandVal(BankMask) == 0xf && // Enable all banks.
16536 Op.getConstantOperandVal(BoundCtrl) != 0) // Zero-fill OOB lanes.
16537 return isCanonicalized(DAG, Op.getOperand(2), QueryVT, UserFlags,
16538 MaxDepth - 1);
16539 return false;
16540 }
16541 case Intrinsic::amdgcn_cvt_pkrtz:
16542 case Intrinsic::amdgcn_cubeid:
16543 case Intrinsic::amdgcn_frexp_mant:
16544 case Intrinsic::amdgcn_fdot2:
16545 case Intrinsic::amdgcn_rcp:
16546 case Intrinsic::amdgcn_rsq:
16547 case Intrinsic::amdgcn_rsq_clamp:
16548 case Intrinsic::amdgcn_rcp_legacy:
16549 case Intrinsic::amdgcn_rsq_legacy:
16550 case Intrinsic::amdgcn_trig_preop:
16551 case Intrinsic::amdgcn_tanh:
16552 case Intrinsic::amdgcn_log:
16553 case Intrinsic::amdgcn_exp2:
16554 case Intrinsic::amdgcn_sqrt:
16555 return true;
16556 default:
16557 break;
16558 }
16559
16560 break;
16561 }
16562 default:
16563 break;
16564 }
16565
16566 // FIXME: denormalsEnabledForType is broken for dynamic
16567 return denormalsEnabledForType(DAG, Op.getValueType()) &&
16568 (UserFlags.hasNoNaNs() || DAG.isKnownNeverSNaN(Op));
16569}
16570
16572 unsigned MaxDepth) const {
16573 const MachineRegisterInfo &MRI = MF.getRegInfo();
16574 MachineInstr *MI = MRI.getVRegDef(Reg);
16575 unsigned Opcode = MI->getOpcode();
16576
16577 if (Opcode == AMDGPU::G_FCANONICALIZE)
16578 return true;
16579
16580 std::optional<FPValueAndVReg> FCR;
16581 // Constant splat (can be padded with undef) or scalar constant.
16583 if (FCR->Value.isSignaling())
16584 return false;
16585 if (!FCR->Value.isDenormal())
16586 return true;
16587
16588 DenormalMode Mode = MF.getDenormalMode(FCR->Value.getSemantics());
16589 return Mode == DenormalMode::getIEEE();
16590 }
16591
16592 if (MaxDepth == 0)
16593 return false;
16594
16595 switch (Opcode) {
16596 case AMDGPU::G_FADD:
16597 case AMDGPU::G_FSUB:
16598 case AMDGPU::G_FMUL:
16599 case AMDGPU::G_FCEIL:
16600 case AMDGPU::G_FFLOOR:
16601 case AMDGPU::G_FRINT:
16602 case AMDGPU::G_FNEARBYINT:
16603 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16604 case AMDGPU::G_INTRINSIC_TRUNC:
16605 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16606 case AMDGPU::G_FMA:
16607 case AMDGPU::G_FMAD:
16608 case AMDGPU::G_FSQRT:
16609 case AMDGPU::G_FDIV:
16610 case AMDGPU::G_FREM:
16611 case AMDGPU::G_FPOW:
16612 case AMDGPU::G_FPEXT:
16613 case AMDGPU::G_FLOG:
16614 case AMDGPU::G_FLOG2:
16615 case AMDGPU::G_FLOG10:
16616 case AMDGPU::G_FPTRUNC:
16617 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16618 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16619 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16620 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16621 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16622 return true;
16623 case AMDGPU::G_FNEG:
16624 case AMDGPU::G_FABS:
16625 case AMDGPU::G_FCOPYSIGN:
16626 return isCanonicalized(MI->getOperand(1).getReg(), MF, MaxDepth - 1);
16627 case AMDGPU::G_FMINNUM:
16628 case AMDGPU::G_FMAXNUM:
16629 case AMDGPU::G_FMINNUM_IEEE:
16630 case AMDGPU::G_FMAXNUM_IEEE:
16631 case AMDGPU::G_FMINIMUM:
16632 case AMDGPU::G_FMAXIMUM:
16633 case AMDGPU::G_FMINIMUMNUM:
16634 case AMDGPU::G_FMAXIMUMNUM: {
16635 if (Subtarget->supportsMinMaxDenormModes() ||
16636 // FIXME: denormalsEnabledForType is broken for dynamic
16637 denormalsEnabledForType(MRI.getType(Reg), MF))
16638 return true;
16639
16640 [[fallthrough]];
16641 }
16642 case AMDGPU::G_BUILD_VECTOR:
16643 for (const MachineOperand &MO : llvm::drop_begin(MI->operands()))
16644 if (!isCanonicalized(MO.getReg(), MF, MaxDepth - 1))
16645 return false;
16646 return true;
16647 case AMDGPU::G_INTRINSIC:
16648 case AMDGPU::G_INTRINSIC_CONVERGENT:
16649 switch (cast<GIntrinsic>(MI)->getIntrinsicID()) {
16650 case Intrinsic::amdgcn_fmul_legacy:
16651 case Intrinsic::amdgcn_fmad_ftz:
16652 case Intrinsic::amdgcn_sqrt:
16653 case Intrinsic::amdgcn_fmed3:
16654 case Intrinsic::amdgcn_sin:
16655 case Intrinsic::amdgcn_cos:
16656 case Intrinsic::amdgcn_log:
16657 case Intrinsic::amdgcn_exp2:
16658 case Intrinsic::amdgcn_log_clamp:
16659 case Intrinsic::amdgcn_rcp:
16660 case Intrinsic::amdgcn_rcp_legacy:
16661 case Intrinsic::amdgcn_rsq:
16662 case Intrinsic::amdgcn_rsq_clamp:
16663 case Intrinsic::amdgcn_rsq_legacy:
16664 case Intrinsic::amdgcn_div_scale:
16665 case Intrinsic::amdgcn_div_fmas:
16666 case Intrinsic::amdgcn_div_fixup:
16667 case Intrinsic::amdgcn_fract:
16668 case Intrinsic::amdgcn_cvt_pkrtz:
16669 case Intrinsic::amdgcn_cubeid:
16670 case Intrinsic::amdgcn_cubema:
16671 case Intrinsic::amdgcn_cubesc:
16672 case Intrinsic::amdgcn_cubetc:
16673 case Intrinsic::amdgcn_frexp_mant:
16674 case Intrinsic::amdgcn_fdot2:
16675 case Intrinsic::amdgcn_trig_preop:
16676 case Intrinsic::amdgcn_tanh:
16677 return true;
16678 default:
16679 break;
16680 }
16681
16682 [[fallthrough]];
16683 default:
16684 return false;
16685 }
16686
16687 llvm_unreachable("invalid operation");
16688}
16689
16690// Constant fold canonicalize.
16691SDValue SITargetLowering::getCanonicalConstantFP(SelectionDAG &DAG,
16692 const SDLoc &SL, EVT VT,
16693 const APFloat &C) const {
16694 // Flush denormals to 0 if not enabled.
16695 if (C.isDenormal()) {
16696 DenormalMode Mode =
16697 DAG.getMachineFunction().getDenormalMode(C.getSemantics());
16698 if (Mode == DenormalMode::getPreserveSign()) {
16699 return DAG.getConstantFP(
16700 APFloat::getZero(C.getSemantics(), C.isNegative()), SL, VT);
16701 }
16702
16703 if (Mode != DenormalMode::getIEEE())
16704 return SDValue();
16705 }
16706
16707 if (C.isNaN()) {
16708 if (C.isSignaling()) {
16709 // Quiet a signaling NaN.
16710 return DAG.getConstantFP(C.makeQuiet(), SL, VT);
16711 }
16712 }
16713
16714 // Already canonical.
16715 return DAG.getConstantFP(C, SL, VT);
16716}
16717
16719 return Op.isUndef() || isa<ConstantFPSDNode>(Op);
16720}
16721
16722SDValue
16723SITargetLowering::performFCanonicalizeCombine(SDNode *N,
16724 DAGCombinerInfo &DCI) const {
16725 SelectionDAG &DAG = DCI.DAG;
16726 SDValue N0 = N->getOperand(0);
16727 EVT VT = N->getValueType(0);
16728
16729 // fcanonicalize undef -> qnan
16730 if (N0.isUndef()) {
16732 return DAG.getConstantFP(QNaN, SDLoc(N), VT);
16733 }
16734
16735 if (ConstantFPSDNode *CFP = isConstOrConstSplatFP(N0))
16736 return getCanonicalConstantFP(DAG, SDLoc(N), VT, CFP->getValueAPF());
16737
16738 // fcanonicalize (build_vector x, k) -> build_vector (fcanonicalize x),
16739 // (fcanonicalize k)
16740 //
16741 // fcanonicalize (build_vector x, undef) -> build_vector (fcanonicalize x), 0
16742
16743 // TODO: This could be better with wider vectors that will be split to v2f16,
16744 // and to consider uses since there aren't that many packed operations.
16745 if (N0.getOpcode() == ISD::BUILD_VECTOR && N0.getNumOperands() == 2 &&
16746 isTypeLegal(VT)) {
16747 SDLoc SL(N);
16748 SDValue NewElts[2];
16749 SDValue Lo = N0.getOperand(0);
16750 SDValue Hi = N0.getOperand(1);
16751 EVT EltVT = Lo.getValueType();
16752
16753 // Only apply this optimization if scalar canonicalize is legal for the
16754 // element type. Otherwise, scalarizing may require widening the scalar back
16755 // to a vector, adding overhead (e.g., bf16 has no scalar instructions).
16757 return SDValue();
16758
16760 for (unsigned I = 0; I != 2; ++I) {
16761 SDValue Op = N0.getOperand(I);
16762 if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16763 NewElts[I] =
16764 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16765 } else if (Op.isUndef()) {
16766 // Handled below based on what the other operand is.
16767 NewElts[I] = Op;
16768 } else {
16769 NewElts[I] = DAG.getNode(ISD::FCANONICALIZE, SL, EltVT, Op);
16770 }
16771 }
16772
16773 // If one half is undef, and one is constant, prefer a splat vector.
16774 // Otherwise, convert the undef to 0.0 since that's cheaper to use and may
16775 // be free with a packed operation.
16776 if (NewElts[0].isUndef()) {
16777 NewElts[0] = isa<ConstantFPSDNode>(NewElts[1])
16778 ? NewElts[1]
16779 : DAG.getConstantFP(0.0f, SL, EltVT);
16780 }
16781
16782 if (NewElts[1].isUndef()) {
16783 NewElts[1] = isa<ConstantFPSDNode>(NewElts[0])
16784 ? NewElts[0]
16785 : DAG.getConstantFP(0.0f, SL, EltVT);
16786 }
16787
16788 return DAG.getBuildVector(VT, SL, NewElts);
16789 }
16790 }
16791
16792 return SDValue();
16793}
16794
16795static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc) {
16796 switch (Opc) {
16797 case ISD::FMAXNUM:
16798 case ISD::FMAXNUM_IEEE:
16799 case ISD::FMAXIMUMNUM:
16800 return AMDGPUISD::FMAX3;
16801 case ISD::FMAXIMUM:
16802 return AMDGPUISD::FMAXIMUM3;
16803 case ISD::SMAX:
16804 return AMDGPUISD::SMAX3;
16805 case ISD::UMAX:
16806 return AMDGPUISD::UMAX3;
16807 case ISD::FMINNUM:
16808 case ISD::FMINNUM_IEEE:
16809 case ISD::FMINIMUMNUM:
16810 return AMDGPUISD::FMIN3;
16811 case ISD::FMINIMUM:
16812 return AMDGPUISD::FMINIMUM3;
16813 case ISD::SMIN:
16814 return AMDGPUISD::SMIN3;
16815 case ISD::UMIN:
16816 return AMDGPUISD::UMIN3;
16817 default:
16818 llvm_unreachable("Not a min/max opcode");
16819 }
16820}
16821
16822SDValue SITargetLowering::performIntMed3ImmCombine(SelectionDAG &DAG,
16823 const SDLoc &SL, SDValue Src,
16824 SDValue MinVal,
16825 SDValue MaxVal,
16826 bool Signed) const {
16827
16828 // med3 comes from
16829 // min(max(x, K0), K1), K0 < K1
16830 // max(min(x, K0), K1), K1 < K0
16831 //
16832 // "MinVal" and "MaxVal" respectively refer to the rhs of the
16833 // min/max op.
16834 ConstantSDNode *MinK = dyn_cast<ConstantSDNode>(MinVal);
16835 ConstantSDNode *MaxK = dyn_cast<ConstantSDNode>(MaxVal);
16836
16837 if (!MinK || !MaxK)
16838 return SDValue();
16839
16840 if (Signed) {
16841 if (MaxK->getAPIntValue().sge(MinK->getAPIntValue()))
16842 return SDValue();
16843 } else {
16844 if (MaxK->getAPIntValue().uge(MinK->getAPIntValue()))
16845 return SDValue();
16846 }
16847
16848 EVT VT = MinK->getValueType(0);
16849 unsigned Med3Opc = Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16850 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16851 return DAG.getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16852
16853 // Note: we could also extend to i32 and use i32 med3 if i16 med3 is
16854 // not available, but this is unlikely to be profitable as constants
16855 // will often need to be materialized & extended, especially on
16856 // pre-GFX10 where VOP3 instructions couldn't take literal operands.
16857 return SDValue();
16858}
16859
16862 return C;
16863
16865 if (ConstantFPSDNode *C = BV->getConstantFPSplatNode())
16866 return C;
16867 }
16868
16869 return nullptr;
16870}
16871
16872SDValue SITargetLowering::performFPMed3ImmCombine(SelectionDAG &DAG,
16873 const SDLoc &SL, SDValue Op0,
16874 SDValue Op1,
16875 bool IsKnownNoNaNs) const {
16876 ConstantFPSDNode *K1 = getSplatConstantFP(Op1);
16877 if (!K1)
16878 return SDValue();
16879
16880 ConstantFPSDNode *K0 = getSplatConstantFP(Op0.getOperand(1));
16881 if (!K0)
16882 return SDValue();
16883
16884 // Ordered >= (although NaN inputs should have folded away by now).
16885 if (K0->getValueAPF() > K1->getValueAPF())
16886 return SDValue();
16887
16888 // med3 with a nan input acts like
16889 // v_min_f32(v_min_f32(S0.f32, S1.f32), S2.f32)
16890 //
16891 // So the result depends on whether the IEEE mode bit is enabled or not with a
16892 // signaling nan input.
16893 // ieee=1
16894 // s0 snan: yields s2
16895 // s1 snan: yields s2
16896 // s2 snan: qnan
16897
16898 // s0 qnan: min(s1, s2)
16899 // s1 qnan: min(s0, s2)
16900 // s2 qnan: min(s0, s1)
16901
16902 // ieee=0
16903 // s0 snan: min(s1, s2)
16904 // s1 snan: min(s0, s2)
16905 // s2 snan: qnan
16906
16907 // s0 qnan: min(s1, s2)
16908 // s1 qnan: min(s0, s2)
16909 // s2 qnan: min(s0, s1)
16910 const MachineFunction &MF = DAG.getMachineFunction();
16911 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
16912
16913 // TODO: Check IEEE bit enabled. We can form fmed3 with IEEE=0 regardless of
16914 // whether the input is a signaling nan if op0 is fmaximum or fmaximumnum. We
16915 // can only form if op0 is fmaxnum_ieee if IEEE=1.
16916 EVT VT = Op0.getValueType();
16917 if (Info->getMode().DX10Clamp) {
16918 // If dx10_clamp is enabled, NaNs clamp to 0.0. This is the same as the
16919 // hardware fmed3 behavior converting to a min.
16920 // FIXME: Should this be allowing -0.0?
16921 if (K1->isOne() && K0->isPosZero())
16922 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Op0.getOperand(0));
16923 }
16924
16925 // med3 for f16 is only available on gfx9+, and not available for v2f16.
16926 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16927 // This isn't safe with signaling NaNs because in IEEE mode, min/max on a
16928 // signaling NaN gives a quiet NaN. The quiet NaN input to the min would
16929 // then give the other result, which is different from med3 with a NaN
16930 // input.
16931 SDValue Var = Op0.getOperand(0);
16932 if (!IsKnownNoNaNs && !DAG.isKnownNeverSNaN(Var))
16933 return SDValue();
16934
16935 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
16936
16937 if ((!K0->hasOneUse() || TII->isInlineConstant(K0->getValueAPF())) &&
16938 (!K1->hasOneUse() || TII->isInlineConstant(K1->getValueAPF()))) {
16939 return DAG.getNode(AMDGPUISD::FMED3, SL, K0->getValueType(0), Var,
16940 SDValue(K0, 0), SDValue(K1, 0));
16941 }
16942 }
16943
16944 return SDValue();
16945}
16946
16947/// \return true if the subtarget supports minimum3 and maximum3 with the given
16948/// base min/max opcode \p Opc for type \p VT.
16949static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc,
16950 EVT VT) {
16951 switch (Opc) {
16952 case ISD::FMINNUM:
16953 case ISD::FMAXNUM:
16954 case ISD::FMINNUM_IEEE:
16955 case ISD::FMAXNUM_IEEE:
16956 case ISD::FMINIMUMNUM:
16957 case ISD::FMAXIMUMNUM:
16958 case AMDGPUISD::FMIN_LEGACY:
16959 case AMDGPUISD::FMAX_LEGACY:
16960 return (VT == MVT::f32) || (VT == MVT::f16 && Subtarget.hasMin3Max3_16()) ||
16961 (VT == MVT::v2f16 && Subtarget.hasMin3Max3PKF16());
16962 case ISD::FMINIMUM:
16963 case ISD::FMAXIMUM:
16964 return (VT == MVT::f32 && Subtarget.hasMinimum3Maximum3F32()) ||
16965 (VT == MVT::f16 && Subtarget.hasMinimum3Maximum3F16()) ||
16966 (VT == MVT::v2f16 && Subtarget.hasMinimum3Maximum3PKF16());
16967 case ISD::SMAX:
16968 case ISD::SMIN:
16969 case ISD::UMAX:
16970 case ISD::UMIN:
16971 return (VT == MVT::i32) || (VT == MVT::i16 && Subtarget.hasMin3Max3_16());
16972 default:
16973 return false;
16974 }
16975
16976 llvm_unreachable("not a min/max opcode");
16977}
16978
16979SDValue SITargetLowering::performMinMaxCombine(SDNode *N,
16980 DAGCombinerInfo &DCI) const {
16981 SelectionDAG &DAG = DCI.DAG;
16982
16983 EVT VT = N->getValueType(0);
16984 unsigned Opc = N->getOpcode();
16985 SDValue Op0 = N->getOperand(0);
16986 SDValue Op1 = N->getOperand(1);
16987
16988 // Only do this if the inner op has one use since this will just increases
16989 // register pressure for no benefit.
16990
16991 if (supportsMin3Max3(*Subtarget, Opc, VT)) {
16992 auto IsTreeWithCombinableChildren = [Opc](SDValue Op) {
16993 return (Op.getOperand(0).getOpcode() == Opc &&
16994 Op.getOperand(0).hasOneUse()) ||
16995 (Op.getOperand(1).getOpcode() == Opc &&
16996 Op.getOperand(1).hasOneUse());
16997 };
16998
16999 bool CanTreeCombineApply = Op0.getOpcode() == Opc && Op0.hasOneUse() &&
17000 Op1.getOpcode() == Opc && Op1.hasOneUse();
17001 bool HasCombinableTreeChild =
17002 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
17003 IsTreeWithCombinableChildren(Op1));
17004
17005 // Tree reduction: when both operands are the same min/max op, restructure
17006 // to keep a 2-op node on top so higher tree levels can still combine.
17007 //
17008 // max(max(a, b), max(c, d)) -> max(max3(a, b, c), d)
17009 // min(min(a, b), min(c, d)) -> min(min3(a, b, c), d)
17010 //
17011 // Defer when either inner op is a tree node with combinable children.
17012 if (CanTreeCombineApply && !HasCombinableTreeChild) {
17013 SDLoc DL(N);
17014 SDValue Inner =
17016 Op0.getOperand(1), Op1.getOperand(0));
17017 return DAG.getNode(Opc, DL, VT, Inner, Op1.getOperand(1));
17018 }
17019
17020 // max(max(a, b), c) -> max3(a, b, c)
17021 // min(min(a, b), c) -> min3(a, b, c)
17022 // Deferred when Op0 is a tree node with combinable children.
17023 if (Op0.getOpcode() == Opc && Op0.hasOneUse() && !HasCombinableTreeChild) {
17024 SDLoc DL(N);
17025 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
17026 Op0.getOperand(0), Op0.getOperand(1), Op1);
17027 }
17028
17029 // Try commuted.
17030 // max(a, max(b, c)) -> max3(a, b, c)
17031 // min(a, min(b, c)) -> min3(a, b, c)
17032 // Deferred when Op1 is a tree node with combinable children.
17033 if (Op1.getOpcode() == Opc && Op1.hasOneUse() && !HasCombinableTreeChild) {
17034 SDLoc DL(N);
17035 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
17036 Op0, Op1.getOperand(0), Op1.getOperand(1));
17037 }
17038 }
17039
17040 // umin(sffbh(x), bitwidth) -> sffbh(x) if x is known to be not 0 or -1.
17041 SDValue FfbhSrc;
17042 uint64_t Clamp = 0;
17043 if (Opc == ISD::UMIN &&
17044 sd_match(Op0,
17046 sd_match(Op1, m_ConstInt(Clamp))) {
17047 unsigned BitWidth = FfbhSrc.getValueType().getScalarSizeInBits();
17048 if (Clamp >= BitWidth) {
17049 KnownBits Known = DAG.computeKnownBits(FfbhSrc);
17050 if (Known.isNonZero() && Known.Zero.getBoolValue())
17051 return Op0;
17052 }
17053 }
17054
17055 // min(max(x, K0), K1), K0 < K1 -> med3(x, K0, K1)
17056 // max(min(x, K0), K1), K1 < K0 -> med3(x, K1, K0)
17057 if (Opc == ISD::SMIN && Op0.getOpcode() == ISD::SMAX && Op0.hasOneUse()) {
17058 if (SDValue Med3 = performIntMed3ImmCombine(
17059 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), true))
17060 return Med3;
17061 }
17062 if (Opc == ISD::SMAX && Op0.getOpcode() == ISD::SMIN && Op0.hasOneUse()) {
17063 if (SDValue Med3 = performIntMed3ImmCombine(
17064 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, true))
17065 return Med3;
17066 }
17067
17068 if (Opc == ISD::UMIN && Op0.getOpcode() == ISD::UMAX && Op0.hasOneUse()) {
17069 if (SDValue Med3 = performIntMed3ImmCombine(
17070 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), false))
17071 return Med3;
17072 }
17073 if (Opc == ISD::UMAX && Op0.getOpcode() == ISD::UMIN && Op0.hasOneUse()) {
17074 if (SDValue Med3 = performIntMed3ImmCombine(
17075 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, false))
17076 return Med3;
17077 }
17078
17079 // if !is_snan(x):
17080 // fminnum(fmaxnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17081 // fminnum_ieee(fmaxnum_ieee(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17082 // fminnumnum(fmaxnumnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17083 // fmin_legacy(fmax_legacy(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17084 if (((Opc == ISD::FMINNUM && Op0.getOpcode() == ISD::FMAXNUM) ||
17087 (Opc == AMDGPUISD::FMIN_LEGACY &&
17088 Op0.getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
17089 (VT == MVT::f32 || VT == MVT::f64 ||
17090 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
17091 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
17092 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
17093 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
17094 Op0.hasOneUse()) {
17095 if (SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(N), Op0, Op1,
17096 N->getFlags().hasNoNaNs()))
17097 return Res;
17098 }
17099
17100 // Prefer fminnum_ieee over fminimum. For gfx950, minimum/maximum are legal
17101 // for some types, but at a higher cost since it's implemented with a 3
17102 // operand form.
17103 const SDNodeFlags Flags = N->getFlags();
17104 if ((Opc == ISD::FMINIMUM || Opc == ISD::FMAXIMUM) && Flags.hasNoNaNs() &&
17105 !Subtarget->hasIEEEMinimumMaximumInsts() &&
17107 unsigned NewOpc =
17109 return DAG.getNode(NewOpc, SDLoc(N), VT, Op0, Op1, Flags);
17110 }
17111
17112 return SDValue();
17113}
17114
17118 // FIXME: Should this be allowing -0.0?
17119 return (CA->isPosZero() && CB->isOne()) ||
17120 (CA->isOne() && CB->isPosZero());
17121 }
17122 }
17123
17124 return false;
17125}
17126
17127// FIXME: Should only worry about snans for version with chain.
17128SDValue SITargetLowering::performFMed3Combine(SDNode *N,
17129 DAGCombinerInfo &DCI) const {
17130 EVT VT = N->getValueType(0);
17131 // v_med3_f32 and v_max_f32 behave identically wrt denorms, exceptions and
17132 // NaNs. With a NaN input, the order of the operands may change the result.
17133
17134 SelectionDAG &DAG = DCI.DAG;
17135 SDLoc SL(N);
17136
17137 SDValue Src0 = N->getOperand(0);
17138 SDValue Src1 = N->getOperand(1);
17139 SDValue Src2 = N->getOperand(2);
17140
17141 if (isClampZeroToOne(Src0, Src1)) {
17142 // const_a, const_b, x -> clamp is safe in all cases including signaling
17143 // nans.
17144 // FIXME: Should this be allowing -0.0?
17145 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
17146 }
17147
17148 const MachineFunction &MF = DAG.getMachineFunction();
17149 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
17150
17151 // FIXME: dx10_clamp behavior assumed in instcombine. Should we really bother
17152 // handling no dx10-clamp?
17153 if (Info->getMode().DX10Clamp) {
17154 // If NaNs is clamped to 0, we are free to reorder the inputs.
17155
17156 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
17157 std::swap(Src0, Src1);
17158
17159 if (isa<ConstantFPSDNode>(Src1) && !isa<ConstantFPSDNode>(Src2))
17160 std::swap(Src1, Src2);
17161
17162 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
17163 std::swap(Src0, Src1);
17164
17165 if (isClampZeroToOne(Src1, Src2))
17166 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
17167 }
17168
17169 return SDValue();
17170}
17171
17172SDValue SITargetLowering::performCvtPkRTZCombine(SDNode *N,
17173 DAGCombinerInfo &DCI) const {
17174 SDValue Src0 = N->getOperand(0);
17175 SDValue Src1 = N->getOperand(1);
17176 if (Src0.isUndef() && Src1.isUndef())
17177 return DCI.DAG.getUNDEF(N->getValueType(0));
17178 return SDValue();
17179}
17180
17181/// V_CVT_SCALEF32_* conversions to a narrow format only read the exponent
17182/// field of their f32 scale operand.
17183SDValue
17184SITargetLowering::performExponentOnlyScaleCombine(SDNode *N,
17185 DAGCombinerInfo &DCI) const {
17186 std::optional<unsigned> ScaleArgIdx =
17187 AMDGPU::getExponentOnlyScaleArgIdx(N->getConstantOperandVal(0));
17188 if (!ScaleArgIdx)
17189 return SDValue();
17190
17191 // Operand 0 is the intrinsic ID.
17192 unsigned OpIdx = *ScaleArgIdx + 1;
17193 SelectionDAG &DAG = DCI.DAG;
17194 SDValue Scale = N->getOperand(OpIdx);
17196
17197 if (SDValue DemandedScale =
17198 SimplifyMultipleUseDemandedBits(Scale, Demanded, DAG)) {
17199 SmallVector<SDValue> Ops(N->ops());
17200 Ops[OpIdx] = DemandedScale;
17201 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SDLoc(N), N->getVTList(), Ops);
17202 }
17203
17204 if (SimplifyDemandedBits(Scale, Demanded, DCI))
17205 return SDValue(N, 0);
17206
17207 return SDValue();
17208}
17209
17210// Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be
17211// expanded into a set of cmp/select instructions.
17213 unsigned NumElem,
17214 bool IsDivergentIdx,
17215 const GCNSubtarget *Subtarget) {
17216 if (Subtarget->getCLOpts().use_divergent_register_indexing)
17217 return false;
17218
17219 unsigned VecSize = EltSize * NumElem;
17220
17221 // Sub-dword vectors of size 2 dword or less have better implementation.
17222 if (VecSize <= 64 && EltSize < 32)
17223 return false;
17224
17225 // Always expand the rest of sub-dword instructions, otherwise it will be
17226 // lowered via memory.
17227 if (EltSize < 32)
17228 return true;
17229
17230 // Always do this if var-idx is divergent, otherwise it will become a loop.
17231 if (IsDivergentIdx)
17232 return true;
17233
17234 // Large vectors would yield too many compares and v_cndmask_b32 instructions.
17235 unsigned NumInsts = NumElem /* Number of compares */ +
17236 ((EltSize + 31) / 32) * NumElem /* Number of cndmasks */;
17237
17238 // On some architectures (GFX9) movrel is not available and it's better
17239 // to expand.
17240 if (Subtarget->useVGPRIndexMode())
17241 return NumInsts <= 16;
17242
17243 // If movrel is available, use it instead of expanding for vector of 8
17244 // elements.
17245 if (Subtarget->hasMovrel())
17246 return NumInsts <= 15;
17247
17248 return true;
17249}
17250
17252 SDValue Idx = N->getOperand(N->getNumOperands() - 1);
17253 if (isa<ConstantSDNode>(Idx))
17254 return false;
17255
17256 SDValue Vec = N->getOperand(0);
17257 EVT VecVT = Vec.getValueType();
17258 EVT EltVT = VecVT.getVectorElementType();
17259 unsigned EltSize = EltVT.getSizeInBits();
17260 unsigned NumElem = VecVT.getVectorNumElements();
17261
17263 EltSize, NumElem, Idx->isDivergent(), getSubtarget());
17264}
17265
17266SDValue
17267SITargetLowering::performExtractVectorEltCombine(SDNode *N,
17268 DAGCombinerInfo &DCI) const {
17269 SDValue Vec = N->getOperand(0);
17270 SelectionDAG &DAG = DCI.DAG;
17271
17272 EVT VecVT = Vec.getValueType();
17273 EVT VecEltVT = VecVT.getVectorElementType();
17274 EVT ResVT = N->getValueType(0);
17275
17276 unsigned VecSize = VecVT.getSizeInBits();
17277 unsigned VecEltSize = VecEltVT.getSizeInBits();
17278
17279 if ((Vec.getOpcode() == ISD::FNEG || Vec.getOpcode() == ISD::FABS) &&
17281 SDLoc SL(N);
17282 SDValue Idx = N->getOperand(1);
17283 SDValue Elt =
17284 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec.getOperand(0), Idx);
17285 return DAG.getNode(Vec.getOpcode(), SL, ResVT, Elt);
17286 }
17287
17288 // (extract_vector_element (and {y0, y1}, (build_vector 0x1f, 0x1f)), index)
17289 // -> (and (extract_vector_element {y0, y1}, index), 0x1f)
17290 // There are optimisations to transform 64-bit shifts into 32-bit shifts
17291 // depending on the shift operand. See e.g. performSraCombine().
17292 // This combine ensures that the optimisation is compatible with v2i32
17293 // legalised AND.
17294 if (VecVT == MVT::v2i32 && Vec->getOpcode() == ISD::AND &&
17295 Vec->getOperand(1)->getOpcode() == ISD::BUILD_VECTOR) {
17296
17298 if (!C || C->getZExtValue() != 0x1f)
17299 return SDValue();
17300
17301 SDLoc SL(N);
17302 SDValue AndMask = DAG.getConstant(0x1f, SL, MVT::i32);
17303 SDValue EVE = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32,
17304 Vec->getOperand(0), N->getOperand(1));
17305 SDValue A = DAG.getNode(ISD::AND, SL, MVT::i32, EVE, AndMask);
17306 DAG.ReplaceAllUsesWith(N, A.getNode());
17307 }
17308
17309 // ScalarRes = EXTRACT_VECTOR_ELT ((vector-BINOP Vec1, Vec2), Idx)
17310 // =>
17311 // Vec1Elt = EXTRACT_VECTOR_ELT(Vec1, Idx)
17312 // Vec2Elt = EXTRACT_VECTOR_ELT(Vec2, Idx)
17313 // ScalarRes = scalar-BINOP Vec1Elt, Vec2Elt
17314 if (Vec.hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17315 SDLoc SL(N);
17316 SDValue Idx = N->getOperand(1);
17317 unsigned Opc = Vec.getOpcode();
17318
17319 switch (Opc) {
17320 default:
17321 break;
17322 // TODO: Support other binary operations.
17323 case ISD::FADD:
17324 case ISD::FSUB:
17325 case ISD::FMUL:
17326 case ISD::ADD:
17327 case ISD::UMIN:
17328 case ISD::UMAX:
17329 case ISD::SMIN:
17330 case ISD::SMAX:
17331 case ISD::FMAXNUM:
17332 case ISD::FMINNUM:
17333 case ISD::FMAXNUM_IEEE:
17334 case ISD::FMINNUM_IEEE:
17335 case ISD::FMAXIMUM:
17336 case ISD::FMINIMUM: {
17337 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17338 Vec.getOperand(0), Idx);
17339 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17340 Vec.getOperand(1), Idx);
17341
17342 DCI.AddToWorklist(Elt0.getNode());
17343 DCI.AddToWorklist(Elt1.getNode());
17344 return DAG.getNode(Opc, SL, ResVT, Elt0, Elt1, Vec->getFlags());
17345 }
17346 }
17347 }
17348
17349 // EXTRACT_VECTOR_ELT (<n x e>, var-idx) => n x select (e, const-idx)
17351 SDLoc SL(N);
17352 SDValue Idx = N->getOperand(1);
17353 SDValue V;
17354 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17355 SDValue IC = DAG.getVectorIdxConstant(I, SL);
17356 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec, IC);
17357 if (I == 0)
17358 V = Elt;
17359 else
17360 V = DAG.getSelectCC(SL, Idx, IC, Elt, V, ISD::SETEQ);
17361 }
17362 return V;
17363 }
17364
17365 // EXTRACT_VECTOR_ELT (v2i32 bitcast (i64/f64:k), Idx)
17366 // =>
17367 // i32:Lo(k) if Idx == 0, or
17368 // i32:Hi(k) if Idx == 1
17369 auto *Idx = dyn_cast<ConstantSDNode>(N->getOperand(1));
17370 if (Vec.getOpcode() == ISD::BITCAST && VecVT == MVT::v2i32 && Idx) {
17371 SDLoc SL(N);
17372 SDValue PeekThrough = Vec.getOperand(0);
17373 auto *KImm = dyn_cast<ConstantSDNode>(PeekThrough);
17374 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17375 uint64_t KImmValue = KImm->getZExtValue();
17376 return DAG.getConstant(
17377 (KImmValue >> (32 * Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17378 }
17379 auto *KFPImm = dyn_cast<ConstantFPSDNode>(PeekThrough);
17380 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17381 uint64_t KFPImmValue =
17382 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17383 return DAG.getConstant((KFPImmValue >> (32 * Idx->getZExtValue())) &
17384 0xffffffff,
17385 SL, MVT::i32);
17386 }
17387 }
17388
17389 if (!DCI.isBeforeLegalize())
17390 return SDValue();
17391
17392 // Try to turn sub-dword accesses of vectors into accesses of the same 32-bit
17393 // elements. This exposes more load reduction opportunities by replacing
17394 // multiple small extract_vector_elements with a single 32-bit extract.
17395 if (isa<MemSDNode>(Vec) && VecEltSize <= 16 && VecEltVT.isByteSized() &&
17396 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17397 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VecVT);
17398
17399 unsigned BitIndex = Idx->getZExtValue() * VecEltSize;
17400 unsigned EltIdx = BitIndex / 32;
17401 unsigned LeftoverBitIdx = BitIndex % 32;
17402 SDLoc SL(N);
17403
17404 SDValue Cast = DAG.getNode(ISD::BITCAST, SL, NewVT, Vec);
17405 DCI.AddToWorklist(Cast.getNode());
17406
17407 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Cast,
17408 DAG.getConstant(EltIdx, SL, MVT::i32));
17409 DCI.AddToWorklist(Elt.getNode());
17410 SDValue Srl = DAG.getNode(ISD::SRL, SL, MVT::i32, Elt,
17411 DAG.getConstant(LeftoverBitIdx, SL, MVT::i32));
17412 DCI.AddToWorklist(Srl.getNode());
17413
17414 EVT VecEltAsIntVT = VecEltVT.changeTypeToInteger();
17415 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SL, VecEltAsIntVT, Srl);
17416 DCI.AddToWorklist(Trunc.getNode());
17417
17418 if (VecEltVT == ResVT) {
17419 return DAG.getNode(ISD::BITCAST, SL, VecEltVT, Trunc);
17420 }
17421
17422 assert(ResVT.isScalarInteger());
17423 return DAG.getAnyExtOrTrunc(Trunc, SL, ResVT);
17424 }
17425
17426 return SDValue();
17427}
17428
17429SDValue
17430SITargetLowering::performInsertVectorEltCombine(SDNode *N,
17431 DAGCombinerInfo &DCI) const {
17432 SDValue Vec = N->getOperand(0);
17433 SDValue Idx = N->getOperand(2);
17434 EVT VecVT = Vec.getValueType();
17435 EVT EltVT = VecVT.getVectorElementType();
17436
17437 // INSERT_VECTOR_ELT (<n x e>, var-idx)
17438 // => BUILD_VECTOR n x select (e, const-idx)
17439 // 16-bit elements are left to lowerINSERT_VECTOR_ELT, which is cheaper.
17441 (EltVT.getSizeInBits() == 16 &&
17443 return SDValue();
17444
17445 SelectionDAG &DAG = DCI.DAG;
17446 SDLoc SL(N);
17447 SDValue Ins = N->getOperand(1);
17448 EVT IdxVT = Idx.getValueType();
17449
17451 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17452 SDValue IC = DAG.getConstant(I, SL, IdxVT);
17453 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec, IC);
17454 SDValue V = DAG.getSelectCC(SL, Idx, IC, Ins, Elt, ISD::SETEQ);
17455 Ops.push_back(V);
17456 }
17457
17458 return DAG.getBuildVector(VecVT, SL, Ops);
17459}
17460
17461/// Return the source of an fp_extend from f16 to f32, or a converted FP
17462/// constant.
17464 if (Src.getOpcode() == ISD::FP_EXTEND &&
17465 Src.getOperand(0).getValueType() == MVT::f16) {
17466 return Src.getOperand(0);
17467 }
17468
17469 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Src)) {
17470 APFloat Val = CFP->getValueAPF();
17471 bool LosesInfo = true;
17473 if (!LosesInfo)
17474 return DAG.getConstantFP(Val, SDLoc(Src), MVT::f16);
17475 }
17476
17477 return SDValue();
17478}
17479
17480SDValue SITargetLowering::performFPRoundCombine(SDNode *N,
17481 DAGCombinerInfo &DCI) const {
17482 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17483 "combine only useful on gfx8");
17484
17485 SDValue TruncSrc = N->getOperand(0);
17486 EVT VT = N->getValueType(0);
17487 if (VT != MVT::f16)
17488 return SDValue();
17489
17490 if (TruncSrc.getOpcode() != AMDGPUISD::FMED3 ||
17491 TruncSrc.getValueType() != MVT::f32 || !TruncSrc.hasOneUse())
17492 return SDValue();
17493
17494 SelectionDAG &DAG = DCI.DAG;
17495 SDLoc SL(N);
17496
17497 // Optimize f16 fmed3 pattern performed on f32. On gfx8 there is no f16 fmed3,
17498 // and expanding it with min/max saves 1 instruction vs. casting to f32 and
17499 // casting back.
17500
17501 // fptrunc (f32 (fmed3 (fpext f16:a, fpext f16:b, fpext f16:c))) =>
17502 // fmin(fmax(a, b), fmax(fmin(a, b), c))
17503 SDValue A = strictFPExtFromF16(DAG, TruncSrc.getOperand(0));
17504 if (!A)
17505 return SDValue();
17506
17507 SDValue B = strictFPExtFromF16(DAG, TruncSrc.getOperand(1));
17508 if (!B)
17509 return SDValue();
17510
17511 SDValue C = strictFPExtFromF16(DAG, TruncSrc.getOperand(2));
17512 if (!C)
17513 return SDValue();
17514
17515 // This changes signaling nan behavior. If an input is a signaling nan, it
17516 // would have been quieted by the fpext originally. We don't care because
17517 // these are unconstrained ops. If we needed to insert quieting canonicalizes
17518 // we would be worse off than just doing the promotion.
17519 SDValue A1 = DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, A, B);
17520 SDValue B1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A, B);
17521 SDValue C1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A1, C);
17522 return DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, B1, C1);
17523}
17524
17525unsigned SITargetLowering::getFusedOpcode(const SelectionDAG &DAG,
17526 const SDNode *N0,
17527 const SDNode *N1) const {
17528 EVT VT = N0->getValueType(0);
17529
17530 // Only do this if we are not trying to support denormals. v_mad_f32 does not
17531 // support denormals ever.
17532 if (((VT == MVT::f32 &&
17534 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17537 return ISD::FMAD;
17538
17539 if (N0->getFlags().hasAllowContract() && N1->getFlags().hasAllowContract() &&
17541 return ISD::FMA;
17542 }
17543
17544 return 0;
17545}
17546
17547// For a reassociatable opcode perform:
17548// op x, (op y, z) -> op (op x, z), y, if x and z are uniform
17549SDValue SITargetLowering::reassociateScalarOps(SDNode *N,
17550 SelectionDAG &DAG) const {
17551 EVT VT = N->getValueType(0);
17552 if (VT != MVT::i32 && VT != MVT::i64)
17553 return SDValue();
17554
17555 if (DAG.isBaseWithConstantOffset(SDValue(N, 0)))
17556 return SDValue();
17557
17558 unsigned Opc = N->getOpcode();
17559 SDValue Op0 = N->getOperand(0);
17560 SDValue Op1 = N->getOperand(1);
17561
17562 if (!(Op0->isDivergent() ^ Op1->isDivergent()))
17563 return SDValue();
17564
17565 if (Op0->isDivergent())
17566 std::swap(Op0, Op1);
17567
17568 if (Op1.getOpcode() != Opc || !Op1.hasOneUse())
17569 return SDValue();
17570
17571 SDValue Op2 = Op1.getOperand(1);
17572 Op1 = Op1.getOperand(0);
17573 if (!(Op1->isDivergent() ^ Op2->isDivergent()))
17574 return SDValue();
17575
17576 if (Op1->isDivergent())
17577 std::swap(Op1, Op2);
17578
17579 SDLoc SL(N);
17580 SDValue Add1 = DAG.getNode(Opc, SL, VT, Op0, Op1);
17581 return DAG.getNode(Opc, SL, VT, Add1, Op2);
17582}
17583
17584static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT,
17585 SDValue N0, SDValue N1, SDValue N2, bool Signed) {
17587 SDVTList VTs = DAG.getVTList(MVT::i64, MVT::i1);
17588 SDValue Mad = DAG.getNode(MadOpc, SL, VTs, N0, N1, N2);
17589 return DAG.getNode(ISD::TRUNCATE, SL, VT, Mad);
17590}
17591
17592// Fold
17593// y = lshr i64 x, 32
17594// res = add (mul i64 y, Const), x where "Const" is a 64-bit constant
17595// with Const.hi == -1
17596// To
17597// res = mad_u64_u32 y.lo ,Const.lo, x.lo
17599 SDValue MulLHS, SDValue MulRHS,
17600 SDValue AddRHS) {
17601 if (MulRHS.getOpcode() == ISD::SRL)
17602 std::swap(MulLHS, MulRHS);
17603
17604 if (MulLHS.getValueType() != MVT::i64 || MulLHS.getOpcode() != ISD::SRL)
17605 return SDValue();
17606
17607 ConstantSDNode *ShiftVal = dyn_cast<ConstantSDNode>(MulLHS.getOperand(1));
17608 if (!ShiftVal || ShiftVal->getAsZExtVal() != 32 ||
17609 MulLHS.getOperand(0) != AddRHS)
17610 return SDValue();
17611
17613 if (!Const || Hi_32(Const->getZExtValue()) != uint32_t(-1))
17614 return SDValue();
17615
17616 SDValue ConstMul =
17617 DAG.getConstant(Lo_32(Const->getZExtValue()), SL, MVT::i32);
17618 return getMad64_32(DAG, SL, MVT::i64,
17619 DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS), ConstMul,
17620 DAG.getZeroExtendInReg(AddRHS, SL, MVT::i32), false);
17621}
17622
17623// Fold (add (mul x, y), z) --> (mad_[iu]64_[iu]32 x, y, z) plus high
17624// multiplies, if any.
17625//
17626// Full 64-bit multiplies that feed into an addition are lowered here instead
17627// of using the generic expansion. The generic expansion ends up with
17628// a tree of ADD nodes that prevents us from using the "add" part of the
17629// MAD instruction. The expansion produced here results in a chain of ADDs
17630// instead of a tree.
17631SDValue SITargetLowering::tryFoldToMad64_32(SDNode *N,
17632 DAGCombinerInfo &DCI) const {
17633 assert(N->isAnyAdd());
17634
17635 SelectionDAG &DAG = DCI.DAG;
17636 EVT VT = N->getValueType(0);
17637 SDLoc SL(N);
17638 SDValue LHS = N->getOperand(0);
17639 SDValue RHS = N->getOperand(1);
17640
17641 if (VT.isVector())
17642 return SDValue();
17643
17644 // S_MUL_HI_[IU]32 was added in gfx9, which allows us to keep the overall
17645 // result in scalar registers for uniform values.
17646 if (!N->isDivergent() && Subtarget->hasSMulHi())
17647 return SDValue();
17648
17649 unsigned NumBits = VT.getScalarSizeInBits();
17650 if (NumBits <= 32 || NumBits > 64)
17651 return SDValue();
17652
17653 if (LHS.getOpcode() != ISD::MUL) {
17654 assert(RHS.getOpcode() == ISD::MUL);
17655 std::swap(LHS, RHS);
17656 }
17657
17658 // Avoid the fold if it would unduly increase the number of multiplies due to
17659 // multiple uses, except on hardware with full-rate multiply-add (which is
17660 // part of full-rate 64-bit ops).
17661 if (!Subtarget->hasFullRate64Ops()) {
17662 unsigned NumUsers = 0;
17663 for (SDNode *User : LHS->users()) {
17664 // There is a use that does not feed into addition, so the multiply can't
17665 // be removed. We prefer MUL + ADD + ADDC over MAD + MUL.
17666 if (!User->isAnyAdd())
17667 return SDValue();
17668
17669 // We prefer 2xMAD over MUL + 2xADD + 2xADDC (code density), and prefer
17670 // MUL + 3xADD + 3xADDC over 3xMAD.
17671 ++NumUsers;
17672 if (NumUsers >= 3)
17673 return SDValue();
17674 }
17675 }
17676
17677 SDValue MulLHS = LHS.getOperand(0);
17678 SDValue MulRHS = LHS.getOperand(1);
17679 SDValue AddRHS = RHS;
17680
17681 if (SDValue FoldedMAD = tryFoldMADwithSRL(DAG, SL, MulLHS, MulRHS, AddRHS))
17682 return FoldedMAD;
17683
17684 // Always check whether operands are small unsigned values, since that
17685 // knowledge is useful in more cases. Check for small signed values only if
17686 // doing so can unlock a shorter code sequence.
17687 bool MulLHSUnsigned32 = numBitsUnsigned(MulLHS, DAG) <= 32;
17688 bool MulRHSUnsigned32 = numBitsUnsigned(MulRHS, DAG) <= 32;
17689
17690 bool MulSignedLo = false;
17691 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17692 MulSignedLo =
17693 numBitsSigned(MulLHS, DAG) <= 32 && numBitsSigned(MulRHS, DAG) <= 32;
17694 }
17695
17696 // The operands and final result all have the same number of bits. If
17697 // operands need to be extended, they can be extended with garbage. The
17698 // resulting garbage in the high bits of the mad_[iu]64_[iu]32 result is
17699 // truncated away in the end.
17700 if (VT != MVT::i64) {
17701 MulLHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulLHS);
17702 MulRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulRHS);
17703 AddRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, AddRHS);
17704 }
17705
17706 // The basic code generated is conceptually straightforward. Pseudo code:
17707 //
17708 // accum = mad_64_32 lhs.lo, rhs.lo, accum
17709 // accum.hi = add (mul lhs.hi, rhs.lo), accum.hi
17710 // accum.hi = add (mul lhs.lo, rhs.hi), accum.hi
17711 //
17712 // The second and third lines are optional, depending on whether the factors
17713 // are {sign,zero}-extended or not.
17714 //
17715 // The actual DAG is noisier than the pseudo code, but only due to
17716 // instructions that disassemble values into low and high parts, and
17717 // assemble the final result.
17718 SDValue One = DAG.getConstant(1, SL, MVT::i32);
17719
17720 auto MulLHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS);
17721 auto MulRHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulRHS);
17722 SDValue Accum =
17723 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17724
17725 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17726 auto [AccumLo, AccumHi] = DAG.SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17727
17728 if (!MulLHSUnsigned32) {
17729 auto MulLHSHi =
17730 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulLHS, One);
17731 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSHi, MulRHSLo);
17732 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17733 }
17734
17735 if (!MulRHSUnsigned32) {
17736 auto MulRHSHi =
17737 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulRHS, One);
17738 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSLo, MulRHSHi);
17739 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17740 }
17741
17742 Accum = DAG.getBuildVector(MVT::v2i32, SL, {AccumLo, AccumHi});
17743 Accum = DAG.getBitcast(MVT::i64, Accum);
17744 }
17745
17746 if (VT != MVT::i64)
17747 Accum = DAG.getNode(ISD::TRUNCATE, SL, VT, Accum);
17748 return Accum;
17749}
17750
17751SDValue
17752SITargetLowering::foldAddSub64WithZeroLowBitsTo32(SDNode *N,
17753 DAGCombinerInfo &DCI) const {
17754 SDValue RHS = N->getOperand(1);
17755 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
17756 if (!CRHS)
17757 return SDValue();
17758
17759 // TODO: Worth using computeKnownBits? Maybe expensive since it's so
17760 // common.
17761 uint64_t Val = CRHS->getZExtValue();
17762 if (countr_zero(Val) >= 32) {
17763 SelectionDAG &DAG = DCI.DAG;
17764 SDLoc SL(N);
17765 SDValue LHS = N->getOperand(0);
17766
17767 // Avoid carry machinery if we know the low half of the add does not
17768 // contribute to the final result.
17769 //
17770 // add i64:x, K if computeTrailingZeros(K) >= 32
17771 // => build_pair (add x.hi, K.hi), x.lo
17772
17773 // Breaking the 64-bit add here with this strange constant is unlikely
17774 // to interfere with addressing mode patterns.
17775
17776 SDValue Hi = getHiHalf64(LHS, DAG);
17777 SDValue ConstHi32 = DAG.getConstant(Hi_32(Val), SL, MVT::i32);
17778 unsigned Opcode = N->getOpcode();
17779 if (Opcode == ISD::PTRADD)
17780 Opcode = ISD::ADD;
17781 SDValue AddHi =
17782 DAG.getNode(Opcode, SL, MVT::i32, Hi, ConstHi32, N->getFlags());
17783
17784 SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
17785 return DAG.getNode(ISD::BUILD_PAIR, SL, MVT::i64, Lo, AddHi);
17786 }
17787
17788 return SDValue();
17789}
17790
17791// Collect the ultimate src of each of the mul node's operands, and confirm
17792// each operand is 8 bytes.
17793static std::optional<ByteProvider<SDValue>>
17794handleMulOperand(const SDValue &MulOperand) {
17795 auto Byte0 = calculateByteProvider(MulOperand, 0, 0);
17796 if (!Byte0 || Byte0->isConstantZero()) {
17797 return std::nullopt;
17798 }
17799 auto Byte1 = calculateByteProvider(MulOperand, 1, 0);
17800 if (Byte1 && !Byte1->isConstantZero()) {
17801 return std::nullopt;
17802 }
17803 return Byte0;
17804}
17805
17806static unsigned addPermMasks(unsigned First, unsigned Second) {
17807 unsigned FirstCs = First & 0x0c0c0c0c;
17808 unsigned SecondCs = Second & 0x0c0c0c0c;
17809 unsigned FirstNoCs = First & ~0x0c0c0c0c;
17810 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17811
17812 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17813 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17814 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17815 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17816
17817 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17818}
17819
17820struct DotSrc {
17822 int64_t PermMask;
17824};
17825
17829 SmallVectorImpl<DotSrc> &Src1s, int Step) {
17830
17831 assert(Src0.Src.has_value() && Src1.Src.has_value());
17832 // Src0s and Src1s are empty, just place arbitrarily.
17833 if (Step == 0) {
17834 Src0s.push_back({*Src0.Src, ((Src0.SrcOffset % 4) << 24) + 0x0c0c0c,
17835 Src0.SrcOffset / 4});
17836 Src1s.push_back({*Src1.Src, ((Src1.SrcOffset % 4) << 24) + 0x0c0c0c,
17837 Src1.SrcOffset / 4});
17838 return;
17839 }
17840
17841 for (int BPI = 0; BPI < 2; BPI++) {
17842 std::pair<ByteProvider<SDValue>, ByteProvider<SDValue>> BPP = {Src0, Src1};
17843 if (BPI == 1) {
17844 BPP = {Src1, Src0};
17845 }
17846 unsigned ZeroMask = 0x0c0c0c0c;
17847 unsigned FMask = 0xFF << (8 * (3 - Step));
17848
17849 unsigned FirstMask =
17850 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17851 unsigned SecondMask =
17852 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17853 // Attempt to find Src vector which contains our SDValue, if so, add our
17854 // perm mask to the existing one. If we are unable to find a match for the
17855 // first SDValue, attempt to find match for the second.
17856 int FirstGroup = -1;
17857 for (int I = 0; I < 2; I++) {
17858 SmallVectorImpl<DotSrc> &Srcs = I == 0 ? Src0s : Src1s;
17859 auto MatchesFirst = [&BPP](DotSrc &IterElt) {
17860 return IterElt.SrcOp == *BPP.first.Src &&
17861 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17862 };
17863
17864 auto *Match = llvm::find_if(Srcs, MatchesFirst);
17865 if (Match != Srcs.end()) {
17866 Match->PermMask = addPermMasks(FirstMask, Match->PermMask);
17867 FirstGroup = I;
17868 break;
17869 }
17870 }
17871 if (FirstGroup != -1) {
17872 SmallVectorImpl<DotSrc> &Srcs = FirstGroup == 1 ? Src0s : Src1s;
17873 auto MatchesSecond = [&BPP](DotSrc &IterElt) {
17874 return IterElt.SrcOp == *BPP.second.Src &&
17875 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17876 };
17877 auto *Match = llvm::find_if(Srcs, MatchesSecond);
17878 if (Match != Srcs.end()) {
17879 Match->PermMask = addPermMasks(SecondMask, Match->PermMask);
17880 } else
17881 Srcs.push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17882 return;
17883 }
17884 }
17885
17886 // If we have made it here, then we could not find a match in Src0s or Src1s
17887 // for either Src0 or Src1, so just place them arbitrarily.
17888
17889 unsigned ZeroMask = 0x0c0c0c0c;
17890 unsigned FMask = 0xFF << (8 * (3 - Step));
17891
17892 Src0s.push_back(
17893 {*Src0.Src,
17894 ((Src0.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17895 Src0.SrcOffset / 4});
17896 Src1s.push_back(
17897 {*Src1.Src,
17898 ((Src1.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17899 Src1.SrcOffset / 4});
17900}
17901
17903 SmallVectorImpl<DotSrc> &Srcs, bool IsSigned,
17904 bool IsAny) {
17905
17906 // If we just have one source, just permute it accordingly.
17907 if (Srcs.size() == 1) {
17908 auto *Elt = Srcs.begin();
17909 auto EltOp = getDWordFromOffset(DAG, SL, Elt->SrcOp, Elt->DWordOffset);
17910
17911 // v_perm will produce the original value
17912 if (Elt->PermMask == 0x3020100)
17913 return EltOp;
17914
17915 return DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17916 DAG.getConstant(Elt->PermMask, SL, MVT::i32));
17917 }
17918
17919 auto *FirstElt = Srcs.begin();
17920 auto *SecondElt = std::next(FirstElt);
17921
17923
17924 // If we have multiple sources in the chain, combine them via perms (using
17925 // calculated perm mask) and Ors.
17926 while (true) {
17927 auto FirstMask = FirstElt->PermMask;
17928 auto SecondMask = SecondElt->PermMask;
17929
17930 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17931 unsigned FirstPlusFour = FirstMask | 0x04040404;
17932 // 0x0c + 0x04 = 0x10, so anding with 0x0F will produced 0x00 for any
17933 // original 0x0C.
17934 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17935
17936 auto PermMask = addPermMasks(FirstMask, SecondMask);
17937 auto FirstVal =
17938 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17939 auto SecondVal =
17940 getDWordFromOffset(DAG, SL, SecondElt->SrcOp, SecondElt->DWordOffset);
17941
17942 Perms.push_back(DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, FirstVal,
17943 SecondVal,
17944 DAG.getConstant(PermMask, SL, MVT::i32)));
17945
17946 FirstElt = std::next(SecondElt);
17947 if (FirstElt == Srcs.end())
17948 break;
17949
17950 SecondElt = std::next(FirstElt);
17951 // If we only have a FirstElt, then just combine that into the cumulative
17952 // source node.
17953 if (SecondElt == Srcs.end()) {
17954 auto EltOp =
17955 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17956
17957 Perms.push_back(
17958 DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17959 DAG.getConstant(FirstElt->PermMask, SL, MVT::i32)));
17960 break;
17961 }
17962 }
17963
17964 assert(Perms.size() == 1 || Perms.size() == 2);
17965 return Perms.size() == 2
17966 ? DAG.getNode(ISD::OR, SL, MVT::i32, Perms[0], Perms[1])
17967 : Perms[0];
17968}
17969
17970static void fixMasks(SmallVectorImpl<DotSrc> &Srcs, unsigned ChainLength) {
17971 for (auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17972 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17973 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17974 EntryMask += ZeroMask;
17975 }
17976}
17977
17978static bool isMul(const SDValue Op) {
17979 auto Opcode = Op.getOpcode();
17980
17981 return (Opcode == ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17982 Opcode == AMDGPUISD::MUL_I24);
17983}
17984
17985static std::optional<bool>
17987 ByteProvider<SDValue> &Src1, const SDValue &S0Op,
17988 const SDValue &S1Op, const SelectionDAG &DAG) {
17989 // If we both ops are i8s (pre legalize-dag), then the signedness semantics
17990 // of the dot4 is irrelevant.
17991 if (S0Op.getValueSizeInBits() == 8 && S1Op.getValueSizeInBits() == 8)
17992 return false;
17993
17994 auto Known0 = DAG.computeKnownBits(S0Op, 0);
17995 bool S0IsUnsigned = Known0.countMinLeadingZeros() > 0;
17996 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17997 auto Known1 = DAG.computeKnownBits(S1Op, 0);
17998 bool S1IsUnsigned = Known1.countMinLeadingZeros() > 0;
17999 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
18000
18001 assert(!(S0IsUnsigned && S0IsSigned));
18002 assert(!(S1IsUnsigned && S1IsSigned));
18003
18004 // There are 9 possible permutations of
18005 // {S0IsUnsigned, S0IsSigned, S1IsUnsigned, S1IsSigned}
18006
18007 // In two permutations, the sign bits are known to be the same for both Ops,
18008 // so simply return Signed / Unsigned corresponding to the MSB
18009
18010 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
18011 return S0IsSigned;
18012
18013 // In another two permutations, the sign bits are known to be opposite. In
18014 // this case return std::nullopt to indicate a bad match.
18015
18016 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
18017 return std::nullopt;
18018
18019 // In the remaining five permutations, we don't know the value of the sign
18020 // bit for at least one Op. Since we have a valid ByteProvider, we know that
18021 // the upper bits must be extension bits. Thus, the only ways for the sign
18022 // bit to be unknown is if it was sign extended from unknown value, or if it
18023 // was any extended. In either case, it is correct to use the signed
18024 // version of the signedness semantics of dot4
18025
18026 // In two of such permutations, we known the sign bit is set for
18027 // one op, and the other is unknown. It is okay to used signed version of
18028 // dot4.
18029 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
18030 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
18031 return true;
18032
18033 // In one such permutation, we don't know either of the sign bits. It is okay
18034 // to used the signed version of dot4.
18035 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
18036 return true;
18037
18038 // In two of such permutations, we known the sign bit is unset for
18039 // one op, and the other is unknown. Return std::nullopt to indicate a
18040 // bad match.
18041 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
18042 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
18043 return std::nullopt;
18044
18045 llvm_unreachable("Fully covered condition");
18046}
18047
18048SDValue SITargetLowering::performAddCombine(SDNode *N,
18049 DAGCombinerInfo &DCI) const {
18050 SelectionDAG &DAG = DCI.DAG;
18051 EVT VT = N->getValueType(0);
18052 SDLoc SL(N);
18053 SDValue LHS = N->getOperand(0);
18054 SDValue RHS = N->getOperand(1);
18055
18056 if (LHS.getOpcode() == ISD::MUL || RHS.getOpcode() == ISD::MUL) {
18057 if (Subtarget->hasMad64_32()) {
18058 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
18059 return Folded;
18060 }
18061 }
18062
18063 if (SDValue V = reassociateScalarOps(N, DAG)) {
18064 return V;
18065 }
18066
18067 if (VT == MVT::i64) {
18068 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18069 return Folded;
18070 }
18071
18072 // dot4 produces a 32-bit result, so a wider VT can't be folded.
18073 if (!VT.isVector() && VT.getSizeInBits() <= 32 &&
18074 (isMul(LHS) || isMul(RHS)) && Subtarget->hasDot7Insts() &&
18075 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
18076 SDValue TempNode(N, 0);
18077 std::optional<bool> IsSigned;
18081
18082 // Match the v_dot4 tree, while collecting src nodes.
18083 int ChainLength = 0;
18084 for (int I = 0; I < 4; I++) {
18085 auto MulIdx = isMul(LHS) ? 0 : isMul(RHS) ? 1 : -1;
18086 if (MulIdx == -1)
18087 break;
18088 auto Src0 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(0));
18089 if (!Src0)
18090 break;
18091 auto Src1 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(1));
18092 if (!Src1)
18093 break;
18094
18095 auto IterIsSigned = checkDot4MulSignedness(
18096 TempNode->getOperand(MulIdx), *Src0, *Src1,
18097 TempNode->getOperand(MulIdx)->getOperand(0),
18098 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
18099 if (!IterIsSigned)
18100 break;
18101 if (!IsSigned)
18102 IsSigned = *IterIsSigned;
18103 if (*IterIsSigned != *IsSigned)
18104 break;
18105 placeSources(*Src0, *Src1, Src0s, Src1s, I);
18106 auto AddIdx = 1 - MulIdx;
18107 // Allow the special case where add (add (mul24, 0), mul24) became ->
18108 // add (mul24, mul24).
18109 if (I == 2 && isMul(TempNode->getOperand(AddIdx))) {
18110 Src2s.push_back(TempNode->getOperand(AddIdx));
18111 auto Src0 =
18112 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(0));
18113 if (!Src0)
18114 break;
18115 auto Src1 =
18116 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(1));
18117 if (!Src1)
18118 break;
18119 auto IterIsSigned = checkDot4MulSignedness(
18120 TempNode->getOperand(AddIdx), *Src0, *Src1,
18121 TempNode->getOperand(AddIdx)->getOperand(0),
18122 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
18123 if (!IterIsSigned)
18124 break;
18125 assert(IsSigned);
18126 if (*IterIsSigned != *IsSigned)
18127 break;
18128 placeSources(*Src0, *Src1, Src0s, Src1s, I + 1);
18129 Src2s.push_back(DAG.getConstant(0, SL, MVT::i32));
18130 ChainLength = I + 2;
18131 break;
18132 }
18133
18134 TempNode = TempNode->getOperand(AddIdx);
18135 Src2s.push_back(TempNode);
18136 ChainLength = I + 1;
18137 // The loop body treats TempNode's operands as addends.
18138 if (TempNode.getOpcode() != ISD::ADD)
18139 break;
18140 LHS = TempNode->getOperand(0);
18141 RHS = TempNode->getOperand(1);
18142 }
18143
18144 if (ChainLength < 2)
18145 return SDValue();
18146
18147 // Masks were constructed with assumption that we would find a chain of
18148 // length 4. If not, then we need to 0 out the MSB bits (via perm mask of
18149 // 0x0c) so they do not affect dot calculation.
18150 if (ChainLength < 4) {
18151 fixMasks(Src0s, ChainLength);
18152 fixMasks(Src1s, ChainLength);
18153 }
18154
18155 SDValue Src0, Src1;
18156
18157 // If we are just using a single source for both, and have permuted the
18158 // bytes consistently, we can just use the sources without permuting
18159 // (commutation).
18160 bool UseOriginalSrc = false;
18161 if (ChainLength == 4 && Src0s.size() == 1 && Src1s.size() == 1 &&
18162 Src0s.begin()->PermMask == Src1s.begin()->PermMask &&
18163 Src0s.begin()->SrcOp.getValueSizeInBits() >= 32 &&
18164 Src1s.begin()->SrcOp.getValueSizeInBits() >= 32) {
18165 SmallVector<unsigned, 4> SrcBytes;
18166 auto Src0Mask = Src0s.begin()->PermMask;
18167 SrcBytes.push_back((Src0Mask >> 24) & 0xFF);
18168 bool UniqueEntries = true;
18169 for (auto I = 1; I < 4; I++) {
18170 auto NextByte = (Src0Mask >> ((3 - I) * 8)) & 0xFF;
18171
18172 if (is_contained(SrcBytes, NextByte)) {
18173 UniqueEntries = false;
18174 break;
18175 }
18176 SrcBytes.push_back(NextByte);
18177 }
18178
18179 if (UniqueEntries) {
18180 UseOriginalSrc = true;
18181
18182 auto *FirstElt = Src0s.begin();
18183 auto FirstEltOp =
18184 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
18185
18186 auto *SecondElt = Src1s.begin();
18187 auto SecondEltOp = getDWordFromOffset(DAG, SL, SecondElt->SrcOp,
18188 SecondElt->DWordOffset);
18189
18190 Src0 = DAG.getBitcastedAnyExtOrTrunc(FirstEltOp, SL,
18191 MVT::getIntegerVT(32));
18192 Src1 = DAG.getBitcastedAnyExtOrTrunc(SecondEltOp, SL,
18193 MVT::getIntegerVT(32));
18194 }
18195 }
18196
18197 if (!UseOriginalSrc) {
18198 Src0 = resolveSources(DAG, SL, Src0s, false, true);
18199 Src1 = resolveSources(DAG, SL, Src1s, false, true);
18200 }
18201
18202 assert(IsSigned);
18203 SDValue Src2 =
18204 DAG.getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
18205
18206 SDValue IID = DAG.getTargetConstant(*IsSigned ? Intrinsic::amdgcn_sdot4
18207 : Intrinsic::amdgcn_udot4,
18208 SL, MVT::i64);
18209
18210 assert(!VT.isVector());
18211 auto Dot = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32, IID, Src0,
18212 Src1, Src2, DAG.getTargetConstant(0, SL, MVT::i1));
18213
18214 return DAG.getExtOrTrunc(*IsSigned, Dot, SL, VT);
18215 }
18216
18217 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
18218 return SDValue();
18219
18220 // add x, zext (setcc) => uaddo_carry x, 0, setcc
18221 // add x, sext (setcc) => usubo_carry x, 0, setcc
18222 unsigned Opc = LHS.getOpcode();
18225 std::swap(RHS, LHS);
18226
18227 Opc = RHS.getOpcode();
18228 switch (Opc) {
18229 default:
18230 break;
18231 case ISD::ZERO_EXTEND:
18232 case ISD::SIGN_EXTEND:
18233 case ISD::ANY_EXTEND: {
18234 auto Cond = RHS.getOperand(0);
18235 // If this won't be a real VOPC output, we would still need to insert an
18236 // extra instruction anyway.
18237 if (!isBoolSGPR(Cond))
18238 break;
18239 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
18240 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
18242 return DAG.getNode(Opc, SL, VTList, Args);
18243 }
18244 case ISD::UADDO_CARRY: {
18245 // add x, (uaddo_carry y, 0, cc) => uaddo_carry x, y, cc
18246 if (!isNullConstant(RHS.getOperand(1)))
18247 break;
18248 SDValue Args[] = {LHS, RHS.getOperand(0), RHS.getOperand(2)};
18249 return DAG.getNode(ISD::UADDO_CARRY, SDLoc(N), RHS->getVTList(), Args);
18250 }
18251 }
18252 return SDValue();
18253}
18254
18255SDValue SITargetLowering::performPtrAddCombine(SDNode *N,
18256 DAGCombinerInfo &DCI) const {
18257 SelectionDAG &DAG = DCI.DAG;
18258 SDLoc DL(N);
18259 EVT VT = N->getValueType(0);
18260 SDValue N0 = N->getOperand(0);
18261 SDValue N1 = N->getOperand(1);
18262
18263 // The following folds transform PTRADDs into regular arithmetic in cases
18264 // where the PTRADD wouldn't be folded as an immediate offset into memory
18265 // instructions anyway. They are target-specific in that other targets might
18266 // prefer to not lose information about the pointer arithmetic.
18267
18268 // Fold (ptradd x, shl(0 - v, k)) -> sub(x, shl(v, k)).
18269 // Adapted from DAGCombiner::visitADDLikeCommutative.
18270 SDValue V, K;
18271 if (sd_match(N1, m_Shl(m_Neg(m_Value(V)), m_Value(K)))) {
18272 SDNodeFlags ShlFlags = N1->getFlags();
18273 // If the original shl is NUW and NSW, the first k+1 bits of 0-v are all 0,
18274 // so v is either 0 or the first k+1 bits of v are all 1 -> NSW can be
18275 // preserved.
18276 SDNodeFlags NewShlFlags =
18277 ShlFlags.hasNoUnsignedWrap() && ShlFlags.hasNoSignedWrap()
18279 : SDNodeFlags();
18280 SDValue Inner = DAG.getNode(ISD::SHL, DL, VT, V, K, NewShlFlags);
18281 DCI.AddToWorklist(Inner.getNode());
18282 return DAG.getNode(ISD::SUB, DL, VT, N0, Inner);
18283 }
18284
18285 // Fold into Mad64 if the right-hand side is a MUL. Analogous to a fold in
18286 // performAddCombine.
18287 if (N1.getOpcode() == ISD::MUL) {
18288 if (Subtarget->hasMad64_32()) {
18289 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
18290 return Folded;
18291 }
18292 }
18293
18294 // If the 32 low bits of the constant are all zero, there is nothing to fold
18295 // into an immediate offset, so it's better to eliminate the unnecessary
18296 // addition for the lower 32 bits than to preserve the PTRADD.
18297 // Analogous to a fold in performAddCombine.
18298 if (VT == MVT::i64) {
18299 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18300 return Folded;
18301 }
18302
18303 if (N1.getOpcode() != ISD::ADD || !N1.hasOneUse())
18304 return SDValue();
18305
18306 SDValue X = N0;
18307 SDValue Y = N1.getOperand(0);
18308 SDValue Z = N1.getOperand(1);
18309 bool YIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Y);
18310 bool ZIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Z);
18311
18312 if (!YIsConstant && !ZIsConstant && !X->isDivergent() &&
18313 Y->isDivergent() != Z->isDivergent()) {
18314 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, y), z) if x and
18315 // y are uniform and z isn't.
18316 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, z), y) if x and
18317 // z are uniform and y isn't.
18318 // The goal is to push uniform operands up in the computation, so that they
18319 // can be handled with scalar operations. We can't use reassociateScalarOps
18320 // for this since it requires two identical commutative operations to
18321 // reassociate.
18322 if (Y->isDivergent())
18323 std::swap(Y, Z);
18324 // If both additions in the original were NUW, reassociation preserves that.
18325 SDNodeFlags ReassocFlags =
18326 (N->getFlags() & N1->getFlags()) & SDNodeFlags::NoUnsignedWrap;
18327 SDValue UniformInner = DAG.getMemBasePlusOffset(X, Y, DL, ReassocFlags);
18328 DCI.AddToWorklist(UniformInner.getNode());
18329 return DAG.getMemBasePlusOffset(UniformInner, Z, DL, ReassocFlags);
18330 }
18331
18332 return SDValue();
18333}
18334
18335static bool isCtlzOpc(unsigned Opc) {
18336 return Opc == ISD::CTLZ || Opc == ISD::CTLZ_ZERO_POISON;
18337}
18338
18339SDValue SITargetLowering::performSubCombine(SDNode *N,
18340 DAGCombinerInfo &DCI) const {
18341 SelectionDAG &DAG = DCI.DAG;
18342 EVT VT = N->getValueType(0);
18343
18344 if (VT == MVT::i64) {
18345 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18346 return Folded;
18347 }
18348
18349 if (VT != MVT::i32)
18350 return SDValue();
18351
18352 SDLoc SL(N);
18353 SDValue LHS = N->getOperand(0);
18354 SDValue RHS = N->getOperand(1);
18355
18356 // sub x, zext (setcc) => usubo_carry x, 0, setcc
18357 // sub x, sext (setcc) => uaddo_carry x, 0, setcc
18358 unsigned Opc = RHS.getOpcode();
18359 switch (Opc) {
18360 default:
18361 break;
18362 case ISD::ZERO_EXTEND:
18363 case ISD::SIGN_EXTEND:
18364 case ISD::ANY_EXTEND: {
18365 auto Cond = RHS.getOperand(0);
18366 // If this won't be a real VOPC output, we would still need to insert an
18367 // extra instruction anyway.
18368 if (!isBoolSGPR(Cond))
18369 break;
18370 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
18371 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
18373 return DAG.getNode(Opc, SL, VTList, Args);
18374 }
18375 }
18376
18377 if (LHS.getOpcode() == ISD::USUBO_CARRY) {
18378 // sub (usubo_carry x, 0, cc), y => usubo_carry x, y, cc
18379 if (!isNullConstant(LHS.getOperand(1)))
18380 return SDValue();
18381 SDValue Args[] = {LHS.getOperand(0), RHS, LHS.getOperand(2)};
18382 return DAG.getNode(ISD::USUBO_CARRY, SDLoc(N), LHS->getVTList(), Args);
18383 }
18384
18385 // sub (ctlz (xor x, (sra x, 31))), 1 -> ctls x.
18386 if (isOneConstant(RHS) && isCtlzOpc(LHS.getOpcode())) {
18387 SDValue CtlzSrc = LHS.getOperand(0);
18388 // Check for xor x, (sra x, 31) pattern.
18389 if (CtlzSrc.getOpcode() == ISD::XOR) {
18390 SDValue X = CtlzSrc.getOperand(0);
18391 SDValue SignExt = CtlzSrc.getOperand(1);
18392 // Try both ordering of XOR operands.
18393 if (SignExt.getOpcode() != ISD::SRA)
18394 std::swap(X, SignExt);
18395 if (SignExt.getOpcode() == ISD::SRA && SignExt.getOperand(0) == X) {
18396 ConstantSDNode *ShiftAmt =
18398 unsigned BitWidth = X.getValueType().getScalarSizeInBits();
18399 if (ShiftAmt && ShiftAmt->getZExtValue() == BitWidth - 1)
18400 return DAG.getNode(ISD::CTLS, SL, VT, X);
18401 }
18402 }
18403 }
18404
18405 return SDValue();
18406}
18407
18408SDValue SITargetLowering::performFAddCombine(SDNode *N,
18409 DAGCombinerInfo &DCI) const {
18410 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18411 return SDValue();
18412
18413 SelectionDAG &DAG = DCI.DAG;
18414 EVT VT = N->getValueType(0);
18415
18416 SDLoc SL(N);
18417 SDValue LHS = N->getOperand(0);
18418 SDValue RHS = N->getOperand(1);
18419
18420 // These should really be instruction patterns, but writing patterns with
18421 // source modifiers is a pain.
18422
18423 // fadd (fadd (a, a), b) -> mad 2.0, a, b
18424 if (LHS.getOpcode() == ISD::FADD) {
18425 SDValue A = LHS.getOperand(0);
18426 if (A == LHS.getOperand(1)) {
18427 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18428 if (FusedOp != 0) {
18429 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18430 return DAG.getNode(FusedOp, SL, VT, A, Two, RHS);
18431 }
18432 }
18433 }
18434
18435 // fadd (b, fadd (a, a)) -> mad 2.0, a, b
18436 if (RHS.getOpcode() == ISD::FADD) {
18437 SDValue A = RHS.getOperand(0);
18438 if (A == RHS.getOperand(1)) {
18439 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18440 if (FusedOp != 0) {
18441 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18442 return DAG.getNode(FusedOp, SL, VT, A, Two, LHS);
18443 }
18444 }
18445 }
18446
18447 return SDValue();
18448}
18449
18450SDValue SITargetLowering::performFSubCombine(SDNode *N,
18451 DAGCombinerInfo &DCI) const {
18452 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18453 return SDValue();
18454
18455 SelectionDAG &DAG = DCI.DAG;
18456 SDLoc SL(N);
18457 EVT VT = N->getValueType(0);
18458 assert(!VT.isVector());
18459
18460 // Try to get the fneg to fold into the source modifier. This undoes generic
18461 // DAG combines and folds them into the mad.
18462 //
18463 // Only do this if we are not trying to support denormals. v_mad_f32 does
18464 // not support denormals ever.
18465 SDValue LHS = N->getOperand(0);
18466 SDValue RHS = N->getOperand(1);
18467 if (LHS.getOpcode() == ISD::FADD) {
18468 // (fsub (fadd a, a), c) -> mad 2.0, a, (fneg c)
18469 SDValue A = LHS.getOperand(0);
18470 if (A == LHS.getOperand(1)) {
18471 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18472 if (FusedOp != 0) {
18473 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18474 SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
18475
18476 return DAG.getNode(FusedOp, SL, VT, A, Two, NegRHS);
18477 }
18478 }
18479 }
18480
18481 if (RHS.getOpcode() == ISD::FADD) {
18482 // (fsub c, (fadd a, a)) -> mad -2.0, a, c
18483
18484 SDValue A = RHS.getOperand(0);
18485 if (A == RHS.getOperand(1)) {
18486 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18487 if (FusedOp != 0) {
18488 const SDValue NegTwo = DAG.getConstantFP(-2.0, SL, VT);
18489 return DAG.getNode(FusedOp, SL, VT, A, NegTwo, LHS);
18490 }
18491 }
18492 }
18493
18494 return SDValue();
18495}
18496
18497SDValue SITargetLowering::performFDivCombine(SDNode *N,
18498 DAGCombinerInfo &DCI) const {
18499 SelectionDAG &DAG = DCI.DAG;
18500 SDLoc SL(N);
18501 EVT VT = N->getValueType(0);
18502
18503 if (VT != MVT::f16 && VT != MVT::bf16)
18504 return SDValue();
18505
18506 SDValue LHS = N->getOperand(0);
18507 SDValue RHS = N->getOperand(1);
18508
18509 SDNodeFlags Flags = N->getFlags();
18510 SDNodeFlags RHSFlags = RHS->getFlags();
18511 if (!Flags.hasAllowContract() || !RHSFlags.hasAllowContract() ||
18512 !RHS->hasOneUse())
18513 return SDValue();
18514
18515 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
18516 bool IsNegative = false;
18517 if (CLHS->isOne() || (IsNegative = CLHS->isMinusOne())) {
18518 // fdiv contract 1.0, (sqrt contract x) -> rsq
18519 // fdiv contract -1.0, (sqrt contract x) -> fneg(rsq)
18520 if (RHS.getOpcode() == ISD::FSQRT) {
18521 // TODO: Or in RHS flags, somehow missing from SDNodeFlags
18522 SDValue SqrtOp = RHS.getOperand(0);
18523 SDValue Rsq;
18524 if (isOperationLegal(ISD::FSQRT, VT)) {
18525 // fsqrt legality correlates to rsq availability of the same type.
18526 Rsq = DAG.getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18527 } else if (VT == MVT::f16) {
18528 // Targets without 16-bit instructions (gfx6/gfx7) have no f16 rsq,
18529 // but v_rsq_f32 is more than accurate enough for f16. Unlike bf16,
18530 // every f16 value (including denormals) extends to a normal f32, and
18531 // an f16 rsq result is never denormal, so the f32 reciprocal square
18532 // root needs no denormal handling. Compute it in f32 and round back.
18533 SDValue Ext =
18534 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, SqrtOp, Flags);
18535 SDValue F32Rsq =
18536 DAG.getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18537 Rsq = DAG.getNode(ISD::FP_ROUND, SL, VT, F32Rsq,
18538 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
18539 } else {
18540 // bf16 shares f32's exponent range, so bf16 denormals would extend to
18541 // f32 denormals that v_rsq_f32 does not handle. Leave it expanded.
18542 return SDValue();
18543 }
18544 return IsNegative ? DAG.getNode(ISD::FNEG, SL, VT, Rsq, Flags) : Rsq;
18545 }
18546 }
18547 }
18548
18549 return SDValue();
18550}
18551
18552SDValue SITargetLowering::performFMulCombine(SDNode *N,
18553 DAGCombinerInfo &DCI) const {
18554 SelectionDAG &DAG = DCI.DAG;
18555 EVT VT = N->getValueType(0);
18556 EVT ScalarVT = VT.getScalarType();
18557 EVT IntVT = VT.changeElementType(*DAG.getContext(), MVT::i32);
18558
18559 if (!N->isDivergent() && getSubtarget()->hasSALUFloatInsts() &&
18560 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18561 // Prefer to use s_mul_f16/f32 instead of v_ldexp_f16/f32.
18562 return SDValue();
18563 }
18564
18565 SDValue LHS = N->getOperand(0);
18566 SDValue RHS = N->getOperand(1);
18567
18568 // It is cheaper to realize i32 inline constants as compared against
18569 // materializing f16 or f64 (or even non-inline f32) values,
18570 // possible via ldexp usage, as shown below :
18571 //
18572 // Given : A = 2^a & B = 2^b ; where a and b are integers.
18573 // fmul x, (select y, A, B) -> ldexp( x, (select i32 y, a, b) )
18574 // fmul x, (select y, -A, -B) -> ldexp( (fneg x), (select i32 y, a, b) )
18575 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18576 (RHS.hasOneUse() && RHS.getOpcode() == ISD::SELECT)) {
18577 const ConstantFPSDNode *TrueNode = isConstOrConstSplatFP(RHS.getOperand(1));
18578 if (!TrueNode)
18579 return SDValue();
18580 const ConstantFPSDNode *FalseNode =
18581 isConstOrConstSplatFP(RHS.getOperand(2));
18582 if (!FalseNode)
18583 return SDValue();
18584
18585 if (TrueNode->isNegative() != FalseNode->isNegative())
18586 return SDValue();
18587
18588 // For f32, only non-inline constants should be transformed.
18589 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
18590 if (ScalarVT == MVT::f32 &&
18591 TII->isInlineConstant(TrueNode->getValueAPF()) &&
18592 TII->isInlineConstant(FalseNode->getValueAPF()))
18593 return SDValue();
18594
18595 int TrueNodeExpVal = TrueNode->getValueAPF().getExactLog2Abs();
18596 if (TrueNodeExpVal == INT_MIN)
18597 return SDValue();
18598 int FalseNodeExpVal = FalseNode->getValueAPF().getExactLog2Abs();
18599 if (FalseNodeExpVal == INT_MIN)
18600 return SDValue();
18601
18602 SDLoc SL(N);
18603 SDValue SelectNode =
18604 DAG.getNode(ISD::SELECT, SL, IntVT, RHS.getOperand(0),
18605 DAG.getSignedConstant(TrueNodeExpVal, SL, IntVT),
18606 DAG.getSignedConstant(FalseNodeExpVal, SL, IntVT));
18607
18608 LHS = TrueNode->isNegative()
18609 ? DAG.getNode(ISD::FNEG, SL, VT, LHS, LHS->getFlags())
18610 : LHS;
18611
18612 return DAG.getNode(ISD::FLDEXP, SL, VT, LHS, SelectNode, N->getFlags());
18613 }
18614
18615 return SDValue();
18616}
18617
18618SDValue SITargetLowering::performFMACombine(SDNode *N,
18619 DAGCombinerInfo &DCI) const {
18620 SelectionDAG &DAG = DCI.DAG;
18621 EVT VT = N->getValueType(0);
18622 SDLoc SL(N);
18623
18624 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18625 return SDValue();
18626
18627 // FMA((F32)S0.x, (F32)S1. x, FMA((F32)S0.y, (F32)S1.y, (F32)z)) ->
18628 // FDOT2((V2F16)S0, (V2F16)S1, (F32)z))
18629 SDValue Op1 = N->getOperand(0);
18630 SDValue Op2 = N->getOperand(1);
18631 SDValue FMA = N->getOperand(2);
18632
18633 if (FMA.getOpcode() != ISD::FMA || Op1.getOpcode() != ISD::FP_EXTEND ||
18634 Op2.getOpcode() != ISD::FP_EXTEND)
18635 return SDValue();
18636
18637 // The fdot2 fold (fma_mix -> dot2) is only safe when both instructions agree
18638 // on how f16 subnormal inputs are handled. However, if both FMAs carry afn
18639 // the caller accepts approximate results, so any subnormal flushing
18640 // introduced by dot2 is acceptable regardless of mode.
18641 //
18642 // gfx90a (CDNA2) is the sole exception (dot2UnconditionalFlush): v_dot2c
18643 // unconditionally flushes f16 subnormal inputs to zero regardless of MODE,
18644 // while v_fma_mix_f32 preserves them when ieee=1 (the default compute kernel
18645 // mode). The fold is safe only when f32 denorm = PreserveSign, which implies
18646 // ieee=0 so both flush.
18647 //
18648 // All other GPUs: v_dot2 does NOT flush f16 subnormal inputs. v_fma_mix_f32
18649 // flushes them only when f32 denorm = PreserveSign. The fold is safe only
18650 // when f32 denorm is IEEE (both preserve the subnormal). Dynamic mode is
18651 // also rejected since the runtime value is unknown.
18652 bool AllowInaccuracy = N->getFlags().hasApproximateFuncs() &&
18653 FMA->getFlags().hasApproximateFuncs();
18654 if (!AllowInaccuracy) {
18655 const MachineFunction &MF = DAG.getMachineFunction();
18656 DenormalMode Mode = MF.getDenormalMode(APFloat::IEEEsingle());
18657 if (Subtarget->dot2UnconditionalFlush()) {
18658 // gfx90a: fold safe only when f32 denorm flushes.
18660 return SDValue();
18661 } else {
18662 // All other GPUs: fold safe only when f32 denorm is IEEE.
18663 if (Mode != DenormalMode::getIEEE())
18664 return SDValue();
18665 }
18666 }
18667
18668 // fp-contract allows reassociating the fma tree into a dot product.
18669 if (N->getFlags().hasAllowContract() && FMA->getFlags().hasAllowContract()) {
18670 Op1 = Op1.getOperand(0);
18671 Op2 = Op2.getOperand(0);
18672 if (Op1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18674 return SDValue();
18675
18676 SDValue Vec1 = Op1.getOperand(0);
18677 SDValue Idx1 = Op1.getOperand(1);
18678 SDValue Vec2 = Op2.getOperand(0);
18679
18680 SDValue FMAOp1 = FMA.getOperand(0);
18681 SDValue FMAOp2 = FMA.getOperand(1);
18682 SDValue FMAAcc = FMA.getOperand(2);
18683
18684 if (FMAOp1.getOpcode() != ISD::FP_EXTEND ||
18685 FMAOp2.getOpcode() != ISD::FP_EXTEND)
18686 return SDValue();
18687
18688 FMAOp1 = FMAOp1.getOperand(0);
18689 FMAOp2 = FMAOp2.getOperand(0);
18690 if (FMAOp1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18692 return SDValue();
18693
18694 SDValue Vec3 = FMAOp1.getOperand(0);
18695 SDValue Vec4 = FMAOp2.getOperand(0);
18696 SDValue Idx2 = FMAOp1.getOperand(1);
18697
18698 if (Idx1 != Op2.getOperand(1) || Idx2 != FMAOp2.getOperand(1))
18699 return SDValue();
18700
18701 if (!isa<ConstantSDNode>(Idx1) || !isa<ConstantSDNode>(Idx2) ||
18702 Idx1 == Idx2)
18703 return SDValue();
18704
18705 if (Vec1 == Vec2 || Vec3 == Vec4)
18706 return SDValue();
18707
18708 if (Vec1.getValueType() != MVT::v2f16 || Vec2.getValueType() != MVT::v2f16)
18709 return SDValue();
18710
18711 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18712 return DAG.getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18713 DAG.getTargetConstant(0, SL, MVT::i1));
18714 }
18715 }
18716 return SDValue();
18717}
18718
18719// Given a double-precision ordered or unordered comparison, return the
18720// condition code for an equivalent integral comparison of the operands' upper
18721// 32 bits, or `SETCC_INVALID` if not possible.
18722// For simplicity, no simplification occurs if the operands are not both known
18723// to have sign bit zero.
18724//
18725// EQ/NE:
18726// If LHS.lo32 == RHS.lo32:
18727// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18728// If LHS.lo32 != RHS.lo32:
18729// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18730// The reduction is not possible if operands may be +0 and -0.
18731// For ordered eq / unordered ne, at most one operand may be NaN.
18732// For unordered eq / ordered ne, neither operand can be NaN.
18733//
18734// LT/GE:
18735// If LHS.lo32 >= RHS.lo32 (unsigned):
18736// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18737// If LHS.lo32 < RHS.lo32 (unsigned):
18738// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18739// The reduction is only supported if both operands are nonnegative.
18740// For ordered lt / unordered ge, the RHS cannot be NaN.
18741// For unordered lt / ordered ge, neither operand can be NaN.
18742//
18743// LE/GT:
18744// If LHS.lo32 > RHS.lo32 (unsigned):
18745// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18746// If LHS.lo32 <= RHS.lo32 (unsigned):
18747// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18748// The reduction is only supported if both operands are nonnegative.
18749// For unordered le / ordered gt, the LHS cannot be NaN.
18750// For ordered le / unordered gt, neither operand can be NaN.
18752 const SDValue LHS,
18753 const SDValue RHS,
18754 const SelectionDAG &DAG) {
18755 EVT VT = LHS.getValueType();
18756 assert(VT == MVT::f64 && "Incorrect operand type!");
18757
18758 const KnownBits RHSBits = DAG.computeKnownBits(RHS);
18759 // Bail if RHS sign bit is not known to be zero.
18760 if (!RHSBits.Zero.isSignBitSet())
18761 return ISD::SETCC_INVALID;
18762
18763 const KnownBits RHSKnownLo32 = RHSBits.trunc(32);
18764 const KnownFPClass RHSFPClass =
18766 const bool RHSMaybeNaN = !RHSFPClass.isKnownNeverNaN();
18767
18768 const KnownBits LHSBits = DAG.computeKnownBits(LHS);
18769 const KnownBits LHSKnownLo32 = LHSBits.trunc(32);
18770 const KnownFPClass LHSFPClass =
18772 const bool LHSMaybeNaN = !LHSFPClass.isKnownNeverNaN();
18773
18774 // Bail if LHS sign bit is not known to be zero.
18775 if (!LHSBits.Zero.isSignBitSet())
18776 return ISD::SETCC_INVALID;
18777
18778 switch (CC) {
18779 default:
18780 break;
18781 case ISD::SETEQ:
18782 case ISD::SETOEQ:
18783 case ISD::SETUEQ:
18784 case ISD::SETONE:
18785 case ISD::SETUNE: {
18786 // OEQ should be false if either operand is NaN, so it suffices that at
18787 // least one operand is not NaN.
18788 if (CC == ISD::SETOEQ && LHSMaybeNaN && RHSMaybeNaN)
18789 break;
18790 // UEQ should be true if either operand is NaN, but this cannot be checked
18791 // on underlying bits.
18792 if (CC == ISD::SETUEQ && (LHSMaybeNaN || RHSMaybeNaN))
18793 break;
18794 // ONE should be false if either operand is NaN, but this cannot be
18795 // checked on underlying bits.
18796 if (CC == ISD::SETONE && (LHSMaybeNaN || RHSMaybeNaN))
18797 break;
18798 // UNE should be true if either operand is NaN, so it suffices that they
18799 // are not both NaN.
18800 if (CC == ISD::SETUNE && LHSMaybeNaN && RHSMaybeNaN)
18801 break;
18802
18803 const std::optional<bool> KnownEq =
18804 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18805
18806 if (!KnownEq)
18807 break;
18808
18809 if (*KnownEq)
18810 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18811 ? ISD::SETEQ
18812 : ISD::SETNE;
18813
18814 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18816 : ISD::SETTRUE;
18817 }
18818 case ISD::SETLT:
18819 case ISD::SETOLT:
18820 case ISD::SETULT:
18821 case ISD::SETGE:
18822 case ISD::SETOGE:
18823 case ISD::SETUGE: {
18824 // OLT should be false if either operand is NaN.
18825 // Since NaNs have maximum exponent and nonzero mantissa, false positives
18826 // are only possible if the RHS is NaN. (No issue with RHS == +inf since
18827 // the inequality is strict)
18828 if (CC == ISD::SETOLT && RHSMaybeNaN)
18829 break;
18830 // ULT should be true if either operand is NaN, but this cannot be ensured
18831 // with a truncated comparison.
18832 if (CC == ISD::SETULT && (LHSMaybeNaN || RHSMaybeNaN))
18833 break;
18834 // OGE should be false if either operand is NaN, but this cannot be
18835 // ensured with a truncated comparison.
18836 if (CC == ISD::SETOGE && (LHSMaybeNaN || RHSMaybeNaN))
18837 break;
18838 // UGE should be true if either operand is NaN.
18839 // False negatives are only possible if the RHS is NaN.
18840 // (No issue with RHS == +inf since the inequality is inclusive)
18841 if (CC == ISD::SETUGE && RHSMaybeNaN)
18842 break;
18843
18844 const std::optional<bool> KnownUge =
18845 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
18846
18847 if (!KnownUge)
18848 break;
18849
18850 if (*KnownUge) {
18851 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
18852 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18853 ? ISD::SETLT
18854 : ISD::SETGE;
18855 }
18856 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
18857 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18858 ? ISD::SETLE
18859 : ISD::SETGT;
18860 }
18861 case ISD::SETLE:
18862 case ISD::SETOLE:
18863 case ISD::SETULE:
18864 case ISD::SETGT:
18865 case ISD::SETOGT:
18866 case ISD::SETUGT: {
18867 // OLE should be false if either operand is NaN, but this cannot be
18868 // ensured with a truncated comparison.
18869 if (CC == ISD::SETOLE && (LHSMaybeNaN || RHSMaybeNaN))
18870 break;
18871 // ULE should be true if either operand is NaN.
18872 // False negatives are only possible if the LHS is NaN.
18873 // (No issue with LHS == +inf since the inequality is inclusive)
18874 if (CC == ISD::SETULE && LHSMaybeNaN)
18875 break;
18876 // OGT should be false if either operand is NaN.
18877 // False positives are only possible if the LHS is NaN.
18878 // (No issue with LHS == +inf since the inequality is strict)
18879 if (CC == ISD::SETOGT && LHSMaybeNaN)
18880 break;
18881 // UGT should be true if either operand is NaN, but this cannot be ensured
18882 // with a truncated comparison.
18883 if (CC == ISD::SETUGT && (LHSMaybeNaN || RHSMaybeNaN))
18884 break;
18885
18886 const std::optional<bool> KnownUle =
18887 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
18888
18889 if (!KnownUle)
18890 break;
18891
18892 if (*KnownUle) {
18893 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
18894 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18895 ? ISD::SETLE
18896 : ISD::SETGT;
18897 }
18898 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
18899 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18900 ? ISD::SETLT
18901 : ISD::SETGE;
18902 }
18903 }
18904
18905 return ISD::SETCC_INVALID;
18906}
18907
18908SDValue SITargetLowering::performSetCCCombine(SDNode *N,
18909 DAGCombinerInfo &DCI) const {
18910 SelectionDAG &DAG = DCI.DAG;
18911 SDLoc SL(N);
18912
18913 SDValue LHS = N->getOperand(0);
18914 SDValue RHS = N->getOperand(1);
18915 EVT VT = LHS.getValueType();
18916 ISD::CondCode CC = N->getOperandCondCode(2);
18917
18918 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
18919 if (!CRHS) {
18921 if (CRHS) {
18922 std::swap(LHS, RHS);
18924 }
18925 }
18926
18927 if (CRHS) {
18928 if (VT == MVT::i32 && LHS.getOpcode() == ISD::SIGN_EXTEND &&
18929 isBoolSGPR(LHS.getOperand(0))) {
18930 // setcc (sext from i1 cc), -1, ne|sgt|ult) => not cc => xor cc, -1
18931 // setcc (sext from i1 cc), -1, eq|sle|uge) => cc
18932 // setcc (sext from i1 cc), 0, eq|sge|ule) => not cc => xor cc, -1
18933 // setcc (sext from i1 cc), 0, ne|ugt|slt) => cc
18934 if ((CRHS->isAllOnes() &&
18935 (CC == ISD::SETNE || CC == ISD::SETGT || CC == ISD::SETULT)) ||
18936 (CRHS->isZero() &&
18937 (CC == ISD::SETEQ || CC == ISD::SETGE || CC == ISD::SETULE)))
18938 return DAG.getNode(ISD::XOR, SL, MVT::i1, LHS.getOperand(0),
18939 DAG.getAllOnesConstant(SL, MVT::i1));
18940 if ((CRHS->isAllOnes() &&
18941 (CC == ISD::SETEQ || CC == ISD::SETLE || CC == ISD::SETUGE)) ||
18942 (CRHS->isZero() &&
18943 (CC == ISD::SETNE || CC == ISD::SETUGT || CC == ISD::SETLT)))
18944 return LHS.getOperand(0);
18945 }
18946
18947 const APInt &CRHSVal = CRHS->getAPIntValue();
18948 if ((CC == ISD::SETEQ || CC == ISD::SETNE) &&
18949 LHS.getOpcode() == ISD::SELECT &&
18950 isa<ConstantSDNode>(LHS.getOperand(1)) &&
18951 isa<ConstantSDNode>(LHS.getOperand(2)) &&
18952 isBoolSGPR(LHS.getOperand(0))) {
18953 // Given CT != FT:
18954 // setcc (select cc, CT, CF), CF, eq => xor cc, -1
18955 // setcc (select cc, CT, CF), CF, ne => cc
18956 // setcc (select cc, CT, CF), CT, ne => xor cc, -1
18957 // setcc (select cc, CT, CF), CT, eq => cc
18958 const APInt &CT = LHS.getConstantOperandAPInt(1);
18959 const APInt &CF = LHS.getConstantOperandAPInt(2);
18960
18961 if (CT != CF) {
18962 if ((CF == CRHSVal && CC == ISD::SETEQ) ||
18963 (CT == CRHSVal && CC == ISD::SETNE))
18964 return DAG.getNOT(SL, LHS.getOperand(0), MVT::i1);
18965 if ((CF == CRHSVal && CC == ISD::SETNE) ||
18966 (CT == CRHSVal && CC == ISD::SETEQ))
18967 return LHS.getOperand(0);
18968 }
18969 }
18970 }
18971
18972 // Truncate 64-bit setcc to only test upper or lower 32-bits.
18973 if (VT == MVT::i64) {
18974 const KnownBits LHSKnown = DAG.computeKnownBits(LHS);
18975 const KnownBits RHSKnown = DAG.computeKnownBits(RHS);
18976 const KnownBits LHSKnownLo32 = LHSKnown.trunc(32);
18977 const KnownBits RHSKnownLo32 = RHSKnown.trunc(32);
18978 // Truncate 64-bit setcc to test only upper 32-bits of its operands in the
18979 // following cases where information about the lower 32-bits of its operands
18980 // is known:
18981 //
18982 // If LHS.lo32 == RHS.lo32:
18983 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18984 // If LHS.lo32 != RHS.lo32:
18985 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18986 // If LHS.lo32 >= RHS.lo32 (unsigned):
18987 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18988 // If LHS.lo32 > RHS.lo32 (unsigned):
18989 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18990 // If LHS.lo32 <= RHS.lo32 (unsigned):
18991 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18992 // If LHS.lo32 < RHS.lo32 (unsigned):
18993 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18994
18995 // NewCC is valid iff we can truncate the setcc to only test the upper 32
18996 // bits
18998
18999 switch (CC) {
19000 default:
19001 llvm_unreachable("Unexpected condition code for integer setcc");
19002 break;
19003 case ISD::SETEQ: {
19004 const std::optional<bool> KnownEq =
19005 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
19006 if (KnownEq)
19007 NewCC = *KnownEq ? ISD::SETEQ : ISD::SETFALSE;
19008
19009 break;
19010 }
19011 case ISD::SETNE: {
19012 const std::optional<bool> KnownEq =
19013 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
19014 if (KnownEq)
19015 NewCC = *KnownEq ? ISD::SETNE : ISD::SETTRUE;
19016
19017 break;
19018 }
19019 case ISD::SETULT:
19020 case ISD::SETUGE:
19021 case ISD::SETLT:
19022 case ISD::SETGE: {
19023 const std::optional<bool> KnownUge =
19024 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
19025 if (KnownUge) {
19026 if (*KnownUge) {
19027 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
19028 NewCC = CC;
19029 } else {
19030 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
19031 NewCC = CC == ISD::SETULT ? ISD::SETULE
19033 : CC == ISD::SETLT ? ISD::SETLE
19034 : ISD::SETGT;
19035 }
19036 }
19037 break;
19038 }
19039 case ISD::SETULE:
19040 case ISD::SETUGT:
19041 case ISD::SETLE:
19042 case ISD::SETGT: {
19043 const std::optional<bool> KnownUle =
19044 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
19045 if (KnownUle) {
19046 if (*KnownUle) {
19047 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
19048 NewCC = CC;
19049 } else {
19050 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
19051 NewCC = CC == ISD::SETULE ? ISD::SETULT
19053 : CC == ISD::SETLE ? ISD::SETLT
19054 : ISD::SETGE;
19055 }
19056 }
19057 break;
19058 }
19059 }
19060
19061 if (NewCC != ISD::SETCC_INVALID)
19062 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
19063 getHiHalf64(RHS, DAG), NewCC);
19064
19065 // Truncate 64-bit setcc to test only lower 32-bits when upper 32-bits are
19066 // known equal.
19067 const KnownBits LHSKnownHi32 = LHSKnown.extractBits(32, 32);
19068 const KnownBits RHSKnownHi32 = RHSKnown.extractBits(32, 32);
19069 const std::optional<bool> KnownEq =
19070 KnownBits::eq(LHSKnownHi32, RHSKnownHi32);
19071
19072 if (KnownEq == true) {
19073 // For signed comparisons, convert to unsigned since upper halves match
19075
19076 SDValue LHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
19077 SDValue RHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, RHS);
19078 return DAG.getSetCC(SL, N->getValueType(0), LHSLo, RHSLo, NewCC);
19079 }
19080 }
19081
19082 // Eliminate setcc by using carryout from add/sub instruction
19083
19084 // LHS = ADD i64 RHS, Z LHSlo = UADDO i32 RHSlo, Zlo
19085 // setcc LHS ult RHS -> LHSHi = UADDO_CARRY i32 RHShi, Zhi
19086 // similarly for subtraction
19087
19088 // LHS = ADD i64 Y, 1 LHSlo = UADDO i32 Ylo, 1
19089 // setcc LHS eq 0 -> LHSHi = UADDO_CARRY i32 Yhi, 0
19090
19091 if (VT == MVT::i64 && ((CC == ISD::SETULT &&
19093 (CC == ISD::SETUGT &&
19095 (CC == ISD::SETEQ && CRHS && CRHS->isZero() &&
19096 sd_match(LHS, m_Add(m_Value(), m_One()))))) {
19097 bool IsAdd = LHS.getOpcode() == ISD::ADD;
19098
19099 SDValue Op0 = LHS.getOperand(0);
19100 SDValue Op1 = LHS.getOperand(1);
19101
19102 SDValue Op0Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op0);
19103 SDValue Op1Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op1);
19104
19105 SDValue Op0Hi = getHiHalf64(Op0, DAG);
19106 SDValue Op1Hi = getHiHalf64(Op1, DAG);
19107
19108 SDValue NodeLo =
19109 DAG.getNode(IsAdd ? ISD::UADDO : ISD::USUBO, SL,
19110 DAG.getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
19111
19112 SDValue CarryInHi = NodeLo.getValue(1);
19113 SDValue NodeHi = DAG.getNode(IsAdd ? ISD::UADDO_CARRY : ISD::USUBO_CARRY,
19114 SL, DAG.getVTList(MVT::i32, MVT::i1),
19115 {Op0Hi, Op1Hi, CarryInHi});
19116
19117 SDValue ResultLo = NodeLo.getValue(0);
19118 SDValue ResultHi = NodeHi.getValue(0);
19119
19120 SDValue JoinedResult =
19121 DAG.getBuildVector(MVT::v2i32, SL, {ResultLo, ResultHi});
19122
19123 SDValue Result = DAG.getNode(ISD::BITCAST, SL, VT, JoinedResult);
19124 SDValue Overflow = NodeHi.getValue(1);
19125 DCI.CombineTo(LHS.getNode(), Result);
19126 return Overflow;
19127 }
19128
19129 if (VT != MVT::f32 && VT != MVT::f64 &&
19130 (!Subtarget->has16BitInsts() || VT != MVT::f16))
19131 return SDValue();
19132
19133 // Match isinf/isfinite pattern
19134 // (fcmp oeq (fabs x), inf) -> (fp_class x, (p_infinity | n_infinity))
19135 // (fcmp one (fabs x), inf) -> (fp_class x,
19136 // (p_normal | n_normal | p_subnormal | n_subnormal | p_zero | n_zero)
19137 if ((CC == ISD::SETOEQ || CC == ISD::SETONE) &&
19138 LHS.getOpcode() == ISD::FABS) {
19139 const ConstantFPSDNode *CRHS = dyn_cast<ConstantFPSDNode>(RHS);
19140 if (!CRHS)
19141 return SDValue();
19142
19143 const APFloat &APF = CRHS->getValueAPF();
19144 if (APF.isInfinity() && !APF.isNegative()) {
19145 const unsigned IsInfMask =
19147 const unsigned IsFiniteMask =
19151 unsigned Mask = CC == ISD::SETOEQ ? IsInfMask : IsFiniteMask;
19152 return DAG.getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1, LHS.getOperand(0),
19153 DAG.getConstant(Mask, SL, MVT::i32));
19154 }
19155 }
19156
19157 if (VT == MVT::f64) {
19159 if (HiHalfCC != ISD::SETCC_INVALID)
19160 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
19161 getHiHalf64(RHS, DAG), HiHalfCC);
19162 }
19163
19164 return SDValue();
19165}
19166
19167SDValue
19168SITargetLowering::performCvtF32UByteNCombine(SDNode *N,
19169 DAGCombinerInfo &DCI) const {
19170 SelectionDAG &DAG = DCI.DAG;
19171 SDLoc SL(N);
19172 unsigned Offset = N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
19173
19174 SDValue Src = N->getOperand(0);
19175 SDValue Shift = N->getOperand(0);
19176
19177 // TODO: Extend type shouldn't matter (assuming legal types).
19178 if (Shift.getOpcode() == ISD::ZERO_EXTEND)
19179 Shift = Shift.getOperand(0);
19180
19181 if (Shift.getOpcode() == ISD::SRL || Shift.getOpcode() == ISD::SHL) {
19182 // cvt_f32_ubyte1 (shl x, 8) -> cvt_f32_ubyte0 x
19183 // cvt_f32_ubyte3 (shl x, 16) -> cvt_f32_ubyte1 x
19184 // cvt_f32_ubyte0 (srl x, 16) -> cvt_f32_ubyte2 x
19185 // cvt_f32_ubyte1 (srl x, 16) -> cvt_f32_ubyte3 x
19186 // cvt_f32_ubyte0 (srl x, 8) -> cvt_f32_ubyte1 x
19187 if (auto *C = dyn_cast<ConstantSDNode>(Shift.getOperand(1))) {
19188 SDValue Shifted = DAG.getZExtOrTrunc(
19189 Shift.getOperand(0), SDLoc(Shift.getOperand(0)), MVT::i32);
19190
19191 unsigned ShiftOffset = 8 * Offset;
19192 if (Shift.getOpcode() == ISD::SHL)
19193 ShiftOffset -= C->getZExtValue();
19194 else
19195 ShiftOffset += C->getZExtValue();
19196
19197 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
19198 return DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
19199 MVT::f32, Shifted);
19200 }
19201 }
19202 }
19203
19205 APInt DemandedBits = APInt::getBitsSet(32, 8 * Offset, 8 * Offset + 8);
19206 if (TLI.SimplifyDemandedBits(Src, DemandedBits, DCI)) {
19207 // We simplified Src. If this node is not dead, visit it again so it is
19208 // folded properly.
19209 if (N->getOpcode() != ISD::DELETED_NODE)
19210 DCI.AddToWorklist(N);
19211 return SDValue(N, 0);
19212 }
19213
19214 // Handle (or x, (srl y, 8)) pattern when known bits are zero.
19215 if (SDValue DemandedSrc =
19216 TLI.SimplifyMultipleUseDemandedBits(Src, DemandedBits, DAG))
19217 return DAG.getNode(N->getOpcode(), SL, MVT::f32, DemandedSrc);
19218
19219 return SDValue();
19220}
19221
19222SDValue SITargetLowering::performClampCombine(SDNode *N,
19223 DAGCombinerInfo &DCI) const {
19224 ConstantFPSDNode *CSrc = dyn_cast<ConstantFPSDNode>(N->getOperand(0));
19225 if (!CSrc)
19226 return SDValue();
19227
19228 const MachineFunction &MF = DCI.DAG.getMachineFunction();
19229 const APFloat &F = CSrc->getValueAPF();
19230 APFloat Zero = APFloat::getZero(F.getSemantics());
19231 if (F < Zero ||
19232 (F.isNaN() && MF.getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
19233 return DCI.DAG.getConstantFP(Zero, SDLoc(N), N->getValueType(0));
19234 }
19235
19236 APFloat One = APFloat::getOne(F.getSemantics());
19237 if (F > One)
19238 return DCI.DAG.getConstantFP(One, SDLoc(N), N->getValueType(0));
19239
19240 return getCanonicalConstantFP(DCI.DAG, SDLoc(N), N->getValueType(0), F);
19241}
19242
19243// Check if V is the exponent result of a frexp operation. Returns the frexp
19244// input via FrexpInput if matched. We only match the exponent (not mantissa)
19245// because V_FREXP_MANT returns its input for Inf/NaN, not zero.
19246static bool isFrexpExp(SDValue V, SDValue &FrexpInput) {
19247 // ISD::FFREXP returns {mant, exp} - only match if using the exp result
19248 // (result number 1).
19249 if (V.getOpcode() == ISD::FFREXP && V.getResNo() == 1) {
19250 FrexpInput = V.getOperand(0);
19251 return true;
19252 }
19254 m_Value(FrexpInput))))
19255 return true;
19256 return false;
19257}
19258
19259SDValue
19260SITargetLowering::performFrexpSelectCombine(SDNode *N,
19261 DAGCombinerInfo &DCI) const {
19262 // This optimization only applies when the hardware handles inf/nan correctly.
19263 if (Subtarget->hasFractBug())
19264 return SDValue();
19265
19266 SDValue Cond = N->getOperand(0);
19267 SDValue TrueVal = N->getOperand(1);
19268 SDValue FalseVal = N->getOperand(2);
19269
19270 // Identify which operand is the frexp result and which is the zero constant.
19271 // Pattern 1: select cond, 0, frexp_result (cond true -> return 0)
19272 // Pattern 2: select cond, frexp_result, 0 (cond false -> return 0)
19273 SDValue FrexpVal;
19274 SDValue ZeroVal;
19275 bool CondSelectsZero; // If true, condition=true selects zero
19276
19277 // Check if FrexpVal comes from ISD::FFREXP (exponent result only) or
19278 // amdgcn_frexp_exp intrinsic.
19279 SDValue FrexpInput;
19280 if (isFrexpExp(FalseVal, FrexpInput)) {
19281 FrexpVal = FalseVal;
19282 ZeroVal = TrueVal;
19283 CondSelectsZero = true;
19284 } else if (isFrexpExp(TrueVal, FrexpInput)) {
19285 FrexpVal = TrueVal;
19286 ZeroVal = FalseVal;
19287 CondSelectsZero = false;
19288 } else {
19289 return SDValue();
19290 }
19291
19292 // frexp_exp returns integer, so check for integer zero.
19293 if (!isNullConstant(ZeroVal))
19294 return SDValue();
19295
19296 // The frexp intrinsics ignore sign, so we can strip sign ops when comparing.
19297 SDValue FrexpInputStripped = peekFPSignOps(FrexpInput);
19298
19299 bool IsNonFiniteTest = false;
19300
19301 // Handle SETCC conditions for inf/nan tests.
19302 // The canonical form of these checks is fcmp + fabs.
19303 if (Cond.getOpcode() == ISD::SETCC) {
19304 ISD::CondCode CC = Cond.getOperandCondCode(2);
19305 SDValue CondLHS = Cond.getOperand(0);
19306 SDValue CondRHS = Cond.getOperand(1);
19307
19308 // Check if LHS is fabs(FrexpInput) - required for infinity comparisons.
19309 SDValue FAbsInput;
19310 bool LHSIsFabs = sd_match(CondLHS, m_FAbs(m_Value(FAbsInput)));
19311 bool LHSMatchesFrexp =
19312 (CondLHS == FrexpInput) ||
19313 (LHSIsFabs && peekFPSignOps(FAbsInput) == FrexpInputStripped) ||
19314 (peekFPSignOps(CondLHS) == FrexpInputStripped);
19315 bool RHSMatchesFrexp = (CondRHS == FrexpInput) ||
19316 (peekFPSignOps(CondRHS) == FrexpInputStripped);
19317
19318 if (CC == ISD::SETUO) {
19319 // fcmp uno x, y - true if either x or y is NaN
19320 // We can only fold if the non-frexp operand is known to never be NaN,
19321 // otherwise the comparison could be true due to the other operand.
19322 // Special case: fcmp uno x, x (same operand) is a valid NaN test.
19323 SelectionDAG &DAG = DCI.DAG;
19324 if (LHSMatchesFrexp &&
19325 (CondLHS == CondRHS || DAG.isKnownNeverNaN(CondRHS)))
19326 IsNonFiniteTest = CondSelectsZero;
19327 else if (RHSMatchesFrexp && DAG.isKnownNeverNaN(CondLHS))
19328 IsNonFiniteTest = CondSelectsZero;
19329 } else if ((CC == ISD::SETOEQ || CC == ISD::SETUEQ) && LHSMatchesFrexp &&
19330 LHSIsFabs &&
19331 sd_match(CondRHS,
19333 CondRHS.getValueType().getFltSemantics())))) {
19334 // fcmp oeq/ueq fabs(x), +inf - true if x is inf (or inf/nan for ueq)
19335 IsNonFiniteTest = CondSelectsZero;
19336 } else if ((CC == ISD::SETONE || CC == ISD::SETUNE) && LHSMatchesFrexp &&
19337 LHSIsFabs &&
19338 sd_match(CondRHS,
19340 CondRHS.getValueType().getFltSemantics())))) {
19341 // fcmp one/une fabs(x), +inf - true if x is NOT inf
19342 IsNonFiniteTest = !CondSelectsZero;
19343 } else if (CC == ISD::SETO) {
19344 // fcmp ord x, y - true if both are NOT NaN
19345 // We can only fold if the non-frexp operand is known to never be NaN,
19346 // otherwise the comparison could be false due to the other operand.
19347 // Special case: fcmp ord x, x (same operand) is a valid not-NaN test.
19348 SelectionDAG &DAG = DCI.DAG;
19349 if (LHSMatchesFrexp &&
19350 (CondLHS == CondRHS || DAG.isKnownNeverNaN(CondRHS)))
19351 IsNonFiniteTest = !CondSelectsZero;
19352 else if (RHSMatchesFrexp && DAG.isKnownNeverNaN(CondLHS))
19353 IsNonFiniteTest = !CondSelectsZero;
19354 }
19355 }
19356
19357 if (!IsNonFiniteTest)
19358 return SDValue();
19359
19360 // The select can be eliminated - just return the frexp result directly.
19361 return FrexpVal;
19362}
19363
19364SDValue SITargetLowering::performSelectCombine(SDNode *N,
19365 DAGCombinerInfo &DCI) const {
19366
19367 // Try to fold CMP + SELECT patterns with shared constants (both FP and
19368 // integer).
19369 // Detect when CMP and SELECT use the same constant and fold them to avoid
19370 // loading the constant twice. Specifically handles patterns like:
19371 // %cmp = icmp eq i32 %val, 4242
19372 // %sel = select i1 %cmp, i32 4242, i32 %other
19373 // It can be optimized to reuse %val instead of 4242 in select.
19374 SDValue Cond = N->getOperand(0);
19375 SDValue TrueVal = N->getOperand(1);
19376 SDValue FalseVal = N->getOperand(2);
19377
19378 // Check if condition is a comparison.
19379 if (Cond.getOpcode() != ISD::SETCC)
19380 return SDValue();
19381
19382 SDValue LHS = Cond.getOperand(0);
19383 SDValue RHS = Cond.getOperand(1);
19384 ISD::CondCode CC = Cond.getOperandCondCode(2);
19385
19386 bool isFloatingPoint = LHS.getValueType().isFloatingPoint();
19387 bool isInteger = LHS.getValueType().isInteger();
19388
19389 // Handle simple floating-point and integer types only.
19390 if (!isFloatingPoint && !isInteger)
19391 return SDValue();
19392
19393 // Bare SETEQ/SETNE is the builder's NaN-impossible downgrade.
19394 bool isEquality = CC == ISD::SETEQ || (isFloatingPoint && CC == ISD::SETOEQ);
19395 bool isNonEquality =
19396 CC == ISD::SETNE || (isFloatingPoint && CC == ISD::SETONE);
19397 if (!isEquality && !isNonEquality)
19398 return SDValue();
19399
19400 SDValue ArgVal, ConstVal;
19401 if ((isFloatingPoint && isa<ConstantFPSDNode>(RHS)) ||
19402 (isInteger && isa<ConstantSDNode>(RHS))) {
19403 ConstVal = RHS;
19404 ArgVal = LHS;
19405 } else if ((isFloatingPoint && isa<ConstantFPSDNode>(LHS)) ||
19406 (isInteger && isa<ConstantSDNode>(LHS))) {
19407 ConstVal = LHS;
19408 ArgVal = RHS;
19409 } else {
19410 return SDValue();
19411 }
19412
19413 // Skip optimization for inlinable immediates.
19414 if (isFloatingPoint) {
19415 const APFloat &Val = cast<ConstantFPSDNode>(ConstVal)->getValueAPF();
19416 if (!Val.isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
19417 return SDValue();
19418 } else {
19419 const std::optional<int64_t> Val =
19420 cast<ConstantSDNode>(ConstVal)->getAPIntValue().trySExtValue();
19421 if (Val && AMDGPU::isInlinableIntLiteral(*Val))
19422 return SDValue();
19423 }
19424
19425 // For equality and non-equality comparisons, patterns:
19426 // select (setcc x, const), const, y -> select (setcc x, const), x, y
19427 // select (setccinv x, const), y, const -> select (setccinv x, const), y, x
19428 if (!(isEquality && TrueVal == ConstVal) &&
19429 !(isNonEquality && FalseVal == ConstVal))
19430 return SDValue();
19431
19432 // SETONE's false arm is also taken for NaN ArgVal, so require NaN excluded.
19433 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
19434 !Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
19435 return SDValue();
19436
19437 SDValue SelectLHS = (isEquality && TrueVal == ConstVal) ? ArgVal : TrueVal;
19438 SDValue SelectRHS =
19439 (isNonEquality && FalseVal == ConstVal) ? ArgVal : FalseVal;
19440 return DCI.DAG.getNode(ISD::SELECT, SDLoc(N), N->getValueType(0), Cond,
19441 SelectLHS, SelectRHS);
19442}
19443
19445 DAGCombinerInfo &DCI) const {
19446 switch (N->getOpcode()) {
19447 case ISD::ABS:
19448 if (SDValue Res = promoteUniformUnaryOpToI32(SDValue(N, 0), DCI))
19449 return Res;
19450 break;
19451 case ISD::ADD:
19452 case ISD::SUB:
19453 case ISD::SHL:
19454 case ISD::SRL:
19455 case ISD::SRA:
19456 case ISD::AND:
19457 case ISD::OR:
19458 case ISD::XOR:
19459 case ISD::MUL:
19460 case ISD::SETCC:
19461 case ISD::SELECT:
19462 case ISD::SMIN:
19463 case ISD::SMAX:
19464 case ISD::UMIN:
19465 case ISD::UMAX:
19466 case ISD::USUBSAT:
19467 case ISD::UADDSAT:
19468 if (auto Res = promoteUniformOpToI32(SDValue(N, 0), DCI))
19469 return Res;
19470 break;
19471 default:
19472 break;
19473 }
19474
19475 if (getTargetMachine().getOptLevel() == CodeGenOptLevel::None)
19476 return SDValue();
19477
19478 switch (N->getOpcode()) {
19479 case ISD::ADD:
19480 return performAddCombine(N, DCI);
19481 case ISD::PTRADD:
19482 return performPtrAddCombine(N, DCI);
19483 case ISD::SUB:
19484 return performSubCombine(N, DCI);
19485 case ISD::FADD:
19486 return performFAddCombine(N, DCI);
19487 case ISD::FSUB:
19488 return performFSubCombine(N, DCI);
19489 case ISD::FDIV:
19490 return performFDivCombine(N, DCI);
19491 case ISD::FMUL:
19492 return performFMulCombine(N, DCI);
19493 case ISD::SETCC:
19494 return performSetCCCombine(N, DCI);
19495 case ISD::SELECT:
19496 if (auto Res = performFrexpSelectCombine(N, DCI))
19497 return Res;
19498 if (auto Res = performSelectCombine(N, DCI))
19499 return Res;
19500 break;
19501 case ISD::FMAXNUM:
19502 case ISD::FMINNUM:
19503 case ISD::FMAXNUM_IEEE:
19504 case ISD::FMINNUM_IEEE:
19505 case ISD::FMAXIMUM:
19506 case ISD::FMINIMUM:
19507 case ISD::FMAXIMUMNUM:
19508 case ISD::FMINIMUMNUM:
19509 case ISD::SMAX:
19510 case ISD::SMIN:
19511 case ISD::UMAX:
19512 case ISD::UMIN:
19513 case AMDGPUISD::FMIN_LEGACY:
19514 case AMDGPUISD::FMAX_LEGACY:
19515 return performMinMaxCombine(N, DCI);
19516 case ISD::FMA:
19517 return performFMACombine(N, DCI);
19518 case ISD::AND:
19519 return performAndCombine(N, DCI);
19520 case ISD::OR:
19521 return performOrCombine(N, DCI);
19522 case ISD::FSHR: {
19524 if (N->getValueType(0) == MVT::i32 && N->isDivergent() &&
19525 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19526 return matchPERM(N, DCI);
19527 }
19528 break;
19529 }
19530 case ISD::XOR:
19531 return performXorCombine(N, DCI);
19532 case ISD::ANY_EXTEND:
19533 case ISD::ZERO_EXTEND:
19534 return performZeroOrAnyExtendCombine(N, DCI);
19535 case ISD::SIGN_EXTEND:
19536 return performExtendTruncShiftCombine(N, DCI);
19538 return performSignExtendInRegCombine(N, DCI);
19539 case AMDGPUISD::FP_CLASS:
19540 return performClassCombine(N, DCI);
19541 case ISD::FCANONICALIZE:
19542 return performFCanonicalizeCombine(N, DCI);
19543 case AMDGPUISD::RCP:
19544 return performRcpCombine(N, DCI);
19545 case ISD::FLDEXP:
19546 case AMDGPUISD::FRACT:
19547 case AMDGPUISD::RSQ:
19548 case AMDGPUISD::RCP_LEGACY:
19549 case AMDGPUISD::RCP_IFLAG:
19550 case AMDGPUISD::RSQ_CLAMP: {
19551 // FIXME: This is probably wrong. If src is an sNaN, it won't be quieted
19552 SDValue Src = N->getOperand(0);
19553 if (Src.isUndef())
19554 return Src;
19555 break;
19556 }
19557 case ISD::SINT_TO_FP:
19558 case ISD::UINT_TO_FP:
19559 return performUCharToFloatCombine(N, DCI);
19560 case ISD::FCOPYSIGN:
19561 return performFCopySignCombine(N, DCI);
19562 case AMDGPUISD::CVT_F32_UBYTE0:
19563 case AMDGPUISD::CVT_F32_UBYTE1:
19564 case AMDGPUISD::CVT_F32_UBYTE2:
19565 case AMDGPUISD::CVT_F32_UBYTE3:
19566 return performCvtF32UByteNCombine(N, DCI);
19567 case AMDGPUISD::FMED3:
19568 return performFMed3Combine(N, DCI);
19569 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19570 return performCvtPkRTZCombine(N, DCI);
19572 if (SDValue Res = performExponentOnlyScaleCombine(N, DCI))
19573 return Res;
19574 break;
19575 case AMDGPUISD::CLAMP:
19576 return performClampCombine(N, DCI);
19577 case ISD::SCALAR_TO_VECTOR: {
19578 SelectionDAG &DAG = DCI.DAG;
19579 EVT VT = N->getValueType(0);
19580
19581 // v2i16 (scalar_to_vector i16:x) -> v2i16 (bitcast (any_extend i16:x))
19582 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19583 SDLoc SL(N);
19584 SDValue Src = N->getOperand(0);
19585 EVT EltVT = Src.getValueType();
19586 if (EltVT != MVT::i16)
19587 Src = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
19588
19589 SDValue Ext = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Src);
19590 return DAG.getNode(ISD::BITCAST, SL, VT, Ext);
19591 }
19592
19593 break;
19594 }
19596 return performExtractVectorEltCombine(N, DCI);
19598 return performInsertVectorEltCombine(N, DCI);
19599 case ISD::FP_ROUND:
19600 return performFPRoundCombine(N, DCI);
19601 case ISD::LOAD: {
19602 if (SDValue Widened = widenLoad(cast<LoadSDNode>(N), DCI))
19603 return Widened;
19604 [[fallthrough]];
19605 }
19606 default: {
19607 if (!DCI.isBeforeLegalize()) {
19608 if (MemSDNode *MemNode = dyn_cast<MemSDNode>(N))
19609 return performMemSDNodeCombine(MemNode, DCI);
19610 }
19611
19612 break;
19613 }
19614 }
19615
19617}
19618
19619/// Helper function for adjustWritemask
19620static unsigned SubIdx2Lane(unsigned Idx) {
19621 switch (Idx) {
19622 default:
19623 return ~0u;
19624 case AMDGPU::sub0:
19625 return 0;
19626 case AMDGPU::sub1:
19627 return 1;
19628 case AMDGPU::sub2:
19629 return 2;
19630 case AMDGPU::sub3:
19631 return 3;
19632 case AMDGPU::sub4:
19633 return 4; // Possible with TFE/LWE
19634 }
19635}
19636
19637/// Adjust the writemask of MIMG, VIMAGE or VSAMPLE instructions
19638SDNode *SITargetLowering::adjustWritemask(MachineSDNode *&Node,
19639 SelectionDAG &DAG) const {
19640 unsigned Opcode = Node->getMachineOpcode();
19641
19642 // Subtract 1 because the vdata output is not a MachineSDNode operand.
19643 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19644 if (D16Idx >= 0 && Node->getConstantOperandVal(D16Idx))
19645 return Node; // not implemented for D16
19646
19647 SDNode *Users[5] = {nullptr};
19648 unsigned Lane = 0;
19649 unsigned DmaskIdx =
19650 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19651 unsigned OldDmask = Node->getConstantOperandVal(DmaskIdx);
19652 unsigned NewDmask = 0;
19653 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19654 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19655 bool UsesTFC = (int(TFEIdx) >= 0 && Node->getConstantOperandVal(TFEIdx)) ||
19656 (int(LWEIdx) >= 0 && Node->getConstantOperandVal(LWEIdx));
19657 unsigned TFCLane = 0;
19658 bool HasChain = Node->getNumValues() > 1;
19659
19660 if (OldDmask == 0) {
19661 // These are folded out, but on the chance it happens don't assert.
19662 return Node;
19663 }
19664
19665 unsigned OldBitsSet = llvm::popcount(OldDmask);
19666 // Work out which is the TFE/LWE lane if that is enabled.
19667 if (UsesTFC) {
19668 TFCLane = OldBitsSet;
19669 }
19670
19671 // Try to figure out the used register components
19672 for (SDUse &Use : Node->uses()) {
19673
19674 // Don't look at users of the chain.
19675 if (Use.getResNo() != 0)
19676 continue;
19677
19678 SDNode *User = Use.getUser();
19679
19680 // Abort if we can't understand the usage
19681 if (!User->isMachineOpcode() ||
19682 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19683 return Node;
19684
19685 // Lane means which subreg of %vgpra_vgprb_vgprc_vgprd is used.
19686 // Note that subregs are packed, i.e. Lane==0 is the first bit set
19687 // in OldDmask, so it can be any of X,Y,Z,W; Lane==1 is the second bit
19688 // set, etc.
19689 Lane = SubIdx2Lane(User->getConstantOperandVal(1));
19690 if (Lane == ~0u)
19691 return Node;
19692
19693 // Check if the use is for the TFE/LWE generated result at VGPRn+1.
19694 if (UsesTFC && Lane == TFCLane) {
19695 Users[Lane] = User;
19696 } else {
19697 // Set which texture component corresponds to the lane.
19698 unsigned Comp;
19699 for (unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19700 Comp = llvm::countr_zero(Dmask);
19701 Dmask &= ~(1 << Comp);
19702 }
19703
19704 // Abort if we have more than one user per component.
19705 if (Users[Lane])
19706 return Node;
19707
19708 Users[Lane] = User;
19709 NewDmask |= 1 << Comp;
19710 }
19711 }
19712
19713 // Don't allow 0 dmask, as hardware assumes one channel enabled.
19714 bool NoChannels = !NewDmask;
19715 if (NoChannels) {
19716 if (!UsesTFC) {
19717 // No uses of the result and not using TFC. Then do nothing.
19718 return Node;
19719 }
19720 // If the original dmask has one channel - then nothing to do
19721 if (OldBitsSet == 1)
19722 return Node;
19723 // Use an arbitrary dmask - required for the instruction to work
19724 NewDmask = 1;
19725 }
19726 // Abort if there's no change
19727 if (NewDmask == OldDmask)
19728 return Node;
19729
19730 unsigned BitsSet = llvm::popcount(NewDmask);
19731
19732 // Check for TFE or LWE - increase the number of channels by one to account
19733 // for the extra return value
19734 // This will need adjustment for D16 if this is also included in
19735 // adjustWriteMask (this function) but at present D16 are excluded.
19736 unsigned NewChannels = BitsSet + UsesTFC;
19737
19738 int NewOpcode =
19739 AMDGPU::getMaskedMIMGOp(Node->getMachineOpcode(), NewChannels);
19740 assert(NewOpcode != -1 &&
19741 NewOpcode != static_cast<int>(Node->getMachineOpcode()) &&
19742 "failed to find equivalent MIMG op");
19743
19744 // Adjust the writemask in the node
19746 llvm::append_range(Ops, Node->ops().take_front(DmaskIdx));
19747 Ops.push_back(DAG.getTargetConstant(NewDmask, SDLoc(Node), MVT::i32));
19748 llvm::append_range(Ops, Node->ops().drop_front(DmaskIdx + 1));
19749
19750 MVT SVT = Node->getValueType(0).getVectorElementType().getSimpleVT();
19751
19752 MVT ResultVT = NewChannels == 1
19753 ? SVT
19754 : MVT::getVectorVT(SVT, NewChannels == 3 ? 4
19755 : NewChannels == 5 ? 8
19756 : NewChannels);
19757 SDVTList NewVTList =
19758 HasChain ? DAG.getVTList(ResultVT, MVT::Other) : DAG.getVTList(ResultVT);
19759
19760 MachineSDNode *NewNode =
19761 DAG.getMachineNode(NewOpcode, SDLoc(Node), NewVTList, Ops);
19762
19763 if (HasChain) {
19764 // Update chain.
19765 DAG.setNodeMemRefs(NewNode, Node->memoperands());
19766 DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), SDValue(NewNode, 1));
19767 }
19768
19769 if (NewChannels == 1) {
19770 assert(Node->hasNUsesOfValue(1, 0));
19771 SDNode *Copy =
19772 DAG.getMachineNode(TargetOpcode::COPY, SDLoc(Node),
19773 Users[Lane]->getValueType(0), SDValue(NewNode, 0));
19774 DAG.ReplaceAllUsesWith(Users[Lane], Copy);
19775 return nullptr;
19776 }
19777
19778 // Update the users of the node with the new indices
19779 for (unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19780 SDNode *User = Users[i];
19781 if (!User) {
19782 // Handle the special case of NoChannels. We set NewDmask to 1 above, but
19783 // Users[0] is still nullptr because channel 0 doesn't really have a use.
19784 if (i || !NoChannels)
19785 continue;
19786 } else {
19787 SDValue Op = DAG.getTargetConstant(Idx, SDLoc(User), MVT::i32);
19788 SDNode *NewUser = DAG.UpdateNodeOperands(User, SDValue(NewNode, 0), Op);
19789 if (NewUser != User) {
19790 DAG.ReplaceAllUsesWith(SDValue(User, 0), SDValue(NewUser, 0));
19791 DAG.RemoveDeadNode(User);
19792 }
19793 }
19794
19795 switch (Idx) {
19796 default:
19797 break;
19798 case AMDGPU::sub0:
19799 Idx = AMDGPU::sub1;
19800 break;
19801 case AMDGPU::sub1:
19802 Idx = AMDGPU::sub2;
19803 break;
19804 case AMDGPU::sub2:
19805 Idx = AMDGPU::sub3;
19806 break;
19807 case AMDGPU::sub3:
19808 Idx = AMDGPU::sub4;
19809 break;
19810 }
19811 }
19812
19813 DAG.RemoveDeadNode(Node);
19814 return nullptr;
19815}
19816
19818 if (Op.getOpcode() == ISD::AssertZext)
19819 Op = Op.getOperand(0);
19820
19821 return isa<FrameIndexSDNode>(Op);
19822}
19823
19824/// Legalize target independent instructions (e.g. INSERT_SUBREG)
19825/// with frame index operands.
19826/// LLVM assumes that inputs are to these instructions are registers.
19827SDNode *
19829 SelectionDAG &DAG) const {
19830 if (Node->getOpcode() == ISD::CopyToReg) {
19831 RegisterSDNode *DestReg = cast<RegisterSDNode>(Node->getOperand(1));
19832 SDValue SrcVal = Node->getOperand(2);
19833
19834 // Insert a copy to a VReg_1 virtual register so LowerI1Copies doesn't have
19835 // to try understanding copies to physical registers.
19836 if (SrcVal.getValueType() == MVT::i1 && DestReg->getReg().isPhysical()) {
19837 SDLoc SL(Node);
19839 SDValue VReg = DAG.getRegister(
19840 MRI.createVirtualRegister(&AMDGPU::VReg_1RegClass), MVT::i1);
19841
19842 SDNode *Glued = Node->getGluedNode();
19843 SDValue ToVReg = DAG.getCopyToReg(
19844 Node->getOperand(0), SL, VReg, SrcVal,
19845 SDValue(Glued, Glued ? Glued->getNumValues() - 1 : 0));
19846 SDValue ToResultReg = DAG.getCopyToReg(ToVReg, SL, SDValue(DestReg, 0),
19847 VReg, ToVReg.getValue(1));
19848 DAG.ReplaceAllUsesWith(Node, ToResultReg.getNode());
19849 DAG.RemoveDeadNode(Node);
19850 return ToResultReg.getNode();
19851 }
19852 }
19853
19855 for (unsigned i = 0; i < Node->getNumOperands(); ++i) {
19856 if (!isFrameIndexOp(Node->getOperand(i))) {
19857 Ops.push_back(Node->getOperand(i));
19858 continue;
19859 }
19860
19861 SDLoc DL(Node);
19862 Ops.push_back(SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL,
19863 Node->getOperand(i).getValueType(),
19864 Node->getOperand(i)),
19865 0));
19866 }
19867
19868 return DAG.UpdateNodeOperands(Node, Ops);
19869}
19870
19871/// Fold the instructions after selecting them.
19872/// Returns null if users were already updated.
19874 SelectionDAG &DAG) const {
19876 unsigned Opcode = Node->getMachineOpcode();
19877
19878 if (TII->isImage(Opcode) && !TII->get(Opcode).mayStore() &&
19879 !TII->isGather4(Opcode) &&
19880 AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::dmask)) {
19881 return adjustWritemask(Node, DAG);
19882 }
19883
19884 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19886 return Node;
19887 }
19888
19889 switch (Opcode) {
19890 case AMDGPU::V_DIV_SCALE_F32_e64:
19891 case AMDGPU::V_DIV_SCALE_F64_e64: {
19892 // Satisfy the operand register constraint when one of the inputs is
19893 // undefined. Ordinarily each undef value will have its own implicit_def of
19894 // a vreg, so force these to use a single register.
19895 SDValue Src0 = Node->getOperand(1);
19896 SDValue Src1 = Node->getOperand(3);
19897 SDValue Src2 = Node->getOperand(5);
19898
19899 if ((Src0.isMachineOpcode() &&
19900 Src0.getMachineOpcode() != AMDGPU::IMPLICIT_DEF) &&
19901 (Src0 == Src1 || Src0 == Src2))
19902 break;
19903
19904 MVT VT = Src0.getValueType().getSimpleVT();
19905 const TargetRegisterClass *RC =
19906 getRegClassFor(VT, Src0.getNode()->isDivergent());
19907
19909 SDValue UndefReg = DAG.getRegister(MRI.createVirtualRegister(RC), VT);
19910
19911 SDValue ImpDef = DAG.getCopyToReg(DAG.getEntryNode(), SDLoc(Node), UndefReg,
19912 Src0, SDValue());
19913
19914 // src0 must be the same register as src1 or src2, even if the value is
19915 // undefined, so make sure we don't violate this constraint.
19916 if (Src0.isMachineOpcode() &&
19917 Src0.getMachineOpcode() == AMDGPU::IMPLICIT_DEF) {
19918 if (Src1.isMachineOpcode() &&
19919 Src1.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19920 Src0 = Src1;
19921 else if (Src2.isMachineOpcode() &&
19922 Src2.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19923 Src0 = Src2;
19924 else {
19925 assert(Src1.getMachineOpcode() == AMDGPU::IMPLICIT_DEF);
19926 Src0 = UndefReg;
19927 Src1 = UndefReg;
19928 }
19929 } else
19930 break;
19931
19933 Ops[1] = Src0;
19934 Ops[3] = Src1;
19935 Ops[5] = Src2;
19936 Ops.push_back(ImpDef.getValue(1));
19937 return DAG.getMachineNode(Opcode, SDLoc(Node), Node->getVTList(), Ops);
19938 }
19939 default:
19940 break;
19941 }
19942
19943 return Node;
19944}
19945
19946// Any MIMG instructions that use tfe or lwe require an initialization of the
19947// result register that will be written in the case of a memory access failure.
19948// The required code is also added to tie this init code to the result of the
19949// img instruction.
19952 const SIRegisterInfo &TRI = TII->getRegisterInfo();
19953 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
19954 MachineBasicBlock &MBB = *MI.getParent();
19955
19956 int DstIdx =
19957 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
19958 unsigned InitIdx = 0;
19959
19960 if (TII->isImage(MI)) {
19961 MachineOperand *TFE = TII->getNamedOperand(MI, AMDGPU::OpName::tfe);
19962 MachineOperand *LWE = TII->getNamedOperand(MI, AMDGPU::OpName::lwe);
19963 MachineOperand *D16 = TII->getNamedOperand(MI, AMDGPU::OpName::d16);
19964
19965 if (!TFE && !LWE) // intersect_ray
19966 return;
19967
19968 unsigned TFEVal = TFE ? TFE->getImm() : 0;
19969 unsigned LWEVal = LWE ? LWE->getImm() : 0;
19970 unsigned D16Val = D16 ? D16->getImm() : 0;
19971
19972 if (!TFEVal && !LWEVal)
19973 return;
19974
19975 // At least one of TFE or LWE are non-zero
19976 // We have to insert a suitable initialization of the result value and
19977 // tie this to the dest of the image instruction.
19978
19979 // Calculate which dword we have to initialize to 0.
19980 MachineOperand *MO_Dmask = TII->getNamedOperand(MI, AMDGPU::OpName::dmask);
19981
19982 // check that dmask operand is found.
19983 assert(MO_Dmask && "Expected dmask operand in instruction");
19984
19985 unsigned dmask = MO_Dmask->getImm();
19986 // Determine the number of active lanes taking into account the
19987 // Gather4 special case
19988 unsigned ActiveLanes = TII->isGather4(MI) ? 4 : llvm::popcount(dmask);
19989
19990 bool Packed = !Subtarget->hasUnpackedD16VMem();
19991
19992 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19993
19994 // Abandon attempt if the dst size isn't large enough
19995 // - this is in fact an error but this is picked up elsewhere and
19996 // reported correctly.
19997 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
19998
19999 uint32_t DstSize = TRI.getRegSizeInBits(*DstRC) / 32;
20000 if (DstSize < InitIdx)
20001 return;
20002 } else if (TII->isMUBUF(MI) && AMDGPU::getMUBUFTfe(MI.getOpcode())) {
20003 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
20004 InitIdx = TRI.getRegSizeInBits(*DstRC) / 32;
20005 } else {
20006 return;
20007 }
20008
20009 const DebugLoc &DL = MI.getDebugLoc();
20010
20011 // Create a register for the initialization value.
20012 Register PrevDst = MRI.cloneVirtualRegister(MI.getOperand(DstIdx).getReg());
20013 unsigned NewDst = 0; // Final initialized value will be in here
20014
20015 // If PRTStrictNull feature is enabled (the default) then initialize
20016 // all the result registers to 0, otherwise just the error indication
20017 // register (VGPRn+1)
20018 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
20019 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
20020
20021 BuildMI(MBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), PrevDst);
20022 for (; SizeLeft; SizeLeft--, CurrIdx++) {
20023 NewDst = MRI.createVirtualRegister(TII->getOpRegClass(MI, DstIdx));
20024 // Initialize dword
20025 Register SubReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
20026 // clang-format off
20027 BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), SubReg)
20028 .addImm(0);
20029 // clang-format on
20030 // Insert into the super-reg
20031 BuildMI(MBB, MI, DL, TII->get(TargetOpcode::INSERT_SUBREG), NewDst)
20032 .addReg(PrevDst)
20033 .addReg(SubReg)
20035
20036 PrevDst = NewDst;
20037 }
20038
20039 // Add as an implicit operand
20040 MI.addOperand(MachineOperand::CreateReg(NewDst, false, true));
20041
20042 // Tie the just added implicit operand to the dst
20043 MI.tieOperands(DstIdx, MI.getNumOperands() - 1);
20044}
20045
20046/// Assign the register class depending on the number of
20047/// bits set in the writemask
20049 SDNode *Node) const {
20051
20052 MachineFunction *MF = MI.getMF();
20054
20055 if (TII->isVOP3(MI.getOpcode())) {
20056 // Make sure constant bus requirements are respected.
20057 TII->legalizeOperandsVOP3(MRI, MI);
20058
20059 if (TII->isMAI(MI)) {
20060 // The ordinary src0, src1, src2 were legalized above.
20061 //
20062 // We have to also legalize the appended v_mfma_ld_scale_b32 operands,
20063 // as a separate instruction.
20064 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
20065 AMDGPU::OpName::scale_src0);
20066 if (Src0Idx != -1) {
20067 int Src1Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
20068 AMDGPU::OpName::scale_src1);
20069 if (TII->usesConstantBus(MRI, MI, Src0Idx) &&
20070 TII->usesConstantBus(MRI, MI, Src1Idx))
20071 TII->legalizeOpWithMove(MI, Src1Idx);
20072 }
20073 }
20074
20075 return;
20076 }
20077
20078 if (TII->isImage(MI))
20079 TII->enforceOperandRCAlignment(MI, AMDGPU::OpName::vaddr);
20080}
20081
20083 uint64_t Val) {
20084 SDValue K = DAG.getTargetConstant(Val, DL, MVT::i32);
20085 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, K), 0);
20086}
20087
20089 const SDLoc &DL,
20090 SDValue Ptr) const {
20092
20093 // Build the half of the subregister with the constants before building the
20094 // full 128-bit register. If we are building multiple resource descriptors,
20095 // this will allow CSEing of the 2-component register.
20096 const SDValue Ops0[] = {
20097 DAG.getTargetConstant(AMDGPU::SGPR_64RegClassID, DL, MVT::i32),
20098 buildSMovImm32(DAG, DL, 0),
20099 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
20100 buildSMovImm32(DAG, DL, TII->getDefaultRsrcDataFormat() >> 32),
20101 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32)};
20102
20103 SDValue SubRegHi = SDValue(
20104 DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v2i32, Ops0), 0);
20105
20106 // Combine the constants and the pointer.
20107 const SDValue Ops1[] = {
20108 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32), Ptr,
20109 DAG.getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32), SubRegHi,
20110 DAG.getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32)};
20111
20112 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops1);
20113}
20114
20115/// Return a resource descriptor with the 'Add TID' bit enabled
20116/// The TID (Thread ID) is multiplied by the stride value (bits [61:48]
20117/// of the resource descriptor) to create an offset, which is added to
20118/// the resource pointer.
20120 SDValue Ptr, uint32_t RsrcDword1,
20121 uint64_t RsrcDword2And3) const {
20122 SDValue PtrLo = DAG.getTargetExtractSubreg(AMDGPU::sub0, DL, MVT::i32, Ptr);
20123 SDValue PtrHi = DAG.getTargetExtractSubreg(AMDGPU::sub1, DL, MVT::i32, Ptr);
20124 if (RsrcDword1) {
20125 PtrHi = DAG.getNode(ISD::OR, DL, MVT::i32, PtrHi,
20126 DAG.getConstant(RsrcDword1, DL, MVT::i32));
20127 }
20128
20129 SDValue DataLo =
20130 buildSMovImm32(DAG, DL, RsrcDword2And3 & UINT64_C(0xFFFFFFFF));
20131 SDValue DataHi = buildSMovImm32(DAG, DL, RsrcDword2And3 >> 32);
20132
20133 const SDValue Ops[] = {
20134 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32),
20135 PtrLo,
20136 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
20137 PtrHi,
20138 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32),
20139 DataLo,
20140 DAG.getTargetConstant(AMDGPU::sub2, DL, MVT::i32),
20141 DataHi,
20142 DAG.getTargetConstant(AMDGPU::sub3, DL, MVT::i32)};
20143
20144 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops);
20145}
20146
20147//===----------------------------------------------------------------------===//
20148// SI Inline Assembly Support
20149//===----------------------------------------------------------------------===//
20150
20151std::pair<unsigned, const TargetRegisterClass *>
20153 StringRef Constraint,
20154 MVT VT) const {
20155 const SIRegisterInfo *TRI = static_cast<const SIRegisterInfo *>(TRI_);
20156
20157 const TargetRegisterClass *RC = nullptr;
20158 if (Constraint.size() == 1) {
20159 // Check if we cannot determine the bit size of the given value type. This
20160 // can happen, for example, in this situation where we have an empty struct
20161 // (size 0): `call void asm "", "v"({} poison)`-
20162 if (VT == MVT::Other)
20163 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20164 const unsigned BitWidth = VT.getSizeInBits();
20165 switch (Constraint[0]) {
20166 default:
20167 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20168 case 's':
20169 case 'r':
20170 switch (BitWidth) {
20171 case 16:
20172 RC = &AMDGPU::SReg_32RegClass;
20173 break;
20174 case 64:
20175 RC = &AMDGPU::SGPR_64RegClass;
20176 break;
20177 default:
20179 if (!RC)
20180 return std::pair(0U, nullptr);
20181 break;
20182 }
20183 break;
20184 case 'v':
20185 switch (BitWidth) {
20186 case 1:
20187 return std::pair(0U, nullptr);
20188 case 16:
20189 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
20190 : &AMDGPU::VGPR_32_Lo256RegClass;
20191 break;
20192 default:
20193 RC = Subtarget->hasVGPRMSBs()
20194 ? TRI->getAlignedLo256VGPRClassForBitWidth(BitWidth)
20195 : TRI->getVGPRClassForBitWidth(BitWidth);
20196 if (!RC)
20197 return std::pair(0U, nullptr);
20198 break;
20199 }
20200 break;
20201 case 'a':
20202 if (!Subtarget->hasMAIInsts())
20203 break;
20204 switch (BitWidth) {
20205 case 1:
20206 return std::pair(0U, nullptr);
20207 case 16:
20208 RC = &AMDGPU::AGPR_32RegClass;
20209 break;
20210 default:
20211 RC = TRI->getAGPRClassForBitWidth(BitWidth);
20212 if (!RC)
20213 return std::pair(0U, nullptr);
20214 break;
20215 }
20216 break;
20217 }
20218 } else if (Constraint == "VA" && Subtarget->hasGFX90AInsts()) {
20219 const unsigned BitWidth = VT.getSizeInBits();
20220 switch (BitWidth) {
20221 case 16:
20222 RC = &AMDGPU::AV_32RegClass;
20223 break;
20224 default:
20225 RC = TRI->getVectorSuperClassForBitWidth(BitWidth);
20226 if (!RC)
20227 return std::pair(0U, nullptr);
20228 break;
20229 }
20230 }
20231
20232 // We actually support i128, i16 and f16 as inline parameters
20233 // even if they are not reported as legal
20234 if (RC && (isTypeLegal(VT) || VT.SimpleTy == MVT::i128 ||
20235 VT.SimpleTy == MVT::i16 || VT.SimpleTy == MVT::f16))
20236 return std::pair(0U, RC);
20237
20238 auto [Kind, Idx, NumRegs] = AMDGPU::parseAsmConstraintPhysReg(Constraint);
20239 if (Kind != '\0') {
20240 if (Kind == 'v') {
20241 RC = &AMDGPU::VGPR_32_Lo256RegClass;
20242 } else if (Kind == 's') {
20243 RC = &AMDGPU::SGPR_32RegClass;
20244 } else if (Kind == 'a') {
20245 RC = &AMDGPU::AGPR_32RegClass;
20246 }
20247
20248 if (RC) {
20249 if (NumRegs > 1) {
20250 if (Idx >= RC->getNumRegs() || Idx + NumRegs - 1 >= RC->getNumRegs())
20251 return std::pair(0U, nullptr);
20252
20253 uint32_t Width = NumRegs * 32;
20254 // Prohibit constraints for register ranges with a width that does not
20255 // match the required type.
20256 if (VT.SimpleTy != MVT::Other && Width != VT.getSizeInBits())
20257 return std::pair(0U, nullptr);
20258
20259 MCRegister Reg = RC->getRegister(Idx);
20261 RC = TRI->getVGPRClassForBitWidth(Width);
20262 else if (SIRegisterInfo::isSGPRClass(RC))
20263 RC = TRI->getSGPRClassForBitWidth(Width);
20264 else if (SIRegisterInfo::isAGPRClass(RC))
20265 RC = TRI->getAGPRClassForBitWidth(Width);
20266 if (RC) {
20267 Reg = TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
20268 if (!Reg) {
20269 // The register class does not contain the requested register,
20270 // e.g., because it is an SGPR pair that would violate alignment
20271 // requirements.
20272 return std::pair(0U, nullptr);
20273 }
20274 return std::pair(Reg, RC);
20275 }
20276 }
20277
20278 // Reject types that do not fit a single 32-bit register: any scalar wider
20279 // than 32 bits, or a vector that is not exactly 32 bits.
20280 if (VT.SimpleTy != MVT::Other &&
20281 (VT.getSizeInBits() > 32 ||
20282 (VT.isVector() && VT.getSizeInBits() != 32)))
20283 return std::pair(0U, nullptr);
20284 if (RC && Idx < RC->getNumRegs())
20285 return std::pair(RC->getRegister(Idx), RC);
20286 return std::pair(0U, nullptr);
20287 }
20288 }
20289
20290 auto Ret = TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20291 if (Ret.first) {
20292 Ret.second = TRI->getPhysRegBaseClass(Ret.first);
20293 if (!Subtarget->useRealTrue16Insts() &&
20294 TRI->getRegSizeInBits(*Ret.second) == 16)
20295 return std::pair(0U, nullptr);
20296 }
20297
20298 return Ret;
20299}
20300
20301static bool isImmConstraint(StringRef Constraint) {
20302 if (Constraint.size() == 1) {
20303 switch (Constraint[0]) {
20304 default:
20305 break;
20306 case 'I':
20307 case 'J':
20308 case 'A':
20309 case 'B':
20310 case 'C':
20311 return true;
20312 }
20313 } else if (Constraint == "DA" || Constraint == "DB") {
20314 return true;
20315 }
20316 return false;
20317}
20318
20321 if (Constraint.size() == 1) {
20322 switch (Constraint[0]) {
20323 default:
20324 break;
20325 case 's':
20326 case 'v':
20327 case 'a':
20328 return C_RegisterClass;
20329 }
20330 } else if (Constraint.size() == 2) {
20331 if (Constraint == "VA")
20332 return C_RegisterClass;
20333 }
20334 if (isImmConstraint(Constraint)) {
20335 return C_Other;
20336 }
20337 return TargetLowering::getConstraintType(Constraint);
20338}
20339
20340static uint64_t clearUnusedBits(uint64_t Val, unsigned Size) {
20342 Val = Val & maskTrailingOnes<uint64_t>(Size);
20343 }
20344 return Val;
20345}
20346
20348 StringRef Constraint,
20349 std::vector<SDValue> &Ops,
20350 SelectionDAG &DAG) const {
20351 if (isImmConstraint(Constraint)) {
20352 uint64_t Val;
20353 if (getAsmOperandConstVal(Op, Val) &&
20354 checkAsmConstraintVal(Op, Constraint, Val)) {
20355 Val = clearUnusedBits(Val, Op.getScalarValueSizeInBits());
20356 Ops.push_back(DAG.getTargetConstant(Val, SDLoc(Op), MVT::i64));
20357 }
20358 } else {
20360 }
20361}
20362
20364 unsigned Size = Op.getScalarValueSizeInBits();
20365 if (Size > 64)
20366 return false;
20367
20368 if (Size == 16 && !Subtarget->has16BitInsts())
20369 return false;
20370
20372 Val = C->getSExtValue();
20373 return true;
20374 }
20376 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
20377 return true;
20378 }
20380 if (Size != 16 || Op.getNumOperands() != 2)
20381 return false;
20382 if (Op.getOperand(0).isUndef() || Op.getOperand(1).isUndef())
20383 return false;
20384 if (ConstantSDNode *C = V->getConstantSplatNode()) {
20385 Val = C->getSExtValue();
20386 return true;
20387 }
20388 if (ConstantFPSDNode *C = V->getConstantFPSplatNode()) {
20389 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
20390 return true;
20391 }
20392 }
20393
20394 return false;
20395}
20396
20398 uint64_t Val) const {
20399 if (Constraint.size() == 1) {
20400 switch (Constraint[0]) {
20401 case 'I':
20403 case 'J':
20404 return isInt<16>(Val);
20405 case 'A':
20406 return checkAsmConstraintValA(Op, Val);
20407 case 'B':
20408 return isInt<32>(Val);
20409 case 'C':
20410 return isUInt<32>(clearUnusedBits(Val, Op.getScalarValueSizeInBits())) ||
20412 default:
20413 break;
20414 }
20415 } else if (Constraint.size() == 2) {
20416 if (Constraint == "DA") {
20417 int64_t HiBits = static_cast<int32_t>(Val >> 32);
20418 int64_t LoBits = static_cast<int32_t>(Val);
20419 return checkAsmConstraintValA(Op, HiBits, 32) &&
20420 checkAsmConstraintValA(Op, LoBits, 32);
20421 }
20422 if (Constraint == "DB") {
20423 return true;
20424 }
20425 }
20426 llvm_unreachable("Invalid asm constraint");
20427}
20428
20430 unsigned MaxSize) const {
20431 unsigned Size = std::min<unsigned>(Op.getScalarValueSizeInBits(), MaxSize);
20432 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
20433 if (Size == 16) {
20434 MVT VT = Op.getSimpleValueType();
20435 switch (VT.SimpleTy) {
20436 default:
20437 return false;
20438 case MVT::i16:
20439 return AMDGPU::isInlinableLiteralI16(Val, HasInv2Pi);
20440 case MVT::f16:
20441 return AMDGPU::isInlinableLiteralFP16(Val, HasInv2Pi);
20442 case MVT::bf16:
20443 return AMDGPU::isInlinableLiteralBF16(Val, HasInv2Pi);
20444 case MVT::v2i16:
20445 return AMDGPU::getInlineEncodingV2I16(Val).has_value();
20446 case MVT::v2f16:
20447 return AMDGPU::getInlineEncodingV2F16(Val).has_value();
20448 case MVT::v2bf16:
20449 return AMDGPU::getInlineEncodingV2BF16(Val).has_value();
20450 }
20451 }
20452 if ((Size == 32 && AMDGPU::isInlinableLiteral32(Val, HasInv2Pi)) ||
20453 (Size == 64 && AMDGPU::isInlinableLiteral64(Val, HasInv2Pi)))
20454 return true;
20455 return false;
20456}
20457
20458static int getAlignedAGPRClassID(unsigned UnalignedClassID) {
20459 switch (UnalignedClassID) {
20460 case AMDGPU::VReg_64RegClassID:
20461 return AMDGPU::VReg_64_Align2RegClassID;
20462 case AMDGPU::VReg_96RegClassID:
20463 return AMDGPU::VReg_96_Align2RegClassID;
20464 case AMDGPU::VReg_128RegClassID:
20465 return AMDGPU::VReg_128_Align2RegClassID;
20466 case AMDGPU::VReg_160RegClassID:
20467 return AMDGPU::VReg_160_Align2RegClassID;
20468 case AMDGPU::VReg_192RegClassID:
20469 return AMDGPU::VReg_192_Align2RegClassID;
20470 case AMDGPU::VReg_224RegClassID:
20471 return AMDGPU::VReg_224_Align2RegClassID;
20472 case AMDGPU::VReg_256RegClassID:
20473 return AMDGPU::VReg_256_Align2RegClassID;
20474 case AMDGPU::VReg_288RegClassID:
20475 return AMDGPU::VReg_288_Align2RegClassID;
20476 case AMDGPU::VReg_320RegClassID:
20477 return AMDGPU::VReg_320_Align2RegClassID;
20478 case AMDGPU::VReg_352RegClassID:
20479 return AMDGPU::VReg_352_Align2RegClassID;
20480 case AMDGPU::VReg_384RegClassID:
20481 return AMDGPU::VReg_384_Align2RegClassID;
20482 case AMDGPU::VReg_512RegClassID:
20483 return AMDGPU::VReg_512_Align2RegClassID;
20484 case AMDGPU::VReg_1024RegClassID:
20485 return AMDGPU::VReg_1024_Align2RegClassID;
20486 case AMDGPU::AReg_64RegClassID:
20487 return AMDGPU::AReg_64_Align2RegClassID;
20488 case AMDGPU::AReg_96RegClassID:
20489 return AMDGPU::AReg_96_Align2RegClassID;
20490 case AMDGPU::AReg_128RegClassID:
20491 return AMDGPU::AReg_128_Align2RegClassID;
20492 case AMDGPU::AReg_160RegClassID:
20493 return AMDGPU::AReg_160_Align2RegClassID;
20494 case AMDGPU::AReg_192RegClassID:
20495 return AMDGPU::AReg_192_Align2RegClassID;
20496 case AMDGPU::AReg_256RegClassID:
20497 return AMDGPU::AReg_256_Align2RegClassID;
20498 case AMDGPU::AReg_512RegClassID:
20499 return AMDGPU::AReg_512_Align2RegClassID;
20500 case AMDGPU::AReg_1024RegClassID:
20501 return AMDGPU::AReg_1024_Align2RegClassID;
20502 default:
20503 return -1;
20504 }
20505}
20506
20507// Figure out which registers should be reserved for stack access. Only after
20508// the function is legalized do we know all of the non-spill stack objects or if
20509// calls are present.
20513 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
20514 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20515 const SIInstrInfo *TII = ST.getInstrInfo();
20516
20517 if (Info->isEntryFunction()) {
20518 // Callable functions have fixed registers used for stack access.
20520 }
20521
20522 // TODO: Move this logic to getReservedRegs()
20523 // Reserve the SGPR(s) to save/restore EXEC for WWM spill/copy handling.
20524 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20525 Register SReg = ST.isWave32()
20526 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20527 : TRI->getAlignedHighSGPRForRC(MF, /*Align=*/2,
20528 &AMDGPU::SGPR_64RegClass);
20529 Info->setSGPRForEXECCopy(SReg);
20530
20531 assert(!TRI->isSubRegister(Info->getScratchRSrcReg(),
20532 Info->getStackPtrOffsetReg()));
20533 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20534 MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20535
20536 // We need to worry about replacing the default register with itself in case
20537 // of MIR testcases missing the MFI.
20538 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20539 MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20540
20541 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20542 MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());
20543
20544 Info->limitOccupancy(MF);
20545
20546 if (ST.isWave32() && !MF.empty()) {
20547 for (auto &MBB : MF) {
20548 for (auto &MI : MBB) {
20549 TII->fixImplicitOperands(MI);
20550 }
20551 }
20552 }
20553
20554 // FIXME: This is a hack to fixup AGPR classes to use the properly aligned
20555 // classes if required. Ideally the register class constraints would differ
20556 // per-subtarget, but there's no easy way to achieve that right now. This is
20557 // not a problem for VGPRs because the correctly aligned VGPR class is implied
20558 // from using them as the register class for legal types.
20559 if (ST.needsAlignedVGPRs()) {
20560 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
20561 const Register Reg = Register::index2VirtReg(I);
20562 const TargetRegisterClass *RC = MRI.getRegClassOrNull(Reg);
20563 if (!RC)
20564 continue;
20565 int NewClassID = getAlignedAGPRClassID(RC->getID());
20566 if (NewClassID != -1)
20567 MRI.setRegClass(Reg, TRI->getRegClass(NewClassID));
20568 }
20569 }
20570
20572}
20573
20576 const APInt &DemandedElts,
20577 const SelectionDAG &DAG,
20578 unsigned Depth) const {
20579 Known.resetAll();
20580 unsigned Opc = Op.getOpcode();
20581 switch (Opc) {
20583 unsigned IID = Op.getConstantOperandVal(0);
20584 switch (IID) {
20585 case Intrinsic::amdgcn_mbcnt_lo:
20586 case Intrinsic::amdgcn_mbcnt_hi: {
20587 const GCNSubtarget &ST =
20589 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20590 // most 31 + src1.
20591 Known.Zero.setBitsFrom(
20592 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20593 KnownBits Known2 = DAG.computeKnownBits(Op.getOperand(2), Depth + 1);
20594 Known = KnownBits::add(Known, Known2);
20595 return;
20596 }
20597 }
20598 break;
20599 }
20600 }
20602 Op, Known, DemandedElts, DAG, Depth);
20603}
20604
20606 KnownBits &Known, const MachineFunction &MF, Align Alignment) const {
20608
20609 // Set the high bits to zero based on the maximum allowed scratch size per
20610 // wave. We can't use vaddr in MUBUF instructions if we don't know the address
20611 // calculation won't overflow, so assume the sign bit is never set.
20612 Known.Zero.setHighBits(getSubtarget()->getKnownHighZeroBitsForFrameIndex());
20613}
20614
20617 unsigned Dim) {
20618 unsigned MaxValue =
20619 ST.getMaxWorkitemID(VT.getMachineFunction().getFunction(), Dim);
20620 Known.Zero.setHighBits(llvm::countl_zero(MaxValue));
20621}
20622
20624 KnownBits &Known, const APInt &DemandedElts,
20625 unsigned BFEWidth, bool SExt, unsigned Depth) {
20627 const MachineOperand &Src1 = MI.getOperand(2);
20628
20629 unsigned Src1Cst = 0;
20630 if (Src1.isImm()) {
20631 Src1Cst = Src1.getImm();
20632 } else if (Src1.isReg()) {
20633 auto Cst = getIConstantVRegValWithLookThrough(Src1.getReg(), MRI);
20634 if (!Cst)
20635 return;
20636 Src1Cst = Cst->Value.getZExtValue();
20637 } else {
20638 return;
20639 }
20640
20641 // Offset is at bits [4:0] for 32 bit, [5:0] for 64 bit.
20642 // Width is always [22:16].
20643 const unsigned Offset =
20644 Src1Cst & maskTrailingOnes<unsigned>((BFEWidth == 32) ? 5 : 6);
20645 const unsigned Width = (Src1Cst >> 16) & maskTrailingOnes<unsigned>(6);
20646
20647 if (Width >= BFEWidth) // Ill-formed.
20648 return;
20649
20650 VT.computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
20651 Depth + 1);
20652
20653 Known = Known.extractBits(Width, Offset);
20654
20655 if (SExt)
20656 Known = Known.sext(BFEWidth);
20657 else
20658 Known = Known.zext(BFEWidth);
20659}
20660
20663 const APInt &DemandedElts, const MachineRegisterInfo &MRI,
20664 unsigned Depth) const {
20665 Known.resetAll();
20666 const MachineInstr *MI = MRI.getVRegDef(R);
20667 switch (MI->getOpcode()) {
20668 case AMDGPU::S_BFE_I32:
20669 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20670 /*SExt=*/true, Depth);
20671 case AMDGPU::S_BFE_U32:
20672 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20673 /*SExt=*/false, Depth);
20674 case AMDGPU::S_BFE_I64:
20675 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20676 /*SExt=*/true, Depth);
20677 case AMDGPU::S_BFE_U64:
20678 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20679 /*SExt=*/false, Depth);
20680 case AMDGPU::G_INTRINSIC:
20681 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20682 Intrinsic::ID IID = cast<GIntrinsic>(MI)->getIntrinsicID();
20683 switch (IID) {
20684 case Intrinsic::amdgcn_workitem_id_x:
20686 break;
20687 case Intrinsic::amdgcn_workitem_id_y:
20689 break;
20690 case Intrinsic::amdgcn_workitem_id_z:
20692 break;
20693 case Intrinsic::amdgcn_mbcnt_lo:
20694 case Intrinsic::amdgcn_mbcnt_hi: {
20695 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20696 // most 31 + src1.
20697 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20698 ? getSubtarget()->getWavefrontSizeLog2()
20699 : 5);
20700 KnownBits Known2;
20701 VT.computeKnownBitsImpl(MI->getOperand(3).getReg(), Known2, DemandedElts,
20702 Depth + 1);
20703 Known = KnownBits::add(Known, Known2);
20704 break;
20705 }
20706 case Intrinsic::amdgcn_groupstaticsize: {
20707 // We can report everything over the maximum size as 0. We can't report
20708 // based on the actual size because we don't know if it's accurate or not
20709 // at any given point.
20710 Known.Zero.setHighBits(
20711 llvm::countl_zero(getSubtarget()->getAddressableLocalMemorySize()));
20712 break;
20713 }
20714 case Intrinsic::amdgcn_readfirstlane:
20715 case Intrinsic::amdgcn_readlane: {
20716 // Result is the data operand's value from some lane.
20717 VT.computeKnownBitsImpl(MI->getOperand(2).getReg(), Known, DemandedElts,
20718 Depth + 1);
20719 break;
20720 }
20721 case Intrinsic::amdgcn_mul_u24:
20722 case Intrinsic::amdgcn_mul_i24: {
20723 Register LHS = MI->getOperand(2).getReg();
20724 Register RHS = MI->getOperand(3).getReg();
20725
20726 KnownBits RHSKnown;
20727 VT.computeKnownBitsImpl(RHS, RHSKnown, DemandedElts, Depth + 1);
20728
20729 bool SelfMultiply = LHS == RHS;
20730
20731 // For a self-multiply both operands are the same value, so RHSKnown also
20732 // describes the LHS; avoid the duplicated query.
20733 KnownBits LHSKnown;
20734 if (SelfMultiply)
20735 LHSKnown = RHSKnown;
20736 else
20737 VT.computeKnownBitsImpl(LHS, LHSKnown, DemandedElts, Depth + 1);
20738
20739 if (SelfMultiply)
20740 SelfMultiply &= isGuaranteedNotToBeUndef(LHS, MRI, Depth + 1);
20741
20742 Known = computeKnownBitsForMul24(LHSKnown, RHSKnown, Known.getBitWidth(),
20743 IID == Intrinsic::amdgcn_mul_i24,
20744 SelfMultiply);
20745 break;
20746 }
20747 }
20748 break;
20749 }
20750 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20751 Known.Zero.setHighBits(24);
20752 break;
20753 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20754 Known.Zero.setHighBits(16);
20755 break;
20756 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20757 // G_AMDGPU_COPY_SCC_VCC converts a uniform boolean in VCC to SGPR s32,
20758 // producing exactly 0 or 1.
20759 Known.Zero.setHighBits(Known.getBitWidth() - 1);
20760 break;
20761 case AMDGPU::G_AMDGPU_SMED3:
20762 case AMDGPU::G_AMDGPU_UMED3: {
20763 auto [Dst, Src0, Src1, Src2] = MI->getFirst4Regs();
20764
20765 KnownBits Known2;
20766 VT.computeKnownBitsImpl(Src2, Known2, DemandedElts, Depth + 1);
20767 if (Known2.isUnknown())
20768 break;
20769
20770 KnownBits Known1;
20771 VT.computeKnownBitsImpl(Src1, Known1, DemandedElts, Depth + 1);
20772 if (Known1.isUnknown())
20773 break;
20774
20775 KnownBits Known0;
20776 VT.computeKnownBitsImpl(Src0, Known0, DemandedElts, Depth + 1);
20777 if (Known0.isUnknown())
20778 break;
20779
20780 // TODO: Handle LeadZero/LeadOne from UMIN/UMAX handling.
20781 Known.Zero = Known0.Zero & Known1.Zero & Known2.Zero;
20782 Known.One = Known0.One & Known1.One & Known2.One;
20783 break;
20784 }
20785 }
20786}
20787
20790 unsigned Depth) const {
20791 const MachineInstr *MI = MRI.getVRegDef(R);
20792 if (auto *GI = dyn_cast<GIntrinsic>(MI)) {
20793 // FIXME: Can this move to generic code? What about the case where the call
20794 // site specifies a lower alignment?
20795 Intrinsic::ID IID = GI->getIntrinsicID();
20797 AttributeList Attrs =
20798 Intrinsic::getAttributes(Ctx, IID, Intrinsic::getType(Ctx, IID));
20799 if (MaybeAlign RetAlign = Attrs.getRetAlignment())
20800 return *RetAlign;
20801 }
20802 return Align(1);
20803}
20804
20806 MachineLoop *ML, const MachineBasicBlock *BlockToAlign) const {
20808 const Align CacheLineAlign = Align(64);
20809
20810 // GFX950: Prevent an 8-byte instruction at the block being aligned from being
20811 // split by the 32-byte instruction fetch window boundary. This avoids a
20812 // significant fetch delay after a backward branch. We use 32-byte alignment
20813 // with max padding of 4 bytes (one s_nop), see
20814 // getMaxPermittedBytesForAlignment().
20815 if (ML && getSubtarget()->getCLOpts().loop_alignment &&
20816 getSubtarget()->hasLoopHeadInstSplitSensitivity()) {
20817 // Loop rotation can make the backedge destination a block other than the
20818 // LoopInfo header, so prefer the block the caller is actually aligning.
20819 if (!BlockToAlign)
20820 BlockToAlign = ML->getHeader();
20821 // Respect user-specified or previously set alignment.
20822 if (BlockToAlign->getAlignment() != PrefAlign)
20823 return BlockToAlign->getAlignment();
20824 if (needsFetchWindowAlignment(*BlockToAlign))
20825 return Align(32);
20826 }
20827
20828 // Pre-GFX10 target did not benefit from loop alignment
20829 if (!ML || !getSubtarget()->getCLOpts().loop_alignment ||
20830 !getSubtarget()->hasInstPrefetch() ||
20831 getSubtarget()->hasInstFwdPrefetchBug())
20832 return PrefAlign;
20833
20834 // On GFX10 I$ is 4 x 64 bytes cache lines.
20835 // By default prefetcher keeps one cache line behind and reads two ahead.
20836 // We can modify it with S_INST_PREFETCH for larger loops to have two lines
20837 // behind and one ahead.
20838 // Therefor we can benefit from aligning loop headers if loop fits 192 bytes.
20839 // If loop fits 64 bytes it always spans no more than two cache lines and
20840 // does not need an alignment.
20841 // Else if loop is less or equal 128 bytes we do not need to modify prefetch,
20842 // Else if loop is less or equal 192 bytes we need two lines behind.
20843
20845 const MachineBasicBlock *Header = ML->getHeader();
20846 if (Header->getAlignment() != PrefAlign)
20847 return Header->getAlignment(); // Already processed.
20848
20849 unsigned LoopSize = 0;
20850 for (const MachineBasicBlock *MBB : ML->blocks()) {
20851 // If inner loop block is aligned assume in average half of the alignment
20852 // size to be added as nops.
20853 if (MBB != Header)
20854 LoopSize += MBB->getAlignment().value() / 2;
20855
20856 for (const MachineInstr &MI : *MBB) {
20857 LoopSize += TII->getInstSizeInBytes(MI);
20858 if (LoopSize > 192)
20859 return PrefAlign;
20860 }
20861 }
20862
20863 if (LoopSize <= 64)
20864 return PrefAlign;
20865
20866 if (LoopSize <= 128)
20867 return CacheLineAlign;
20868
20869 // If any of parent loops is surrounded by prefetch instructions do not
20870 // insert new for inner loop, which would reset parent's settings.
20871 for (MachineLoop *P = ML->getParentLoop(); P; P = P->getParentLoop()) {
20872 if (MachineBasicBlock *Exit = P->getExitBlock()) {
20873 auto I = Exit->getFirstNonDebugInstr();
20874 if (I != Exit->end() && I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20875 return CacheLineAlign;
20876 }
20877 }
20878
20879 MachineBasicBlock *Pre = ML->getLoopPreheader();
20880 MachineBasicBlock *Exit = ML->getExitBlock();
20881
20882 if (Pre && Exit) {
20883 auto PreTerm = Pre->getFirstTerminator();
20884 if (PreTerm == Pre->begin() ||
20885 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20886 BuildMI(*Pre, PreTerm, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20887 .addImm(1); // prefetch 2 lines behind PC
20888
20889 auto ExitHead = Exit->getFirstNonDebugInstr();
20890 if (ExitHead == Exit->end() ||
20891 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20892 BuildMI(*Exit, ExitHead, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20893 .addImm(2); // prefetch 1 line behind PC
20894 }
20895
20896 return CacheLineAlign;
20897}
20898
20900 MachineBasicBlock *MBB) const {
20901 // GFX950: Limit padding to 4 bytes (one s_nop) for blocks where an 8-byte
20902 // instruction could be split by the 32-byte fetch window boundary.
20903 // See getPrefLoopAlignment() for context.
20904 if (needsFetchWindowAlignment(*MBB))
20905 return 4;
20907}
20908
20909bool SITargetLowering::needsFetchWindowAlignment(
20910 const MachineBasicBlock &MBB) const {
20911 if (!getSubtarget()->hasLoopHeadInstSplitSensitivity())
20912 return false;
20914 for (const MachineInstr &MI : MBB) {
20915 if (MI.isMetaInstruction())
20916 continue;
20917 // Instructions larger than 4 bytes can be split by a 32-byte boundary.
20918 return TII->getInstSizeInBytes(MI) > 4;
20919 }
20920 return false;
20921}
20922
20923[[maybe_unused]]
20924static bool isCopyFromRegOfInlineAsm(const SDNode *N) {
20925 assert(N->getOpcode() == ISD::CopyFromReg);
20926 do {
20927 // Follow the chain until we find an INLINEASM node.
20928 N = N->getOperand(0).getNode();
20929 if (N->getOpcode() == ISD::INLINEASM || N->getOpcode() == ISD::INLINEASM_BR)
20930 return true;
20931 } while (N->getOpcode() == ISD::CopyFromReg);
20932 return false;
20933}
20934
20937 UniformityInfo *UA) const {
20938 switch (N->getOpcode()) {
20939 case ISD::CopyFromReg: {
20940 const RegisterSDNode *R = cast<RegisterSDNode>(N->getOperand(1));
20941 const MachineRegisterInfo &MRI = FLI->MF->getRegInfo();
20942 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20943 Register Reg = R->getReg();
20944
20945 // FIXME: Why does this need to consider isLiveIn?
20946 if (Reg.isPhysical() || MRI.isLiveIn(Reg))
20947 return !TRI->isSGPRReg(MRI, Reg);
20948
20949 if (const Value *V = FLI->getValueFromVirtualReg(R->getReg()))
20950 return UA->isDivergentAtDef(V);
20951
20953 return !TRI->isSGPRReg(MRI, Reg);
20954 }
20955 case ISD::LOAD: {
20956 const LoadSDNode *L = cast<LoadSDNode>(N);
20957 unsigned AS = L->getAddressSpace();
20958 // A flat load may access private memory.
20960 }
20961 case ISD::CALLSEQ_END:
20962 return true;
20964 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(0));
20966 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(1));
20967 case AMDGPUISD::ATOMIC_CMP_SWAP:
20968 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20969 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20970 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20971 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20972 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20973 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20974 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20975 case AMDGPUISD::BUFFER_ATOMIC_AND:
20976 case AMDGPUISD::BUFFER_ATOMIC_OR:
20977 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20978 case AMDGPUISD::BUFFER_ATOMIC_INC:
20979 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20980 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20981 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20982 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20983 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20984 // Target-specific read-modify-write atomics are sources of divergence.
20985 return true;
20986 default:
20987 if (auto *A = dyn_cast<AtomicSDNode>(N)) {
20988 // Generic read-modify-write atomics are sources of divergence.
20989 return A->readMem() && A->writeMem();
20990 }
20991 return false;
20992 }
20993}
20994
20996 EVT VT) const {
20997 switch (VT.getScalarType().getSimpleVT().SimpleTy) {
20998 case MVT::f32:
21000 case MVT::f64:
21001 case MVT::f16:
21003 default:
21004 return false;
21005 }
21006}
21007
21009 LLT Ty, const MachineFunction &MF) const {
21010 switch (Ty.getScalarSizeInBits()) {
21011 case 32:
21012 return !denormalModeIsFlushAllF32(MF);
21013 case 64:
21014 case 16:
21015 return !denormalModeIsFlushAllF64F16(MF);
21016 default:
21017 return false;
21018 }
21019}
21020
21022 const APInt &DemandedElts,
21023 const SelectionDAG &DAG,
21024 bool SNaN,
21025 unsigned Depth) const {
21026 if (Op.getOpcode() == AMDGPUISD::CLAMP) {
21027 const MachineFunction &MF = DAG.getMachineFunction();
21029
21030 if (Info->getMode().DX10Clamp)
21031 return true; // Clamped to 0.
21032 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);
21033 }
21034
21036 DAG, SNaN, Depth);
21037}
21038
21039namespace {
21040
21041/// Why a floating-point atomic instruction which may flush denormals is
21042/// acceptable.
21043enum class AtomicFlushDenormalReason {
21044 Native,
21045 IEEE,
21046 IgnoreDenormalMode,
21047 FunctionFlushesDenormals
21048};
21049
21050/// Why a native floating-point atomic instruction is acceptable for a global
21051/// memory address.
21052enum class GlobalFPAtomicLegality {
21053 Illegal,
21054 AgentScopeFineGrainedRemoteMemory,
21055 EmulatedSystemScope,
21056 NoRemoteMemory,
21057 NoFineGrainedMemory
21058};
21059
21060} // end anonymous namespace
21061
21062// On older subtargets, global FP atomic instructions have a hardcoded FP mode
21063// and do not support FP32 denormals, and only support v2f16/f64 denormals.
21064static AtomicFlushDenormalReason
21066 if (RMW->hasMetadata(LLVMContext::MD_atomic_ignore_denormal_mode))
21067 return AtomicFlushDenormalReason::IgnoreDenormalMode;
21068
21069 const fltSemantics &Flt = RMW->getType()->getScalarType()->getFltSemantics();
21070 auto DenormMode = RMW->getFunction()->getDenormalMode(Flt);
21071 return DenormMode == DenormalMode::getPreserveSign()
21072 ? AtomicFlushDenormalReason::FunctionFlushesDenormals
21073 : AtomicFlushDenormalReason::IEEE;
21074}
21075
21076static OptimizationRemark
21078 GlobalFPAtomicLegality MemLegality,
21079 AtomicFlushDenormalReason DenormReason) {
21080 LLVMContext &Ctx = RMW->getContext();
21081 StringRef MemScope = Ctx.getSyncScopeName(RMW->getSyncScopeID()).value_or("");
21082 if (MemScope.empty())
21083 MemScope = "system";
21084
21085 OptimizationRemark R(DEBUG_TYPE, "Passed", RMW);
21086 R << "hardware instruction generated for atomic "
21087 << ore::NV("Operation", RMW->getOperationName(RMW->getOperation()))
21088 << " at " << ore::NV("SyncScope", MemScope) << " scope since ";
21089
21090 switch (MemLegality) {
21091 case GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory:
21092 R << "fine-grained remote memory atomics work below system scope";
21093 break;
21094 case GlobalFPAtomicLegality::EmulatedSystemScope:
21095 R << "system scope atomics are emulated in hardware";
21096 break;
21097 case GlobalFPAtomicLegality::NoRemoteMemory:
21098 R << "memory is not remote (!amdgpu.no.remote.memory)";
21099 break;
21100 case GlobalFPAtomicLegality::NoFineGrainedMemory:
21101 R << "memory is not fine-grained (!amdgpu.no.fine.grained.memory)";
21102 break;
21103 case GlobalFPAtomicLegality::Illegal:
21104 llvm_unreachable("remark for illegal atomic");
21105 }
21106
21107 switch (DenormReason) {
21108 case AtomicFlushDenormalReason::Native:
21109 break;
21110 case AtomicFlushDenormalReason::IgnoreDenormalMode:
21111 R << ", and denormals may be flushed (!atomic.ignore.denormal.mode)";
21112 break;
21113 case AtomicFlushDenormalReason::FunctionFlushesDenormals:
21114 R << ", and the floating-point environment flushes denormals";
21115 break;
21116 case AtomicFlushDenormalReason::IEEE:
21117 llvm_unreachable("remark for illegal atomic");
21118 }
21119
21120 return R;
21121}
21122
21123static bool isV2F16OrV2BF16(Type *Ty) {
21124 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
21125 Type *EltTy = VT->getElementType();
21126 return VT->getNumElements() == 2 &&
21127 (EltTy->isHalfTy() || EltTy->isBFloatTy());
21128 }
21129
21130 return false;
21131}
21132
21133static bool isV2F16(Type *Ty) {
21135 return VT && VT->getNumElements() == 2 && VT->getElementType()->isHalfTy();
21136}
21137
21138static bool isV2BF16(Type *Ty) {
21140 return VT && VT->getNumElements() == 2 && VT->getElementType()->isBFloatTy();
21141}
21142
21143/// \return true if atomicrmw integer ops work for the type.
21144static bool isAtomicRMWLegalIntTy(Type *Ty) {
21145 if (auto *IT = dyn_cast<IntegerType>(Ty)) {
21146 unsigned BW = IT->getBitWidth();
21147 return BW == 32 || BW == 64;
21148 }
21149
21150 return false;
21151}
21152
21153/// \return true if this atomicrmw xchg type can be selected.
21154static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW) {
21155 Type *Ty = RMW->getType();
21156 if (isAtomicRMWLegalIntTy(Ty))
21157 return true;
21158
21159 if (PointerType *PT = dyn_cast<PointerType>(Ty)) {
21160 const DataLayout &DL = RMW->getFunction()->getDataLayout();
21161 unsigned BW = DL.getPointerSizeInBits(PT->getAddressSpace());
21162 return BW == 32 || BW == 64;
21163 }
21164
21165 if (Ty->isFloatTy() || Ty->isDoubleTy())
21166 return true;
21167
21169 return VT->getNumElements() == 2 &&
21170 VT->getElementType()->getPrimitiveSizeInBits() == 16;
21171 }
21172
21173 return false;
21174}
21175
21176/// \returns whether it's valid to emit a native instruction for \p RMW, and
21177/// why, based on the properties of the target memory.
21178static GlobalFPAtomicLegality
21180 const AtomicRMWInst *RMW, bool HasSystemScope) {
21181 // The remote/fine-grained access logic is different from the integer
21182 // atomics. Without AgentScopeFineGrainedRemoteMemoryAtomics support,
21183 // fine-grained access does not work, even for a device local allocation.
21184 //
21185 // With AgentScopeFineGrainedRemoteMemoryAtomics, system scoped device local
21186 // allocations work.
21187 if (HasSystemScope) {
21188 if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
21189 RMW->hasMetadata("amdgpu.no.remote.memory"))
21190 return GlobalFPAtomicLegality::NoRemoteMemory;
21191 if (Subtarget.hasEmulatedSystemScopeAtomics())
21192 return GlobalFPAtomicLegality::EmulatedSystemScope;
21193 } else if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
21194 return GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory;
21195
21196 return RMW->hasMetadata("amdgpu.no.fine.grained.memory")
21197 ? GlobalFPAtomicLegality::NoFineGrainedMemory
21198 : GlobalFPAtomicLegality::Illegal;
21199}
21200
21201/// \return Action to perform on AtomicRMWInsts for integer operations.
21208
21209/// Return if a flat address space atomicrmw can access private memory.
21211 const MDNode *MD = I->getMetadata(LLVMContext::MD_noalias_addrspace);
21212 return !MD ||
21214}
21215
21218 // For GAS, lower to flat atomic.
21219 return STI.hasGloballyAddressableScratch()
21222}
21223
21226 unsigned AS = RMW->getPointerAddressSpace();
21227 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
21229
21230 // 64-bit flat atomics that dynamically reside in private memory will silently
21231 // be dropped.
21232 //
21233 // Note that we will emit a new copy of the original atomic in the expansion,
21234 // which will be incrementally relegalized.
21235 const DataLayout &DL = RMW->getFunction()->getDataLayout();
21236 if (AS == AMDGPUAS::FLAT_ADDRESS &&
21237 DL.getTypeSizeInBits(RMW->getType()) == 64 &&
21240
21241 GlobalFPAtomicLegality MemLegality = GlobalFPAtomicLegality::Illegal;
21242 AtomicFlushDenormalReason DenormReason = AtomicFlushDenormalReason::Native;
21243 auto ReportHWInst = [&](TargetLowering::AtomicExpansionKind Kind) {
21245 ORE.emit([&]() {
21246 return emitAtomicRMWLegalRemark(RMW, MemLegality, DenormReason);
21247 });
21248 return Kind;
21249 };
21250
21251 auto SSID = RMW->getSyncScopeID();
21252 bool HasSystemScope =
21253 SSID == SyncScope::System ||
21255 getTargetMachine().getTargetTriple(), AtomicScope::System,
21256 /*OneAddressSpace=*/true));
21257
21258 auto Op = RMW->getOperation();
21259 switch (Op) {
21261 // PCIe supports add and xchg for system atomics.
21262 return isAtomicRMWLegalXChgTy(RMW)
21265 case AtomicRMWInst::Add:
21266 // PCIe supports add and xchg for system atomics.
21268 case AtomicRMWInst::Sub:
21269 case AtomicRMWInst::And:
21270 case AtomicRMWInst::Or:
21271 case AtomicRMWInst::Xor:
21272 case AtomicRMWInst::Max:
21273 case AtomicRMWInst::Min:
21280 if (Op == AtomicRMWInst::USubCond && !Subtarget->hasCondSubInsts())
21282 if (Op == AtomicRMWInst::USubSat) {
21283 // The global and buffer forms predate the LDS and flat ones.
21284 if (!Subtarget->hasSubClampInsts() ||
21285 (AS == AMDGPUAS::LOCAL_ADDRESS &&
21286 !Subtarget->hasAtomicDsCondSubClampInsts()) ||
21287 (AS == AMDGPUAS::FLAT_ADDRESS &&
21288 !Subtarget->hasAtomicCondSubClampFlatInsts()))
21290 }
21292 auto *IT = dyn_cast<IntegerType>(RMW->getType());
21293 if (!IT || IT->getBitWidth() != 32)
21295 }
21296
21299 if (Subtarget->hasEmulatedSystemScopeAtomics())
21301
21302 // On most subtargets, for atomicrmw operations other than add/xchg,
21303 // whether or not the instructions will behave correctly depends on where
21304 // the address physically resides and what interconnect is used in the
21305 // system configuration. On some some targets the instruction will nop,
21306 // and in others synchronization will only occur at degraded device scope.
21307 //
21308 // If the allocation is known local to the device, the instructions should
21309 // work correctly.
21310 if (RMW->hasMetadata("amdgpu.no.remote.memory"))
21312
21313 // If fine-grained remote memory works at device scope, we don't need to
21314 // do anything.
21315 if (!HasSystemScope &&
21316 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
21318
21319 // If we are targeting a remote allocated address, it depends what kind of
21320 // allocation the address belongs to.
21321 //
21322 // If the allocation is fine-grained (in host memory, or in PCIe peer
21323 // device memory), the operation will fail depending on the target.
21324 //
21325 // Note fine-grained host memory access does work on APUs or if XGMI is
21326 // used, but we do not know if we are targeting an APU or the system
21327 // configuration from the ISA version/target-cpu.
21328 if (RMW->hasMetadata("amdgpu.no.fine.grained.memory"))
21330
21333 // Atomic sub/or/xor do not work over PCI express, but atomic add
21334 // does. InstCombine transforms these with 0 to or, so undo that.
21335 // Sub-word types are not selectable and take the cmpxchg expansion.
21336 if (const Constant *ConstVal = dyn_cast<Constant>(RMW->getValOperand());
21337 ConstVal && ConstVal->isNullValue() &&
21340 }
21341
21342 // If the allocation could be in remote, fine-grained memory, the rmw
21343 // instructions may fail. cmpxchg should work, so emit that. On some
21344 // system configurations, PCIe atomics aren't supported so cmpxchg won't
21345 // even work, so you're out of luck anyway.
21346
21347 // In summary:
21348 //
21349 // Cases that may fail:
21350 // - fine-grained pinned host memory
21351 // - fine-grained migratable host memory
21352 // - fine-grained PCIe peer device
21353 //
21354 // Cases that should work, but may be treated overly conservatively.
21355 // - fine-grained host memory on an APU
21356 // - fine-grained XGMI peer device
21358 }
21359
21361 }
21362 case AtomicRMWInst::FAdd: {
21363 Type *Ty = RMW->getType();
21364
21365 // TODO: Handle REGION_ADDRESS
21366 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
21367 // DS F32 FP atomics do respect the denormal mode, but the rounding mode
21368 // is fixed to round-to-nearest-even.
21369 //
21370 // F64 / PK_F16 / PK_BF16 never flush and are also fixed to
21371 // round-to-nearest-even.
21372 //
21373 // We ignore the rounding mode problem, even in strictfp. The C++ standard
21374 // suggests it is OK if the floating-point mode may not match the calling
21375 // thread.
21376 if (Ty->isFloatTy()) {
21377 return Subtarget->hasLDSFPAtomicAddF32() ? AtomicExpansionKind::None
21379 }
21380
21381 if (Ty->isDoubleTy()) {
21382 // Ignores denormal mode, but we don't consider flushing mandatory.
21383 return Subtarget->hasLdsAtomicAddF64() ? AtomicExpansionKind::None
21385 }
21386
21387 if (Subtarget->hasAtomicDsPkAdd16Insts() && isV2F16OrV2BF16(Ty))
21389
21391 }
21392
21393 // LDS atomics respect the denormal mode from the mode register.
21394 //
21395 // Traditionally f32 global/buffer memory atomics would unconditionally
21396 // flush denormals, but newer targets do not flush. f64/f16/bf16 cases never
21397 // flush.
21398 //
21399 // On targets with flat atomic fadd, denormals would flush depending on
21400 // whether the target address resides in LDS or global memory. We consider
21401 // this flat-maybe-flush as will-flush.
21402 if (Ty->isFloatTy() &&
21403 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport()) {
21404 DenormReason = getAtomicFlushDenormalReason(RMW);
21405 if (DenormReason == AtomicFlushDenormalReason::IEEE)
21407 }
21408
21409 MemLegality =
21410 getGlobalMemoryFPAtomicLegality(*Subtarget, RMW, HasSystemScope);
21411 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21412 if (AS == AMDGPUAS::FLAT_ADDRESS) {
21413 // gfx942, gfx12
21414 if (Subtarget->hasAtomicFlatPkAdd16Insts() && isV2F16OrV2BF16(Ty))
21415 return ReportHWInst(AtomicExpansionKind::None);
21416 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS)) {
21417 // gfx90a, gfx942, gfx12
21418 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
21419 return ReportHWInst(AtomicExpansionKind::None);
21420
21421 // gfx942, gfx12
21422 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() && isV2BF16(Ty))
21423 return ReportHWInst(AtomicExpansionKind::None);
21424 } else if (AS == AMDGPUAS::BUFFER_FAT_POINTER) {
21425 // gfx90a, gfx942, gfx12
21426 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
21427 return ReportHWInst(AtomicExpansionKind::None);
21428
21429 // While gfx90a/gfx942 supports v2bf16 for global/flat, it does not for
21430 // buffer. gfx12 does have the buffer version.
21431 if (Subtarget->hasAtomicBufferPkAddBF16Inst() && isV2BF16(Ty))
21432 return ReportHWInst(AtomicExpansionKind::None);
21433 }
21434
21435 // global and flat atomic fadd f64: gfx90a, gfx942.
21436 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
21437 return ReportHWInst(AtomicExpansionKind::None);
21438
21439 if (AS != AMDGPUAS::FLAT_ADDRESS) {
21440 if (Ty->isFloatTy()) {
21441 // global/buffer atomic fadd f32 no-rtn: gfx908, gfx90a, gfx942,
21442 // gfx11+.
21443 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21444 return ReportHWInst(AtomicExpansionKind::None);
21445 // global/buffer atomic fadd f32 rtn: gfx90a, gfx942, gfx11+.
21446 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21447 return ReportHWInst(AtomicExpansionKind::None);
21448 } else {
21449 // gfx908
21450 if (RMW->use_empty() &&
21451 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
21452 isV2F16(Ty))
21453 return ReportHWInst(AtomicExpansionKind::None);
21454 }
21455 }
21456
21457 // flat atomic fadd f32: gfx942, gfx11+.
21458 if (AS == AMDGPUAS::FLAT_ADDRESS && Ty->isFloatTy()) {
21459 if (Subtarget->hasFlatAtomicFaddF32Inst())
21460 return ReportHWInst(AtomicExpansionKind::None);
21461
21462 // If it is in flat address space, and the type is float, we will try to
21463 // expand it, if the target supports global and lds atomic fadd. The
21464 // reason we need that is, in the expansion, we emit the check of
21465 // address space. If it is in global address space, we emit the global
21466 // atomic fadd; if it is in shared address space, we emit the LDS atomic
21467 // fadd.
21468 if (Subtarget->hasLDSFPAtomicAddF32()) {
21469 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21471 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21473 }
21474 }
21475 }
21476
21478 }
21480 case AtomicRMWInst::FMax: {
21481 Type *Ty = RMW->getType();
21482
21483 // LDS float and double fmin/fmax were always supported.
21484 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
21485 return Ty->isFloatTy() || Ty->isDoubleTy() ? AtomicExpansionKind::None
21487 }
21488
21489 MemLegality =
21490 getGlobalMemoryFPAtomicLegality(*Subtarget, RMW, HasSystemScope);
21491 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21492 // For flat and global cases:
21493 // float, double in gfx7. Manual claims denormal support.
21494 // Removed in gfx8.
21495 // float, double restored in gfx10.
21496 // double removed again in gfx11, so only f32 for gfx11/gfx12.
21497 //
21498 // For gfx9, gfx90a and gfx942 support f64 for global (same as fadd), but
21499 // no f32.
21500 if (AS == AMDGPUAS::FLAT_ADDRESS) {
21501 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
21502 return ReportHWInst(AtomicExpansionKind::None);
21503 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
21504 return ReportHWInst(AtomicExpansionKind::None);
21505 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS) ||
21507 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
21508 return ReportHWInst(AtomicExpansionKind::None);
21509 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
21510 return ReportHWInst(AtomicExpansionKind::None);
21511 }
21512 }
21513
21515 }
21518 default:
21520 }
21521
21522 llvm_unreachable("covered atomicrmw op switch");
21523}
21524
21531
21538
21541 const AtomicCmpXchgInst *CmpX) const {
21542 unsigned AddrSpace = CmpX->getPointerAddressSpace();
21543 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS)
21545
21546 if (AddrSpace != AMDGPUAS::FLAT_ADDRESS || !flatInstrMayAccessPrivate(CmpX))
21548
21549 const DataLayout &DL = CmpX->getDataLayout();
21550
21551 Type *ValTy = CmpX->getNewValOperand()->getType();
21552
21553 // If a 64-bit flat atomic may alias private, we need to avoid using the
21554 // atomic in the private case.
21555 return DL.getTypeSizeInBits(ValTy) == 64 ? AtomicExpansionKind::CustomExpand
21557}
21558
21559const TargetRegisterClass *
21560SITargetLowering::getRegClassFor(MVT VT, bool isDivergent) const {
21562 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
21563 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
21564 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
21565 : &AMDGPU::SReg_32RegClass;
21566 if (!TRI->isSGPRClass(RC) && !isDivergent)
21567 return TRI->getEquivalentSGPRClass(RC);
21568 if (TRI->isSGPRClass(RC) && isDivergent) {
21569 if (Subtarget->hasGFX90AInsts())
21570 return TRI->getEquivalentAVClass(RC);
21571 return TRI->getEquivalentVGPRClass(RC);
21572 }
21573
21574 return RC;
21575}
21576
21577// FIXME: This is a workaround for DivergenceAnalysis not understanding always
21578// uniform values (as produced by the mask results of control flow intrinsics)
21579// used outside of divergent blocks. The phi users need to also be treated as
21580// always uniform.
21581//
21582// FIXME: DA is no longer in-use. Does this still apply to UniformityAnalysis?
21584 unsigned WaveSize) {
21585 // FIXME: We assume we never cast the mask results of a control flow
21586 // intrinsic.
21587 // Early exit if the type won't be consistent as a compile time hack.
21588 IntegerType *IT = dyn_cast<IntegerType>(V->getType());
21589 if (!IT || IT->getBitWidth() != WaveSize)
21590 return false;
21591
21592 if (!isa<Instruction>(V))
21593 return false;
21594 if (!Visited.insert(V).second)
21595 return false;
21596 bool Result = false;
21597 for (const auto *U : V->users()) {
21599 if (V == U->getOperand(1)) {
21600 switch (Intrinsic->getIntrinsicID()) {
21601 default:
21602 Result = false;
21603 break;
21604 case Intrinsic::amdgcn_if_break:
21605 case Intrinsic::amdgcn_if:
21606 case Intrinsic::amdgcn_else:
21607 Result = true;
21608 break;
21609 }
21610 }
21611 if (V == U->getOperand(0)) {
21612 switch (Intrinsic->getIntrinsicID()) {
21613 default:
21614 Result = false;
21615 break;
21616 case Intrinsic::amdgcn_end_cf:
21617 case Intrinsic::amdgcn_loop:
21618 Result = true;
21619 break;
21620 }
21621 }
21622 } else {
21623 Result = hasCFUser(U, Visited, WaveSize);
21624 }
21625 if (Result)
21626 break;
21627 }
21628 return Result;
21629}
21630
21632 const Value *V) const {
21633 if (const CallInst *CI = dyn_cast<CallInst>(V)) {
21634 if (CI->isInlineAsm()) {
21635 // FIXME: This cannot give a correct answer. This should only trigger in
21636 // the case where inline asm returns mixed SGPR and VGPR results, used
21637 // outside the defining block. We don't have a specific result to
21638 // consider, so this assumes if any value is SGPR, the overall register
21639 // also needs to be SGPR.
21640 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
21642 MF.getDataLayout(), Subtarget->getRegisterInfo(), *CI);
21643 for (auto &TC : TargetConstraints) {
21644 if (TC.Type == InlineAsm::isOutput) {
21646 const TargetRegisterClass *RC =
21647 getRegForInlineAsmConstraint(SIRI, TC.ConstraintCode,
21648 TC.ConstraintVT)
21649 .second;
21650 if (RC && SIRI->isSGPRClass(RC))
21651 return true;
21652 }
21653 }
21654 }
21655 }
21657 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21658}
21659
21661 for (SDUse &Use : N->uses()) {
21663 if (getBasePtrIndex(M) == Use.getOperandNo())
21664 return true;
21665 }
21666 }
21667 return false;
21668}
21669
21671 SDValue N1) const {
21672 if (!N0.hasOneUse())
21673 return false;
21674 // Take care of the opportunity to keep N0 uniform
21675 if (N0->isDivergent() || !N1->isDivergent())
21676 return true;
21677 // Check if we have a good chance to form the memory access pattern with the
21678 // base and offset
21679 return (DAG.isBaseWithConstantOffset(N0) &&
21681}
21682
21684 Register N0, Register N1) const {
21685 return MRI.hasOneNonDBGUse(N0); // FIXME: handle regbanks
21686}
21687
21690 // Propagate metadata set by AMDGPUAnnotateUniformValues to the MMO of a load.
21692 if (I.getMetadata("amdgpu.noclobber"))
21693 Flags |= MONoClobber;
21694 if (I.getMetadata("amdgpu.last.use"))
21695 Flags |= MOLastUse;
21696 if (MDNode *N = I.getMetadata("amdgpu.cfs")) {
21697 const ConstantAsMetadata *CAM = cast<ConstantAsMetadata>(N->getOperand(0));
21699 unsigned CFS = CI->getZExtValue() & AMDGPU::CPol::CFS_MASK;
21700 static_assert((MOCFSB0 << 1) == MOCFSB1,
21701 "MOCFSB0 and MOCFSB1 are not adjacent bits");
21702 Flags |= static_cast<MachineMemOperand::Flags>(CFS * MOCFSB0);
21703 }
21704 return Flags;
21705}
21706
21708 Instruction *AI) const {
21709 // Given: atomicrmw fadd ptr %addr, float %val ordering
21710 //
21711 // With this expansion we produce the following code:
21712 // [...]
21713 // %is.shared = call i1 @llvm.amdgcn.is.shared(ptr %addr)
21714 // br i1 %is.shared, label %atomicrmw.shared, label %atomicrmw.check.private
21715 //
21716 // atomicrmw.shared:
21717 // %cast.shared = addrspacecast ptr %addr to ptr addrspace(3)
21718 // %loaded.shared = atomicrmw fadd ptr addrspace(3) %cast.shared,
21719 // float %val ordering
21720 // br label %atomicrmw.phi
21721 //
21722 // atomicrmw.check.private:
21723 // %is.private = call i1 @llvm.amdgcn.is.private(ptr %int8ptr)
21724 // br i1 %is.private, label %atomicrmw.private, label %atomicrmw.global
21725 //
21726 // atomicrmw.private:
21727 // %cast.private = addrspacecast ptr %addr to ptr addrspace(5)
21728 // %loaded.private = load float, ptr addrspace(5) %cast.private
21729 // %val.new = fadd float %loaded.private, %val
21730 // store float %val.new, ptr addrspace(5) %cast.private
21731 // br label %atomicrmw.phi
21732 //
21733 // atomicrmw.global:
21734 // %cast.global = addrspacecast ptr %addr to ptr addrspace(1)
21735 // %loaded.global = atomicrmw fadd ptr addrspace(1) %cast.global,
21736 // float %val ordering
21737 // br label %atomicrmw.phi
21738 //
21739 // atomicrmw.phi:
21740 // %loaded.phi = phi float [ %loaded.shared, %atomicrmw.shared ],
21741 // [ %loaded.private, %atomicrmw.private ],
21742 // [ %loaded.global, %atomicrmw.global ]
21743 // br label %atomicrmw.end
21744 //
21745 // atomicrmw.end:
21746 // [...]
21747 //
21748 //
21749 // For 64-bit atomics which may reside in private memory, we perform a simpler
21750 // version that only inserts the private check, and uses the flat operation.
21751
21752 IRBuilder<> Builder(AI);
21753 LLVMContext &Ctx = Builder.getContext();
21754
21755 auto *RMW = dyn_cast<AtomicRMWInst>(AI);
21756 const unsigned PtrOpIdx = RMW ? AtomicRMWInst::getPointerOperandIndex()
21758 Value *Addr = AI->getOperand(PtrOpIdx);
21759
21760 /// TODO: Only need to check private, then emit flat-known-not private (no
21761 /// need for shared block, or cast to global).
21763
21764 Align Alignment;
21765 if (RMW)
21766 Alignment = RMW->getAlign();
21767 else if (CX)
21768 Alignment = CX->getAlign();
21769 else
21770 llvm_unreachable("unhandled atomic operation");
21771
21772 // FullFlatEmulation is true if we need to issue the private, shared, and
21773 // global cases.
21774 //
21775 // If this is false, we are only dealing with the flat-targeting-private case,
21776 // where we only insert a check for private and still use the flat instruction
21777 // for global and shared.
21778
21779 bool FullFlatEmulation =
21780 RMW && RMW->getOperation() == AtomicRMWInst::FAdd &&
21781 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21782 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21783 RMW->getType()->isDoubleTy()));
21784
21785 // If the return value isn't used, do not introduce a false use in the phi.
21786 bool ReturnValueIsUsed = !AI->use_empty();
21787
21788 BasicBlock *BB = Builder.GetInsertBlock();
21789 Function *F = BB->getParent();
21790 BasicBlock *ExitBB =
21791 BB->splitBasicBlock(Builder.GetInsertPoint(), "atomicrmw.end");
21792 BasicBlock *SharedBB = nullptr;
21793
21794 BasicBlock *CheckPrivateBB = BB;
21795 if (FullFlatEmulation) {
21796 SharedBB = BasicBlock::Create(Ctx, "atomicrmw.shared", F, ExitBB);
21797 CheckPrivateBB =
21798 BasicBlock::Create(Ctx, "atomicrmw.check.private", F, ExitBB);
21799 }
21800
21801 BasicBlock *PrivateBB =
21802 BasicBlock::Create(Ctx, "atomicrmw.private", F, ExitBB);
21803 BasicBlock *GlobalBB = BasicBlock::Create(Ctx, "atomicrmw.global", F, ExitBB);
21804 BasicBlock *PhiBB = BasicBlock::Create(Ctx, "atomicrmw.phi", F, ExitBB);
21805
21806 std::prev(BB->end())->eraseFromParent();
21807 Builder.SetInsertPoint(BB);
21808
21809 Value *LoadedShared = nullptr;
21810 if (FullFlatEmulation) {
21811 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21812 {Addr}, nullptr, "is.shared");
21813 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21814 Builder.SetInsertPoint(SharedBB);
21815 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21817
21818 Instruction *Clone = AI->clone();
21819 Clone->insertInto(SharedBB, SharedBB->end());
21820 Clone->getOperandUse(PtrOpIdx).set(CastToLocal);
21821 LoadedShared = Clone;
21822
21823 Builder.CreateBr(PhiBB);
21824 Builder.SetInsertPoint(CheckPrivateBB);
21825 }
21826
21827 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21828 {Addr}, nullptr, "is.private");
21829 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21830
21831 Builder.SetInsertPoint(PrivateBB);
21832
21833 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21835
21836 Value *LoadedPrivate;
21837 if (RMW) {
21838 LoadedPrivate = Builder.CreateAlignedLoad(
21839 RMW->getType(), CastToPrivate, RMW->getAlign(), RMW->isVolatile(),
21840 "loaded.private");
21841
21842 Value *NewVal = buildAtomicRMWValue(RMW->getOperation(), Builder,
21843 LoadedPrivate, RMW->getValOperand());
21844
21845 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign(),
21846 RMW->isVolatile());
21847 } else {
21848 auto [ResultLoad, Equal] = buildCmpXchgValue(
21849 Builder, CastToPrivate, CX->getCompareOperand(), CX->getNewValOperand(),
21850 CX->getAlign(), CX->isVolatile());
21851
21852 Value *Insert = Builder.CreateInsertValue(PoisonValue::get(CX->getType()),
21853 ResultLoad, 0);
21854 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21855 }
21856
21857 Builder.CreateBr(PhiBB);
21858
21859 Builder.SetInsertPoint(GlobalBB);
21860
21861 // Continue using a flat instruction if we only emitted the check for private.
21862 Instruction *LoadedGlobal = AI;
21863 if (FullFlatEmulation) {
21864 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21866 AI->getOperandUse(PtrOpIdx).set(CastToGlobal);
21867 }
21868
21869 AI->removeFromParent();
21870 AI->insertInto(GlobalBB, GlobalBB->end());
21871
21872 // The new atomicrmw may go through another round of legalization later.
21873 if (!FullFlatEmulation) {
21874 // We inserted the runtime check already, make sure we do not try to
21875 // re-expand this.
21876 // TODO: Should union with any existing metadata.
21877 MDBuilder MDB(F->getContext());
21878 MDNode *RangeNotPrivate =
21881 LoadedGlobal->setMetadata(LLVMContext::MD_noalias_addrspace,
21882 RangeNotPrivate);
21883 }
21884
21885 Builder.CreateBr(PhiBB);
21886
21887 Builder.SetInsertPoint(PhiBB);
21888
21889 if (ReturnValueIsUsed) {
21890 PHINode *Loaded = Builder.CreatePHI(AI->getType(), 3);
21891 AI->replaceAllUsesWith(Loaded);
21892 if (FullFlatEmulation)
21893 Loaded->addIncoming(LoadedShared, SharedBB);
21894 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21895 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21896 Loaded->takeName(AI);
21897 }
21898
21899 Builder.CreateBr(ExitBB);
21900}
21901
21903 unsigned PtrOpIdx) {
21904 Value *PtrOp = I->getOperand(PtrOpIdx);
21907
21908 Type *FlatPtr = PointerType::get(I->getContext(), AMDGPUAS::FLAT_ADDRESS);
21909 Value *ASCast = CastInst::CreatePointerCast(PtrOp, FlatPtr, "scratch.ascast",
21910 I->getIterator());
21911 I->setOperand(PtrOpIdx, ASCast);
21912}
21913
21916
21919
21922 if (const auto *ConstVal = dyn_cast<Constant>(AI->getValOperand());
21923 ConstVal && ConstVal->isNullValue() &&
21925 // atomicrmw or %ptr, 0 -> atomicrmw add %ptr, 0
21927
21928 // We may still need the private-alias-flat handling below.
21929
21930 // TODO: Skip this for cases where we cannot access remote memory.
21931 }
21932 }
21933
21934 // The non-flat expansions should only perform the de-canonicalization of
21935 // identity values.
21937 return;
21938
21940}
21941
21948
21952
21954 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21955}
21956
21958 if (SI->getPointerAddressSpace() == AMDGPUAS::PRIVATE_ADDRESS)
21959 return convertScratchAtomicToFlatAtomic(SI, SI->getPointerOperandIndex());
21960
21962 "Expand Atomic Store only handles SCRATCH -> FLAT conversion");
21963}
static bool isMul(MachineInstr *MI)
unsigned NumParts
return SDValue()
static unsigned getIntrinsicID(const SDNode *N)
const AArch64Subtarget & Subtarget
const TargetLowering & TLI
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:665
@ 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
MachineBasicBlock * Folded
SmallVector< MachineOperand, 4 > Cond
int64_t C1
RISCVCC::CondCode CC
MachineRegisterInfo & MRI
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 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 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:479
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
static KnownBits computeKnownBitsForMul24(const KnownBits &LHSKnown, const KnownBits &RHSKnown, unsigned BitWidth, bool IsSigned, bool SelfMultiply)
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 constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:380
static constexpr const fltSemantics & IEEEhalf()
Definition APFloat.h:303
static constexpr const fltSemantics & IEEEsingle()
Definition APFloat.h:305
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
Definition APFloat.h:1253
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:6098
LLVM_READONLY int getExactLog2Abs() const
Definition APFloat.h:1683
bool isNegative() const
Definition APFloat.h:1612
bool isNormal() const
Definition APFloat.h:1616
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
Definition APFloat.h:1221
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
Definition APFloat.h:1271
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition APFloat.h:1231
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition APFloat.h:1212
bool isInfinity() const
Definition APFloat.h:1609
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.
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:886
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:895
Argument * getArg(unsigned i) const
Definition Function.h:880
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
unsigned getMaxPrivateElementSize(bool ForBufferRSrc=false) 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:2987
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.
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.
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.
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,...
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
ISD::CondCode getOperandCondCode(unsigned Num) const
Helper method returns the CondCode of a CondCodeSDNode.
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 LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static unsigned getSubRegFromChannel(uint64_t Channel, uint64_t NumRegs=1)
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 reserve(size_type N)
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.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
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:525
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:352
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:548
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.
APInt getExponentOnlyScaleDemandedBits()
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)
std::optional< unsigned > getExponentOnlyScaleArgIdx(unsigned IntrID)
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)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi, bool *IsBF16)
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:851
@ 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:811
@ 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:885
@ 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:912
@ 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:771
@ 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:820
@ SET_ROUNDING
Set rounding mode.
@ CONVERGENCECTRL_GLUE
This does not correspond to any convergence control intrinsic.
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:876
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:681
@ 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:828
@ 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:824
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:720
@ 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:793
@ 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:882
@ 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:843
@ 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:920
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:751
@ 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:837
@ 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:958
@ 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:763
@ 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:819
@ 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:991
@ 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:977
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:888
@ 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:865
@ 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
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:75
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:546
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.
LLVM_ABI bool isGuaranteedNotToBeUndef(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Returns true if V cannot be undef, but may be poison.
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:49
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:57
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:393
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:440
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:53
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
Definition SIInstrInfo.h:72
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:881
#define N
int64_t DWordOffset
int64_t PermMask
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(PreloadedValue Value) const
static MCRegister getPrivateSegmentBufferReg(CallingConv::ID CC)
Returns the register a non-entry function with calling convention CC expects the private segment buff...
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:433
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:160
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:144
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
Definition ValueTypes.h:338
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:170
ElementCount getVectorElementCount() const
Definition ValueTypes.h:388
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:411
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:281
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:423
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:516
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
Definition ValueTypes.h:450
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:354
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:419
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:191
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:361
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:366
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:136
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
Definition ValueTypes.h:196
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
Definition ValueTypes.h:180
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:374
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.
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