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 "AMDGPUInstrInfo.h"
17#include "AMDGPULaneMaskUtils.h"
18#include "AMDGPUMemoryUtils.h"
20#include "AMDGPUTargetMachine.h"
21#include "GCNSubtarget.h"
24#include "SIRegisterInfo.h"
25#include "llvm/ADT/APFloat.h"
26#include "llvm/ADT/APInt.h"
28#include "llvm/ADT/Statistic.h"
43#include "llvm/IR/IRBuilder.h"
45#include "llvm/IR/IntrinsicsAMDGPU.h"
46#include "llvm/IR/IntrinsicsR600.h"
47#include "llvm/IR/MDBuilder.h"
51#include "llvm/Support/ModRef.h"
54#include <optional>
55
56using namespace llvm;
57using namespace llvm::SDPatternMatch;
58
59#define DEBUG_TYPE "si-lower"
60
61STATISTIC(NumTailCalls, "Number of tail calls");
62
63static cl::opt<bool>
64 DisableLoopAlignment("amdgpu-disable-loop-alignment",
65 cl::desc("Do not align and prefetch loops"),
66 cl::init(false));
67
69 "amdgpu-use-divergent-register-indexing", cl::Hidden,
70 cl::desc("Use indirect register addressing for divergent indexes"),
71 cl::init(false));
72
74 return MF.getInfo<SIMachineFunctionInfo>()->getMode().getDenormalFPEnv();
75}
76
81
86
87static unsigned findFirstFreeSGPR(CCState &CCInfo) {
88 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
89 for (unsigned Reg = 0; Reg < NumSGPRs; ++Reg) {
90 if (!CCInfo.isAllocated(AMDGPU::SGPR0 + Reg)) {
91 return AMDGPU::SGPR0 + Reg;
92 }
93 }
94 llvm_unreachable("Cannot allocate sgpr");
95}
96
98 const GCNSubtarget &STI)
99 : AMDGPUTargetLowering(TM, STI, STI), Subtarget(&STI) {
100 addRegisterClass(MVT::i1, &AMDGPU::VReg_1RegClass);
101 addRegisterClass(MVT::i64, &AMDGPU::SReg_64RegClass);
102
103 addRegisterClass(MVT::i32, &AMDGPU::SReg_32RegClass);
104
105 const SIRegisterInfo *TRI = STI.getRegisterInfo();
106 const TargetRegisterClass *V32RegClass =
107 TRI->getDefaultVectorSuperClassForBitWidth(32);
108 addRegisterClass(MVT::f32, V32RegClass);
109
110 addRegisterClass(MVT::v2i32, &AMDGPU::SReg_64RegClass);
111
112 const TargetRegisterClass *V64RegClass =
113 TRI->getDefaultVectorSuperClassForBitWidth(64);
114
115 addRegisterClass(MVT::f64, V64RegClass);
116 addRegisterClass(MVT::v2f32, V64RegClass);
117 addRegisterClass(MVT::Untyped, V64RegClass);
118
119 addRegisterClass(MVT::v3i32, &AMDGPU::SGPR_96RegClass);
120 addRegisterClass(MVT::v3f32, TRI->getDefaultVectorSuperClassForBitWidth(96));
121
122 addRegisterClass(MVT::v2i64, &AMDGPU::SGPR_128RegClass);
123 addRegisterClass(MVT::v2f64, &AMDGPU::SGPR_128RegClass);
124
125 addRegisterClass(MVT::v4i32, &AMDGPU::SGPR_128RegClass);
126 addRegisterClass(MVT::v4f32, TRI->getDefaultVectorSuperClassForBitWidth(128));
127
128 addRegisterClass(MVT::v5i32, &AMDGPU::SGPR_160RegClass);
129 addRegisterClass(MVT::v5f32, TRI->getDefaultVectorSuperClassForBitWidth(160));
130
131 addRegisterClass(MVT::v6i32, &AMDGPU::SGPR_192RegClass);
132 addRegisterClass(MVT::v6f32, TRI->getDefaultVectorSuperClassForBitWidth(192));
133
134 addRegisterClass(MVT::v3i64, &AMDGPU::SGPR_192RegClass);
135 addRegisterClass(MVT::v3f64, TRI->getDefaultVectorSuperClassForBitWidth(192));
136
137 addRegisterClass(MVT::v7i32, &AMDGPU::SGPR_224RegClass);
138 addRegisterClass(MVT::v7f32, TRI->getDefaultVectorSuperClassForBitWidth(224));
139
140 addRegisterClass(MVT::v8i32, &AMDGPU::SGPR_256RegClass);
141 addRegisterClass(MVT::v8f32, TRI->getDefaultVectorSuperClassForBitWidth(256));
142
143 addRegisterClass(MVT::v4i64, &AMDGPU::SGPR_256RegClass);
144 addRegisterClass(MVT::v4f64, TRI->getDefaultVectorSuperClassForBitWidth(256));
145
146 addRegisterClass(MVT::v9i32, &AMDGPU::SGPR_288RegClass);
147 addRegisterClass(MVT::v9f32, TRI->getDefaultVectorSuperClassForBitWidth(288));
148
149 addRegisterClass(MVT::v10i32, &AMDGPU::SGPR_320RegClass);
150 addRegisterClass(MVT::v10f32,
151 TRI->getDefaultVectorSuperClassForBitWidth(320));
152
153 addRegisterClass(MVT::v11i32, &AMDGPU::SGPR_352RegClass);
154 addRegisterClass(MVT::v11f32,
155 TRI->getDefaultVectorSuperClassForBitWidth(352));
156
157 addRegisterClass(MVT::v12i32, &AMDGPU::SGPR_384RegClass);
158 addRegisterClass(MVT::v12f32,
159 TRI->getDefaultVectorSuperClassForBitWidth(384));
160
161 addRegisterClass(MVT::v16i32, &AMDGPU::SGPR_512RegClass);
162 addRegisterClass(MVT::v16f32,
163 TRI->getDefaultVectorSuperClassForBitWidth(512));
164
165 addRegisterClass(MVT::v8i64, &AMDGPU::SGPR_512RegClass);
166 addRegisterClass(MVT::v8f64, TRI->getDefaultVectorSuperClassForBitWidth(512));
167
168 addRegisterClass(MVT::v16i64, &AMDGPU::SGPR_1024RegClass);
169 addRegisterClass(MVT::v16f64,
170 TRI->getDefaultVectorSuperClassForBitWidth(1024));
171
172 if (Subtarget->has16BitInsts()) {
173 if (Subtarget->useRealTrue16Insts()) {
174 addRegisterClass(MVT::i16, &AMDGPU::VGPR_16RegClass);
175 addRegisterClass(MVT::f16, &AMDGPU::VGPR_16RegClass);
176 addRegisterClass(MVT::bf16, &AMDGPU::VGPR_16RegClass);
177 } else {
178 addRegisterClass(MVT::i16, &AMDGPU::SReg_32RegClass);
179 addRegisterClass(MVT::f16, &AMDGPU::SReg_32RegClass);
180 addRegisterClass(MVT::bf16, &AMDGPU::SReg_32RegClass);
181 }
182
183 // Unless there are also VOP3P operations, not operations are really legal.
184 addRegisterClass(MVT::v2i16, &AMDGPU::SReg_32RegClass);
185 addRegisterClass(MVT::v2f16, &AMDGPU::SReg_32RegClass);
186 addRegisterClass(MVT::v2bf16, &AMDGPU::SReg_32RegClass);
187 addRegisterClass(MVT::v4i16, &AMDGPU::SReg_64RegClass);
188 addRegisterClass(MVT::v4f16, &AMDGPU::SReg_64RegClass);
189 addRegisterClass(MVT::v4bf16, &AMDGPU::SReg_64RegClass);
190 addRegisterClass(MVT::v8i16, &AMDGPU::SGPR_128RegClass);
191 addRegisterClass(MVT::v8f16, &AMDGPU::SGPR_128RegClass);
192 addRegisterClass(MVT::v8bf16, &AMDGPU::SGPR_128RegClass);
193 addRegisterClass(MVT::v16i16, &AMDGPU::SGPR_256RegClass);
194 addRegisterClass(MVT::v16f16, &AMDGPU::SGPR_256RegClass);
195 addRegisterClass(MVT::v16bf16, &AMDGPU::SGPR_256RegClass);
196 addRegisterClass(MVT::v32i16, &AMDGPU::SGPR_512RegClass);
197 addRegisterClass(MVT::v32f16, &AMDGPU::SGPR_512RegClass);
198 addRegisterClass(MVT::v32bf16, &AMDGPU::SGPR_512RegClass);
199 }
200
201 addRegisterClass(MVT::v32i32, &AMDGPU::VReg_1024RegClass);
202 addRegisterClass(MVT::v32f32,
203 TRI->getDefaultVectorSuperClassForBitWidth(1024));
204
205 computeRegisterProperties(Subtarget->getRegisterInfo());
206
209
210 // The boolean content concept here is too inflexible. Compares only ever
211 // really produce a 1-bit result. Any copy/extend from these will turn into a
212 // select, and zext/1 or sext/-1 are equally cheap. Arbitrarily choose 0/1, as
213 // it's what most targets use.
216
217 // We need to custom lower vector stores from local memory
219 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
220 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
221 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
222 MVT::i1, MVT::v32i32},
223 Custom);
224
226 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
227 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
228 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
229 MVT::i1, MVT::v32i32},
230 Custom);
231
232 if (isTypeLegal(MVT::bf16)) {
233 for (unsigned Opc :
242 ISD::SETCC}) {
243 setOperationAction(Opc, MVT::bf16, Promote);
244 }
245
246 // Only targets with packed bf16 instructions, e.g. gfx13.
247 if (Subtarget->hasBF16PackedInsts()) {
248 // Don't use Expand for fsub - the DAG combiner will undo fadd+fneg back
249 // to fsub, causing a libcall (which doesn't exist for bf16). Instead,
250 // directly expand to widened v2bf16 operations.
252 // Promote scalar operations to a v2bf16 operation with an unused high
253 // lane.
254 for (unsigned Opc : {ISD::FADD, ISD::FMUL, ISD::FMA, ISD::FMAXNUM,
256 AddPromotedToType(Opc, MVT::bf16, MVT::v2bf16);
257 }
258
260
262 AddPromotedToType(ISD::SELECT, MVT::bf16, MVT::i16);
263
267
268 // We only need to custom lower because we can't specify an action for bf16
269 // sources.
272 }
273
274 setTruncStoreAction(MVT::v2i32, MVT::v2i16, Expand);
275 setTruncStoreAction(MVT::v3i32, MVT::v3i16, Expand);
276 setTruncStoreAction(MVT::v4i32, MVT::v4i16, Expand);
277 setTruncStoreAction(MVT::v8i32, MVT::v8i16, Expand);
278 setTruncStoreAction(MVT::v16i32, MVT::v16i16, Expand);
279 setTruncStoreAction(MVT::v32i32, MVT::v32i16, Expand);
280 setTruncStoreAction(MVT::v2i32, MVT::v2i8, Expand);
281 setTruncStoreAction(MVT::v4i32, MVT::v4i8, Expand);
282 setTruncStoreAction(MVT::v8i32, MVT::v8i8, Expand);
283 setTruncStoreAction(MVT::v16i32, MVT::v16i8, Expand);
284 setTruncStoreAction(MVT::v32i32, MVT::v32i8, Expand);
285 setTruncStoreAction(MVT::v2i16, MVT::v2i8, Expand);
286 setTruncStoreAction(MVT::v4i16, MVT::v4i8, Expand);
287 setTruncStoreAction(MVT::v8i16, MVT::v8i8, Expand);
288 setTruncStoreAction(MVT::v16i16, MVT::v16i8, Expand);
289 setTruncStoreAction(MVT::v32i16, MVT::v32i8, Expand);
290
291 setTruncStoreAction(MVT::v3i64, MVT::v3i16, Expand);
292 setTruncStoreAction(MVT::v3i64, MVT::v3i32, Expand);
293 setTruncStoreAction(MVT::v4i64, MVT::v4i8, Expand);
294 setTruncStoreAction(MVT::v8i64, MVT::v8i8, Expand);
295 setTruncStoreAction(MVT::v8i64, MVT::v8i16, Expand);
296 setTruncStoreAction(MVT::v8i64, MVT::v8i32, Expand);
297 setTruncStoreAction(MVT::v16i64, MVT::v16i32, Expand);
298
299 setOperationAction(ISD::GlobalAddress, {MVT::i32, MVT::i64}, Custom);
300 setOperationAction(ISD::BlockAddress, {MVT::i32, MVT::i64}, Custom);
301 setOperationAction(ISD::ExternalSymbol, {MVT::i32, MVT::i64}, Custom);
302
306 AddPromotedToType(ISD::SELECT, MVT::f64, MVT::i64);
307
308 setOperationAction(ISD::FSQRT, {MVT::f32, MVT::f64}, Custom);
309
311 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1}, Expand);
312
314 setOperationAction(ISD::SETCC, {MVT::v2i1, MVT::v4i1}, Expand);
315 AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32);
316
318 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
319 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
320 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
321 Expand);
323 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
324 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
325 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
326 Expand);
327
329 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
330 MVT::v3i16, MVT::v4i16, MVT::Other},
331 Custom);
332
335 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64}, Expand);
336
339
342
344 Expand);
345
347
348 // We only support LOAD/STORE and vector manipulation ops for vectors
349 // with > 4 elements.
350 for (MVT VT :
351 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
352 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
353 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
354 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
355 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
356 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
357 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
358 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
359 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
360 switch (Op) {
361 case ISD::LOAD:
362 case ISD::STORE:
364 case ISD::BITCAST:
365 case ISD::UNDEF:
366 case ISD::POISON:
370 case ISD::IS_FPCLASS:
371 break;
376 break;
377 default:
379 break;
380 }
381 }
382 }
383
385
386 // TODO: For dynamic 64-bit vector inserts/extracts, should emit a pseudo that
387 // is expanded to avoid having two separate loops in case the index is a VGPR.
388
389 // Most operations are naturally 32-bit vector operations. We only support
390 // load and store of i64 vectors, so promote v2i64 vector operations to v4i32.
391 for (MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
393 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v4i32);
394
396 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v4i32);
397
399 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v4i32);
400
402 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v4i32);
403 }
404
405 for (MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
407 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v6i32);
408
410 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v6i32);
411
413 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v6i32);
414
416 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v6i32);
417 }
418
419 for (MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
421 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v8i32);
422
424 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v8i32);
425
427 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v8i32);
428
430 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v8i32);
431 }
432
433 for (MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
435 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v16i32);
436
438 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v16i32);
439
441 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v16i32);
442
444 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v16i32);
445 }
446
447 for (MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
449 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v32i32);
450
452 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v32i32);
453
455 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v32i32);
456
458 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v32i32);
459 }
460
462 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
463 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
464 Custom);
465
466 if (Subtarget->hasPkMovB32()) {
467 // TODO: 16-bit element vectors should be legal with even aligned elements.
468 // TODO: Can be legal with wider source types than the result with
469 // subregister extracts.
470 setOperationAction(ISD::VECTOR_SHUFFLE, {MVT::v2i32, MVT::v2f32}, Legal);
471 }
472
474 // Prevent SELECT v2i32 from being implemented with the above bitwise ops and
475 // instead lower to cndmask in SITargetLowering::LowerSELECT().
477 // Enable MatchRotate to produce ISD::ROTR, which is later transformed to
478 // alignbit.
479 setOperationAction(ISD::ROTR, MVT::v2i32, Custom);
480
481 setOperationAction(ISD::BUILD_VECTOR, {MVT::v4f16, MVT::v4i16, MVT::v4bf16},
482 Custom);
483
484 // Avoid stack access for these.
485 // TODO: Generalize to more vector types.
487 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
488 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
489 Custom);
490
491 // Deal with vec3 vector operations when widened to vec4.
493 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32}, Custom);
494
495 // Deal with vec5/6/7 vector operations when widened to vec8.
497 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
498 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
499 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
500 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
501 Custom);
502
503 // BUFFER/FLAT_ATOMIC_CMP_SWAP on GCN GPUs needs input marshalling,
504 // and output demarshalling
505 setOperationAction(ISD::ATOMIC_CMP_SWAP, {MVT::i32, MVT::i64}, Custom);
506
507 // We can't return success/failure, only the old value,
508 // let LLVM add the comparison
510 Expand);
511
512 setOperationAction(ISD::ADDRSPACECAST, {MVT::i32, MVT::i64}, Custom);
513
514 setOperationAction(ISD::BITREVERSE, {MVT::i32, MVT::i64}, Legal);
515
516 // FIXME: This should be narrowed to i32, but that only happens if i64 is
517 // illegal.
518 // FIXME: Should lower sub-i32 bswaps to bit-ops without v_perm_b32.
519 setOperationAction(ISD::BSWAP, {MVT::i64, MVT::i32}, Legal);
520
521 // On SI this is s_memtime and s_memrealtime on VI.
523
524 if (Subtarget->hasSMemRealTime() ||
525 Subtarget->getGeneration() >= AMDGPUSubtarget::GFX11)
528
529 if (Subtarget->has16BitInsts()) {
532 setOperationAction(ISD::IS_FPCLASS, {MVT::f16, MVT::f32, MVT::f64}, Legal);
535 } else {
537 }
538
539 if (Subtarget->hasMadMacF32Insts())
541
545
546 // We only really have 32-bit BFE instructions (and 16-bit on VI).
547 //
548 // On SI+ there are 64-bit BFEs, but they are scalar only and there isn't any
549 // effort to match them now. We want this to be false for i64 cases when the
550 // extraction isn't restricted to the upper or lower half. Ideally we would
551 // have some pass reduce 64-bit extracts to 32-bit if possible. Extracts that
552 // span the midpoint are probably relatively rare, so don't worry about them
553 // for now.
555
556 // Clamp modifier on add/sub
557 if (Subtarget->hasIntClamp())
559
560 if (Subtarget->hasAddNoCarryInsts())
561 setOperationAction({ISD::SADDSAT, ISD::SSUBSAT}, {MVT::i16, MVT::i32},
562 Legal);
563
564 // Do not have s_{min|max}_*f64 instruction f64 will only be lowered to
565 // v_{min|max}_*f64
566 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
569 {MVT::f64, MVT::f32}, Legal);
570 } else {
573 {MVT::f64, MVT::f32}, Custom);
574 // These are really only legal for ieee_mode functions. We should be
575 // avoiding them for functions that don't have ieee_mode enabled, so just
576 // say they are legal.
578 {MVT::f64, MVT::f32}, Legal);
579 }
580
581 if (Subtarget->haveRoundOpsF64())
583 Legal);
584 else
586 MVT::f64, Custom);
587
589 setOperationAction({ISD::FLDEXP, ISD::STRICT_FLDEXP}, {MVT::f32, MVT::f64},
590 Legal);
591 setOperationAction(ISD::FFREXP, {MVT::f32, MVT::f64}, Custom);
592
595
596 setOperationAction(ISD::BF16_TO_FP, {MVT::i16, MVT::f32, MVT::f64}, Expand);
597 setOperationAction(ISD::FP_TO_BF16, {MVT::i16, MVT::f32, MVT::f64}, Expand);
598
600 Custom);
602 Custom);
604 Custom);
605
606 // Custom lower these because we can't specify a rule based on an illegal
607 // source bf16.
610
611 if (Subtarget->has16BitInsts()) {
614 MVT::i16, Legal);
615
616 AddPromotedToType(ISD::SIGN_EXTEND, MVT::i16, MVT::i32);
617
619 MVT::i16, Expand);
620
624 ISD::CTPOP},
625 MVT::i16, Promote);
626
628
629 setTruncStoreAction(MVT::i64, MVT::i16, Expand);
630
632 AddPromotedToType(ISD::FP16_TO_FP, MVT::i16, MVT::i32);
634 AddPromotedToType(ISD::FP_TO_FP16, MVT::i16, MVT::i32);
635
640
642
643 // F16 - Constant Actions.
646
647 // F16 - Load/Store Actions.
649 AddPromotedToType(ISD::LOAD, MVT::f16, MVT::i16);
651 AddPromotedToType(ISD::STORE, MVT::f16, MVT::i16);
652
653 // BF16 - Load/Store Actions.
655 AddPromotedToType(ISD::LOAD, MVT::bf16, MVT::i16);
657 AddPromotedToType(ISD::STORE, MVT::bf16, MVT::i16);
658
659 // F16 - VOP1 Actions.
662 MVT::f16, Custom);
663
664 // BF16 - VOP1 Actions.
665 if (Subtarget->hasBF16TransInsts())
667
668 // F16 - VOP2 Actions.
669 setOperationAction({ISD::BR_CC, ISD::SELECT_CC}, {MVT::f16, MVT::bf16},
670 Expand);
674
675 // F16 - VOP3 Actions.
677 if (STI.hasMadF16())
679
680 for (MVT VT :
681 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
682 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
683 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
684 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
685 switch (Op) {
686 case ISD::LOAD:
687 case ISD::STORE:
689 case ISD::BITCAST:
690 case ISD::UNDEF:
691 case ISD::POISON:
696 case ISD::IS_FPCLASS:
697 break;
700 case ISD::FSIN:
701 case ISD::FCOS:
703 break;
704 default:
706 break;
707 }
708 }
709 }
710
711 // v_perm_b32 can handle either of these.
712 setOperationAction(ISD::BSWAP, {MVT::i16, MVT::v2i16}, Legal);
714
715 // Legalize vector types for sat conversions to select v_cvt_pk_[iu]16_f32.
716 if (Subtarget->hasVCvtPkIU16F32())
719 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
720 Custom);
721
722 // XXX - Do these do anything? Vector constants turn into build_vector.
723 setOperationAction(ISD::Constant, {MVT::v2i16, MVT::v2f16}, Legal);
724
726 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Legal);
727
729 AddPromotedToType(ISD::STORE, MVT::v2i16, MVT::i32);
731 AddPromotedToType(ISD::STORE, MVT::v2f16, MVT::i32);
732
734 AddPromotedToType(ISD::LOAD, MVT::v2i16, MVT::i32);
736 AddPromotedToType(ISD::LOAD, MVT::v2f16, MVT::i32);
737
739 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v2i16, MVT::i32);
741 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v2f16, MVT::i32);
742
744 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v2i16, MVT::i32);
746 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v2f16, MVT::i32);
747
748 setOperationAction(ISD::AND, MVT::v2i16, Promote);
749 AddPromotedToType(ISD::AND, MVT::v2i16, MVT::i32);
750 setOperationAction(ISD::OR, MVT::v2i16, Promote);
751 AddPromotedToType(ISD::OR, MVT::v2i16, MVT::i32);
752 setOperationAction(ISD::XOR, MVT::v2i16, Promote);
753 AddPromotedToType(ISD::XOR, MVT::v2i16, MVT::i32);
754
756 AddPromotedToType(ISD::LOAD, MVT::v4i16, MVT::v2i32);
758 AddPromotedToType(ISD::LOAD, MVT::v4f16, MVT::v2i32);
759 setOperationAction(ISD::LOAD, MVT::v4bf16, Promote);
760 AddPromotedToType(ISD::LOAD, MVT::v4bf16, MVT::v2i32);
761
763 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v4i16, MVT::i64);
765 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v4f16, MVT::i64);
766
768 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v4i16, MVT::i64);
770 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v4f16, MVT::i64);
771
773 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
775 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
777 AddPromotedToType(ISD::STORE, MVT::v4bf16, MVT::v2i32);
778
780 AddPromotedToType(ISD::LOAD, MVT::v8i16, MVT::v4i32);
782 AddPromotedToType(ISD::LOAD, MVT::v8f16, MVT::v4i32);
783 setOperationAction(ISD::LOAD, MVT::v8bf16, Promote);
784 AddPromotedToType(ISD::LOAD, MVT::v8bf16, MVT::v4i32);
785
787 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
789 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
790
792 AddPromotedToType(ISD::STORE, MVT::v8i16, MVT::v4i32);
794 AddPromotedToType(ISD::STORE, MVT::v8f16, MVT::v4i32);
796 AddPromotedToType(ISD::STORE, MVT::v8bf16, MVT::v4i32);
797
798 setOperationAction(ISD::LOAD, MVT::v16i16, Promote);
799 AddPromotedToType(ISD::LOAD, MVT::v16i16, MVT::v8i32);
800 setOperationAction(ISD::LOAD, MVT::v16f16, Promote);
801 AddPromotedToType(ISD::LOAD, MVT::v16f16, MVT::v8i32);
802 setOperationAction(ISD::LOAD, MVT::v16bf16, Promote);
803 AddPromotedToType(ISD::LOAD, MVT::v16bf16, MVT::v8i32);
804
806 AddPromotedToType(ISD::STORE, MVT::v16i16, MVT::v8i32);
808 AddPromotedToType(ISD::STORE, MVT::v16f16, MVT::v8i32);
809 setOperationAction(ISD::STORE, MVT::v16bf16, Promote);
810 AddPromotedToType(ISD::STORE, MVT::v16bf16, MVT::v8i32);
811
812 setOperationAction(ISD::LOAD, MVT::v32i16, Promote);
813 AddPromotedToType(ISD::LOAD, MVT::v32i16, MVT::v16i32);
814 setOperationAction(ISD::LOAD, MVT::v32f16, Promote);
815 AddPromotedToType(ISD::LOAD, MVT::v32f16, MVT::v16i32);
816 setOperationAction(ISD::LOAD, MVT::v32bf16, Promote);
817 AddPromotedToType(ISD::LOAD, MVT::v32bf16, MVT::v16i32);
818
820 AddPromotedToType(ISD::STORE, MVT::v32i16, MVT::v16i32);
822 AddPromotedToType(ISD::STORE, MVT::v32f16, MVT::v16i32);
823 setOperationAction(ISD::STORE, MVT::v32bf16, Promote);
824 AddPromotedToType(ISD::STORE, MVT::v32bf16, MVT::v16i32);
825
827 MVT::v2i32, Expand);
829
831 MVT::v4i32, Expand);
832
834 MVT::v8i32, Expand);
835
836 setOperationAction(ISD::BUILD_VECTOR, {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
837 Subtarget->hasVOP3PInsts() ? Legal : Custom);
838
839 setOperationAction(ISD::FNEG, {MVT::v2f16, MVT::v2bf16}, Legal);
840 // This isn't really legal, but this avoids the legalizer unrolling it (and
841 // allows matching fneg (fabs x) patterns)
842 setOperationAction(ISD::FABS, {MVT::v2f16, MVT::v2bf16}, Legal);
843
844 // Can do this in one BFI plus a constant materialize.
846 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
847 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
848 MVT::v32f16, MVT::v32bf16},
849 Custom);
850 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
853 MVT::f16, Legal);
854
857 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16}, Custom);
858 } else {
861 MVT::f16, Custom);
862
864 Legal);
865
868 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
869 Custom);
870
872 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
873 Expand);
874 }
875
876 for (MVT Vec16 :
877 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
878 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
881 Vec16, Custom);
883 }
884 }
885
886 if (Subtarget->hasVOP3PInsts()) {
890 MVT::v2i16, Legal);
891
894 MVT::v2f16, Legal);
895
897 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Custom);
898
900 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
901 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
902 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
903 Custom);
904
905 for (MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
906 // Split vector operations.
911 VT, Custom);
912
913 for (MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
914 // Split vector operations.
917 VT, Custom);
918
919 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
922 MVT::v2f16, Legal);
923 } else {
925 Legal);
926
929 {MVT::v2f16, MVT::v4f16}, Custom);
930 }
931 setOperationAction(ISD::FEXP, MVT::v2f16, Custom);
932 setOperationAction(ISD::SELECT, {MVT::v4i16, MVT::v4f16, MVT::v4bf16},
933 Custom);
934
935 if (Subtarget->hasBF16PackedInsts()) {
939 MVT::v2bf16, Legal);
940
941 for (MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
942 // Split vector operations.
946 VT, Custom);
947 }
948
949 if (Subtarget->hasAnyPackedFP32Ops()) {
951 MVT::v2f32, Legal);
953 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
954 Custom);
955 }
956 if (Subtarget->hasAnyPackedFP64Ops()) {
959 MVT::v2f64, Legal);
962 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64}, Custom);
963
964 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
967 MVT::v2f64, Legal);
968
971 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64}, Custom);
972 } else {
974 Legal);
977 MVT::v2f64, Custom);
980 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
981 Custom);
982 }
983 }
984
985 if (Subtarget->hasAnyPackedU64Ops()) {
987 MVT::v2i64, Legal);
989 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
990 Custom);
991 }
992 }
993
995
996 if (Subtarget->has16BitInsts()) {
998 AddPromotedToType(ISD::SELECT, MVT::v2i16, MVT::i32);
1000 AddPromotedToType(ISD::SELECT, MVT::v2f16, MVT::i32);
1001 setOperationAction(ISD::SELECT, MVT::v2bf16, Promote);
1002 AddPromotedToType(ISD::SELECT, MVT::v2bf16, MVT::i32);
1003 } else {
1004 // Legalization hack.
1005 setOperationAction(ISD::SELECT, {MVT::v2i16, MVT::v2f16}, Custom);
1006
1008 }
1009
1011 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
1012 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1013 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
1014 MVT::v32f16, MVT::v32bf16},
1015 Custom);
1016
1018
1019 if (Subtarget->useVMulU64Inst())
1020 setOperationAction(ISD::MUL, MVT::i64, Legal);
1021 else if (Subtarget->hasScalarSMulU64())
1023
1024 if (Subtarget->hasMad64_32())
1026
1027 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
1029
1030 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
1032 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16}, Legal);
1033 } else {
1034 // FIXME: For nnan fmaximum, emit the fmaximum3 instead of fmaxnum
1035 if (Subtarget->hasMinimum3Maximum3F32())
1037
1038 if (Subtarget->hasMinimum3Maximum3PKF16()) {
1040
1041 // If only the vector form is available, we need to widen to a vector.
1042 if (!Subtarget->hasMinimum3Maximum3F16())
1044 MVT::v2f16);
1045 }
1046 }
1047
1048 if (Subtarget->hasVOP3PInsts()) {
1049 // We want to break these into v2f16 pieces, not scalarize.
1051 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1052 Custom);
1053 }
1054
1055 if (Subtarget->useMinMaxI64Insts())
1057 Legal);
1058
1060 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1061 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1062 MVT::i8},
1063 Custom);
1064
1066 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1067 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1068 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1069 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1070 Custom);
1071
1073 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1074 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1075 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1076 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1077 Custom);
1078
1084
1085 // TODO: Could move this to custom lowering, could benefit from combines on
1086 // extract of relevant bits.
1088
1090
1091 if (Subtarget->hasBF16ConversionInsts()) {
1093 {MVT::bf16, MVT::v2bf16}, Custom);
1095 }
1096
1097 if (Subtarget->hasBF16TransInsts()) {
1099 }
1100
1101 const bool HasE5M3ConversionInsts =
1102 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
1103 if (Subtarget->hasOCPFP8ConversionInsts() || HasE5M3ConversionInsts) {
1104 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f32, MVT::v2f32},
1105 Custom);
1107
1108 // i8 result promotes to i16, wider vectors split down to v2i8, and v2i8 is
1109 // handled in ReplaceNodeResults before the legalizer splits it per lane.
1110 setOperationAction(ISD::CONVERT_TO_ARBITRARY_FP, {MVT::i16, MVT::v2i8},
1111 Custom);
1112 }
1113
1114 if (Subtarget->hasFP8F16ConversionInsts()) {
1115 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f16, MVT::v2f16},
1116 Custom);
1117 }
1118
1119 if (Subtarget->hasCvtPkF16F32Inst()) {
1121 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1122 Custom);
1123 }
1124
1127 ISD::SUB,
1128 ISD::MUL,
1129 ISD::FADD,
1130 ISD::FSUB,
1131 ISD::FDIV,
1132 ISD::FMUL,
1141 ISD::FMA,
1142 ISD::ABS,
1143 ISD::SMIN,
1144 ISD::SMAX,
1145 ISD::UMIN,
1146 ISD::UMAX,
1147 ISD::SETCC,
1149 ISD::SMIN,
1150 ISD::SMAX,
1151 ISD::UMIN,
1152 ISD::UMAX,
1155 ISD::AND,
1156 ISD::OR,
1157 ISD::XOR,
1158 ISD::SHL,
1159 ISD::SRL,
1160 ISD::SRA,
1161 ISD::FSHR,
1172
1173 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1175
1176 // All memory operations. Some folding on the pointer operand is done to help
1177 // matching the constant offsets in the addressing modes.
1179 ISD::STORE,
1204
1205 // FIXME: In other contexts we pretend this is a per-function property.
1207
1209}
1210
1211const GCNSubtarget *SITargetLowering::getSubtarget() const { return Subtarget; }
1212
1214 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1215 return RCRegs;
1216}
1217
1218//===----------------------------------------------------------------------===//
1219// TargetLowering queries
1220//===----------------------------------------------------------------------===//
1221
1222// v_mad_mix* support a conversion from f16 to f32.
1223//
1224// There is only one special case when denormals are enabled we don't currently,
1225// where this is OK to use.
1226bool SITargetLowering::isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode,
1227 EVT DestVT, EVT SrcVT) const {
1228 return DestVT.getScalarType() == MVT::f32 &&
1229 ((((Opcode == ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1230 (Opcode == ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1231 SrcVT.getScalarType() == MVT::f16) ||
1232 (Opcode == ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1233 SrcVT.getScalarType() == MVT::bf16)) &&
1234 // TODO: This probably only requires no input flushing?
1236}
1237
1239 LLT DestTy, LLT SrcTy) const {
1240 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1241 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1242 DestTy.getScalarSizeInBits() == 32 &&
1243 SrcTy.getScalarSizeInBits() == 16 &&
1244 // TODO: This probably only requires no input flushing?
1245 denormalModeIsFlushAllF32(*MI.getMF());
1246}
1247
1249 // SI has some legal vector types, but no legal vector operations. Say no
1250 // shuffles are legal in order to prefer scalarizing some vector operations.
1251 return false;
1252}
1253
1255 CallingConv::ID CC,
1256 EVT VT) const {
1258 return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
1259
1260 if (VT.isVector()) {
1261 EVT ScalarVT = VT.getScalarType();
1262 unsigned Size = ScalarVT.getSizeInBits();
1263 if (Size == 16) {
1264 return Subtarget->has16BitInsts()
1265 ? MVT::getVectorVT(ScalarVT.getSimpleVT(), 2)
1266 : MVT::i32;
1267 }
1268
1269 if (Size < 16)
1270 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1271 return Size == 32 ? ScalarVT.getSimpleVT() : MVT::i32;
1272 }
1273
1274 if (!Subtarget->has16BitInsts() && VT.getSizeInBits() == 16)
1275 return MVT::i32;
1276
1277 if (VT.getSizeInBits() > 32)
1278 return MVT::i32;
1279
1280 return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
1281}
1282
1284 CallingConv::ID CC,
1285 EVT VT) const {
1287 return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
1288
1289 if (VT.isVector()) {
1290 unsigned NumElts = VT.getVectorNumElements();
1291 EVT ScalarVT = VT.getScalarType();
1292 unsigned Size = ScalarVT.getSizeInBits();
1293
1294 // FIXME: Should probably promote 8-bit vectors to i16.
1295 if (Size == 16)
1296 return (NumElts + 1) / 2;
1297
1298 if (Size <= 32)
1299 return NumElts;
1300
1301 if (Size > 32)
1302 return NumElts * ((Size + 31) / 32);
1303 } else if (VT.getSizeInBits() > 32)
1304 return (VT.getSizeInBits() + 31) / 32;
1305
1306 return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
1307}
1308
1310 LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT,
1311 unsigned &NumIntermediates, MVT &RegisterVT) const {
1312 if (CC != CallingConv::AMDGPU_KERNEL && VT.isVector()) {
1313 unsigned NumElts = VT.getVectorNumElements();
1314 EVT ScalarVT = VT.getScalarType();
1315 unsigned Size = ScalarVT.getSizeInBits();
1316 // FIXME: We should fix the ABI to be the same on targets without 16-bit
1317 // support, but unless we can properly handle 3-vectors, it will be still be
1318 // inconsistent.
1319 if (Size == 16) {
1320 MVT SimpleIntermediateVT =
1322 IntermediateVT = SimpleIntermediateVT;
1323 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1324 NumIntermediates = (NumElts + 1) / 2;
1325 return (NumElts + 1) / 2;
1326 }
1327
1328 if (Size == 32) {
1329 RegisterVT = ScalarVT.getSimpleVT();
1330 IntermediateVT = RegisterVT;
1331 NumIntermediates = NumElts;
1332 return NumIntermediates;
1333 }
1334
1335 if (Size < 16 && Subtarget->has16BitInsts()) {
1336 // FIXME: Should probably form v2i16 pieces
1337 RegisterVT = MVT::i16;
1338 IntermediateVT = ScalarVT;
1339 NumIntermediates = NumElts;
1340 return NumIntermediates;
1341 }
1342
1343 if (Size != 16 && Size <= 32) {
1344 RegisterVT = MVT::i32;
1345 IntermediateVT = ScalarVT;
1346 NumIntermediates = NumElts;
1347 return NumIntermediates;
1348 }
1349
1350 if (Size > 32) {
1351 RegisterVT = MVT::i32;
1352 IntermediateVT = RegisterVT;
1353 NumIntermediates = NumElts * ((Size + 31) / 32);
1354 return NumIntermediates;
1355 }
1356 }
1357
1359 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1360}
1361
1363 const DataLayout &DL, Type *Ty,
1364 unsigned MaxNumLanes) {
1365 assert(MaxNumLanes != 0);
1366
1367 LLVMContext &Ctx = Ty->getContext();
1368 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1369 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1370 return EVT::getVectorVT(Ctx, TLI.getValueType(DL, VT->getElementType()),
1371 NumElts);
1372 }
1373
1374 return TLI.getValueType(DL, Ty);
1375}
1376
1377// Peek through TFE struct returns to only use the data size.
1379 const DataLayout &DL, Type *Ty,
1380 unsigned MaxNumLanes) {
1381 auto *ST = dyn_cast<StructType>(Ty);
1382 if (!ST)
1383 return memVTFromLoadIntrData(TLI, DL, Ty, MaxNumLanes);
1384
1385 // TFE intrinsics return an aggregate type.
1386 assert(ST->getNumContainedTypes() == 2 &&
1387 ST->getContainedType(1)->isIntegerTy(32));
1388 return memVTFromLoadIntrData(TLI, DL, ST->getContainedType(0), MaxNumLanes);
1389}
1390
1391/// Map address space 7 to MVT::amdgpuBufferFatPointer because that's its
1392/// in-memory representation. This return value is a custom type because there
1393/// is no MVT::i160 and adding one breaks integer promotion logic. While this
1394/// could cause issues during codegen, these address space 7 pointers will be
1395/// rewritten away by then. Therefore, we can return MVT::amdgpuBufferFatPointer
1396/// in order to allow pre-codegen passes that query TargetTransformInfo, often
1397/// for cost modeling, to work. (This also sets us up decently for doing the
1398/// buffer lowering in GlobalISel if SelectionDAG ever goes away.)
1400 if (AMDGPUAS::BUFFER_FAT_POINTER == AS && DL.getPointerSizeInBits(AS) == 160)
1401 return MVT::amdgpuBufferFatPointer;
1403 DL.getPointerSizeInBits(AS) == 192)
1404 return MVT::amdgpuBufferStridedPointer;
1406}
1407/// Similarly, the in-memory representation of a p7 is {p8, i32}, aka
1408/// v8i32 when padding is added.
1409/// The in-memory representation of a p9 is {p8, i32, i32}, which is
1410/// also v8i32 with padding.
1412 if ((AMDGPUAS::BUFFER_FAT_POINTER == AS &&
1413 DL.getPointerSizeInBits(AS) == 160) ||
1415 DL.getPointerSizeInBits(AS) == 192))
1416 return MVT::v8i32;
1418}
1419
1420static unsigned getIntrMemWidth(unsigned IntrID) {
1421 switch (IntrID) {
1422 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1423 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1424 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1425 return 8;
1426 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1427 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1428 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1429 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1430 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1431 case Intrinsic::amdgcn_flat_load_monitor_b32:
1432 case Intrinsic::amdgcn_global_load_monitor_b32:
1433 return 32;
1434 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1435 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1436 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1437 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1438 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1439 case Intrinsic::amdgcn_flat_load_monitor_b64:
1440 case Intrinsic::amdgcn_global_load_monitor_b64:
1441 return 64;
1442 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1443 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1444 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1445 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1446 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1447 case Intrinsic::amdgcn_flat_load_monitor_b128:
1448 case Intrinsic::amdgcn_global_load_monitor_b128:
1449 return 128;
1450 default:
1451 llvm_unreachable("Unknown width");
1452 }
1453}
1454
1456 unsigned ArgIdx) {
1457 Value *OrderingArg = CI.getArgOperand(ArgIdx);
1458 unsigned Ord = cast<ConstantInt>(OrderingArg)->getZExtValue();
1459 switch (AtomicOrderingCABI(Ord)) {
1462 break;
1465 break;
1468 break;
1469 default:
1471 }
1472}
1473
1474static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx) {
1475 MDNode *ScopeMD = cast<MDNode>(
1476 cast<MetadataAsValue>(CI.getArgOperand(ArgIdx))->getMetadata());
1477 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1478 return CI.getContext().getOrInsertSyncScopeID(Scope);
1479}
1480
1482 const CallBase &CI,
1483 MachineFunction &MF,
1484 unsigned IntrID) const {
1486 if (CI.hasMetadata(LLVMContext::MD_invariant_load))
1488 if (CI.hasMetadata(LLVMContext::MD_nontemporal))
1490 Flags |= getTargetMMOFlags(CI);
1491
1492 if (const AMDGPU::RsrcIntrinsic *RsrcIntr =
1494 AttributeSet Attr =
1496 MemoryEffects ME = Attr.getMemoryEffects();
1497 if (ME.doesNotAccessMemory())
1498 return;
1499
1500 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1501 if (!IsSPrefetch) {
1502 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1503 if (Aux->getZExtValue() & AMDGPU::CPol::VOLATILE)
1505 }
1506
1508
1509 IntrinsicInfo Info;
1510 // TODO: Should images get their own address space?
1512
1513 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = nullptr;
1514 if (RsrcIntr->IsImage) {
1515 const AMDGPU::ImageDimIntrinsicInfo *Intr =
1517 BaseOpcode = AMDGPU::getMIMGBaseOpcodeInfo(Intr->BaseOpcode);
1518 Info.align.reset();
1519 }
1520
1521 Value *RsrcArg = CI.getArgOperand(RsrcIntr->RsrcArg);
1522 if (auto *RsrcPtrTy = dyn_cast<PointerType>(RsrcArg->getType())) {
1523 if (RsrcPtrTy->getAddressSpace() == AMDGPUAS::BUFFER_RESOURCE)
1524 // We conservatively set the memory operand of a buffer intrinsic to the
1525 // base resource pointer, so that we can access alias information about
1526 // those pointers. Cases like "this points at the same value
1527 // but with a different offset" are handled in
1528 // areMemAccessesTriviallyDisjoint.
1529 Info.ptrVal = RsrcArg;
1530 }
1531
1532 if (ME.onlyReadsMemory()) {
1533 if (RsrcIntr->IsImage) {
1534 unsigned MaxNumLanes = 4;
1535
1536 if (!BaseOpcode->Gather4) {
1537 // If this isn't a gather, we may have excess loaded elements in the
1538 // IR type. Check the dmask for the real number of elements loaded.
1539 unsigned DMask =
1540 cast<ConstantInt>(CI.getArgOperand(0))->getZExtValue();
1541 MaxNumLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1542 }
1543
1544 Info.memVT = memVTFromLoadIntrReturn(*this, MF.getDataLayout(),
1545 CI.getType(), MaxNumLanes);
1546 } else {
1547 Info.memVT =
1549 std::numeric_limits<unsigned>::max());
1550 }
1551
1552 // FIXME: What does alignment mean for an image?
1553 Info.opc = ISD::INTRINSIC_W_CHAIN;
1554 Info.flags = Flags | MachineMemOperand::MOLoad;
1555 } else if (ME.onlyWritesMemory()) {
1556 Info.opc = ISD::INTRINSIC_VOID;
1557
1558 Type *DataTy = CI.getArgOperand(0)->getType();
1559 if (RsrcIntr->IsImage) {
1560 unsigned DMask = cast<ConstantInt>(CI.getArgOperand(1))->getZExtValue();
1561 unsigned DMaskLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1562 Info.memVT = memVTFromLoadIntrData(*this, MF.getDataLayout(), DataTy,
1563 DMaskLanes);
1564 } else
1565 Info.memVT = getValueType(MF.getDataLayout(), DataTy);
1566
1567 Info.flags = Flags | MachineMemOperand::MOStore;
1568 } else {
1569 // Atomic, NoReturn Sampler or prefetch
1570 Info.opc = CI.getType()->isVoidTy() ? ISD::INTRINSIC_VOID
1572
1573 switch (IntrID) {
1574 default:
1575 Info.flags = Flags | MachineMemOperand::MOLoad;
1576 if (!IsSPrefetch)
1577 Info.flags |= MachineMemOperand::MOStore;
1578
1579 if ((RsrcIntr->IsImage && BaseOpcode->NoReturn) || IsSPrefetch) {
1580 // Fake memory access type for no return sampler intrinsics
1581 Info.memVT = MVT::i32;
1582 } else {
1583 // XXX - Should this be volatile without known ordering?
1584 Info.flags |= MachineMemOperand::MOVolatile;
1585 Info.memVT = MVT::getVT(CI.getArgOperand(0)->getType());
1586 }
1587 break;
1588 case Intrinsic::amdgcn_raw_buffer_load_lds:
1589 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1590 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1591 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1592 case Intrinsic::amdgcn_struct_buffer_load_lds:
1593 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1594 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1595 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1596 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1597
1598 // Entry 0: Load from buffer.
1599 // Don't set an offset, since the pointer value always represents the
1600 // base of the buffer.
1601 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1602 Info.flags = Flags | MachineMemOperand::MOLoad;
1603 Infos.push_back(Info);
1604
1605 // Entry 1: Store to LDS.
1606 // Instruction offset is applied, and an additional per-lane offset
1607 // which we simulate using a larger memory type.
1608 Info.memVT = EVT::getIntegerVT(
1609 CI.getContext(), Width * 8 * Subtarget->getWavefrontSize());
1610 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1611 Info.offset = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 2))
1612 ->getZExtValue();
1613 Info.fallbackAddressSpace = AMDGPUAS::LOCAL_ADDRESS;
1614 Info.flags = Flags | MachineMemOperand::MOStore;
1615 Infos.push_back(Info);
1616 return;
1617 }
1618 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1619 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1620 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1621 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1622 Info.memVT =
1624 std::numeric_limits<unsigned>::max());
1625 Info.flags = Flags | MachineMemOperand::MOLoad;
1626 Infos.push_back(Info);
1627 return;
1628 }
1629 }
1630 }
1631 Infos.push_back(Info);
1632 return;
1633 }
1634
1635 IntrinsicInfo Info;
1636 switch (IntrID) {
1637 case Intrinsic::amdgcn_ds_ordered_add:
1638 case Intrinsic::amdgcn_ds_ordered_swap: {
1639 Info.opc = ISD::INTRINSIC_W_CHAIN;
1640 Info.memVT = MVT::getVT(CI.getType());
1641 Info.ptrVal = CI.getOperand(0);
1642 Info.align.reset();
1644
1645 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(4));
1646 if (!Vol->isZero())
1647 Info.flags |= MachineMemOperand::MOVolatile;
1648
1649 Infos.push_back(Info);
1650 return;
1651 }
1652 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1653 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1654 Info.opc = ISD::INTRINSIC_W_CHAIN;
1655 Info.memVT = MVT::getVT(CI.getOperand(0)->getType());
1656 Info.ptrVal = nullptr;
1657 Info.fallbackAddressSpace = AMDGPUAS::STREAMOUT_REGISTER;
1659 Infos.push_back(Info);
1660 return;
1661 }
1662 case Intrinsic::amdgcn_ds_append:
1663 case Intrinsic::amdgcn_ds_consume: {
1664 Info.opc = ISD::INTRINSIC_W_CHAIN;
1665 Info.memVT = MVT::getVT(CI.getType());
1666 Info.ptrVal = CI.getOperand(0);
1667 Info.align.reset();
1669
1670 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(1));
1671 if (!Vol->isZero())
1672 Info.flags |= MachineMemOperand::MOVolatile;
1673
1674 Infos.push_back(Info);
1675 return;
1676 }
1677 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1678 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1679 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1682 Info.memVT = MVT::getVT(CI.getType());
1683 Info.ptrVal = CI.getOperand(0);
1684 Info.memVT = MVT::i64;
1685 Info.size = 8;
1686 Info.align.reset();
1688 Info.order = AtomicOrdering::Monotonic;
1689 Infos.push_back(Info);
1690 return;
1691 }
1692 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1693 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1694 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1695 Info.opc = ISD::INTRINSIC_W_CHAIN;
1696 Info.memVT =
1697 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1698 ? CI.getType()
1700 ->getElementType(0)); // XXX: what is correct VT?
1701
1702 Info.fallbackAddressSpace = AMDGPUAS::BUFFER_RESOURCE;
1703 Info.align.reset();
1704 Info.flags = Flags | MachineMemOperand::MOLoad |
1706 Infos.push_back(Info);
1707 return;
1708 }
1709 case Intrinsic::amdgcn_global_atomic_fmin_num:
1710 case Intrinsic::amdgcn_global_atomic_fmax_num:
1711 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1712 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1713 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1714 Info.opc = ISD::INTRINSIC_W_CHAIN;
1715 Info.memVT = MVT::getVT(CI.getType());
1716 Info.ptrVal = CI.getOperand(0);
1717 Info.align.reset();
1718 Info.flags =
1721 Infos.push_back(Info);
1722 return;
1723 }
1724 case Intrinsic::amdgcn_cluster_load_b32:
1725 case Intrinsic::amdgcn_cluster_load_b64:
1726 case Intrinsic::amdgcn_cluster_load_b128:
1727 case Intrinsic::amdgcn_ds_load_tr6_b96:
1728 case Intrinsic::amdgcn_ds_load_tr4_b64:
1729 case Intrinsic::amdgcn_ds_load_tr8_b64:
1730 case Intrinsic::amdgcn_ds_load_tr16_b128:
1731 case Intrinsic::amdgcn_global_load_tr6_b96:
1732 case Intrinsic::amdgcn_global_load_tr4_b64:
1733 case Intrinsic::amdgcn_global_load_tr_b64:
1734 case Intrinsic::amdgcn_global_load_tr_b128:
1735 case Intrinsic::amdgcn_ds_read_tr4_b64:
1736 case Intrinsic::amdgcn_ds_read_tr6_b96:
1737 case Intrinsic::amdgcn_ds_read_tr8_b64:
1738 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1739 Info.opc = ISD::INTRINSIC_W_CHAIN;
1740 Info.memVT = MVT::getVT(CI.getType());
1741 Info.ptrVal = CI.getOperand(0);
1742 Info.align.reset();
1743 Info.flags = Flags | MachineMemOperand::MOLoad;
1744 Infos.push_back(Info);
1745 return;
1746 }
1747 case Intrinsic::amdgcn_flat_load_monitor_b32:
1748 case Intrinsic::amdgcn_flat_load_monitor_b64:
1749 case Intrinsic::amdgcn_flat_load_monitor_b128:
1750 case Intrinsic::amdgcn_global_load_monitor_b32:
1751 case Intrinsic::amdgcn_global_load_monitor_b64:
1752 case Intrinsic::amdgcn_global_load_monitor_b128: {
1753 Info.opc = ISD::INTRINSIC_W_CHAIN;
1754 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1755 Info.ptrVal = CI.getOperand(0);
1756 Info.align.reset();
1757 Info.flags = MachineMemOperand::MOLoad;
1758 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1759 Info.ssid = parseSyncscopeMDArg(CI, 2);
1760 Infos.push_back(Info);
1761 return;
1762 }
1763 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1764 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1765 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1766 Info.opc = ISD::INTRINSIC_W_CHAIN;
1767 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1768 Info.ptrVal = CI.getOperand(0);
1769 Info.align.reset();
1771 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1772 Info.ssid = parseSyncscopeMDArg(CI, 2);
1773 Infos.push_back(Info);
1774 return;
1775 }
1776 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1777 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1778 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1779 Info.opc = ISD::INTRINSIC_VOID;
1780 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1781 Info.ptrVal = CI.getArgOperand(0);
1782 Info.align.reset();
1784 Info.order = parseAtomicOrderingCABIArg(CI, 2);
1785 Info.ssid = parseSyncscopeMDArg(CI, 3);
1786 Infos.push_back(Info);
1787 return;
1788 }
1789 case Intrinsic::amdgcn_ds_gws_init:
1790 case Intrinsic::amdgcn_ds_gws_barrier:
1791 case Intrinsic::amdgcn_ds_gws_sema_v:
1792 case Intrinsic::amdgcn_ds_gws_sema_br:
1793 case Intrinsic::amdgcn_ds_gws_sema_p:
1794 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1795 Info.opc = ISD::INTRINSIC_VOID;
1796
1797 const GCNTargetMachine &TM =
1798 static_cast<const GCNTargetMachine &>(getTargetMachine());
1799
1801 Info.ptrVal = MFI->getGWSPSV(TM);
1802
1803 // This is an abstract access, but we need to specify a type and size.
1804 Info.memVT = MVT::i32;
1805 Info.size = 4;
1806 Info.align = Align(4);
1807
1808 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1809 Info.flags = Flags | MachineMemOperand::MOLoad;
1810 else
1811 Info.flags = Flags | MachineMemOperand::MOStore;
1812 Infos.push_back(Info);
1813 return;
1814 }
1815 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1816 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1817 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1818 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1819 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1820 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1821 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1822 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1823 // Entry 0: Load from source (global/flat).
1824 Info.opc = ISD::INTRINSIC_VOID;
1825 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1826 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1827 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1828 Info.flags = Flags | MachineMemOperand::MOLoad;
1829 Infos.push_back(Info);
1830
1831 // Entry 1: Store to LDS (same offset).
1832 Info.flags = Flags | MachineMemOperand::MOStore;
1833 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1834 Infos.push_back(Info);
1835 return;
1836 }
1837 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1838 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1839 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1840 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1841 // Entry 0: Load from LDS.
1842 Info.opc = ISD::INTRINSIC_VOID;
1843 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1844 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1845 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1846 Info.flags = Flags | MachineMemOperand::MOLoad;
1847 Infos.push_back(Info);
1848
1849 // Entry 1: Store to global (same offset).
1850 Info.flags = Flags | MachineMemOperand::MOStore;
1851 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1852 Infos.push_back(Info);
1853 return;
1854 }
1855 case Intrinsic::amdgcn_av_load_b128:
1856 case Intrinsic::amdgcn_av_store_b128: {
1857 bool IsStore = IntrID == Intrinsic::amdgcn_av_store_b128;
1858 Info.opc = IsStore ? ISD::INTRINSIC_VOID : ISD::INTRINSIC_W_CHAIN;
1859 Info.memVT = MVT::v4i32;
1860 Info.ptrVal = CI.getArgOperand(0);
1861 Info.align = Align(16);
1862 Info.flags |=
1864 // Pretend to be atomic so that SIMemoryLegalizer::expandStore sets cache
1865 // flags appropriately.
1866 Info.order = AtomicOrdering::Monotonic;
1867
1868 LLVMContext &Ctx = CI.getContext();
1869 unsigned ScopeIdx = CI.arg_size() - 1;
1870 MDNode *ScopeMD = cast<MDNode>(
1871 cast<MetadataAsValue>(CI.getArgOperand(ScopeIdx))->getMetadata());
1872 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1873 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1874 Infos.push_back(Info);
1875 return;
1876 }
1877 case Intrinsic::amdgcn_load_to_lds:
1878 case Intrinsic::amdgcn_load_async_to_lds:
1879 case Intrinsic::amdgcn_global_load_lds:
1880 case Intrinsic::amdgcn_global_load_async_lds: {
1881 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1882 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1883 bool IsVolatile = Aux->getZExtValue() & AMDGPU::CPol::VOLATILE;
1884 if (IsVolatile)
1886
1887 // Entry 0: Load from source (global/flat).
1888 Info.opc = ISD::INTRINSIC_VOID;
1889 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1890 Info.ptrVal = CI.getArgOperand(0); // Source pointer
1891 Info.offset = cast<ConstantInt>(CI.getArgOperand(3))->getSExtValue();
1892 Info.flags = Flags | MachineMemOperand::MOLoad;
1893 Infos.push_back(Info);
1894
1895 // Entry 1: Store to LDS.
1896 // Same offset from the instruction, but an additional per-lane offset is
1897 // added. Represent that using a wider memory type.
1898 Info.memVT = EVT::getIntegerVT(CI.getContext(),
1899 Width * 8 * Subtarget->getWavefrontSize());
1900 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1901 Info.flags = Flags | MachineMemOperand::MOStore;
1902 Infos.push_back(Info);
1903 return;
1904 }
1905 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1906 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1907 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1908 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1909 Info.opc = ISD::INTRINSIC_W_CHAIN;
1910
1911 const GCNTargetMachine &TM =
1912 static_cast<const GCNTargetMachine &>(getTargetMachine());
1913
1915 Info.ptrVal = MFI->getGWSPSV(TM);
1916
1917 // This is an abstract access, but we need to specify a type and size.
1918 Info.memVT = MVT::i32;
1919 Info.size = 4;
1920 Info.align = Align(4);
1921
1923 Infos.push_back(Info);
1924 return;
1925 }
1926 case Intrinsic::amdgcn_s_prefetch_data:
1927 case Intrinsic::amdgcn_s_prefetch_inst:
1928 case Intrinsic::amdgcn_flat_prefetch:
1929 case Intrinsic::amdgcn_global_prefetch: {
1930 Info.opc = ISD::INTRINSIC_VOID;
1931 Info.memVT = EVT::getIntegerVT(CI.getContext(), 8);
1932 Info.ptrVal = CI.getArgOperand(0);
1933 Info.flags = Flags | MachineMemOperand::MOLoad;
1934 Infos.push_back(Info);
1935 return;
1936 }
1937 default:
1938 return;
1939 }
1940}
1941
1944 Type *&AccessTy) const {
1945 Value *Ptr = nullptr;
1946 switch (II->getIntrinsicID()) {
1947 case Intrinsic::amdgcn_cluster_load_b128:
1948 case Intrinsic::amdgcn_cluster_load_b64:
1949 case Intrinsic::amdgcn_cluster_load_b32:
1950 case Intrinsic::amdgcn_ds_append:
1951 case Intrinsic::amdgcn_ds_consume:
1952 case Intrinsic::amdgcn_ds_load_tr8_b64:
1953 case Intrinsic::amdgcn_ds_load_tr16_b128:
1954 case Intrinsic::amdgcn_ds_load_tr4_b64:
1955 case Intrinsic::amdgcn_ds_load_tr6_b96:
1956 case Intrinsic::amdgcn_ds_read_tr4_b64:
1957 case Intrinsic::amdgcn_ds_read_tr6_b96:
1958 case Intrinsic::amdgcn_ds_read_tr8_b64:
1959 case Intrinsic::amdgcn_ds_read_tr16_b64:
1960 case Intrinsic::amdgcn_ds_ordered_add:
1961 case Intrinsic::amdgcn_ds_ordered_swap:
1962 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1963 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1964 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1965 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1966 case Intrinsic::amdgcn_global_atomic_fmax_num:
1967 case Intrinsic::amdgcn_global_atomic_fmin_num:
1968 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1969 case Intrinsic::amdgcn_global_load_tr_b64:
1970 case Intrinsic::amdgcn_global_load_tr_b128:
1971 case Intrinsic::amdgcn_global_load_tr4_b64:
1972 case Intrinsic::amdgcn_global_load_tr6_b96:
1973 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1974 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1975 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1976 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1977 case Intrinsic::amdgcn_av_load_b128:
1978 case Intrinsic::amdgcn_av_store_b128:
1979 Ptr = II->getArgOperand(0);
1980 break;
1981 case Intrinsic::amdgcn_load_to_lds:
1982 case Intrinsic::amdgcn_load_async_to_lds:
1983 case Intrinsic::amdgcn_global_load_lds:
1984 case Intrinsic::amdgcn_global_load_async_lds:
1985 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1986 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1987 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1988 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1989 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1990 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1991 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1992 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1993 Ptr = II->getArgOperand(1);
1994 break;
1995 default:
1996 return false;
1997 }
1998 AccessTy = II->getType();
1999 Ops.push_back(Ptr);
2000 return true;
2001}
2002
2004 unsigned AddrSpace) const {
2005 if (!Subtarget->hasFlatInstOffsets()) {
2006 // Flat instructions do not have offsets, and only have the register
2007 // address.
2008 return AM.BaseOffs == 0 && AM.Scale == 0;
2009 }
2010
2012 FlatAddrSpace FlatVariant =
2013 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS ? FlatAddrSpace::FlatGlobal
2014 : AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ? FlatAddrSpace::FlatScratch
2015 : FlatAddrSpace::FLAT;
2016
2017 return AM.Scale == 0 &&
2018 (AM.BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
2019 AM.BaseOffs, AddrSpace, FlatVariant));
2020}
2021
2023 if (Subtarget->hasFlatGlobalInsts())
2025
2026 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
2027 // Assume the we will use FLAT for all global memory accesses
2028 // on VI.
2029 // FIXME: This assumption is currently wrong. On VI we still use
2030 // MUBUF instructions for the r + i addressing mode. As currently
2031 // implemented, the MUBUF instructions only work on buffer < 4GB.
2032 // It may be possible to support > 4GB buffers with MUBUF instructions,
2033 // by setting the stride value in the resource descriptor which would
2034 // increase the size limit to (stride * 4GB). However, this is risky,
2035 // because it has never been validated.
2037 }
2038
2039 return isLegalMUBUFAddressingMode(AM);
2040}
2041
2042bool SITargetLowering::isLegalMUBUFAddressingMode(const AddrMode &AM) const {
2043 // MUBUF / MTBUF instructions have a 12-bit unsigned byte offset, and
2044 // additionally can do r + r + i with addr64. 32-bit has more addressing
2045 // mode options. Depending on the resource constant, it can also do
2046 // (i64 r0) + (i32 r1) * (i14 i).
2047 //
2048 // Private arrays end up using a scratch buffer most of the time, so also
2049 // assume those use MUBUF instructions. Scratch loads / stores are currently
2050 // implemented as mubuf instructions with offen bit set, so slightly
2051 // different than the normal addr64.
2052 const SIInstrInfo *TII = Subtarget->getInstrInfo();
2053 if (!TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2054 return false;
2055
2056 // FIXME: Since we can split immediate into soffset and immediate offset,
2057 // would it make sense to allow any immediate?
2058
2059 switch (AM.Scale) {
2060 case 0: // r + i or just i, depending on HasBaseReg.
2061 return true;
2062 case 1:
2063 return true; // We have r + r or r + i.
2064 case 2:
2065 if (AM.HasBaseReg) {
2066 // Reject 2 * r + r.
2067 return false;
2068 }
2069
2070 // Allow 2 * r as r + r
2071 // Or 2 * r + i is allowed as r + r + i.
2072 return true;
2073 default: // Don't allow n * r
2074 return false;
2075 }
2076}
2077
2079 const AddrMode &AM, Type *Ty,
2080 unsigned AS,
2081 Instruction *I) const {
2082 // No global is ever allowed as a base.
2083 if (AM.BaseGV)
2084 return false;
2085
2086 if (AS == AMDGPUAS::GLOBAL_ADDRESS)
2087 return isLegalGlobalAddressingMode(AM);
2088
2089 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
2093 // If the offset isn't a multiple of 4, it probably isn't going to be
2094 // correctly aligned.
2095 // FIXME: Can we get the real alignment here?
2096 if (AM.BaseOffs % 4 != 0)
2097 return isLegalMUBUFAddressingMode(AM);
2098
2099 if (!Subtarget->hasScalarSubwordLoads()) {
2100 // There are no SMRD extloads, so if we have to do a small type access we
2101 // will use a MUBUF load.
2102 // FIXME?: We also need to do this if unaligned, but we don't know the
2103 // alignment here.
2104 if (Ty->isSized() && DL.getTypeStoreSize(Ty) < 4)
2105 return isLegalGlobalAddressingMode(AM);
2106 }
2107
2108 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS) {
2109 // SMRD instructions have an 8-bit, dword offset on SI.
2110 if (!isUInt<8>(AM.BaseOffs / 4))
2111 return false;
2112 } else if (Subtarget->getGeneration() == AMDGPUSubtarget::SEA_ISLANDS) {
2113 // On CI+, this can also be a 32-bit literal constant offset. If it fits
2114 // in 8-bits, it can use a smaller encoding.
2115 if (!isUInt<32>(AM.BaseOffs / 4))
2116 return false;
2117 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX9) {
2118 // On VI, these use the SMEM format and the offset is 20-bit in bytes.
2119 if (!isUInt<20>(AM.BaseOffs))
2120 return false;
2121 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX12) {
2122 // On GFX9 the offset is signed 21-bit in bytes (but must not be negative
2123 // for S_BUFFER_* instructions).
2124 if (!isInt<21>(AM.BaseOffs))
2125 return false;
2126 } else {
2127 // On GFX12, all offsets are signed 24-bit in bytes.
2128 if (!isInt<24>(AM.BaseOffs))
2129 return false;
2130 }
2131
2132 if ((AS == AMDGPUAS::CONSTANT_ADDRESS ||
2134 AM.BaseOffs < 0) {
2135 // Scalar (non-buffer) loads can only use a negative offset if
2136 // soffset+offset is non-negative. Since the compiler can only prove that
2137 // in a few special cases, it is safer to claim that negative offsets are
2138 // not supported.
2139 return false;
2140 }
2141
2142 if (AM.Scale == 0) // r + i or just i, depending on HasBaseReg.
2143 return true;
2144
2145 if (AM.Scale == 1 && AM.HasBaseReg)
2146 return true;
2147
2148 return false;
2149 }
2150
2151 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
2152 return Subtarget->hasFlatScratchEnabled()
2154 : isLegalMUBUFAddressingMode(AM);
2155
2156 if (AS == AMDGPUAS::LOCAL_ADDRESS ||
2157 (AS == AMDGPUAS::REGION_ADDRESS && Subtarget->hasGDS())) {
2158 // Basic, single offset DS instructions allow a 16-bit unsigned immediate
2159 // field.
2160 // XXX - If doing a 4-byte aligned 8-byte type access, we effectively have
2161 // an 8-bit dword offset but we don't know the alignment here.
2162 if (!isUInt<16>(AM.BaseOffs))
2163 return false;
2164
2165 if (AM.Scale == 0) // r + i or just i, depending on HasBaseReg.
2166 return true;
2167
2168 if (AM.Scale == 1 && AM.HasBaseReg)
2169 return true;
2170
2171 return false;
2172 }
2173
2175 // For an unknown address space, this usually means that this is for some
2176 // reason being used for pure arithmetic, and not based on some addressing
2177 // computation. We don't have instructions that compute pointers with any
2178 // addressing modes, so treat them as having no offset like flat
2179 // instructions.
2181 }
2182
2183 // Assume a user alias of global for unknown address spaces.
2184 return isLegalGlobalAddressingMode(AM);
2185}
2186
2188 const MachineFunction &MF) const {
2190 return (MemVT.getSizeInBits() <= 4 * 32);
2191 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
2192 unsigned MaxPrivateBits = 8 * getSubtarget()->getMaxPrivateElementSize();
2193 return (MemVT.getSizeInBits() <= MaxPrivateBits);
2194 }
2196 return (MemVT.getSizeInBits() <= 2 * 32);
2197 return true;
2198}
2199
2201 unsigned Size, unsigned AddrSpace, Align Alignment,
2202 MachineMemOperand::Flags Flags, unsigned *IsFast) const {
2203 if (IsFast)
2204 *IsFast = 0;
2205
2206 if (AddrSpace == AMDGPUAS::LOCAL_ADDRESS ||
2207 AddrSpace == AMDGPUAS::REGION_ADDRESS) {
2208 // Check if alignment requirements for ds_read/write instructions are
2209 // disabled.
2210 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment < Align(4))
2211 return false;
2212
2213 Align RequiredAlignment(
2214 PowerOf2Ceil(divideCeil(Size, 8))); // Natural alignment.
2215 if (Subtarget->hasLDSMisalignedBugInWGPMode() && Size > 32 &&
2216 Alignment < RequiredAlignment)
2217 return false;
2218
2219 // Either, the alignment requirements are "enabled", or there is an
2220 // unaligned LDS access related hardware bug though alignment requirements
2221 // are "disabled". In either case, we need to check for proper alignment
2222 // requirements.
2223 //
2224 switch (Size) {
2225 case 64:
2226 // SI has a hardware bug in the LDS / GDS bounds checking: if the base
2227 // address is negative, then the instruction is incorrectly treated as
2228 // out-of-bounds even if base + offsets is in bounds. Split vectorized
2229 // loads here to avoid emitting ds_read2_b32. We may re-combine the
2230 // load later in the SILoadStoreOptimizer.
2231 if (!Subtarget->hasUsableDSOffset() && Alignment < Align(8))
2232 return false;
2233
2234 // 8 byte accessing via ds_read/write_b64 require 8-byte alignment, but we
2235 // can do a 4 byte aligned, 8 byte access in a single operation using
2236 // ds_read2/write2_b32 with adjacent offsets.
2237 RequiredAlignment = Align(4);
2238
2239 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2240 // We will either select ds_read_b64/ds_write_b64 or ds_read2_b32/
2241 // ds_write2_b32 depending on the alignment. In either case with either
2242 // alignment there is no faster way of doing this.
2243
2244 // The numbers returned here and below are not additive, it is a 'speed
2245 // rank'. They are just meant to be compared to decide if a certain way
2246 // of lowering an operation is faster than another. For that purpose
2247 // naturally aligned operation gets it bitsize to indicate that "it
2248 // operates with a speed comparable to N-bit wide load". With the full
2249 // alignment ds128 is slower than ds96 for example. If underaligned it
2250 // is comparable to a speed of a single dword access, which would then
2251 // mean 32 < 128 and it is faster to issue a wide load regardless.
2252 // 1 is simply "slow, don't do it". I.e. comparing an aligned load to a
2253 // wider load which will not be aligned anymore the latter is slower.
2254 if (IsFast)
2255 *IsFast = (Alignment >= RequiredAlignment) ? 64
2256 : (Alignment < Align(4)) ? 32
2257 : 1;
2258 return true;
2259 }
2260
2261 break;
2262 case 96:
2263 if (!Subtarget->hasDS96AndDS128())
2264 return false;
2265
2266 // 12 byte accessing via ds_read/write_b96 require 16-byte alignment on
2267 // gfx8 and older.
2268
2269 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2270 // Naturally aligned access is fastest. However, also report it is Fast
2271 // if memory is aligned less than DWORD. A narrow load or store will be
2272 // be equally slow as a single ds_read_b96/ds_write_b96, but there will
2273 // be more of them, so overall we will pay less penalty issuing a single
2274 // instruction.
2275
2276 // See comment on the values above.
2277 if (IsFast)
2278 *IsFast = (Alignment >= RequiredAlignment) ? 96
2279 : (Alignment < Align(4)) ? 32
2280 : 1;
2281 return true;
2282 }
2283
2284 break;
2285 case 128:
2286 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2287 return false;
2288
2289 // 16 byte accessing via ds_read/write_b128 require 16-byte alignment on
2290 // gfx8 and older, but we can do a 8 byte aligned, 16 byte access in a
2291 // single operation using ds_read2/write2_b64.
2292 RequiredAlignment = Align(8);
2293
2294 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2295 // Naturally aligned access is fastest. However, also report it is Fast
2296 // if memory is aligned less than DWORD. A narrow load or store will be
2297 // be equally slow as a single ds_read_b128/ds_write_b128, but there
2298 // will be more of them, so overall we will pay less penalty issuing a
2299 // single instruction.
2300
2301 // See comment on the values above.
2302 if (IsFast)
2303 *IsFast = (Alignment >= RequiredAlignment) ? 128
2304 : (Alignment < Align(4)) ? 32
2305 : 1;
2306 return true;
2307 }
2308
2309 break;
2310 default:
2311 if (Size > 32)
2312 return false;
2313
2314 break;
2315 }
2316
2317 // See comment on the values above.
2318 // Note that we have a single-dword or sub-dword here, so if underaligned
2319 // it is a slowest possible access, hence returned value is 0.
2320 if (IsFast)
2321 *IsFast = (Alignment >= RequiredAlignment) ? Size : 0;
2322
2323 return Alignment >= RequiredAlignment ||
2324 Subtarget->hasUnalignedDSAccessEnabled();
2325 }
2326
2327 // FIXME: We have to be conservative here and assume that flat operations
2328 // will access scratch. If we had access to the IR function, then we
2329 // could determine if any private memory was used in the function.
2330 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ||
2331 AddrSpace == AMDGPUAS::FLAT_ADDRESS) {
2332 bool AlignedBy4 = Alignment >= Align(4);
2333 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2334 if (IsFast)
2335 *IsFast = AlignedBy4 ? Size : 1;
2336 return true;
2337 }
2338
2339 if (IsFast)
2340 *IsFast = AlignedBy4;
2341
2342 return AlignedBy4;
2343 }
2344
2345 // So long as they are correct, wide global memory operations perform better
2346 // than multiple smaller memory ops -- even when misaligned
2347 if (AMDGPU::isExtendedGlobalAddrSpace(AddrSpace)) {
2348 if (IsFast)
2349 *IsFast = Size;
2350
2351 return Alignment >= Align(4) ||
2352 Subtarget->hasUnalignedBufferAccessEnabled();
2353 }
2354
2355 // Ensure robust out-of-bounds guarantees for buffer accesses are met when the
2356 // "amdgpu.buffer.oob.mode" module flag has not enabled relaxed untyped-buffer
2357 // OOB semantics. Normally hardware will ensure proper
2358 // out-of-bounds behavior, but in the edge case where an access starts
2359 // out-of-bounds and then enters in-bounds, the entire access would be treated
2360 // as out-of-bounds. Prevent misaligned memory accesses by requiring the
2361 // natural alignment of buffer accesses.
2362 if (AddrSpace == AMDGPUAS::BUFFER_FAT_POINTER ||
2363 AddrSpace == AMDGPUAS::BUFFER_RESOURCE ||
2364 AddrSpace == AMDGPUAS::BUFFER_STRIDED_POINTER) {
2365 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2366 Alignment < Align(PowerOf2Ceil(divideCeil(Size, 8))))
2367 return false;
2368 }
2369
2370 // Smaller than dword value must be aligned.
2371 if (Size < 32)
2372 return false;
2373
2374 // 8.1.6 - For Dword or larger reads or writes, the two LSBs of the
2375 // byte-address are ignored, thus forcing Dword alignment.
2376 // This applies to private, global, and constant memory.
2377 if (IsFast)
2378 *IsFast = 1;
2379
2380 return Size >= 32 && Alignment >= Align(4);
2381}
2382
2384 EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
2385 unsigned *IsFast) const {
2387 Alignment, Flags, IsFast);
2388}
2389
2391 LLVMContext &Context, const MemOp &Op,
2392 const AttributeList &FuncAttributes) const {
2393 // FIXME: Should account for address space here.
2394
2395 // The default fallback uses the private pointer size as a guess for a type to
2396 // use. Make sure we switch these to 64-bit accesses.
2397
2398 if (Op.size() >= 16 &&
2399 Op.isDstAligned(Align(4))) // XXX: Should only do for global
2400 return MVT::v4i32;
2401
2402 if (Op.size() >= 8 && Op.isDstAligned(Align(4)))
2403 return MVT::v2i32;
2404
2405 // Use the default.
2406 return MVT::Other;
2407}
2408
2410 const MemSDNode *MemNode = cast<MemSDNode>(N);
2411 return MemNode->getMemOperand()->getFlags() & MONoClobber;
2412}
2413
2418
2420 unsigned DestAS) const {
2421 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
2422 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
2423 Subtarget->hasGloballyAddressableScratch()) {
2424 // Flat -> private requires subtracting src_flat_scratch_base_lo.
2425 return false;
2426 }
2427
2428 // Flat -> private/local is a simple truncate.
2429 // Flat -> global is no-op
2430 return true;
2431 }
2432
2433 const GCNTargetMachine &TM =
2434 static_cast<const GCNTargetMachine &>(getTargetMachine());
2435 return TM.isNoopAddrSpaceCast(SrcAS, DestAS);
2436}
2437
2445
2447 Type *Ty) const {
2448 // FIXME: Could be smarter if called for vector constants.
2449 return true;
2450}
2451
2454 unsigned Index) const {
2457
2458 // TODO: Add more cases that are cheap.
2459 if (Index == 0)
2462}
2463
2464bool SITargetLowering::isExtractVecEltCheap(EVT VT, unsigned Index) const {
2465 // TODO: This should be more aggressive, particular for 16-bit element
2466 // vectors. However there are some mixed improvements and regressions.
2467 EVT EltTy = VT.getVectorElementType();
2468 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2469 return EltTy.getSizeInBits() % MinAlign == 0;
2470}
2471
2473 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2474 switch (Op) {
2475 case ISD::LOAD:
2476 case ISD::STORE:
2477 return true;
2478 default:
2479 return false;
2480 }
2481 }
2482
2483 // SimplifySetCC uses this function to determine whether or not it should
2484 // create setcc with i1 operands. We don't have instructions for i1 setcc.
2485 if (VT == MVT::i1 && Op == ISD::SETCC)
2486 return false;
2487
2489}
2490
2493 // This isn't really a constant pool but close enough.
2496 return PtrInfo;
2497}
2498
2499SDValue SITargetLowering::lowerKernArgParameterPtr(SelectionDAG &DAG,
2500 const SDLoc &SL,
2501 SDValue Chain,
2502 uint64_t Offset) const {
2503 const DataLayout &DL = DAG.getDataLayout();
2507
2508 auto [InputPtrReg, RC, ArgTy] =
2509 Info->getPreloadedValue(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
2510
2511 // We may not have the kernarg segment argument if we have no kernel
2512 // arguments.
2513 if (!InputPtrReg)
2514 return DAG.getConstant(Offset, SL, PtrVT);
2515
2517 SDValue BasePtr = DAG.getCopyFromReg(
2518 Chain, SL, MRI.getLiveInVirtReg(InputPtrReg->getRegister()), PtrVT);
2519
2520 return DAG.getObjectPtrOffset(SL, BasePtr, TypeSize::getFixed(Offset));
2521}
2522
2523SDValue SITargetLowering::getImplicitArgPtr(SelectionDAG &DAG,
2524 const SDLoc &SL) const {
2527 return lowerKernArgParameterPtr(DAG, SL, DAG.getEntryNode(), Offset);
2528}
2529
2530SDValue SITargetLowering::getLDSKernelId(SelectionDAG &DAG,
2531 const SDLoc &SL) const {
2532
2534 std::optional<uint32_t> KnownSize =
2536 if (KnownSize.has_value())
2537 return DAG.getConstant(*KnownSize, SL, MVT::i32);
2538 return SDValue();
2539}
2540
2541SDValue SITargetLowering::convertArgType(SelectionDAG &DAG, EVT VT, EVT MemVT,
2542 const SDLoc &SL, SDValue Val,
2543 bool Signed,
2544 const ISD::InputArg *Arg) const {
2545 // First, if it is a widened vector, narrow it.
2546 if (VT.isVector() &&
2548 EVT NarrowedVT =
2551 Val = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, NarrowedVT, Val,
2552 DAG.getConstant(0, SL, MVT::i32));
2553 }
2554
2555 // Then convert the vector elements or scalar value.
2556 if (Arg && (Arg->Flags.isSExt() || Arg->Flags.isZExt()) && VT.bitsLT(MemVT)) {
2557 unsigned Opc = Arg->Flags.isZExt() ? ISD::AssertZext : ISD::AssertSext;
2558 Val = DAG.getNode(Opc, SL, MemVT, Val, DAG.getValueType(VT));
2559 }
2560
2561 if (MemVT.isFloatingPoint()) {
2562 if (VT.isFloatingPoint()) {
2563 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2564 } else {
2565 assert(!MemVT.isVector());
2566 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
2567 SDValue Cast = DAG.getBitcast(IntVT, Val);
2568 Val = DAG.getAnyExtOrTrunc(Cast, SL, VT);
2569 }
2570 } else if (Signed)
2571 Val = DAG.getSExtOrTrunc(Val, SL, VT);
2572 else
2573 Val = DAG.getZExtOrTrunc(Val, SL, VT);
2574
2575 return Val;
2576}
2577
2578SDValue SITargetLowering::lowerKernargMemParameter(
2579 SelectionDAG &DAG, EVT VT, EVT MemVT, const SDLoc &SL, SDValue Chain,
2580 uint64_t Offset, Align Alignment, bool Signed,
2581 const ISD::InputArg *Arg) const {
2582
2583 MachinePointerInfo PtrInfo =
2585
2586 // Try to avoid using an extload by loading earlier than the argument address,
2587 // and extracting the relevant bits. The load should hopefully be merged with
2588 // the previous argument.
2589 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
2590 // TODO: Handle align < 4 and size >= 4 (can happen with packed structs).
2591 int64_t AlignDownOffset = alignDown(Offset, 4);
2592 int64_t OffsetDiff = Offset - AlignDownOffset;
2593
2594 EVT IntVT = MemVT.changeTypeToInteger();
2595
2596 // TODO: If we passed in the base kernel offset we could have a better
2597 // alignment than 4, but we don't really need it.
2598 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2599 SDValue Load = DAG.getLoad(MVT::i32, SL, Chain, Ptr,
2600 PtrInfo.getWithOffset(AlignDownOffset), Align(4),
2603
2604 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, SL, MVT::i32);
2605 SDValue Extract = DAG.getNode(ISD::SRL, SL, MVT::i32, Load, ShiftAmt);
2606
2607 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, SL, IntVT, Extract);
2608 ArgVal = DAG.getNode(ISD::BITCAST, SL, MemVT, ArgVal);
2609 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal, Signed, Arg);
2610
2611 return DAG.getMergeValues({ArgVal, Load.getValue(1)}, SL);
2612 }
2613
2614 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, Offset);
2615 SDValue Load = DAG.getLoad(
2616 MemVT, SL, Chain, Ptr, PtrInfo.getWithOffset(Offset), Alignment,
2618
2619 SDValue Val = convertArgType(DAG, VT, MemVT, SL, Load, Signed, Arg);
2620 return DAG.getMergeValues({Val, Load.getValue(1)}, SL);
2621}
2622
2623/// Coerce an argument which was passed in a different ABI type to the original
2624/// expected value type.
2625SDValue SITargetLowering::convertABITypeToValueType(SelectionDAG &DAG,
2626 SDValue Val,
2627 CCValAssign &VA,
2628 const SDLoc &SL) const {
2629 EVT ValVT = VA.getValVT();
2630
2631 // If this is an 8 or 16-bit value, it is really passed promoted
2632 // to 32 bits. Insert an assert[sz]ext to capture this, then
2633 // truncate to the right size.
2634 switch (VA.getLocInfo()) {
2635 case CCValAssign::Full:
2636 return Val;
2637 case CCValAssign::BCvt:
2638 return DAG.getNode(ISD::BITCAST, SL, ValVT, Val);
2639 case CCValAssign::SExt:
2640 Val = DAG.getNode(ISD::AssertSext, SL, VA.getLocVT(), Val,
2641 DAG.getValueType(ValVT));
2642 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2643 case CCValAssign::ZExt:
2644 Val = DAG.getNode(ISD::AssertZext, SL, VA.getLocVT(), Val,
2645 DAG.getValueType(ValVT));
2646 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2647 case CCValAssign::AExt:
2648 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2649 default:
2650 llvm_unreachable("Unknown loc info!");
2651 }
2652}
2653
2654SDValue SITargetLowering::lowerStackParameter(SelectionDAG &DAG,
2655 CCValAssign &VA, const SDLoc &SL,
2656 SDValue Chain,
2657 const ISD::InputArg &Arg) const {
2659 MachineFrameInfo &MFI = MF.getFrameInfo();
2660
2661 if (Arg.Flags.isByVal()) {
2662 unsigned Size = Arg.Flags.getByValSize();
2663 int FrameIdx = MFI.CreateFixedObject(Size, VA.getLocMemOffset(), false);
2664 return DAG.getFrameIndex(FrameIdx, MVT::i32);
2665 }
2666
2667 unsigned ArgOffset = VA.getLocMemOffset();
2668 unsigned ArgSize = VA.getValVT().getStoreSize();
2669
2670 int FI = MFI.CreateFixedObject(ArgSize, ArgOffset, true);
2671
2672 // Create load nodes to retrieve arguments from the stack.
2673 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
2674
2675 // For NON_EXTLOAD, generic code in getLoad assert(ValVT == MemVT)
2677 MVT MemVT = VA.getValVT();
2678
2679 switch (VA.getLocInfo()) {
2680 default:
2681 break;
2682 case CCValAssign::BCvt:
2683 MemVT = VA.getLocVT();
2684 break;
2685 case CCValAssign::SExt:
2686 ExtType = ISD::SEXTLOAD;
2687 break;
2688 case CCValAssign::ZExt:
2689 ExtType = ISD::ZEXTLOAD;
2690 break;
2691 case CCValAssign::AExt:
2692 ExtType = ISD::EXTLOAD;
2693 break;
2694 }
2695
2696 SDValue ArgValue = DAG.getExtLoad(
2697 ExtType, SL, VA.getLocVT(), Chain, FIN,
2699
2700 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2701 if (ConvertedVal == ArgValue)
2702 return ConvertedVal;
2703
2704 return DAG.getMergeValues({ConvertedVal, ArgValue.getValue(1)}, SL);
2705}
2706
2707SDValue SITargetLowering::lowerWorkGroupId(
2708 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2711 AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const {
2712 if (!Subtarget->hasClusters())
2713 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2714
2715 // Clusters are supported. Return the global position in the grid. If clusters
2716 // are enabled, WorkGroupIdPV returns the cluster ID not the workgroup ID.
2717
2718 // WorkGroupIdXYZ = ClusterId == 0 ?
2719 // ClusterIdXYZ :
2720 // ClusterIdXYZ * (ClusterMaxIdXYZ + 1) + ClusterWorkGroupIdXYZ
2721 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2722 SDLoc SL(ClusterIdXYZ);
2723 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2724 SDValue One = DAG.getConstant(1, SL, VT);
2725 SDValue ClusterSizeXYZ = DAG.getNode(ISD::ADD, SL, VT, ClusterMaxIdXYZ, One);
2726 SDValue ClusterWorkGroupIdXYZ =
2727 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2728 SDValue GlobalIdXYZ =
2729 DAG.getNode(ISD::ADD, SL, VT, ClusterWorkGroupIdXYZ,
2730 DAG.getNode(ISD::MUL, SL, VT, ClusterIdXYZ, ClusterSizeXYZ));
2731
2732 switch (MFI.getClusterDims().getKind()) {
2735 return GlobalIdXYZ;
2737 return ClusterIdXYZ;
2739 using namespace AMDGPU::Hwreg;
2740 SDValue ClusterIdField =
2741 DAG.getTargetConstant(HwregEncoding::encode(ID_IB_STS2, 6, 4), SL, VT);
2742 SDNode *GetReg =
2743 DAG.getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2744 SDValue ClusterId(GetReg, 0);
2745 SDValue Zero = DAG.getConstant(0, SL, VT);
2746 return DAG.getNode(ISD::SELECT_CC, SL, VT, ClusterId, Zero, ClusterIdXYZ,
2747 GlobalIdXYZ, DAG.getCondCode(ISD::SETEQ));
2748 }
2749 }
2750
2751 llvm_unreachable("nothing should reach here");
2752}
2753
2754SDValue SITargetLowering::getPreloadedValue(
2755 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2757 const ArgDescriptor *Reg = nullptr;
2758 const TargetRegisterClass *RC = nullptr;
2759 LLT Ty;
2760
2762 const ArgDescriptor WorkGroupIDX =
2763 ArgDescriptor::createRegister(AMDGPU::TTMP9);
2764 // If GridZ is not programmed in an entry function then the hardware will set
2765 // it to all zeros, so there is no need to mask the GridY value in the low
2766 // order bits.
2767 const ArgDescriptor WorkGroupIDY = ArgDescriptor::createRegister(
2768 AMDGPU::TTMP7,
2769 AMDGPU::isEntryFunctionCC(CC) && !MFI.hasWorkGroupIDZ() ? ~0u : 0xFFFFu);
2770 const ArgDescriptor WorkGroupIDZ =
2771 ArgDescriptor::createRegister(AMDGPU::TTMP7, 0xFFFF0000u);
2772 const ArgDescriptor ClusterWorkGroupIDX =
2773 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000000Fu);
2774 const ArgDescriptor ClusterWorkGroupIDY =
2775 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000000F0u);
2776 const ArgDescriptor ClusterWorkGroupIDZ =
2777 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00000F00u);
2778 const ArgDescriptor ClusterWorkGroupMaxIDX =
2779 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000F000u);
2780 const ArgDescriptor ClusterWorkGroupMaxIDY =
2781 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000F0000u);
2782 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2783 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00F00000u);
2784 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2785 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0F000000u);
2786
2787 auto LoadConstant = [&](unsigned N) {
2788 return DAG.getConstant(N, SDLoc(), VT);
2789 };
2790
2791 if (Subtarget->hasArchitectedSGPRs() &&
2793 AMDGPU::ClusterDimsAttr ClusterDims = MFI.getClusterDims();
2794 bool HasFixedDims = ClusterDims.isFixedDims();
2795
2796 switch (PVID) {
2798 Reg = &WorkGroupIDX;
2799 RC = &AMDGPU::SReg_32RegClass;
2800 Ty = LLT::scalar(32);
2801 break;
2803 Reg = &WorkGroupIDY;
2804 RC = &AMDGPU::SReg_32RegClass;
2805 Ty = LLT::scalar(32);
2806 break;
2808 Reg = &WorkGroupIDZ;
2809 RC = &AMDGPU::SReg_32RegClass;
2810 Ty = LLT::scalar(32);
2811 break;
2813 if (HasFixedDims && ClusterDims.getDims()[0] == 1)
2814 return LoadConstant(0);
2815 Reg = &ClusterWorkGroupIDX;
2816 RC = &AMDGPU::SReg_32RegClass;
2817 Ty = LLT::scalar(32);
2818 break;
2820 if (HasFixedDims && ClusterDims.getDims()[1] == 1)
2821 return LoadConstant(0);
2822 Reg = &ClusterWorkGroupIDY;
2823 RC = &AMDGPU::SReg_32RegClass;
2824 Ty = LLT::scalar(32);
2825 break;
2827 if (HasFixedDims && ClusterDims.getDims()[2] == 1)
2828 return LoadConstant(0);
2829 Reg = &ClusterWorkGroupIDZ;
2830 RC = &AMDGPU::SReg_32RegClass;
2831 Ty = LLT::scalar(32);
2832 break;
2834 if (HasFixedDims)
2835 return LoadConstant(ClusterDims.getDims()[0] - 1);
2836 Reg = &ClusterWorkGroupMaxIDX;
2837 RC = &AMDGPU::SReg_32RegClass;
2838 Ty = LLT::scalar(32);
2839 break;
2841 if (HasFixedDims)
2842 return LoadConstant(ClusterDims.getDims()[1] - 1);
2843 Reg = &ClusterWorkGroupMaxIDY;
2844 RC = &AMDGPU::SReg_32RegClass;
2845 Ty = LLT::scalar(32);
2846 break;
2848 if (HasFixedDims)
2849 return LoadConstant(ClusterDims.getDims()[2] - 1);
2850 Reg = &ClusterWorkGroupMaxIDZ;
2851 RC = &AMDGPU::SReg_32RegClass;
2852 Ty = LLT::scalar(32);
2853 break;
2855 Reg = &ClusterWorkGroupMaxFlatID;
2856 RC = &AMDGPU::SReg_32RegClass;
2857 Ty = LLT::scalar(32);
2858 break;
2859 default:
2860 break;
2861 }
2862 }
2863
2864 if (!Reg)
2865 std::tie(Reg, RC, Ty) = MFI.getPreloadedValue(PVID);
2866 if (!Reg) {
2868 // It's possible for a kernarg intrinsic call to appear in a kernel with
2869 // no allocated segment, in which case we do not add the user sgpr
2870 // argument, so just return null.
2871 return DAG.getConstant(0, SDLoc(), VT);
2872 }
2873
2874 // It's undefined behavior if a function marked with the amdgpu-no-*
2875 // attributes uses the corresponding intrinsic.
2876 return DAG.getPOISON(VT);
2877 }
2878
2879 return loadInputValue(DAG, RC, VT, SDLoc(DAG.getEntryNode()), *Reg);
2880}
2881
2883 CallingConv::ID CallConv,
2884 ArrayRef<ISD::InputArg> Ins, BitVector &Skipped,
2885 FunctionType *FType,
2886 SIMachineFunctionInfo *Info) {
2887 for (unsigned I = 0, E = Ins.size(), PSInputNum = 0; I != E; ++I) {
2888 const ISD::InputArg *Arg = &Ins[I];
2889
2890 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2891 "vector type argument should have been split");
2892
2893 // First check if it's a PS input addr.
2894 if (CallConv == CallingConv::AMDGPU_PS && !Arg->Flags.isInReg() &&
2895 PSInputNum <= 15) {
2896 bool SkipArg = !Arg->Used && !Info->isPSInputAllocated(PSInputNum);
2897
2898 // Inconveniently only the first part of the split is marked as isSplit,
2899 // so skip to the end. We only want to increment PSInputNum once for the
2900 // entire split argument.
2901 if (Arg->Flags.isSplit()) {
2902 while (!Arg->Flags.isSplitEnd()) {
2903 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2904 "unexpected vector split in ps argument type");
2905 if (!SkipArg)
2906 Splits.push_back(*Arg);
2907 Arg = &Ins[++I];
2908 }
2909 }
2910
2911 if (SkipArg) {
2912 // We can safely skip PS inputs.
2913 Skipped.set(Arg->getOrigArgIndex());
2914 ++PSInputNum;
2915 continue;
2916 }
2917
2918 Info->markPSInputAllocated(PSInputNum);
2919 if (Arg->Used)
2920 Info->markPSInputEnabled(PSInputNum);
2921
2922 ++PSInputNum;
2923 }
2924
2925 Splits.push_back(*Arg);
2926 }
2927}
2928
2929// Allocate special inputs passed in VGPRs.
2931 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
2932 SIMachineFunctionInfo &Info) const {
2933 const LLT S32 = LLT::scalar(32);
2934 MachineRegisterInfo &MRI = MF.getRegInfo();
2935
2936 if (Info.hasWorkItemIDX()) {
2937 Register Reg = AMDGPU::VGPR0;
2938 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), S32);
2939
2940 CCInfo.AllocateReg(Reg);
2941 unsigned Mask =
2942 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
2943 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
2944 }
2945
2946 if (Info.hasWorkItemIDY()) {
2947 assert(Info.hasWorkItemIDX());
2948 if (Subtarget->hasPackedTID()) {
2949 Info.setWorkItemIDY(
2950 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 10));
2951 } else {
2952 unsigned Reg = AMDGPU::VGPR1;
2953 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), S32);
2954
2955 CCInfo.AllocateReg(Reg);
2956 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg));
2957 }
2958 }
2959
2960 if (Info.hasWorkItemIDZ()) {
2961 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
2962 if (Subtarget->hasPackedTID()) {
2963 Info.setWorkItemIDZ(
2964 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 20));
2965 } else {
2966 unsigned Reg = AMDGPU::VGPR2;
2967 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), S32);
2968
2969 CCInfo.AllocateReg(Reg);
2970 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg));
2971 }
2972 }
2973}
2974
2975// Try to allocate a VGPR at the end of the argument list, or if no argument
2976// VGPRs are left allocating a stack slot.
2977// If \p Mask is given it indicates bitfield position in the register.
2978// If \p Arg is given use it with new ]p Mask instead of allocating new.
2979static ArgDescriptor allocateVGPR32Input(CCState &CCInfo, unsigned Mask = ~0u,
2980 ArgDescriptor Arg = ArgDescriptor()) {
2981 if (Arg.isSet())
2982 return ArgDescriptor::createArg(Arg, Mask);
2983
2984 ArrayRef<MCPhysReg> ArgVGPRs = ArrayRef(AMDGPU::VGPR_32RegClass.begin(), 32);
2985 unsigned RegIdx = CCInfo.getFirstUnallocated(ArgVGPRs);
2986 if (RegIdx == ArgVGPRs.size()) {
2987 // Spill to stack required.
2988 int64_t Offset = CCInfo.AllocateStack(4, Align(4));
2989
2990 return ArgDescriptor::createStack(Offset, Mask);
2991 }
2992
2993 unsigned Reg = ArgVGPRs[RegIdx];
2994 Reg = CCInfo.AllocateReg(Reg);
2995 assert(Reg != AMDGPU::NoRegister);
2996
2997 MachineFunction &MF = CCInfo.getMachineFunction();
2998 Register LiveInVReg = MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass);
2999 MF.getRegInfo().setType(LiveInVReg, LLT::scalar(32));
3000 return ArgDescriptor::createRegister(Reg, Mask);
3001}
3002
3004 const TargetRegisterClass *RC,
3005 unsigned NumArgRegs) {
3006 ArrayRef<MCPhysReg> ArgSGPRs = ArrayRef(RC->begin(), 32);
3007 unsigned RegIdx = CCInfo.getFirstUnallocated(ArgSGPRs);
3008 if (RegIdx == ArgSGPRs.size())
3009 report_fatal_error("ran out of SGPRs for arguments");
3010
3011 unsigned Reg = ArgSGPRs[RegIdx];
3012 Reg = CCInfo.AllocateReg(Reg);
3013 assert(Reg != AMDGPU::NoRegister);
3014
3015 MachineFunction &MF = CCInfo.getMachineFunction();
3016 MF.addLiveIn(Reg, RC);
3018}
3019
3020// If this has a fixed position, we still should allocate the register in the
3021// CCInfo state. Technically we could get away with this for values passed
3022// outside of the normal argument range.
3024 const TargetRegisterClass *RC,
3025 MCRegister Reg) {
3026 Reg = CCInfo.AllocateReg(Reg);
3027 assert(Reg != AMDGPU::NoRegister);
3028 MachineFunction &MF = CCInfo.getMachineFunction();
3029 MF.addLiveIn(Reg, RC);
3030}
3031
3032static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg) {
3033 if (Arg) {
3034 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_32RegClass,
3035 Arg.getRegister());
3036 } else
3037 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_32RegClass, 32);
3038}
3039
3040static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg) {
3041 if (Arg) {
3042 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_64RegClass,
3043 Arg.getRegister());
3044 } else
3045 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_64RegClass, 16);
3046}
3047
3048/// Allocate implicit function VGPR arguments at the end of allocated user
3049/// arguments.
3051 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3052 SIMachineFunctionInfo &Info) const {
3053 const unsigned Mask = 0x3ff;
3054 ArgDescriptor Arg;
3055
3056 if (Info.hasWorkItemIDX()) {
3057 Arg = allocateVGPR32Input(CCInfo, Mask);
3058 Info.setWorkItemIDX(Arg);
3059 }
3060
3061 if (Info.hasWorkItemIDY()) {
3062 Arg = allocateVGPR32Input(CCInfo, Mask << 10, Arg);
3063 Info.setWorkItemIDY(Arg);
3064 }
3065
3066 if (Info.hasWorkItemIDZ())
3067 Info.setWorkItemIDZ(allocateVGPR32Input(CCInfo, Mask << 20, Arg));
3068}
3069
3070/// Allocate implicit function VGPR arguments in fixed registers.
3072 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3073 SIMachineFunctionInfo &Info) const {
3074 Register Reg = CCInfo.AllocateReg(AMDGPU::VGPR31);
3075 if (!Reg)
3076 report_fatal_error("failed to allocate VGPR for implicit arguments");
3077
3078 const unsigned Mask = 0x3ff;
3079 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
3080 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg, Mask << 10));
3081 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg, Mask << 20));
3082}
3083
3085 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3086 SIMachineFunctionInfo &Info) const {
3087 auto &ArgInfo = Info.getArgInfo();
3088 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3089
3090 // TODO: Unify handling with private memory pointers.
3091 if (UserSGPRInfo.hasDispatchPtr())
3092 allocateSGPR64Input(CCInfo, ArgInfo.DispatchPtr);
3093
3094 if (UserSGPRInfo.hasQueuePtr())
3095 allocateSGPR64Input(CCInfo, ArgInfo.QueuePtr);
3096
3097 // Implicit arg ptr takes the place of the kernarg segment pointer. This is a
3098 // constant offset from the kernarg segment.
3099 if (Info.hasImplicitArgPtr())
3100 allocateSGPR64Input(CCInfo, ArgInfo.ImplicitArgPtr);
3101
3102 if (UserSGPRInfo.hasDispatchID())
3103 allocateSGPR64Input(CCInfo, ArgInfo.DispatchID);
3104
3105 // flat_scratch_init is not applicable for non-kernel functions.
3106
3107 if (Info.hasWorkGroupIDX())
3108 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDX);
3109
3110 if (Info.hasWorkGroupIDY())
3111 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDY);
3112
3113 if (Info.hasWorkGroupIDZ())
3114 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDZ);
3115
3116 if (Info.hasLDSKernelId())
3117 allocateSGPR32Input(CCInfo, ArgInfo.LDSKernelId);
3118}
3119
3120// Allocate special inputs passed in user SGPRs.
3122 MachineFunction &MF,
3123 const SIRegisterInfo &TRI,
3124 SIMachineFunctionInfo &Info) const {
3125 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3126 if (UserSGPRInfo.hasImplicitBufferPtr()) {
3127 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(TRI);
3128 MF.addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3129 CCInfo.AllocateReg(ImplicitBufferPtrReg);
3130 }
3131
3132 // FIXME: How should these inputs interact with inreg / custom SGPR inputs?
3133 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
3134 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(TRI);
3135 MF.addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3136 CCInfo.AllocateReg(PrivateSegmentBufferReg);
3137 }
3138
3139 if (UserSGPRInfo.hasDispatchPtr()) {
3140 Register DispatchPtrReg = Info.addDispatchPtr(TRI);
3141 MF.addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3142 CCInfo.AllocateReg(DispatchPtrReg);
3143 }
3144
3145 if (UserSGPRInfo.hasQueuePtr()) {
3146 Register QueuePtrReg = Info.addQueuePtr(TRI);
3147 MF.addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3148 CCInfo.AllocateReg(QueuePtrReg);
3149 }
3150
3151 if (UserSGPRInfo.hasKernargSegmentPtr()) {
3152 MachineRegisterInfo &MRI = MF.getRegInfo();
3153 Register InputPtrReg = Info.addKernargSegmentPtr(TRI);
3154 CCInfo.AllocateReg(InputPtrReg);
3155
3156 Register VReg = MF.addLiveIn(InputPtrReg, &AMDGPU::SGPR_64RegClass);
3158 }
3159
3160 if (UserSGPRInfo.hasDispatchID()) {
3161 Register DispatchIDReg = Info.addDispatchID(TRI);
3162 MF.addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3163 CCInfo.AllocateReg(DispatchIDReg);
3164 }
3165
3166 if (UserSGPRInfo.hasFlatScratchInit() && !getSubtarget()->isAmdPalOS()) {
3167 Register FlatScratchInitReg = Info.addFlatScratchInit(TRI);
3168 MF.addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3169 CCInfo.AllocateReg(FlatScratchInitReg);
3170 }
3171
3172 if (UserSGPRInfo.hasPrivateSegmentSize()) {
3173 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(TRI);
3174 MF.addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3175 CCInfo.AllocateReg(PrivateSegmentSizeReg);
3176 }
3177
3178 // TODO: Add GridWorkGroupCount user SGPRs when used. For now with HSA we read
3179 // these from the dispatch pointer.
3180}
3181
3182// Allocate pre-loaded kernel arguemtns. Arguments to be preloading must be
3183// sequential starting from the first argument.
3185 CCState &CCInfo, SmallVectorImpl<CCValAssign> &ArgLocs,
3187 const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const {
3188 Function &F = MF.getFunction();
3189 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3190 GCNUserSGPRUsageInfo &SGPRInfo = Info.getUserSGPRInfo();
3191 bool InPreloadSequence = true;
3192 unsigned InIdx = 0;
3193 bool AlignedForImplictArgs = false;
3194 unsigned ImplicitArgOffset = 0;
3195 for (auto &Arg : F.args()) {
3196 if (!InPreloadSequence || !Arg.hasInRegAttr())
3197 break;
3198
3199 unsigned ArgIdx = Arg.getArgNo();
3200 // Don't preload non-original args or parts not in the current preload
3201 // sequence.
3202 if (InIdx < Ins.size() &&
3203 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3204 break;
3205
3206 for (; InIdx < Ins.size() && Ins[InIdx].isOrigArg() &&
3207 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3208 InIdx++) {
3209 assert(ArgLocs[ArgIdx].isMemLoc());
3210 auto &ArgLoc = ArgLocs[InIdx];
3211 const Align KernelArgBaseAlign = Align(16);
3212 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3213 Align Alignment = commonAlignment(KernelArgBaseAlign, ArgOffset);
3214 unsigned NumAllocSGPRs =
3215 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3216
3217 // Fix alignment for hidden arguments.
3218 if (Arg.hasAttribute("amdgpu-hidden-argument")) {
3219 if (!AlignedForImplictArgs) {
3220 ImplicitArgOffset =
3221 alignTo(LastExplicitArgOffset,
3222 Subtarget->getAlignmentForImplicitArgPtr()) -
3223 LastExplicitArgOffset;
3224 AlignedForImplictArgs = true;
3225 }
3226 ArgOffset += ImplicitArgOffset;
3227 }
3228
3229 // Arg is preloaded into the previous SGPR.
3230 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3231 assert(InIdx >= 1 && "No previous SGPR");
3232 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3233 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3234 continue;
3235 }
3236
3237 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3238 unsigned PaddingSGPRs = alignTo(Padding, 4) / 4;
3239 // Check for free user SGPRs for preloading.
3240 if (PaddingSGPRs + NumAllocSGPRs > SGPRInfo.getNumFreeUserSGPRs()) {
3241 InPreloadSequence = false;
3242 break;
3243 }
3244
3245 // Preload this argument.
3246 const TargetRegisterClass *RC =
3247 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3248 SmallVectorImpl<MCRegister> *PreloadRegs =
3249 Info.addPreloadedKernArg(TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3250
3251 if (PreloadRegs->size() > 1)
3252 RC = &AMDGPU::SGPR_32RegClass;
3253 for (auto &Reg : *PreloadRegs) {
3254 assert(Reg);
3255 MF.addLiveIn(Reg, RC);
3256 CCInfo.AllocateReg(Reg);
3257 }
3258
3259 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3260 }
3261 }
3262}
3263
3265 const SIRegisterInfo &TRI,
3266 SIMachineFunctionInfo &Info) const {
3267 // Always allocate this last since it is a synthetic preload.
3268 if (Info.hasLDSKernelId()) {
3269 Register Reg = Info.addLDSKernelId();
3270 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3271 CCInfo.AllocateReg(Reg);
3272 }
3273}
3274
3275// Allocate special input registers that are initialized per-wave.
3278 CallingConv::ID CallConv,
3279 bool IsShader) const {
3280 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3281 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3282 // Note: user SGPRs are handled by the front-end for graphics shaders
3283 // Pad up the used user SGPRs with dead inputs.
3284
3285 // TODO: NumRequiredSystemSGPRs computation should be adjusted appropriately
3286 // before enabling architected SGPRs for workgroup IDs.
3287 assert(!HasArchitectedSGPRs && "Unhandled feature for the subtarget");
3288
3289 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3290 // Note we do not count the PrivateSegmentWaveByteOffset. We do not want to
3291 // rely on it to reach 16 since if we end up having no stack usage, it will
3292 // not really be added.
3293 unsigned NumRequiredSystemSGPRs =
3294 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3295 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3296 for (unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3297 Register Reg = Info.addReservedUserSGPR();
3298 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3299 CCInfo.AllocateReg(Reg);
3300 }
3301 }
3302
3303 if (!HasArchitectedSGPRs) {
3304 if (Info.hasWorkGroupIDX()) {
3305 Register Reg = Info.addWorkGroupIDX();
3306 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3307 CCInfo.AllocateReg(Reg);
3308 }
3309
3310 if (Info.hasWorkGroupIDY()) {
3311 Register Reg = Info.addWorkGroupIDY();
3312 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3313 CCInfo.AllocateReg(Reg);
3314 }
3315
3316 if (Info.hasWorkGroupIDZ()) {
3317 Register Reg = Info.addWorkGroupIDZ();
3318 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3319 CCInfo.AllocateReg(Reg);
3320 }
3321 }
3322
3323 if (Info.hasWorkGroupInfo()) {
3324 Register Reg = Info.addWorkGroupInfo();
3325 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3326 CCInfo.AllocateReg(Reg);
3327 }
3328
3329 if (Info.hasPrivateSegmentWaveByteOffset()) {
3330 // Scratch wave offset passed in system SGPR.
3331 unsigned PrivateSegmentWaveByteOffsetReg;
3332
3333 if (IsShader) {
3334 PrivateSegmentWaveByteOffsetReg =
3335 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3336
3337 // This is true if the scratch wave byte offset doesn't have a fixed
3338 // location.
3339 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3340 PrivateSegmentWaveByteOffsetReg = findFirstFreeSGPR(CCInfo);
3341 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3342 }
3343 } else
3344 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3345
3346 MF.addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3347 CCInfo.AllocateReg(PrivateSegmentWaveByteOffsetReg);
3348 }
3349
3350 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3351 Info.getNumPreloadedSGPRs() >= 16);
3352}
3353
3355 MachineFunction &MF,
3356 const SIRegisterInfo &TRI,
3357 SIMachineFunctionInfo &Info) {
3358 // Now that we've figured out where the scratch register inputs are, see if
3359 // should reserve the arguments and use them directly.
3360 MachineFrameInfo &MFI = MF.getFrameInfo();
3361 bool HasStackObjects = MFI.hasStackObjects();
3362 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3363
3364 // Record that we know we have non-spill stack objects so we don't need to
3365 // check all stack objects later.
3366 if (HasStackObjects)
3367 Info.setHasNonSpillStackObjects(true);
3368
3369 // Everything live out of a block is spilled with fast regalloc, so it's
3370 // almost certain that spilling will be required.
3372 HasStackObjects = true;
3373
3374 // For now assume stack access is needed in any callee functions, so we need
3375 // the scratch registers to pass in.
3376 bool RequiresStackAccess = HasStackObjects || MFI.hasCalls();
3377
3378 if (!ST.hasFlatScratchEnabled()) {
3379 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.getFunction())) {
3380 // If we have stack objects, we unquestionably need the private buffer
3381 // resource. For the Code Object V2 ABI, this will be the first 4 user
3382 // SGPR inputs. We can reserve those and use them directly.
3383
3384 Register PrivateSegmentBufferReg =
3386 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3387 } else {
3388 unsigned ReservedBufferReg = TRI.reservedPrivateSegmentBufferReg(MF);
3389 // We tentatively reserve the last registers (skipping the last registers
3390 // which may contain VCC, FLAT_SCR, and XNACK). After register allocation,
3391 // we'll replace these with the ones immediately after those which were
3392 // really allocated. In the prologue copies will be inserted from the
3393 // argument to these reserved registers.
3394
3395 // Without HSA, relocations are used for the scratch pointer and the
3396 // buffer resource setup is always inserted in the prologue. Scratch wave
3397 // offset is still in an input SGPR.
3398 Info.setScratchRSrcReg(ReservedBufferReg);
3399 }
3400 }
3401
3402 MachineRegisterInfo &MRI = MF.getRegInfo();
3403
3404 // For entry functions we have to set up the stack pointer if we use it,
3405 // whereas non-entry functions get this "for free". This means there is no
3406 // intrinsic advantage to using S32 over S34 in cases where we do not have
3407 // calls but do need a frame pointer (i.e. if we are requested to have one
3408 // because frame pointer elimination is disabled). To keep things simple we
3409 // only ever use S32 as the call ABI stack pointer, and so using it does not
3410 // imply we need a separate frame pointer.
3411 //
3412 // Try to use s32 as the SP, but move it if it would interfere with input
3413 // arguments. This won't work with calls though.
3414 //
3415 // FIXME: Move SP to avoid any possible inputs, or find a way to spill input
3416 // registers.
3417 if (!MRI.isLiveIn(AMDGPU::SGPR32)) {
3418 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3419 } else {
3421
3422 if (MFI.hasCalls())
3423 report_fatal_error("call in graphics shader with too many input SGPRs");
3424
3425 for (unsigned Reg : AMDGPU::SGPR_32RegClass) {
3426 if (!MRI.isLiveIn(Reg)) {
3427 Info.setStackPtrOffsetReg(Reg);
3428 break;
3429 }
3430 }
3431
3432 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3433 report_fatal_error("failed to find register for SP");
3434 }
3435
3436 // hasFP should be accurate for entry functions even before the frame is
3437 // finalized, because it does not rely on the known stack size, only
3438 // properties like whether variable sized objects are present.
3439 if (ST.getFrameLowering()->hasFP(MF)) {
3440 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3441 }
3442}
3443
3446 return !Info->isEntryFunction();
3447}
3448
3450
3452 MachineBasicBlock *Entry,
3453 const SmallVectorImpl<MachineBasicBlock *> &Exits) const {
3455
3456 const MCPhysReg *IStart = TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3457 if (!IStart)
3458 return;
3459
3460 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3461 MachineRegisterInfo *MRI = &Entry->getParent()->getRegInfo();
3462 MachineBasicBlock::iterator MBBI = Entry->begin();
3463 for (const MCPhysReg *I = IStart; *I; ++I) {
3464 const TargetRegisterClass *RC = nullptr;
3465 if (AMDGPU::SReg_64RegClass.contains(*I))
3466 RC = &AMDGPU::SGPR_64RegClass;
3467 else if (AMDGPU::SReg_32RegClass.contains(*I))
3468 RC = &AMDGPU::SGPR_32RegClass;
3469 else
3470 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3471
3472 Register NewVR = MRI->createVirtualRegister(RC);
3473 // Create copy from CSR to a virtual register.
3474 Entry->addLiveIn(*I);
3475 BuildMI(*Entry, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY), NewVR)
3476 .addReg(*I);
3477
3478 // Insert the copy-back instructions right before the terminator.
3479 for (auto *Exit : Exits)
3480 BuildMI(*Exit, Exit->getFirstTerminator(), DebugLoc(),
3481 TII->get(TargetOpcode::COPY), *I)
3482 .addReg(NewVR);
3483 }
3484}
3485
3487 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
3488 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3489 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
3491
3493 const Function &Fn = MF.getFunction();
3496 bool IsError = false;
3497
3498 if (Subtarget->isAmdHsaOS() && AMDGPU::isGraphics(CallConv)) {
3500 Fn, "unsupported non-compute shaders with HSA", DL.getDebugLoc()));
3501 IsError = true;
3502 }
3503
3506 BitVector Skipped(Fn.arg_size());
3507 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
3508 *DAG.getContext());
3509
3510 bool IsGraphics = AMDGPU::isGraphics(CallConv);
3511 bool IsKernel = AMDGPU::isKernel(CallConv);
3512 bool IsEntryFunc = AMDGPU::isEntryFunctionCC(CallConv);
3513
3514 if (IsGraphics) {
3515 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info->getUserSGPRInfo();
3516 assert(!UserSGPRInfo.hasDispatchPtr() &&
3517 !UserSGPRInfo.hasKernargSegmentPtr() && !Info->hasWorkGroupInfo() &&
3518 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3519 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3520 (void)UserSGPRInfo;
3521 if (!Subtarget->hasFlatScratchEnabled())
3522 assert(!UserSGPRInfo.hasFlatScratchInit());
3523 if ((CallConv != CallingConv::AMDGPU_CS &&
3524 CallConv != CallingConv::AMDGPU_Gfx &&
3525 CallConv != CallingConv::AMDGPU_Gfx_WholeWave) ||
3526 !Subtarget->hasArchitectedSGPRs())
3527 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3528 !Info->hasWorkGroupIDZ());
3529 }
3530
3531 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3532
3533 if (CallConv == CallingConv::AMDGPU_PS) {
3534 processPSInputArgs(Splits, CallConv, Ins, Skipped, FType, Info);
3535
3536 // At least one interpolation mode must be enabled or else the GPU will
3537 // hang.
3538 //
3539 // Check PSInputAddr instead of PSInputEnable. The idea is that if the user
3540 // set PSInputAddr, the user wants to enable some bits after the compilation
3541 // based on run-time states. Since we can't know what the final PSInputEna
3542 // will look like, so we shouldn't do anything here and the user should take
3543 // responsibility for the correct programming.
3544 //
3545 // Otherwise, the following restrictions apply:
3546 // - At least one of PERSP_* (0xF) or LINEAR_* (0x70) must be enabled.
3547 // - If POS_W_FLOAT (11) is enabled, at least one of PERSP_* must be
3548 // enabled too.
3549 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3550 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3551 CCInfo.AllocateReg(AMDGPU::VGPR0);
3552 CCInfo.AllocateReg(AMDGPU::VGPR1);
3553 Info->markPSInputAllocated(0);
3554 Info->markPSInputEnabled(0);
3555 }
3556 if (Subtarget->isAmdPalOS()) {
3557 // For isAmdPalOS, the user does not enable some bits after compilation
3558 // based on run-time states; the register values being generated here are
3559 // the final ones set in hardware. Therefore we need to apply the
3560 // workaround to PSInputAddr and PSInputEnable together. (The case where
3561 // a bit is set in PSInputAddr but not PSInputEnable is where the
3562 // frontend set up an input arg for a particular interpolation mode, but
3563 // nothing uses that input arg. Really we should have an earlier pass
3564 // that removes such an arg.)
3565 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3566 if ((PsInputBits & 0x7F) == 0 ||
3567 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3568 Info->markPSInputEnabled(llvm::countr_zero(Info->getPSInputAddr()));
3569 }
3570 } else if (IsKernel) {
3571 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3572 } else {
3573 Splits.append(IsWholeWaveFunc ? std::next(Ins.begin()) : Ins.begin(),
3574 Ins.end());
3575 }
3576
3577 if (IsKernel)
3578 analyzeFormalArgumentsCompute(CCInfo, Ins);
3579
3580 if (IsEntryFunc) {
3581 allocateSpecialEntryInputVGPRs(CCInfo, MF, *TRI, *Info);
3582 allocateHSAUserSGPRs(CCInfo, MF, *TRI, *Info);
3583 if (IsKernel && Subtarget->hasKernargPreload())
3584 allocatePreloadKernArgSGPRs(CCInfo, ArgLocs, Ins, MF, *TRI, *Info);
3585
3586 allocateLDSKernelId(CCInfo, MF, *TRI, *Info);
3587 } else if (!IsGraphics) {
3588 // For the fixed ABI, pass workitem IDs in the last argument register.
3589 allocateSpecialInputVGPRsFixed(CCInfo, MF, *TRI, *Info);
3590
3591 // FIXME: Sink this into allocateSpecialInputSGPRs
3592 if (!Subtarget->hasFlatScratchEnabled())
3593 CCInfo.AllocateReg(Info->getScratchRSrcReg());
3594
3595 allocateSpecialInputSGPRs(CCInfo, MF, *TRI, *Info);
3596 }
3597
3598 if (!IsKernel) {
3599 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, isVarArg);
3600 CCInfo.AnalyzeFormalArguments(Splits, AssignFn);
3601
3602 // This assumes the registers are allocated by CCInfo in ascending order
3603 // with no gaps.
3604 Info->setNumWaveDispatchSGPRs(
3605 CCInfo.getFirstUnallocated(AMDGPU::SGPR_32RegClass.getRegisters()));
3606 Info->setNumWaveDispatchVGPRs(
3607 CCInfo.getFirstUnallocated(AMDGPU::VGPR_32RegClass.getRegisters()));
3608 } else if (Info->getNumKernargPreloadedSGPRs()) {
3609 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3610 }
3611
3613
3614 if (IsWholeWaveFunc) {
3615 SDValue Setup = DAG.getNode(AMDGPUISD::WHOLE_WAVE_SETUP, DL,
3616 {MVT::i1, MVT::Other}, Chain);
3617 InVals.push_back(Setup.getValue(0));
3618 Chains.push_back(Setup.getValue(1));
3619 }
3620
3621 // FIXME: This is the minimum kernel argument alignment. We should improve
3622 // this to the maximum alignment of the arguments.
3623 //
3624 // FIXME: Alignment of explicit arguments totally broken with non-0 explicit
3625 // kern arg offset.
3626 const Align KernelArgBaseAlign = Align(16);
3627
3628 for (unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.size(), ArgIdx = 0; i != e;
3629 ++i) {
3630 const ISD::InputArg &Arg = Ins[i];
3631 if ((Arg.isOrigArg() && Skipped[Arg.getOrigArgIndex()]) || IsError) {
3632 InVals.push_back(DAG.getPOISON(Arg.VT));
3633 continue;
3634 }
3635
3636 CCValAssign &VA = ArgLocs[ArgIdx++];
3637 MVT VT = VA.getLocVT();
3638
3639 if (IsEntryFunc && VA.isMemLoc()) {
3640 VT = Ins[i].VT;
3641 EVT MemVT = VA.getLocVT();
3642
3643 const uint64_t Offset = VA.getLocMemOffset();
3644 Align Alignment = commonAlignment(KernelArgBaseAlign, Offset);
3645
3646 if (Arg.Flags.isByRef()) {
3647 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, Chain, Offset);
3648
3649 const GCNTargetMachine &TM =
3650 static_cast<const GCNTargetMachine &>(getTargetMachine());
3651 if (!TM.isNoopAddrSpaceCast(AMDGPUAS::CONSTANT_ADDRESS,
3652 Arg.Flags.getPointerAddrSpace())) {
3655 }
3656
3657 InVals.push_back(Ptr);
3658 continue;
3659 }
3660
3661 SDValue NewArg;
3662 if (Arg.isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3663 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
3664 // In this case the argument is packed into the previous preload SGPR.
3665 int64_t AlignDownOffset = alignDown(Offset, 4);
3666 int64_t OffsetDiff = Offset - AlignDownOffset;
3667 EVT IntVT = MemVT.changeTypeToInteger();
3668
3669 const SIMachineFunctionInfo *Info =
3672 Register Reg =
3673 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3674
3675 assert(Reg);
3676 Register VReg = MRI.getLiveInVirtReg(Reg);
3677 SDValue Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3678
3679 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, DL, MVT::i32);
3680 SDValue Extract = DAG.getNode(ISD::SRL, DL, MVT::i32, Copy, ShiftAmt);
3681
3682 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Extract);
3683 ArgVal = DAG.getNode(ISD::BITCAST, DL, MemVT, ArgVal);
3684 NewArg = convertArgType(DAG, VT, MemVT, DL, ArgVal,
3685 Ins[i].Flags.isSExt(), &Ins[i]);
3686
3687 NewArg = DAG.getMergeValues({NewArg, Copy.getValue(1)}, DL);
3688 } else {
3689 const SIMachineFunctionInfo *Info =
3692 const SmallVectorImpl<MCRegister> &PreloadRegs =
3693 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3694
3695 SDValue Copy;
3696 if (PreloadRegs.size() == 1) {
3697 Register VReg = MRI.getLiveInVirtReg(PreloadRegs[0]);
3698 const TargetRegisterClass *RC = MRI.getRegClass(VReg);
3699 NewArg = DAG.getCopyFromReg(
3700 Chain, DL, VReg,
3702 TRI->getRegSizeInBits(*RC)));
3703
3704 } else {
3705 // If the kernarg alignment does not match the alignment of the SGPR
3706 // tuple RC that can accommodate this argument, it will be built up
3707 // via copies from from the individual SGPRs that the argument was
3708 // preloaded to.
3710 for (auto Reg : PreloadRegs) {
3711 Register VReg = MRI.getLiveInVirtReg(Reg);
3712 Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3713 Elts.push_back(Copy);
3714 }
3715 NewArg =
3716 DAG.getBuildVector(EVT::getVectorVT(*DAG.getContext(), MVT::i32,
3717 PreloadRegs.size()),
3718 DL, Elts);
3719 }
3720
3721 // If the argument was preloaded to multiple consecutive 32-bit
3722 // registers because of misalignment between addressable SGPR tuples
3723 // and the argument size, we can still assume that because of kernarg
3724 // segment alignment restrictions that NewArg's size is the same as
3725 // MemVT and just do a bitcast. If MemVT is less than 32-bits we add a
3726 // truncate since we cannot preload to less than a single SGPR and the
3727 // MemVT may be smaller.
3728 EVT MemVTInt =
3730 if (MemVT.bitsLT(NewArg.getSimpleValueType()))
3731 NewArg = DAG.getNode(ISD::TRUNCATE, DL, MemVTInt, NewArg);
3732
3733 NewArg = DAG.getBitcast(MemVT, NewArg);
3734 NewArg = convertArgType(DAG, VT, MemVT, DL, NewArg,
3735 Ins[i].Flags.isSExt(), &Ins[i]);
3736 NewArg = DAG.getMergeValues({NewArg, Chain}, DL);
3737 }
3738 } else {
3739 // Hidden arguments that are in the kernel signature must be preloaded
3740 // to user SGPRs. Print a diagnostic error if a hidden argument is in
3741 // the argument list and is not preloaded.
3742 if (Arg.isOrigArg()) {
3743 Argument *OrigArg = Fn.getArg(Arg.getOrigArgIndex());
3744 if (OrigArg->hasAttribute("amdgpu-hidden-argument")) {
3746 *OrigArg->getParent(),
3747 "hidden argument in kernel signature was not preloaded",
3748 DL.getDebugLoc()));
3749 }
3750 }
3751
3752 NewArg =
3753 lowerKernargMemParameter(DAG, VT, MemVT, DL, Chain, Offset,
3754 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3755 }
3756 Chains.push_back(NewArg.getValue(1));
3757
3758 auto *ParamTy =
3759 dyn_cast<PointerType>(FType->getParamType(Ins[i].getOrigArgIndex()));
3760 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS &&
3761 ParamTy &&
3762 (ParamTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
3763 ParamTy->getAddressSpace() == AMDGPUAS::REGION_ADDRESS)) {
3764 // On SI local pointers are just offsets into LDS, so they are always
3765 // less than 16-bits. On CI and newer they could potentially be
3766 // real pointers, so we can't guarantee their size.
3767 NewArg = DAG.getNode(ISD::AssertZext, DL, NewArg.getValueType(), NewArg,
3768 DAG.getValueType(MVT::i16));
3769 }
3770
3771 InVals.push_back(NewArg);
3772 continue;
3773 }
3774 if (!IsEntryFunc && VA.isMemLoc()) {
3775 SDValue Val = lowerStackParameter(DAG, VA, DL, Chain, Arg);
3776 InVals.push_back(Val);
3777 if (!Arg.Flags.isByVal())
3778 Chains.push_back(Val.getValue(1));
3779 continue;
3780 }
3781
3782 assert(VA.isRegLoc() && "Parameter must be in a register!");
3783
3784 Register Reg = VA.getLocReg();
3785 const TargetRegisterClass *RC = nullptr;
3786 if (AMDGPU::VGPR_32RegClass.contains(Reg))
3787 RC = &AMDGPU::VGPR_32RegClass;
3788 else if (AMDGPU::SGPR_32RegClass.contains(Reg))
3789 RC = &AMDGPU::SGPR_32RegClass;
3790 else
3791 llvm_unreachable("Unexpected register class in LowerFormalArguments!");
3792
3793 Reg = MF.addLiveIn(Reg, RC);
3794 SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, VT);
3795 if (Arg.Flags.isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3796 // FIXME: Need to forward the chains created by `CopyFromReg`s, make sure
3797 // they will read physical regs before any side effect instructions.
3798 SDValue ReadFirstLane =
3799 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3801 ReadFirstLane, Val);
3802 }
3803
3804 if (Arg.Flags.isSRet()) {
3805 // The return object should be reasonably addressable.
3806 Val = annotateStackObjectPointer(Val, DAG, DL,
3808 }
3809
3810 Val = convertABITypeToValueType(DAG, Val, VA, DL);
3811 InVals.push_back(Val);
3812 }
3813
3814 // Start adding system SGPRs.
3815 if (IsEntryFunc)
3816 allocateSystemSGPRs(CCInfo, MF, *Info, CallConv, IsGraphics);
3817
3818 unsigned StackArgSize = CCInfo.getStackSize();
3819 Info->setBytesInStackArgArea(StackArgSize);
3820
3821 return Chains.empty() ? Chain
3822 : DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
3823}
3824
3825// TODO: If return values can't fit in registers, we should return as many as
3826// possible in registers before passing on stack.
3828 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
3829 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
3830 const Type *RetTy) const {
3831 // Replacing returns with sret/stack usage doesn't make sense for shaders.
3832 // FIXME: Also sort of a workaround for custom vector splitting in LowerReturn
3833 // for shaders. Vector types should be explicitly handled by CC.
3834 if (AMDGPU::isEntryFunctionCC(CallConv))
3835 return true;
3836
3838 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3839 if (!CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)))
3840 return false;
3841
3842 // We must use the stack if return would require unavailable registers.
3843 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3844 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3845 for (unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3846 if (CCInfo.isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3847 return false;
3848
3849 return true;
3850}
3851
3852SDValue
3854 bool isVarArg,
3856 const SmallVectorImpl<SDValue> &OutVals,
3857 const SDLoc &DL, SelectionDAG &DAG) const {
3861
3862 if (AMDGPU::isKernel(CallConv)) {
3863 return AMDGPUTargetLowering::LowerReturn(Chain, CallConv, isVarArg, Outs,
3864 OutVals, DL, DAG);
3865 }
3866
3867 bool IsShader = AMDGPU::isShader(CallConv);
3868
3869 Info->setIfReturnsVoid(Outs.empty());
3870 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3871
3872 // CCValAssign - represent the assignment of the return value to a location.
3874
3875 // CCState - Info about the registers and stack slots.
3876 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
3877 *DAG.getContext());
3878
3879 // Analyze outgoing return values.
3880 CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, isVarArg));
3881
3882 SDValue Glue;
3884 RetOps.push_back(Chain); // Operand #0 = Chain (updated below)
3885
3886 SDValue ReadFirstLane =
3887 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3888 // Copy the result values into the output registers.
3889 for (unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.size(); I != E;
3890 ++I, ++RealRVLocIdx) {
3891 CCValAssign &VA = RVLocs[I];
3892 assert(VA.isRegLoc() && "Can only return in registers!");
3893 // TODO: Partially return in registers if return values don't fit.
3894 SDValue Arg = OutVals[RealRVLocIdx];
3895
3896 // Copied from other backends.
3897 switch (VA.getLocInfo()) {
3898 case CCValAssign::Full:
3899 break;
3900 case CCValAssign::BCvt:
3901 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
3902 break;
3903 case CCValAssign::SExt:
3904 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
3905 break;
3906 case CCValAssign::ZExt:
3907 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
3908 break;
3909 case CCValAssign::AExt:
3910 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
3911 break;
3912 default:
3913 llvm_unreachable("Unknown loc info!");
3914 }
3915 if (TRI->isSGPRPhysReg(VA.getLocReg()))
3917 ReadFirstLane, Arg);
3918 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Glue);
3919 Glue = Chain.getValue(1);
3920 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
3921 }
3922
3923 // FIXME: Does sret work properly?
3924 if (!Info->isEntryFunction()) {
3925 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
3926 const MCPhysReg *I =
3927 TRI->getCalleeSavedRegsViaCopy(&DAG.getMachineFunction());
3928 if (I) {
3929 for (; *I; ++I) {
3930 if (AMDGPU::SReg_64RegClass.contains(*I))
3931 RetOps.push_back(DAG.getRegister(*I, MVT::i64));
3932 else if (AMDGPU::SReg_32RegClass.contains(*I))
3933 RetOps.push_back(DAG.getRegister(*I, MVT::i32));
3934 else
3935 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3936 }
3937 }
3938 }
3939
3940 // Update chain and glue.
3941 RetOps[0] = Chain;
3942 if (Glue.getNode())
3943 RetOps.push_back(Glue);
3944
3945 unsigned Opc = AMDGPUISD::ENDPGM;
3946 if (!IsWaveEnd)
3947 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3948 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3949 : AMDGPUISD::RET_GLUE;
3950 return DAG.getNode(Opc, DL, MVT::Other, RetOps);
3951}
3952
3954 SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
3955 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3956 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, bool IsThisReturn,
3957 SDValue ThisVal) const {
3958 CCAssignFn *RetCC = CCAssignFnForReturn(CallConv, IsVarArg);
3959
3960 // Assign locations to each value returned by this call.
3962 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
3963 *DAG.getContext());
3964 CCInfo.AnalyzeCallResult(Ins, RetCC);
3965
3966 // Copy all of the result registers out of their specified physreg.
3967 for (CCValAssign VA : RVLocs) {
3968 SDValue Val;
3969
3970 if (VA.isRegLoc()) {
3971 Val =
3972 DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), InGlue);
3973 Chain = Val.getValue(1);
3974 InGlue = Val.getValue(2);
3975 } else if (VA.isMemLoc()) {
3976 report_fatal_error("TODO: return values in memory");
3977 } else
3978 llvm_unreachable("unknown argument location type");
3979
3980 switch (VA.getLocInfo()) {
3981 case CCValAssign::Full:
3982 break;
3983 case CCValAssign::BCvt:
3984 Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
3985 break;
3986 case CCValAssign::ZExt:
3987 Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val,
3988 DAG.getValueType(VA.getValVT()));
3989 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
3990 break;
3991 case CCValAssign::SExt:
3992 Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val,
3993 DAG.getValueType(VA.getValVT()));
3994 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
3995 break;
3996 case CCValAssign::AExt:
3997 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
3998 break;
3999 default:
4000 llvm_unreachable("Unknown loc info!");
4001 }
4002
4003 InVals.push_back(Val);
4004 }
4005
4006 return Chain;
4007}
4008
4009// Add code to pass special inputs required depending on used features separate
4010// from the explicit user arguments present in the IR.
4012 CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info,
4013 SmallVectorImpl<std::pair<unsigned, SDValue>> &RegsToPass,
4014 SmallVectorImpl<SDValue> &MemOpChains, SDValue Chain) const {
4015 // If we don't have a call site, this was a call inserted by
4016 // legalization. These can never use special inputs.
4017 if (!CLI.CB)
4018 return;
4019
4020 SelectionDAG &DAG = CLI.DAG;
4021 const SDLoc &DL = CLI.DL;
4022 const Function &F = DAG.getMachineFunction().getFunction();
4023
4024 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
4025 const AMDGPUFunctionArgInfo &CallerArgInfo = Info.getArgInfo();
4026
4027 const AMDGPUFunctionArgInfo &CalleeArgInfo =
4029
4030 // TODO: Unify with private memory register handling. This is complicated by
4031 // the fact that at least in kernels, the input argument is not necessarily
4032 // in the same location as the input.
4033 // clang-format off
4034 static constexpr std::pair<AMDGPUFunctionArgInfo::PreloadedValue,
4035 std::array<StringLiteral, 2>> ImplicitAttrs[] = {
4036 {AMDGPUFunctionArgInfo::DISPATCH_PTR, {"amdgpu-no-dispatch-ptr", ""}},
4037 {AMDGPUFunctionArgInfo::QUEUE_PTR, {"amdgpu-no-queue-ptr", ""}},
4038 {AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR, {"amdgpu-no-implicitarg-ptr", ""}},
4039 {AMDGPUFunctionArgInfo::DISPATCH_ID, {"amdgpu-no-dispatch-id", ""}},
4040 {AMDGPUFunctionArgInfo::WORKGROUP_ID_X, {"amdgpu-no-workgroup-id-x", "amdgpu-no-cluster-id-x"}},
4041 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Y, {"amdgpu-no-workgroup-id-y", "amdgpu-no-cluster-id-y"}},
4042 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Z, {"amdgpu-no-workgroup-id-z", "amdgpu-no-cluster-id-z"}},
4043 {AMDGPUFunctionArgInfo::LDS_KERNEL_ID, {"amdgpu-no-lds-kernel-id", ""}},
4044 };
4045 // clang-format on
4046
4047 for (auto [InputID, Attrs] : ImplicitAttrs) {
4048 // If the callee does not use the attribute value, skip copying the value.
4049 if (all_of(Attrs, [&](StringRef Attr) {
4050 return Attr.empty() || CLI.CB->hasFnAttr(Attr);
4051 }))
4052 continue;
4053
4054 const auto [OutgoingArg, ArgRC, ArgTy] =
4055 CalleeArgInfo.getPreloadedValue(InputID);
4056 if (!OutgoingArg)
4057 continue;
4058
4059 const auto [IncomingArg, IncomingArgRC, Ty] =
4060 CallerArgInfo.getPreloadedValue(InputID);
4061 assert(IncomingArgRC == ArgRC);
4062
4063 // All special arguments are ints for now.
4064 EVT ArgVT = TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4065 SDValue InputReg;
4066
4067 if (IncomingArg) {
4068 InputReg = loadInputValue(DAG, ArgRC, ArgVT, DL, *IncomingArg);
4069 } else if (InputID == AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR) {
4070 // The implicit arg ptr is special because it doesn't have a corresponding
4071 // input for kernels, and is computed from the kernarg segment pointer.
4072 InputReg = getImplicitArgPtr(DAG, DL);
4073 } else if (InputID == AMDGPUFunctionArgInfo::LDS_KERNEL_ID) {
4074 std::optional<uint32_t> Id =
4076 if (Id.has_value()) {
4077 InputReg = DAG.getConstant(*Id, DL, ArgVT);
4078 } else {
4079 InputReg = DAG.getPOISON(ArgVT);
4080 }
4081 } else {
4082 // We may have proven the input wasn't needed, although the ABI is
4083 // requiring it. We just need to allocate the register appropriately.
4084 InputReg = DAG.getPOISON(ArgVT);
4085 }
4086
4087 if (OutgoingArg->isRegister()) {
4088 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4089 if (!CCInfo.AllocateReg(OutgoingArg->getRegister()))
4090 report_fatal_error("failed to allocate implicit input argument");
4091 } else {
4092 unsigned SpecialArgOffset =
4093 CCInfo.AllocateStack(ArgVT.getStoreSize(), Align(4));
4094 SDValue ArgStore =
4095 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4096 MemOpChains.push_back(ArgStore);
4097 }
4098 }
4099
4100 // Pack workitem IDs into a single register or pass it as is if already
4101 // packed.
4102
4103 auto [OutgoingArg, ArgRC, Ty] =
4105 if (!OutgoingArg)
4106 std::tie(OutgoingArg, ArgRC, Ty) =
4108 if (!OutgoingArg)
4109 std::tie(OutgoingArg, ArgRC, Ty) =
4111 if (!OutgoingArg)
4112 return;
4113
4114 const ArgDescriptor *IncomingArgX = std::get<0>(
4116 const ArgDescriptor *IncomingArgY = std::get<0>(
4118 const ArgDescriptor *IncomingArgZ = std::get<0>(
4120
4121 SDValue InputReg;
4122 SDLoc SL;
4123
4124 const bool NeedWorkItemIDX = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-x");
4125 const bool NeedWorkItemIDY = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-y");
4126 const bool NeedWorkItemIDZ = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-z");
4127
4128 // If incoming ids are not packed we need to pack them.
4129 if (IncomingArgX && !IncomingArgX->isMasked() && CalleeArgInfo.WorkItemIDX &&
4130 NeedWorkItemIDX) {
4131 if (Subtarget->getMaxWorkitemID(F, 0) != 0) {
4132 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgX);
4133 } else {
4134 InputReg = DAG.getConstant(0, DL, MVT::i32);
4135 }
4136 }
4137
4138 if (IncomingArgY && !IncomingArgY->isMasked() && CalleeArgInfo.WorkItemIDY &&
4139 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(F, 1) != 0) {
4140 SDValue Y = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgY);
4141 Y = DAG.getNode(ISD::SHL, SL, MVT::i32, Y,
4142 DAG.getShiftAmountConstant(10, MVT::i32, SL));
4143 InputReg = InputReg.getNode()
4144 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Y)
4145 : Y;
4146 }
4147
4148 if (IncomingArgZ && !IncomingArgZ->isMasked() && CalleeArgInfo.WorkItemIDZ &&
4149 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(F, 2) != 0) {
4150 SDValue Z = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgZ);
4151 Z = DAG.getNode(ISD::SHL, SL, MVT::i32, Z,
4152 DAG.getShiftAmountConstant(20, MVT::i32, SL));
4153 InputReg = InputReg.getNode()
4154 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Z)
4155 : Z;
4156 }
4157
4158 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4159 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4160 // We're in a situation where the outgoing function requires the workitem
4161 // ID, but the calling function does not have it (e.g a graphics function
4162 // calling a C calling convention function). This is illegal, but we need
4163 // to produce something.
4164 InputReg = DAG.getPOISON(MVT::i32);
4165 } else {
4166 // Workitem ids are already packed, any of present incoming arguments
4167 // will carry all required fields.
4168 ArgDescriptor IncomingArg =
4169 ArgDescriptor::createArg(IncomingArgX ? *IncomingArgX
4170 : IncomingArgY ? *IncomingArgY
4171 : *IncomingArgZ,
4172 ~0u);
4173 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, IncomingArg);
4174 }
4175 }
4176
4177 if (OutgoingArg->isRegister()) {
4178 if (InputReg)
4179 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4180
4181 CCInfo.AllocateReg(OutgoingArg->getRegister());
4182 } else {
4183 unsigned SpecialArgOffset = CCInfo.AllocateStack(4, Align(4));
4184 if (InputReg) {
4185 SDValue ArgStore =
4186 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4187 MemOpChains.push_back(ArgStore);
4188 }
4189 }
4190}
4191
4193 SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg,
4195 const SmallVectorImpl<SDValue> &OutVals,
4196 const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const {
4197 if (AMDGPU::isChainCC(CalleeCC))
4198 return true;
4199
4200 if (!AMDGPU::mayTailCallThisCC(CalleeCC))
4201 return false;
4202
4203 // For a divergent call target, we need to do a waterfall loop over the
4204 // possible callees which precludes us from using a simple jump.
4205 if (Callee->isDivergent())
4206 return false;
4207
4209 const Function &CallerF = MF.getFunction();
4210 CallingConv::ID CallerCC = CallerF.getCallingConv();
4212 const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC);
4213
4214 // Kernels aren't callable, and don't have a live in return address so it
4215 // doesn't make sense to do a tail call with entry functions.
4216 if (!CallerPreserved)
4217 return false;
4218
4219 bool CCMatch = CallerCC == CalleeCC;
4220
4222 if (AMDGPU::canGuaranteeTCO(CalleeCC) && CCMatch)
4223 return true;
4224 return false;
4225 }
4226
4227 // TODO: Can we handle var args?
4228 if (IsVarArg)
4229 return false;
4230
4231 for (const Argument &Arg : CallerF.args()) {
4232 if (Arg.hasByValAttr())
4233 return false;
4234 }
4235
4236 LLVMContext &Ctx = *DAG.getContext();
4237
4238 // Check that the call results are passed in the same way.
4239 if (!CCState::resultsCompatible(CalleeCC, CallerCC, MF, Ctx, Ins,
4240 CCAssignFnForCall(CalleeCC, IsVarArg),
4241 CCAssignFnForCall(CallerCC, IsVarArg)))
4242 return false;
4243
4244 // The callee has to preserve all registers the caller needs to preserve.
4245 if (!CCMatch) {
4246 const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC);
4247 if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4248 return false;
4249 }
4250
4251 // Nothing more to check if the callee is taking no arguments.
4252 if (Outs.empty())
4253 return true;
4254
4256 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4257
4258 // FIXME: We are not allocating special input registers, so we will be
4259 // deciding based on incorrect register assignments.
4260 CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CalleeCC, IsVarArg));
4261
4262 const SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
4263 // If the stack arguments for this call do not fit into our own save area then
4264 // the call cannot be made tail.
4265 // TODO: Is this really necessary?
4266 if (CCInfo.getStackSize() > FuncInfo->getBytesInStackArgArea())
4267 return false;
4268
4269 for (const auto &[CCVA, ArgVal] : zip_equal(ArgLocs, OutVals)) {
4270 // FIXME: What about inreg arguments that end up passed in memory?
4271 if (!CCVA.isRegLoc())
4272 continue;
4273
4274 // If we are passing an argument in an SGPR, and the value is divergent,
4275 // this call requires a waterfall loop.
4276 if (ArgVal->isDivergent() && TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4277 LLVM_DEBUG(
4278 dbgs() << "Cannot tail call due to divergent outgoing argument in "
4279 << printReg(CCVA.getLocReg(), TRI) << '\n');
4280 return false;
4281 }
4282 }
4283
4284 const MachineRegisterInfo &MRI = MF.getRegInfo();
4285 return parametersInCSRMatch(MRI, CallerPreserved, ArgLocs, OutVals);
4286}
4287
4289 if (!CI->isTailCall())
4290 return false;
4291
4292 const Function *ParentFn = CI->getFunction();
4294 return false;
4295 return true;
4296}
4297
4298namespace {
4299// Chain calls have special arguments that we need to handle. These are
4300// tagging along at the end of the arguments list(s), after the SGPR and VGPR
4301// arguments (index 0 and 1 respectively).
4302enum ChainCallArgIdx {
4303 Exec = 2,
4304 Flags,
4305 NumVGPRs,
4306 FallbackExec,
4307 FallbackCallee
4308};
4309} // anonymous namespace
4310
4311// The wave scratch offset register is used as the global base pointer.
4313 SmallVectorImpl<SDValue> &InVals) const {
4314 CallingConv::ID CallConv = CLI.CallConv;
4315 bool IsChainCallConv = AMDGPU::isChainCC(CallConv);
4316
4317 SelectionDAG &DAG = CLI.DAG;
4318
4319 const SDLoc &DL = CLI.DL;
4320 SDValue Chain = CLI.Chain;
4321 SDValue Callee = CLI.Callee;
4322
4323 llvm::SmallVector<SDValue, 6> ChainCallSpecialArgs;
4324 bool UsesDynamicVGPRs = false;
4325 if (IsChainCallConv) {
4326 // The last arguments should be the value that we need to put in EXEC,
4327 // followed by the flags and any other arguments with special meanings.
4328 // Pop them out of CLI.Outs and CLI.OutVals before we do any processing so
4329 // we don't treat them like the "real" arguments.
4330 auto RequestedExecIt =
4331 llvm::find_if(CLI.Outs, [](const ISD::OutputArg &Arg) {
4332 return Arg.OrigArgIndex == 2;
4333 });
4334 assert(RequestedExecIt != CLI.Outs.end() && "No node for EXEC");
4335
4336 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.Outs.begin();
4337 CLI.OutVals.erase(CLI.OutVals.begin() + SpecialArgsBeginIdx,
4338 CLI.OutVals.end());
4339 CLI.Outs.erase(RequestedExecIt, CLI.Outs.end());
4340
4341 assert(CLI.Outs.back().OrigArgIndex < 2 &&
4342 "Haven't popped all the special args");
4343
4344 TargetLowering::ArgListEntry RequestedExecArg =
4345 CLI.Args[ChainCallArgIdx::Exec];
4346 if (!RequestedExecArg.Ty->isIntegerTy(Subtarget->getWavefrontSize()))
4347 return lowerUnhandledCall(CLI, InVals, "Invalid value for EXEC");
4348
4349 // Convert constants into TargetConstants, so they become immediate operands
4350 // instead of being selected into S_MOV.
4351 auto PushNodeOrTargetConstant = [&](TargetLowering::ArgListEntry Arg) {
4352 if (const auto *ArgNode = dyn_cast<ConstantSDNode>(Arg.Node)) {
4353 ChainCallSpecialArgs.push_back(DAG.getTargetConstant(
4354 ArgNode->getAPIntValue(), DL, ArgNode->getValueType(0)));
4355 } else
4356 ChainCallSpecialArgs.push_back(Arg.Node);
4357 };
4358
4359 PushNodeOrTargetConstant(RequestedExecArg);
4360
4361 // Process any other special arguments depending on the value of the flags.
4362 TargetLowering::ArgListEntry Flags = CLI.Args[ChainCallArgIdx::Flags];
4363
4364 const APInt &FlagsValue = cast<ConstantSDNode>(Flags.Node)->getAPIntValue();
4365 if (FlagsValue.isZero()) {
4366 if (CLI.Args.size() > ChainCallArgIdx::Flags + 1)
4367 return lowerUnhandledCall(CLI, InVals,
4368 "no additional args allowed if flags == 0");
4369 } else if (FlagsValue.isOneBitSet(0)) {
4370 if (CLI.Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4371 return lowerUnhandledCall(CLI, InVals, "expected 3 additional args");
4372 }
4373
4374 if (!Subtarget->isWave32()) {
4375 return lowerUnhandledCall(
4376 CLI, InVals, "dynamic VGPR mode is only supported for wave32");
4377 }
4378
4379 UsesDynamicVGPRs = true;
4380 std::for_each(CLI.Args.begin() + ChainCallArgIdx::NumVGPRs,
4381 CLI.Args.end(), PushNodeOrTargetConstant);
4382 }
4383 }
4384
4386 SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
4388 bool &IsTailCall = CLI.IsTailCall;
4389 bool IsVarArg = CLI.IsVarArg;
4390 bool IsSibCall = false;
4392
4393 if (Callee.isUndef() || isNullConstant(Callee)) {
4394 if (!CLI.IsTailCall) {
4395 for (ISD::InputArg &Arg : CLI.Ins)
4396 InVals.push_back(DAG.getPOISON(Arg.VT));
4397 }
4398
4399 return Chain;
4400 }
4401
4402 if (IsVarArg) {
4403 return lowerUnhandledCall(CLI, InVals,
4404 "unsupported call to variadic function ");
4405 }
4406
4407 if (!CLI.CB)
4408 return lowerUnhandledCall(CLI, InVals, "unsupported libcall legalization");
4409
4410 if (IsTailCall && MF.getTarget().Options.GuaranteedTailCallOpt) {
4411 return lowerUnhandledCall(CLI, InVals,
4412 "unsupported required tail call to function ");
4413 }
4414
4415 if (IsTailCall) {
4416 IsTailCall = isEligibleForTailCallOptimization(Callee, CallConv, IsVarArg,
4417 Outs, OutVals, Ins, DAG);
4418 if (!IsTailCall &&
4419 ((CLI.CB && CLI.CB->isMustTailCall()) || IsChainCallConv)) {
4420 report_fatal_error("failed to perform tail call elimination on a call "
4421 "site marked musttail or on llvm.amdgcn.cs.chain");
4422 }
4423
4424 bool TailCallOpt = MF.getTarget().Options.GuaranteedTailCallOpt;
4425
4426 // A sibling call is one where we're under the usual C ABI and not planning
4427 // to change that but can still do a tail call:
4428 if (!TailCallOpt && IsTailCall)
4429 IsSibCall = true;
4430
4431 if (IsTailCall)
4432 ++NumTailCalls;
4433 }
4434
4437 SmallVector<SDValue, 8> MemOpChains;
4438
4439 // Analyze operands of the call, assigning locations to each operand.
4441 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
4442 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, IsVarArg);
4443
4444 if (CallConv != CallingConv::AMDGPU_Gfx && !AMDGPU::isChainCC(CallConv) &&
4446 // With a fixed ABI, allocate fixed registers before user arguments.
4447 passSpecialInputs(CLI, CCInfo, *Info, RegsToPass, MemOpChains, Chain);
4448 }
4449
4450 // Mark the scratch resource descriptor as allocated so the CC analysis
4451 // does not assign user arguments to these registers, matching the callee.
4452 if (!Subtarget->hasFlatScratchEnabled())
4453 CCInfo.AllocateReg(Info->getScratchRSrcReg());
4454
4455 CCInfo.AnalyzeCallOperands(Outs, AssignFn);
4456
4457 // Get a count of how many bytes are to be pushed on the stack.
4458 unsigned NumBytes = CCInfo.getStackSize();
4459
4460 if (IsSibCall) {
4461 // Since we're not changing the ABI to make this a tail call, the memory
4462 // operands are already available in the caller's incoming argument space.
4463 NumBytes = 0;
4464 }
4465
4466 // FPDiff is the byte offset of the call's argument area from the callee's.
4467 // Stores to callee stack arguments will be placed in FixedStackSlots offset
4468 // by this amount for a tail call. In a sibling call it must be 0 because the
4469 // caller will deallocate the entire stack and the callee still expects its
4470 // arguments to begin at SP+0. Completely unused for non-tail calls.
4471 int32_t FPDiff = 0;
4472 MachineFrameInfo &MFI = MF.getFrameInfo();
4473 auto *TRI = Subtarget->getRegisterInfo();
4474
4475 // Adjust the stack pointer for the new arguments...
4476 // These operations are automatically eliminated by the prolog/epilog pass
4477 if (!IsSibCall)
4478 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL);
4479
4480 if (!IsSibCall || IsChainCallConv) {
4481 if (!Subtarget->hasFlatScratchEnabled()) {
4482 SmallVector<SDValue, 4> CopyFromChains;
4483
4484 // In the HSA case, this should be an identity copy.
4485 SDValue ScratchRSrcReg =
4486 DAG.getCopyFromReg(Chain, DL, Info->getScratchRSrcReg(), MVT::v4i32);
4487 RegsToPass.emplace_back(IsChainCallConv
4488 ? AMDGPU::SGPR48_SGPR49_SGPR50_SGPR51
4489 : AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3,
4490 ScratchRSrcReg);
4491 CopyFromChains.push_back(ScratchRSrcReg.getValue(1));
4492 Chain = DAG.getTokenFactor(DL, CopyFromChains);
4493 }
4494 }
4495
4496 const unsigned NumSpecialInputs = RegsToPass.size();
4497
4498 MVT PtrVT = MVT::i32;
4499
4500 // Walk the register/memloc assignments, inserting copies/loads.
4501 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4502 CCValAssign &VA = ArgLocs[i];
4503 SDValue Arg = OutVals[i];
4504
4505 // Promote the value if needed.
4506 switch (VA.getLocInfo()) {
4507 case CCValAssign::Full:
4508 break;
4509 case CCValAssign::BCvt:
4510 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
4511 break;
4512 case CCValAssign::ZExt:
4513 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
4514 break;
4515 case CCValAssign::SExt:
4516 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
4517 break;
4518 case CCValAssign::AExt:
4519 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
4520 break;
4521 case CCValAssign::FPExt:
4522 Arg = DAG.getNode(ISD::FP_EXTEND, DL, VA.getLocVT(), Arg);
4523 break;
4524 default:
4525 llvm_unreachable("Unknown loc info!");
4526 }
4527
4528 if (VA.isRegLoc()) {
4529 RegsToPass.push_back(std::pair(VA.getLocReg(), Arg));
4530 } else {
4531 assert(VA.isMemLoc());
4532
4533 SDValue DstAddr;
4534 MachinePointerInfo DstInfo;
4535
4536 unsigned LocMemOffset = VA.getLocMemOffset();
4537 int32_t Offset = LocMemOffset;
4538
4539 SDValue PtrOff = DAG.getConstant(Offset, DL, PtrVT);
4540 MaybeAlign Alignment;
4541
4542 if (IsTailCall) {
4543 ISD::ArgFlagsTy Flags = Outs[i].Flags;
4544 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4545 : VA.getValVT().getStoreSize();
4546
4547 // FIXME: We can have better than the minimum byval required alignment.
4548 Alignment =
4549 Flags.isByVal()
4550 ? Flags.getNonZeroByValAlign()
4551 : commonAlignment(Subtarget->getStackAlignment(), Offset);
4552
4553 Offset = Offset + FPDiff;
4554 int FI = MFI.CreateFixedObject(OpSize, Offset, true);
4555
4556 DstAddr = DAG.getFrameIndex(FI, PtrVT);
4557 DstInfo = MachinePointerInfo::getFixedStack(MF, FI);
4558
4559 // Make sure any stack arguments overlapping with where we're storing
4560 // are loaded before this eventual operation. Otherwise they'll be
4561 // clobbered.
4562
4563 // FIXME: Why is this really necessary? This seems to just result in a
4564 // lot of code to copy the stack and write them back to the same
4565 // locations, which are supposed to be immutable?
4566 Chain = addTokenForArgument(Chain, DAG, MFI, FI);
4567 } else {
4568 // Stores to the argument stack area are relative to the stack pointer.
4569 SDValue SP = DAG.getCopyFromReg(Chain, DL, Info->getStackPtrOffsetReg(),
4570 MVT::i32);
4571 DstAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, SP, PtrOff);
4572 DstInfo = MachinePointerInfo::getStack(MF, LocMemOffset);
4573 Alignment =
4574 commonAlignment(Subtarget->getStackAlignment(), LocMemOffset);
4575 }
4576
4577 if (Outs[i].Flags.isByVal()) {
4578 SDValue SizeNode =
4579 DAG.getConstant(Outs[i].Flags.getByValSize(), DL, MVT::i32);
4580 SDValue Cpy =
4581 DAG.getMemcpy(Chain, DL, DstAddr, Arg, SizeNode,
4582 Outs[i].Flags.getNonZeroByValAlign(),
4583 Outs[i].Flags.getNonZeroByValAlign(),
4584 /*isVol = */ false, /*AlwaysInline = */ true,
4585 /*CI=*/nullptr, std::nullopt, DstInfo,
4587
4588 MemOpChains.push_back(Cpy);
4589 } else {
4590 SDValue Store =
4591 DAG.getStore(Chain, DL, Arg, DstAddr, DstInfo, Alignment);
4592 MemOpChains.push_back(Store);
4593 }
4594 }
4595 }
4596
4597 if (!MemOpChains.empty())
4598 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
4599
4600 SDValue ReadFirstLaneID =
4601 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4602
4603 SDValue TokenGlue;
4604 if (CLI.ConvergenceControlToken) {
4605 TokenGlue = DAG.getNode(ISD::CONVERGENCECTRL_GLUE, DL, MVT::Glue,
4607 }
4608
4609 // Build a sequence of copy-to-reg nodes chained together with token chain
4610 // and flag operands which copy the outgoing args into the appropriate regs.
4611 SDValue InGlue;
4612
4613 unsigned ArgIdx = 0;
4614 for (auto [Reg, Val] : RegsToPass) {
4615 if (ArgIdx++ >= NumSpecialInputs &&
4616 (IsChainCallConv || !Val->isDivergent()) && TRI->isSGPRPhysReg(Reg)) {
4617 // For chain calls, the inreg arguments are required to be
4618 // uniform. Speculatively Insert a readfirstlane in case we cannot prove
4619 // they are uniform.
4620 //
4621 // For other calls, if an inreg arguments is known to be uniform,
4622 // speculatively insert a readfirstlane in case it is in a VGPR.
4623 //
4624 // FIXME: We need to execute this in a waterfall loop if it is a divergent
4625 // value, so let that continue to produce invalid code.
4626
4627 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Val});
4628 if (TokenGlue)
4629 ReadfirstlaneArgs.push_back(TokenGlue);
4631 ReadfirstlaneArgs);
4632 }
4633
4634 Chain = DAG.getCopyToReg(Chain, DL, Reg, Val, InGlue);
4635 InGlue = Chain.getValue(1);
4636 }
4637
4638 // We don't usually want to end the call-sequence here because we would tidy
4639 // the frame up *after* the call, however in the ABI-changing tail-call case
4640 // we've carefully laid out the parameters so that when sp is reset they'll be
4641 // in the correct location.
4642 if (IsTailCall && !IsSibCall) {
4643 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
4644 InGlue = Chain.getValue(1);
4645 }
4646
4647 std::vector<SDValue> Ops({Chain});
4648
4649 // Add a redundant copy of the callee global which will not be legalized, as
4650 // we need direct access to the callee later.
4652 const GlobalValue *GV = GSD->getGlobal();
4653 Ops.push_back(Callee);
4654 Ops.push_back(DAG.getTargetGlobalAddress(GV, DL, MVT::i64));
4655 } else {
4656 if (IsTailCall) {
4657 // isEligibleForTailCallOptimization considered whether the call target is
4658 // divergent, but we may still end up with a uniform value in a VGPR.
4659 // Insert a readfirstlane just in case.
4660 SDValue ReadFirstLaneID =
4661 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4662
4663 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Callee});
4664 if (TokenGlue)
4665 ReadfirstlaneArgs.push_back(TokenGlue); // Wire up convergence token.
4666 Callee = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Callee.getValueType(),
4667 ReadfirstlaneArgs);
4668 }
4669
4670 Ops.push_back(Callee);
4671 Ops.push_back(DAG.getTargetConstant(0, DL, MVT::i64));
4672 }
4673
4674 if (IsTailCall) {
4675 // Each tail call may have to adjust the stack by a different amount, so
4676 // this information must travel along with the operation for eventual
4677 // consumption by emitEpilogue.
4678 Ops.push_back(DAG.getTargetConstant(FPDiff, DL, MVT::i32));
4679 }
4680
4681 if (IsChainCallConv)
4682 llvm::append_range(Ops, ChainCallSpecialArgs);
4683
4684 // Add argument registers to the end of the list so that they are known live
4685 // into the call.
4686 for (auto &[Reg, Val] : RegsToPass)
4687 Ops.push_back(DAG.getRegister(Reg, Val.getValueType()));
4688
4689 // Add a register mask operand representing the call-preserved registers.
4690 const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
4691 assert(Mask && "Missing call preserved mask for calling convention");
4692 Ops.push_back(DAG.getRegisterMask(Mask));
4693
4694 if (SDValue Token = CLI.ConvergenceControlToken) {
4696 GlueOps.push_back(Token);
4697 if (InGlue)
4698 GlueOps.push_back(InGlue);
4699
4700 InGlue = SDValue(DAG.getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, DL,
4701 MVT::Glue, GlueOps),
4702 0);
4703 }
4704
4705 if (InGlue)
4706 Ops.push_back(InGlue);
4707
4708 // If we're doing a tall call, use a TC_RETURN here rather than an
4709 // actual call instruction.
4710 if (IsTailCall) {
4711 MFI.setHasTailCall();
4712 unsigned OPC = AMDGPUISD::TC_RETURN;
4713 switch (CallConv) {
4715 OPC = AMDGPUISD::TC_RETURN_GFX;
4716 break;
4719 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4720 : AMDGPUISD::TC_RETURN_CHAIN;
4721 break;
4722 }
4723
4724 // If the caller is a whole wave function, we need to use a special opcode
4725 // so we can patch up EXEC.
4726 if (Info->isWholeWaveFunction())
4727 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4728
4729 return DAG.getNode(OPC, DL, MVT::Other, Ops);
4730 }
4731
4732 // Returns a chain and a flag for retval copy to use.
4733 SDValue Call = DAG.getNode(AMDGPUISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops);
4734 Chain = Call.getValue(0);
4735 InGlue = Call.getValue(1);
4736
4737 uint64_t CalleePopBytes = NumBytes;
4738 Chain = DAG.getCALLSEQ_END(Chain, 0, CalleePopBytes, InGlue, DL);
4739 if (!Ins.empty())
4740 InGlue = Chain.getValue(1);
4741
4742 // Handle result values, copying them out of physregs into vregs that we
4743 // return.
4744 return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG,
4745 InVals, /*IsThisReturn=*/false, SDValue());
4746}
4747
4748// This is similar to the default implementation in ExpandDYNAMIC_STACKALLOC,
4749// except for:
4750// 1. Stack growth direction(default: downwards, AMDGPU: upwards), and
4751// 2. Scale size where, scale = wave-reduction(alloca-size) * wave-size
4753 SelectionDAG &DAG) const {
4754 const MachineFunction &MF = DAG.getMachineFunction();
4756
4757 SDLoc dl(Op);
4758 EVT VT = Op.getValueType();
4759 SDValue Chain = Op.getOperand(0);
4760 Register SPReg = Info->getStackPtrOffsetReg();
4761
4762 // Chain the dynamic stack allocation so that it doesn't modify the stack
4763 // pointer when other instructions are using the stack.
4764 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, dl);
4765
4766 SDValue Size = Op.getOperand(1);
4767 SDValue BaseAddr = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
4768 Align Alignment = cast<ConstantSDNode>(Op.getOperand(2))->getAlignValue();
4769
4770 const TargetFrameLowering *TFL = Subtarget->getFrameLowering();
4772 "Stack grows upwards for AMDGPU");
4773
4774 Chain = BaseAddr.getValue(1);
4775 // When using flat-scratch, the stack offset is unscaled.
4776 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4777 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4778
4779 Align StackAlign = TFL->getStackAlign();
4780 if (Alignment > StackAlign) {
4781 uint64_t ScaledAlignment = Alignment.value()
4782 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4783 uint64_t StackAlignMask = ScaledAlignment - 1;
4784 SDValue TmpAddr = DAG.getNode(ISD::ADD, dl, VT, BaseAddr,
4785 DAG.getConstant(StackAlignMask, dl, VT));
4786 BaseAddr = DAG.getNode(ISD::AND, dl, VT, TmpAddr,
4787 DAG.getSignedConstant(-ScaledAlignment, dl, VT));
4788 }
4789
4790 assert(Size.getValueType() == MVT::i32 && "Size must be 32-bit");
4791 SDValue NewSP;
4793 // Increase the stack pointer by the size of the alloca.
4794 // If not using flat-scratch, we have to scale the size by the wave-size.
4795 SDValue ScaledSize =
4796 HasFlatScratch
4797 ? Size
4798 : DAG.getNode(ISD::SHL, dl, VT, Size,
4799 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4800 NewSP = DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value
4801 } else {
4802 // For dynamic sized alloca, perform wave-wide reduction to get max of
4803 // alloca size(divergent), and then scale it (when not using flat-scratch)
4804 // by wave-size.
4805 SDValue WaveReduction =
4806 DAG.getTargetConstant(Intrinsic::amdgcn_wave_reduce_umax, dl, MVT::i32);
4807 Size = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, WaveReduction,
4808 Size, DAG.getTargetConstant(0, dl, MVT::i32));
4809 SDValue ScaledSize = Size;
4810 if (!HasFlatScratch) {
4811 ScaledSize =
4812 DAG.getNode(ISD::SHL, dl, VT, Size,
4813 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4814 }
4815 NewSP =
4816 DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value in vgpr.
4817 SDValue ReadFirstLaneID =
4818 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, dl, MVT::i32);
4819 NewSP = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, ReadFirstLaneID,
4820 NewSP);
4821 }
4822
4823 Chain = DAG.getCopyToReg(Chain, dl, SPReg, NewSP); // Output chain
4824 SDValue CallSeqEnd = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), dl);
4825
4826 return DAG.getMergeValues({BaseAddr, CallSeqEnd}, dl);
4827}
4828
4830 if (Op.getValueType() != MVT::i32)
4831 return Op; // Defer to cannot select error.
4832
4834 SDLoc SL(Op);
4835
4836 SDValue CopyFromSP = DAG.getCopyFromReg(Op->getOperand(0), SL, SP, MVT::i32);
4837
4838 // Convert from wave uniform to swizzled vector address. This should protect
4839 // from any edge cases where the stacksave result isn't directly used with
4840 // stackrestore.
4841 SDValue VectorAddress =
4842 DAG.getNode(AMDGPUISD::WAVE_ADDRESS, SL, MVT::i32, CopyFromSP);
4843 return DAG.getMergeValues({VectorAddress, CopyFromSP.getValue(1)}, SL);
4844}
4845
4847 SelectionDAG &DAG) const {
4848 SDLoc SL(Op);
4849 assert(Op.getValueType() == MVT::i32);
4850
4851 uint32_t BothRoundHwReg =
4853 SDValue GetRoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
4854
4855 SDValue IntrinID =
4856 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
4857 SDValue GetReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, Op->getVTList(),
4858 Op.getOperand(0), IntrinID, GetRoundBothImm);
4859
4860 // There are two rounding modes, one for f32 and one for f64/f16. We only
4861 // report in the standard value range if both are the same.
4862 //
4863 // The raw values also differ from the expected FLT_ROUNDS values. Nearest
4864 // ties away from zero is not supported, and the other values are rotated by
4865 // 1.
4866 //
4867 // If the two rounding modes are not the same, report a target defined value.
4868
4869 // Mode register rounding mode fields:
4870 //
4871 // [1:0] Single-precision round mode.
4872 // [3:2] Double/Half-precision round mode.
4873 //
4874 // 0=nearest even; 1= +infinity; 2= -infinity, 3= toward zero.
4875 //
4876 // Hardware Spec
4877 // Toward-0 3 0
4878 // Nearest Even 0 1
4879 // +Inf 1 2
4880 // -Inf 2 3
4881 // NearestAway0 N/A 4
4882 //
4883 // We have to handle 16 permutations of a 4-bit value, so we create a 64-bit
4884 // table we can index by the raw hardware mode.
4885 //
4886 // (trunc (FltRoundConversionTable >> MODE.fp_round)) & 0xf
4887
4888 SDValue BitTable =
4890
4891 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4892 SDValue RoundModeTimesNumBits =
4893 DAG.getNode(ISD::SHL, SL, MVT::i32, GetReg, Two);
4894
4895 // TODO: We could possibly avoid a 64-bit shift and use a simpler table if we
4896 // knew only one mode was demanded.
4897 SDValue TableValue =
4898 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
4899 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
4900
4901 SDValue EntryMask = DAG.getConstant(0xf, SL, MVT::i32);
4902 SDValue TableEntry =
4903 DAG.getNode(ISD::AND, SL, MVT::i32, TruncTable, EntryMask);
4904
4905 // There's a gap in the 4-bit encoded table and actual enum values, so offset
4906 // if it's an extended value.
4907 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
4908 SDValue IsStandardValue =
4909 DAG.getSetCC(SL, MVT::i1, TableEntry, Four, ISD::SETULT);
4910 SDValue EnumOffset = DAG.getNode(ISD::ADD, SL, MVT::i32, TableEntry, Four);
4911 SDValue Result = DAG.getNode(ISD::SELECT, SL, MVT::i32, IsStandardValue,
4912 TableEntry, EnumOffset);
4913
4914 return DAG.getMergeValues({Result, GetReg.getValue(1)}, SL);
4915}
4916
4918 SelectionDAG &DAG) const {
4919 SDLoc SL(Op);
4920
4921 SDValue NewMode = Op.getOperand(1);
4922 assert(NewMode.getValueType() == MVT::i32);
4923
4924 // Index a table of 4-bit entries mapping from the C FLT_ROUNDS values to the
4925 // hardware MODE.fp_round values.
4926 if (auto *ConstMode = dyn_cast<ConstantSDNode>(NewMode)) {
4927 uint32_t ClampedVal = std::min(
4928 static_cast<uint32_t>(ConstMode->getZExtValue()),
4930 NewMode = DAG.getConstant(
4931 AMDGPU::decodeFltRoundToHWConversionTable(ClampedVal), SL, MVT::i32);
4932 } else {
4933 // If we know the input can only be one of the supported standard modes in
4934 // the range 0-3, we can use a simplified mapping to hardware values.
4935 KnownBits KB = DAG.computeKnownBits(NewMode);
4936 const bool UseReducedTable = KB.countMinLeadingZeros() >= 30;
4937 // The supported standard values are 0-3. The extended values start at 8. We
4938 // need to offset by 4 if the value is in the extended range.
4939
4940 if (UseReducedTable) {
4941 // Truncate to the low 32-bits.
4942 SDValue BitTable = DAG.getConstant(
4943 AMDGPU::FltRoundToHWConversionTable & 0xffff, SL, MVT::i32);
4944
4945 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4946 SDValue RoundModeTimesNumBits =
4947 DAG.getNode(ISD::SHL, SL, MVT::i32, NewMode, Two);
4948
4949 NewMode =
4950 DAG.getNode(ISD::SRL, SL, MVT::i32, BitTable, RoundModeTimesNumBits);
4951
4952 // TODO: SimplifyDemandedBits on the setreg source here can likely reduce
4953 // the table extracted bits into inline immediates.
4954 } else {
4955 // table_index = umin(value, value - 4)
4956 // MODE.fp_round = (bit_table >> (table_index << 2)) & 0xf
4957 SDValue BitTable =
4959
4960 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
4961 SDValue OffsetEnum = DAG.getNode(ISD::SUB, SL, MVT::i32, NewMode, Four);
4962 SDValue IndexVal =
4963 DAG.getNode(ISD::UMIN, SL, MVT::i32, NewMode, OffsetEnum);
4964
4965 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4966 SDValue RoundModeTimesNumBits =
4967 DAG.getNode(ISD::SHL, SL, MVT::i32, IndexVal, Two);
4968
4969 SDValue TableValue =
4970 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
4971 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
4972
4973 // No need to mask out the high bits since the setreg will ignore them
4974 // anyway.
4975 NewMode = TruncTable;
4976 }
4977
4978 // Insert a readfirstlane in case the value is a VGPR. We could do this
4979 // earlier and keep more operations scalar, but that interferes with
4980 // combining the source.
4981 SDValue ReadFirstLaneID =
4982 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
4983 NewMode = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
4984 ReadFirstLaneID, NewMode);
4985 }
4986
4987 // N.B. The setreg will be later folded into s_round_mode on supported
4988 // targets.
4989 SDValue IntrinID =
4990 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
4991 uint32_t BothRoundHwReg =
4993 SDValue RoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
4994
4995 SDValue SetReg =
4996 DAG.getNode(ISD::INTRINSIC_VOID, SL, Op->getVTList(), Op.getOperand(0),
4997 IntrinID, RoundBothImm, NewMode);
4998
4999 return SetReg;
5000}
5001
5003 if (Op->isDivergent() &&
5004 (!Subtarget->hasVmemPrefInsts() || !Op.getConstantOperandVal(4)))
5005 // Cannot do I$ prefetch with divergent pointer.
5006 return SDValue();
5007
5008 switch (cast<MemSDNode>(Op)->getAddressSpace()) {
5012 break;
5014 if (Subtarget->hasSafeSmemPrefetch())
5015 break;
5016 [[fallthrough]];
5017 default:
5018 return SDValue();
5019 }
5020
5021 // I$ prefetch
5022 if (!Subtarget->hasSafeSmemPrefetch() && !Op.getConstantOperandVal(4))
5023 return SDValue();
5024
5025 return Op;
5026}
5027
5028// Work around DAG legality rules only based on the result type.
5030 bool IsStrict = Op.getOpcode() == ISD::STRICT_FP_EXTEND;
5031 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
5032 EVT SrcVT = Src.getValueType();
5033
5034 if (SrcVT.getScalarType() != MVT::bf16)
5035 return Op;
5036
5037 SDLoc SL(Op);
5038 SDValue BitCast =
5039 DAG.getNode(ISD::BITCAST, SL, SrcVT.changeTypeToInteger(), Src);
5040
5041 EVT DstVT = Op.getValueType();
5042 if (IsStrict)
5043 llvm_unreachable("Need STRICT_BF16_TO_FP");
5044
5045 return DAG.getNode(ISD::BF16_TO_FP, SL, DstVT, BitCast);
5046}
5047
5049 SDLoc SL(Op);
5050 if (Op.getValueType() != MVT::i64)
5051 return Op;
5052
5053 uint32_t ModeHwReg =
5055 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5056 uint32_t TrapHwReg =
5058 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5059
5060 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::Other);
5061 SDValue IntrinID =
5062 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
5063 SDValue GetModeReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5064 Op.getOperand(0), IntrinID, ModeHwRegImm);
5065 SDValue GetTrapReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5066 Op.getOperand(0), IntrinID, TrapHwRegImm);
5067 SDValue TokenReg =
5068 DAG.getNode(ISD::TokenFactor, SL, MVT::Other, GetModeReg.getValue(1),
5069 GetTrapReg.getValue(1));
5070
5071 SDValue CvtPtr =
5072 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, GetModeReg, GetTrapReg);
5073 SDValue Result = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
5074
5075 return DAG.getMergeValues({Result, TokenReg}, SL);
5076}
5077
5079 SDLoc SL(Op);
5080 if (Op.getOperand(1).getValueType() != MVT::i64)
5081 return Op;
5082
5083 SDValue Input = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op.getOperand(1));
5084 SDValue NewModeReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5085 DAG.getConstant(0, SL, MVT::i32));
5086 SDValue NewTrapReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5087 DAG.getConstant(1, SL, MVT::i32));
5088
5089 SDValue ReadFirstLaneID =
5090 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
5091 NewModeReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5092 ReadFirstLaneID, NewModeReg);
5093 NewTrapReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5094 ReadFirstLaneID, NewTrapReg);
5095
5096 unsigned ModeHwReg =
5098 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5099 unsigned TrapHwReg =
5101 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5102
5103 SDValue IntrinID =
5104 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
5105 SDValue SetModeReg =
5106 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5107 IntrinID, ModeHwRegImm, NewModeReg);
5108 SDValue SetTrapReg =
5109 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5110 IntrinID, TrapHwRegImm, NewTrapReg);
5111 return DAG.getNode(ISD::TokenFactor, SL, MVT::Other, SetTrapReg, SetModeReg);
5112}
5113
5115 const MachineFunction &MF) const {
5116 const Function &Fn = MF.getFunction();
5117
5118 Register Reg =
5120 .Case("m0", AMDGPU::M0)
5121 .Case("exec", AMDGPU::EXEC)
5122 .Case("exec_lo", AMDGPU::EXEC_LO)
5123 .Case("exec_hi", AMDGPU::EXEC_HI)
5124 .Case("flat_scratch", AMDGPU::FLAT_SCR)
5125 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5126 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5127 .Case("src_flat_scratch_base", AMDGPU::SRC_FLAT_SCRATCH_BASE)
5128 .Case("src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
5129 .Case("src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
5130 .Default(Register());
5131 if (!Reg)
5132 return Reg;
5133
5134 if (!Subtarget->hasFlatScrRegister() &&
5135 Subtarget->getRegisterInfo()->regsOverlap(Reg, AMDGPU::FLAT_SCR)) {
5136 Fn.getContext().emitError(Twine("invalid register \"" + StringRef(RegName) +
5137 "\" for subtarget."));
5138 }
5139
5140 if (!Subtarget->hasGloballyAddressableScratch() &&
5141 Subtarget->getRegisterInfo()->regsOverlap(
5142 Reg, AMDGPU::SRC_FLAT_SCRATCH_BASE)) {
5143 Fn.getContext().emitError(Twine("invalid register \"" + StringRef(RegName) +
5144 "\" for subtarget."));
5145 }
5146
5147 switch (Reg) {
5148 case AMDGPU::M0:
5149 case AMDGPU::EXEC_LO:
5150 case AMDGPU::EXEC_HI:
5151 case AMDGPU::FLAT_SCR_LO:
5152 case AMDGPU::FLAT_SCR_HI:
5153 case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
5154 case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
5155 if (VT.getSizeInBits() == 32)
5156 return Reg;
5157 break;
5158 case AMDGPU::EXEC:
5159 case AMDGPU::FLAT_SCR:
5160 case AMDGPU::SRC_FLAT_SCRATCH_BASE:
5161 if (VT.getSizeInBits() == 64)
5162 return Reg;
5163 break;
5164 default:
5165 llvm_unreachable("missing register type checking");
5166 }
5167
5169 Twine("invalid type for register \"" + StringRef(RegName) + "\"."));
5170}
5171
5172// If kill is not the last instruction, split the block so kill is always a
5173// proper terminator.
5176 MachineBasicBlock *BB) const {
5177 MachineBasicBlock *SplitBB = BB->splitAt(MI, /*UpdateLiveIns=*/true);
5179 MI.setDesc(TII->getKillTerminatorFromPseudo(MI.getOpcode()));
5180 return SplitBB;
5181}
5182
5183// Split block \p MBB at \p MI, as to insert a loop. If \p InstInLoop is true,
5184// \p MI will be the only instruction in the loop body block. Otherwise, it will
5185// be the first instruction in the remainder block.
5186//
5187/// \returns { LoopBody, Remainder }
5188static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5190 MachineFunction *MF = MBB.getParent();
5192
5193 // To insert the loop we need to split the block. Move everything after this
5194 // point to a new block, and insert a new empty block between the two.
5196 MachineBasicBlock *RemainderBB = MF->CreateMachineBasicBlock();
5198 ++MBBI;
5199
5200 MF->insert(MBBI, LoopBB);
5201 MF->insert(MBBI, RemainderBB);
5202
5203 LoopBB->addSuccessor(LoopBB);
5204 LoopBB->addSuccessor(RemainderBB);
5205
5206 // Move the rest of the block into a new block.
5207 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
5208
5209 if (InstInLoop) {
5210 auto Next = std::next(I);
5211
5212 // Move instruction to loop body.
5213 LoopBB->splice(LoopBB->begin(), &MBB, I, Next);
5214
5215 // Move the rest of the block.
5216 RemainderBB->splice(RemainderBB->begin(), &MBB, Next, MBB.end());
5217 } else {
5218 RemainderBB->splice(RemainderBB->begin(), &MBB, I, MBB.end());
5219 }
5220
5221 MBB.addSuccessor(LoopBB);
5222
5223 return std::pair(LoopBB, RemainderBB);
5224}
5225
5226/// Insert \p MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
5228 MachineBasicBlock *MBB = MI.getParent();
5230 auto I = MI.getIterator();
5231 auto E = std::next(I);
5232
5233 // clang-format off
5234 BuildMI(*MBB, E, MI.getDebugLoc(), TII->get(AMDGPU::S_WAITCNT))
5235 .addImm(0);
5236 // clang-format on
5237
5238 MIBundleBuilder Bundler(*MBB, I, E);
5239 finalizeBundle(*MBB, Bundler.begin());
5240}
5241
5244 MachineBasicBlock *BB) const {
5245 const DebugLoc &DL = MI.getDebugLoc();
5246
5248
5250
5251 // Apparently kill flags are only valid if the def is in the same block?
5252 if (MachineOperand *Src = TII->getNamedOperand(MI, AMDGPU::OpName::data0))
5253 Src->setIsKill(false);
5254
5255 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, *BB, true);
5256
5257 MachineBasicBlock::iterator I = LoopBB->end();
5258
5259 const unsigned EncodedReg = AMDGPU::Hwreg::HwregEncoding::encode(
5261
5262 // Clear TRAP_STS.MEM_VIOL
5263 BuildMI(*LoopBB, LoopBB->begin(), DL, TII->get(AMDGPU::S_SETREG_IMM32_B32))
5264 .addImm(0)
5265 .addImm(EncodedReg);
5266
5268
5269 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5270
5271 // Load and check TRAP_STS.MEM_VIOL
5272 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_GETREG_B32), Reg)
5273 .addImm(EncodedReg);
5274
5275 // FIXME: Do we need to use an isel pseudo that may clobber scc?
5276 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CMP_LG_U32))
5277 .addReg(Reg, RegState::Kill)
5278 .addImm(0);
5279 // clang-format off
5280 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
5281 .addMBB(LoopBB);
5282 // clang-format on
5283
5284 return RemainderBB;
5285}
5286
5287// Do a v_movrels_b32 or v_movreld_b32 for each unique value of \p IdxReg in the
5288// wavefront. If the value is uniform and just happens to be in a VGPR, this
5289// will only do one iteration. In the worst case, this will loop 64 times.
5290//
5291// TODO: Just use v_readlane_b32 if we know the VGPR has a uniform value.
5294 MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB,
5295 const DebugLoc &DL, const MachineOperand &Idx,
5296 unsigned InitReg, unsigned ResultReg, unsigned PhiReg,
5297 unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode,
5298 Register &SGPRIdxReg) {
5299
5300 MachineFunction *MF = OrigBB.getParent();
5301 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5302 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5305
5306 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5307 Register PhiExec = MRI.createVirtualRegister(BoolRC);
5308 Register NewExec = MRI.createVirtualRegister(BoolRC);
5309 Register CurrentIdxReg =
5310 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5311 Register CondReg = MRI.createVirtualRegister(BoolRC);
5312
5313 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiReg)
5314 .addReg(InitReg)
5315 .addMBB(&OrigBB)
5316 .addReg(ResultReg)
5317 .addMBB(&LoopBB);
5318
5319 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiExec)
5320 .addReg(InitSaveExecReg)
5321 .addMBB(&OrigBB)
5322 .addReg(NewExec)
5323 .addMBB(&LoopBB);
5324
5325 // Read the next variant <- also loop target.
5326 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5327 .addReg(Idx.getReg(), getUndefRegState(Idx.isUndef()));
5328
5329 // Compare the just read M0 value to all possible Idx values.
5330 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5331 .addReg(CurrentIdxReg)
5332 .addReg(Idx.getReg(), {}, Idx.getSubReg());
5333
5334 // Update EXEC, save the original EXEC value to VCC.
5335 BuildMI(LoopBB, I, DL, TII->get(LMC.AndSaveExecOpc), NewExec)
5336 .addReg(CondReg, RegState::Kill);
5337
5338 MRI.setSimpleHint(NewExec, CondReg);
5339
5340 if (UseGPRIdxMode) {
5341 if (Offset == 0) {
5342 SGPRIdxReg = CurrentIdxReg;
5343 } else {
5344 SGPRIdxReg = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
5345 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5346 .addReg(CurrentIdxReg, RegState::Kill)
5347 .addImm(Offset);
5348 }
5349 } else {
5350 // Move index from VCC into M0
5351 if (Offset == 0) {
5352 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5353 .addReg(CurrentIdxReg, RegState::Kill);
5354 } else {
5355 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5356 .addReg(CurrentIdxReg, RegState::Kill)
5357 .addImm(Offset);
5358 }
5359 }
5360
5361 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
5362 MachineInstr *InsertPt =
5363 BuildMI(LoopBB, I, DL, TII->get(LMC.XorTermOpc), LMC.ExecReg)
5364 .addReg(LMC.ExecReg)
5365 .addReg(NewExec);
5366
5367 // XXX - s_xor_b64 sets scc to 1 if the result is nonzero, so can we use
5368 // s_cbranch_scc0?
5369
5370 // Loop back to V_READFIRSTLANE_B32 if there are still variants to cover.
5371 // clang-format off
5372 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
5373 .addMBB(&LoopBB);
5374 // clang-format on
5375
5376 return InsertPt->getIterator();
5377}
5378
5379// This has slightly sub-optimal regalloc when the source vector is killed by
5380// the read. The register allocator does not understand that the kill is
5381// per-workitem, so is kept alive for the whole loop so we end up not re-using a
5382// subregister from it, using 1 more VGPR than necessary. This was saved when
5383// this was expanded after register allocation.
5386 unsigned InitResultReg, unsigned PhiReg, int Offset,
5387 bool UseGPRIdxMode, Register &SGPRIdxReg) {
5388 MachineFunction *MF = MBB.getParent();
5389 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5390 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5391 MachineRegisterInfo &MRI = MF->getRegInfo();
5392 const DebugLoc &DL = MI.getDebugLoc();
5394
5395 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
5396 Register DstReg = MI.getOperand(0).getReg();
5397 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
5398 Register TmpExec = MRI.createVirtualRegister(BoolXExecRC);
5400
5401 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), TmpExec);
5402
5403 // Save the EXEC mask
5404 // clang-format off
5405 BuildMI(MBB, I, DL, TII->get(LMC.MovOpc), SaveExec)
5406 .addReg(LMC.ExecReg);
5407 // clang-format on
5408
5409 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, MBB, false);
5410
5411 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5412
5413 auto InsPt = emitLoadM0FromVGPRLoop(TII, MRI, MBB, *LoopBB, DL, *Idx,
5414 InitResultReg, DstReg, PhiReg, TmpExec,
5415 Offset, UseGPRIdxMode, SGPRIdxReg);
5416
5417 MachineBasicBlock *LandingPad = MF->CreateMachineBasicBlock();
5419 ++MBBI;
5420 MF->insert(MBBI, LandingPad);
5421 LoopBB->removeSuccessor(RemainderBB);
5422 LandingPad->addSuccessor(RemainderBB);
5423 LoopBB->addSuccessor(LandingPad);
5424 MachineBasicBlock::iterator First = LandingPad->begin();
5425 // clang-format off
5426 BuildMI(*LandingPad, First, DL, TII->get(LMC.MovOpc), LMC.ExecReg)
5427 .addReg(SaveExec);
5428 // clang-format on
5429
5430 return InsPt;
5431}
5432
5433// Returns subreg index, offset
5434static std::pair<unsigned, int>
5436 const TargetRegisterClass *SuperRC, unsigned VecReg,
5437 int Offset) {
5438 int NumElts = TRI.getRegSizeInBits(*SuperRC) / 32;
5439
5440 // Skip out of bounds offsets, or else we would end up using an undefined
5441 // register.
5442 if (Offset >= NumElts || Offset < 0)
5443 return std::pair(AMDGPU::sub0, Offset);
5444
5445 return std::pair(SIRegisterInfo::getSubRegFromChannel(Offset), 0);
5446}
5447
5450 int Offset) {
5451 MachineBasicBlock *MBB = MI.getParent();
5452 const DebugLoc &DL = MI.getDebugLoc();
5454
5455 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5456
5457 assert(Idx->getReg() != AMDGPU::NoRegister);
5458
5459 if (Offset == 0) {
5460 // clang-format off
5461 BuildMI(*MBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5462 .add(*Idx);
5463 // clang-format on
5464 } else {
5465 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5466 .add(*Idx)
5467 .addImm(Offset);
5468 }
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 if (Offset == 0)
5481 return Idx->getReg();
5482
5483 Register Tmp = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5484 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), Tmp)
5485 .add(*Idx)
5486 .addImm(Offset);
5487 return Tmp;
5488}
5489
5492 const GCNSubtarget &ST) {
5493 const SIInstrInfo *TII = ST.getInstrInfo();
5494 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5495 MachineFunction *MF = MBB.getParent();
5496 MachineRegisterInfo &MRI = MF->getRegInfo();
5497
5498 Register Dst = MI.getOperand(0).getReg();
5499 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5500 Register SrcReg = TII->getNamedOperand(MI, AMDGPU::OpName::src)->getReg();
5501 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5502
5503 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcReg);
5504 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5505
5506 unsigned SubReg;
5507 std::tie(SubReg, Offset) =
5508 computeIndirectRegAndOffset(TRI, VecRC, SrcReg, Offset);
5509
5510 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5511
5512 // Check for a SGPR index.
5513 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5515 const DebugLoc &DL = MI.getDebugLoc();
5516
5517 if (UseGPRIdxMode) {
5518 // TODO: Look at the uses to avoid the copy. This may require rescheduling
5519 // to avoid interfering with other uses, so probably requires a new
5520 // optimization pass.
5521 Register Idx = getIndirectSGPRIdx(TII, MRI, MI, Offset);
5522
5523 const MCInstrDesc &GPRIDXDesc =
5524 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5525 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5526 .addReg(SrcReg)
5527 .addReg(Idx)
5528 .addImm(SubReg);
5529 } else {
5531
5532 BuildMI(MBB, I, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5533 .addReg(SrcReg, {}, SubReg)
5534 .addReg(SrcReg, RegState::Implicit);
5535 }
5536
5537 MI.eraseFromParent();
5538
5539 return &MBB;
5540 }
5541
5542 // Control flow needs to be inserted if indexing with a VGPR.
5543 const DebugLoc &DL = MI.getDebugLoc();
5545
5546 Register PhiReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5547 Register InitReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5548
5549 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), InitReg);
5550
5551 Register SGPRIdxReg;
5552 auto InsPt = loadM0FromVGPR(TII, MBB, MI, InitReg, PhiReg, Offset,
5553 UseGPRIdxMode, SGPRIdxReg);
5554
5555 MachineBasicBlock *LoopBB = InsPt->getParent();
5556
5557 if (UseGPRIdxMode) {
5558 const MCInstrDesc &GPRIDXDesc =
5559 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5560
5561 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5562 .addReg(SrcReg)
5563 .addReg(SGPRIdxReg)
5564 .addImm(SubReg);
5565 } else {
5566 BuildMI(*LoopBB, InsPt, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5567 .addReg(SrcReg, {}, SubReg)
5568 .addReg(SrcReg, RegState::Implicit);
5569 }
5570
5571 MI.eraseFromParent();
5572
5573 return LoopBB;
5574}
5575
5578 const GCNSubtarget &ST) {
5579 const SIInstrInfo *TII = ST.getInstrInfo();
5580 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5581 MachineFunction *MF = MBB.getParent();
5582 MachineRegisterInfo &MRI = MF->getRegInfo();
5583
5584 Register Dst = MI.getOperand(0).getReg();
5585 const MachineOperand *SrcVec = TII->getNamedOperand(MI, AMDGPU::OpName::src);
5586 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5587 const MachineOperand *Val = TII->getNamedOperand(MI, AMDGPU::OpName::val);
5588 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5589 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcVec->getReg());
5590 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5591
5592 // This can be an immediate, but will be folded later.
5593 assert(Val->getReg());
5594
5595 unsigned SubReg;
5596 std::tie(SubReg, Offset) =
5597 computeIndirectRegAndOffset(TRI, VecRC, SrcVec->getReg(), Offset);
5598 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5599
5600 if (Idx->getReg() == AMDGPU::NoRegister) {
5602 const DebugLoc &DL = MI.getDebugLoc();
5603
5604 assert(Offset == 0);
5605
5606 BuildMI(MBB, I, DL, TII->get(TargetOpcode::INSERT_SUBREG), Dst)
5607 .add(*SrcVec)
5608 .add(*Val)
5609 .addImm(SubReg);
5610
5611 MI.eraseFromParent();
5612 return &MBB;
5613 }
5614
5615 // Check for a SGPR index.
5616 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5618 const DebugLoc &DL = MI.getDebugLoc();
5619
5620 if (UseGPRIdxMode) {
5621 Register Idx = getIndirectSGPRIdx(TII, MRI, MI, Offset);
5622
5623 const MCInstrDesc &GPRIDXDesc =
5624 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5625 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5626 .addReg(SrcVec->getReg())
5627 .add(*Val)
5628 .addReg(Idx)
5629 .addImm(SubReg);
5630 } else {
5632
5633 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5634 TRI.getRegSizeInBits(*VecRC), 32, false);
5635 BuildMI(MBB, I, DL, MovRelDesc, Dst)
5636 .addReg(SrcVec->getReg())
5637 .add(*Val)
5638 .addImm(SubReg);
5639 }
5640 MI.eraseFromParent();
5641 return &MBB;
5642 }
5643
5644 // Control flow needs to be inserted if indexing with a VGPR.
5645 if (Val->isReg())
5646 MRI.clearKillFlags(Val->getReg());
5647
5648 const DebugLoc &DL = MI.getDebugLoc();
5649
5650 Register PhiReg = MRI.createVirtualRegister(VecRC);
5651
5652 Register SGPRIdxReg;
5653 auto InsPt = loadM0FromVGPR(TII, MBB, MI, SrcVec->getReg(), PhiReg, Offset,
5654 UseGPRIdxMode, SGPRIdxReg);
5655 MachineBasicBlock *LoopBB = InsPt->getParent();
5656
5657 if (UseGPRIdxMode) {
5658 const MCInstrDesc &GPRIDXDesc =
5659 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5660
5661 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5662 .addReg(PhiReg)
5663 .add(*Val)
5664 .addReg(SGPRIdxReg)
5665 .addImm(SubReg);
5666 } else {
5667 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5668 TRI.getRegSizeInBits(*VecRC), 32, false);
5669 BuildMI(*LoopBB, InsPt, DL, MovRelDesc, Dst)
5670 .addReg(PhiReg)
5671 .add(*Val)
5672 .addImm(SubReg);
5673 }
5674
5675 MI.eraseFromParent();
5676 return LoopBB;
5677}
5678
5680 MachineBasicBlock *BB) {
5681 // For targets older than GFX12, we emit a sequence of 32-bit operations.
5682 // For GFX12, we emit s_add_u64 and s_sub_u64.
5683 MachineFunction *MF = BB->getParent();
5684 const SIInstrInfo *TII = MF->getSubtarget<GCNSubtarget>().getInstrInfo();
5685 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5687 const DebugLoc &DL = MI.getDebugLoc();
5688 MachineOperand &Dest = MI.getOperand(0);
5689 MachineOperand &Src0 = MI.getOperand(1);
5690 MachineOperand &Src1 = MI.getOperand(2);
5691 bool IsAdd = (MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5692 if (ST.hasScalarAddSub64()) {
5693 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5694 // clang-format off
5695 BuildMI(*BB, MI, DL, TII->get(Opc), Dest.getReg())
5696 .add(Src0)
5697 .add(Src1);
5698 // clang-format on
5699 } else {
5700 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5701 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5702
5703 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5704 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5705
5706 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5707 MI, MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5708 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5709 MI, MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5710
5711 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5712 MI, MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5713 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5714 MI, MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5715
5716 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5717 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5718 BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0).add(Src0Sub0).add(Src1Sub0);
5719 BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1).add(Src0Sub1).add(Src1Sub1);
5720 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
5721 .addReg(DestSub0)
5722 .addImm(AMDGPU::sub0)
5723 .addReg(DestSub1)
5724 .addImm(AMDGPU::sub1);
5725 }
5726 MI.eraseFromParent();
5727 return BB;
5728}
5729
5731 MachineFunction *MF = BB->getParent();
5732 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5733 const SIInstrInfo *TII = ST.getInstrInfo();
5734 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5735 MachineRegisterInfo &MRI = MF->getRegInfo();
5736 const DebugLoc &DL = MI.getDebugLoc();
5737 Register Dst = MI.getOperand(0).getReg();
5738 const MachineOperand &Src0 = MI.getOperand(1);
5739 const MachineOperand &Src1 = MI.getOperand(2);
5740 Register SrcCond = MI.getOperand(3).getReg();
5741
5742 Register DstLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5743 Register DstHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5744 const TargetRegisterClass *CondRC = TRI->getWaveMaskRegClass();
5745 Register SrcCondCopy = MRI.createVirtualRegister(CondRC);
5746
5747 int Src0Idx =
5748 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
5749 int Src1Idx =
5750 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);
5751 const TargetRegisterClass *Src0RC =
5752 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src0Idx));
5753 const TargetRegisterClass *Src1RC =
5754 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src1Idx));
5755
5756 const TargetRegisterClass *Src0SubRC =
5757 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5758 const TargetRegisterClass *Src1SubRC =
5759 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5760
5761 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5762 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5763 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5764 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5765
5766 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5767 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5768 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5769 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5770
5771 BuildMI(*BB, MI, DL, TII->get(AMDGPU::COPY), SrcCondCopy).addReg(SrcCond);
5772 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstLo)
5773 .addImm(0)
5774 .add(Src0Sub0)
5775 .addImm(0)
5776 .add(Src1Sub0)
5777 .addReg(SrcCondCopy);
5778
5779 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstHi)
5780 .addImm(0)
5781 .add(Src0Sub1)
5782 .addImm(0)
5783 .add(Src1Sub1)
5784 .addReg(SrcCondCopy);
5785
5786 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE), Dst)
5787 .addReg(DstLo)
5788 .addImm(AMDGPU::sub0)
5789 .addReg(DstHi)
5790 .addImm(AMDGPU::sub1);
5791 MI.eraseFromParent();
5792}
5793
5795 switch (Opc) {
5796 case AMDGPU::S_MIN_U32:
5797 return std::numeric_limits<uint32_t>::max();
5798 case AMDGPU::S_MIN_I32:
5799 return std::numeric_limits<int32_t>::max();
5800 case AMDGPU::S_MAX_U32:
5801 return std::numeric_limits<uint32_t>::min();
5802 case AMDGPU::S_MAX_I32:
5803 return std::numeric_limits<int32_t>::min();
5804 case AMDGPU::V_ADD_F32_e64: // -0.0
5805 return 0x80000000;
5806 case AMDGPU::V_SUB_F32_e64: // +0.0
5807 return 0x0;
5808 case AMDGPU::S_ADD_I32:
5809 case AMDGPU::S_SUB_I32:
5810 case AMDGPU::S_OR_B32:
5811 case AMDGPU::S_XOR_B32:
5812 return std::numeric_limits<uint32_t>::min();
5813 case AMDGPU::S_AND_B32:
5814 return std::numeric_limits<uint32_t>::max();
5815 case AMDGPU::V_MIN_F32_e64:
5816 case AMDGPU::V_MAX_F32_e64:
5817 return 0x7fc00000; // qNAN
5818 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5819 return std::numeric_limits<uint64_t>::max();
5820 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5821 return std::numeric_limits<int64_t>::max();
5822 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5823 return std::numeric_limits<uint64_t>::min();
5824 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5825 return std::numeric_limits<int64_t>::min();
5826 case AMDGPU::V_MIN_F64_e64:
5827 case AMDGPU::V_MAX_F64_e64:
5828 case AMDGPU::V_MIN_NUM_F64_e64:
5829 case AMDGPU::V_MAX_NUM_F64_e64:
5830 return 0x7FF8000000000000; // qNAN
5831 case AMDGPU::S_ADD_U64_PSEUDO:
5832 case AMDGPU::S_SUB_U64_PSEUDO:
5833 case AMDGPU::S_OR_B64:
5834 case AMDGPU::S_XOR_B64:
5835 return std::numeric_limits<uint64_t>::min();
5836 case AMDGPU::S_AND_B64:
5837 return std::numeric_limits<uint64_t>::max();
5838 case AMDGPU::V_ADD_F64_e64:
5839 case AMDGPU::V_ADD_F64_pseudo_e64:
5840 return 0x8000000000000000; // -0.0
5841 default:
5842 llvm_unreachable("Unexpected opcode in getIdentityValueForWaveReduction");
5843 }
5844}
5845
5846static bool is32bitWaveReduceOperation(unsigned Opc) {
5847 return Opc == AMDGPU::S_MIN_U32 || Opc == AMDGPU::S_MIN_I32 ||
5848 Opc == AMDGPU::S_MAX_U32 || Opc == AMDGPU::S_MAX_I32 ||
5849 Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32 ||
5850 Opc == AMDGPU::S_AND_B32 || Opc == AMDGPU::S_OR_B32 ||
5851 Opc == AMDGPU::S_XOR_B32 || Opc == AMDGPU::V_MIN_F32_e64 ||
5852 Opc == AMDGPU::V_MAX_F32_e64 || Opc == AMDGPU::V_ADD_F32_e64 ||
5853 Opc == AMDGPU::V_SUB_F32_e64;
5854}
5855
5857 return Opc == AMDGPU::V_MIN_F32_e64 || Opc == AMDGPU::V_MAX_F32_e64 ||
5858 Opc == AMDGPU::V_ADD_F32_e64 || Opc == AMDGPU::V_SUB_F32_e64 ||
5859 Opc == AMDGPU::V_MIN_F64_e64 || Opc == AMDGPU::V_MAX_F64_e64 ||
5860 Opc == AMDGPU::V_MIN_NUM_F64_e64 || Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5861 Opc == AMDGPU::V_ADD_F64_e64 || Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5862}
5863
5864static std::tuple<unsigned, unsigned>
5866 unsigned DPPOpc;
5867 switch (Opc) {
5868 case AMDGPU::S_MIN_U32:
5869 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5870 break;
5871 case AMDGPU::S_MIN_I32:
5872 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5873 break;
5874 case AMDGPU::S_MAX_U32:
5875 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5876 break;
5877 case AMDGPU::S_MAX_I32:
5878 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5879 break;
5880 case AMDGPU::S_ADD_I32:
5881 case AMDGPU::S_SUB_I32:
5882 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5883 : AMDGPU::V_ADD_CO_U32_dpp;
5884 break;
5885 case AMDGPU::S_AND_B32:
5886 DPPOpc = AMDGPU::V_AND_B32_dpp;
5887 break;
5888 case AMDGPU::S_OR_B32:
5889 DPPOpc = AMDGPU::V_OR_B32_dpp;
5890 break;
5891 case AMDGPU::S_XOR_B32:
5892 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5893 break;
5894 case AMDGPU::V_ADD_F32_e64:
5895 case AMDGPU::V_SUB_F32_e64:
5896 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5897 break;
5898 case AMDGPU::V_MIN_F32_e64:
5899 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5900 break;
5901 case AMDGPU::V_MAX_F32_e64:
5902 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5903 break;
5904 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5905 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5906 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5907 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5908 case AMDGPU::S_ADD_U64_PSEUDO:
5909 case AMDGPU::S_SUB_U64_PSEUDO:
5910 case AMDGPU::S_AND_B64:
5911 case AMDGPU::S_OR_B64:
5912 case AMDGPU::S_XOR_B64:
5913 case AMDGPU::V_MIN_NUM_F64_e64:
5914 case AMDGPU::V_MIN_F64_e64:
5915 case AMDGPU::V_MAX_NUM_F64_e64:
5916 case AMDGPU::V_MAX_F64_e64:
5917 case AMDGPU::V_ADD_F64_pseudo_e64:
5918 case AMDGPU::V_ADD_F64_e64:
5919 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5920 break;
5921 default:
5922 llvm_unreachable("unhandled lane op");
5923 }
5924 unsigned ClampOpc = Opc;
5925 if (!ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
5926 if (Opc == AMDGPU::S_SUB_I32)
5927 ClampOpc = AMDGPU::S_ADD_I32;
5928 if (Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO)
5929 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5930 else if (Opc == AMDGPU::S_AND_B64)
5931 ClampOpc = AMDGPU::V_AND_B32_e64;
5932 else if (Opc == AMDGPU::S_OR_B64)
5933 ClampOpc = AMDGPU::V_OR_B32_e64;
5934 else if (Opc == AMDGPU::S_XOR_B64)
5935 ClampOpc = AMDGPU::V_XOR_B32_e64;
5936 else
5937 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5938 }
5939 return {DPPOpc, ClampOpc};
5940}
5941
5942static std::pair<Register, Register>
5944 const TargetRegisterClass *SrcRC, const GCNSubtarget &ST,
5945 MachineRegisterInfo &MRI) {
5946 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5947 const SIInstrInfo *TII = ST.getInstrInfo();
5948 const TargetRegisterClass *SrcSubRC =
5949 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5950 Register Op1L =
5951 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5952 Register Op1H =
5953 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub1, SrcSubRC);
5954 return {Op1L, Op1H};
5955}
5956
5959 const GCNSubtarget &ST,
5960 unsigned Opc) {
5962 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5963 const DebugLoc &DL = MI.getDebugLoc();
5964 const SIInstrInfo *TII = ST.getInstrInfo();
5965
5966 // Reduction operations depend on whether the input operand is SGPR or VGPR.
5967 Register SrcReg = MI.getOperand(1).getReg();
5968 bool isSGPR = TRI->isSGPRClass(MRI.getRegClass(SrcReg));
5969 Register DstReg = MI.getOperand(0).getReg();
5970 unsigned Stratergy = static_cast<unsigned>(MI.getOperand(2).getImm());
5971 enum WAVE_REDUCE_STRATEGY : unsigned { DEFAULT = 0, ITERATIVE = 1, DPP = 2 };
5972 MachineBasicBlock *RetBB = nullptr;
5973 unsigned MIOpc = MI.getOpcode();
5974 auto BuildRegSequence = [&](MachineBasicBlock &BB,
5976 Register Src0, Register Src1) {
5977 auto RegSequence =
5978 BuildMI(BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dst)
5979 .addReg(Src0)
5980 .addImm(AMDGPU::sub0)
5981 .addReg(Src1)
5982 .addImm(AMDGPU::sub1);
5983 return RegSequence;
5984 };
5985 if (isSGPR) {
5986 switch (Opc) {
5987 case AMDGPU::S_MIN_U32:
5988 case AMDGPU::S_MIN_I32:
5989 case AMDGPU::V_MIN_F32_e64:
5990 case AMDGPU::S_MAX_U32:
5991 case AMDGPU::S_MAX_I32:
5992 case AMDGPU::V_MAX_F32_e64:
5993 case AMDGPU::S_AND_B32:
5994 case AMDGPU::S_OR_B32: {
5995 // Idempotent operations.
5996 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstReg).addReg(SrcReg);
5997 RetBB = &BB;
5998 break;
5999 }
6000 case AMDGPU::V_CMP_LT_U64_e64: // umin
6001 case AMDGPU::V_CMP_LT_I64_e64: // min
6002 case AMDGPU::V_CMP_GT_U64_e64: // umax
6003 case AMDGPU::V_CMP_GT_I64_e64: // max
6004 case AMDGPU::V_MIN_F64_e64:
6005 case AMDGPU::V_MIN_NUM_F64_e64:
6006 case AMDGPU::V_MAX_F64_e64:
6007 case AMDGPU::V_MAX_NUM_F64_e64:
6008 case AMDGPU::S_AND_B64:
6009 case AMDGPU::S_OR_B64: {
6010 // Idempotent operations.
6011 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B64), DstReg).addReg(SrcReg);
6012 RetBB = &BB;
6013 break;
6014 }
6015 case AMDGPU::S_XOR_B32:
6016 case AMDGPU::S_XOR_B64:
6017 case AMDGPU::S_ADD_I32:
6018 case AMDGPU::S_ADD_U64_PSEUDO:
6019 case AMDGPU::V_ADD_F32_e64:
6020 case AMDGPU::V_ADD_F64_e64:
6021 case AMDGPU::V_ADD_F64_pseudo_e64:
6022 case AMDGPU::S_SUB_I32:
6023 case AMDGPU::S_SUB_U64_PSEUDO:
6024 case AMDGPU::V_SUB_F32_e64: {
6025 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
6026 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
6027 Register ExecMask = MRI.createVirtualRegister(WaveMaskRegClass);
6028 Register NumActiveLanes =
6029 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6030
6031 bool IsWave32 = ST.isWave32();
6032 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6033 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6034 unsigned BitCountOpc =
6035 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
6036
6037 BuildMI(BB, MI, DL, TII->get(MovOpc), ExecMask).addReg(ExecReg);
6038
6039 auto NewAccumulator =
6040 BuildMI(BB, MI, DL, TII->get(BitCountOpc), NumActiveLanes)
6041 .addReg(ExecMask);
6042
6043 switch (Opc) {
6044 case AMDGPU::S_XOR_B32:
6045 case AMDGPU::S_XOR_B64: {
6046 // Performing an XOR operation on a uniform value
6047 // depends on the parity of the number of active lanes.
6048 // For even parity, the result will be 0, for odd
6049 // parity the result will be the same as the input value.
6050 Register ParityRegister =
6051 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6052
6053 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_AND_B32), ParityRegister)
6054 .addReg(NewAccumulator->getOperand(0).getReg())
6055 .addImm(1)
6056 .setOperandDead(3); // Dead scc
6057 if (Opc == AMDGPU::S_XOR_B32) {
6058 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6059 .addReg(SrcReg)
6060 .addReg(ParityRegister);
6061 } else {
6062 Register DestSub0 =
6063 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6064 Register DestSub1 =
6065 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6066 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6067 MRI.getRegClass(SrcReg), ST, MRI);
6068 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6069 .addReg(Op1L)
6070 .addReg(ParityRegister);
6071 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub1)
6072 .addReg(Op1H)
6073 .addReg(ParityRegister);
6074 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6075 }
6076 break;
6077 }
6078 case AMDGPU::S_SUB_I32: {
6079 Register NegatedVal = MRI.createVirtualRegister(DstRegClass);
6080
6081 // Take the negation of the source operand.
6082 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedVal)
6083 .addImm(0)
6084 .addReg(SrcReg);
6085 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6086 .addReg(NegatedVal)
6087 .addReg(NewAccumulator->getOperand(0).getReg());
6088 break;
6089 }
6090 case AMDGPU::S_ADD_I32: {
6091 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6092 .addReg(SrcReg)
6093 .addReg(NewAccumulator->getOperand(0).getReg());
6094 break;
6095 }
6096 case AMDGPU::S_ADD_U64_PSEUDO:
6097 case AMDGPU::S_SUB_U64_PSEUDO: {
6098 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6099 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6100 Register Op1H_Op0L_Reg =
6101 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6102 Register Op1L_Op0H_Reg =
6103 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6104 Register CarryReg =
6105 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6106 Register AddReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6107 Register NegatedValLo =
6108 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6109 Register NegatedValHi =
6110 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6111 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6112 MRI.getRegClass(SrcReg), ST, MRI);
6113 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6114 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedValLo)
6115 .addImm(0)
6116 .addReg(NewAccumulator->getOperand(0).getReg())
6117 .setOperandDead(3); // Dead scc
6118 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ASHR_I32), NegatedValHi)
6119 .addReg(NegatedValLo)
6120 .addImm(31)
6121 .setOperandDead(3); // Dead scc
6122 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1L_Op0H_Reg)
6123 .addReg(Op1L)
6124 .addReg(NegatedValHi);
6125 }
6126 Register LowOpcode = Opc == AMDGPU::S_SUB_U64_PSEUDO
6127 ? NegatedValLo
6128 : NewAccumulator->getOperand(0).getReg();
6129 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6130 .addReg(Op1L)
6131 .addReg(LowOpcode);
6132 if (ST.hasScalarMulHiInsts()) {
6133 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_HI_U32), CarryReg)
6134 .addReg(Op1L)
6135 .addReg(LowOpcode);
6136 } else {
6137 Register VCarryReg =
6138 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6139 Register LowOpVGPR =
6140 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6141 BuildMI(BB, MI, DL, TII->get(AMDGPU::COPY), LowOpVGPR)
6142 .addReg(LowOpcode);
6143 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6144 .addReg(Op1L)
6145 .addReg(LowOpVGPR);
6146 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6147 .addReg(VCarryReg);
6148 }
6149 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1H_Op0L_Reg)
6150 .addReg(Op1H)
6151 .addReg(LowOpcode);
6152
6153 Register HiVal = Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6154 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), HiVal)
6155 .addReg(CarryReg)
6156 .addReg(Op1H_Op0L_Reg)
6157 .setOperandDead(3); // Dead scc
6158
6159 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6160 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), DestSub1)
6161 .addReg(HiVal)
6162 .addReg(Op1L_Op0H_Reg)
6163 .setOperandDead(3); // Dead scc
6164 }
6165 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6166 break;
6167 }
6168 case AMDGPU::V_ADD_F32_e64:
6169 case AMDGPU::V_ADD_F64_e64:
6170 case AMDGPU::V_ADD_F64_pseudo_e64:
6171 case AMDGPU::V_SUB_F32_e64: {
6172 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6173 const TargetRegisterClass *VregRC = TII->getRegClass(TII->get(Opc), 0);
6174 Register ActiveLanesVreg = MRI.createVirtualRegister(VregRC);
6175 Register DstVreg = MRI.createVirtualRegister(VregRC);
6176 // Get number of active lanes as a float val.
6177 BuildMI(BB, MI, DL,
6178 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6179 : AMDGPU::V_CVT_F64_I32_e64),
6180 ActiveLanesVreg)
6181 .addReg(NewAccumulator->getOperand(0).getReg())
6182 .addImm(0) // clamp
6183 .addImm(0); // output-modifier
6184
6185 // Take negation of input for SUB reduction
6186 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6187 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6190 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6191 : ST.getGeneration() >= AMDGPUSubtarget::GFX12
6192 ? AMDGPU::V_MUL_F64_pseudo_e64
6193 : AMDGPU::V_MUL_F64_e64;
6194 auto DestVregInst = BuildMI(BB, MI, DL, TII->get(MulOpc),
6195 DstVreg)
6196 .addImm(srcMod) // src0 modifier
6197 .addReg(SrcReg)
6198 .addImm(SISrcMods::NONE) // src1 modifier
6199 .addReg(ActiveLanesVreg)
6200 .addImm(SISrcMods::NONE) // clamp
6201 .addImm(SISrcMods::NONE); // output-mod
6202 if (is32BitOpc) {
6203 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6204 .addReg(DstVreg);
6205 } else {
6206 Register LaneValueLoReg =
6207 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6208 Register LaneValueHiReg =
6209 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6210 auto [Op1L, Op1H] =
6211 ExtractSubRegs(MI, DestVregInst->getOperand(0), VregRC, ST, MRI);
6212 // lane value input should be in an sgpr
6213 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6214 LaneValueLoReg)
6215 .addReg(Op1L);
6216 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6217 LaneValueHiReg)
6218 .addReg(Op1H);
6219 NewAccumulator =
6220 BuildRegSequence(BB, MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6221 }
6222 }
6223 }
6224 RetBB = &BB;
6225 }
6226 }
6227 } else {
6229 Register SrcReg = MI.getOperand(1).getReg();
6230 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6232 bool NeedsMovDPP = !is32BitOpc;
6233 // Create virtual registers required for lowering.
6234 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
6235 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
6236 const TargetRegisterClass *SrcRegClass = MRI.getRegClass(SrcReg);
6237 bool IsWave32 = ST.isWave32();
6238 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6239 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6240 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6241 !ST.hasDPP()) { // If target doesn't support DPP operations, default to
6242 // iterative stratergy
6243
6244 // To reduce the VGPR using iterative approach, we need to iterate
6245 // over all the active lanes. Lowering consists of ComputeLoop,
6246 // which iterate over only active lanes. We use copy of EXEC register
6247 // as induction variable and every active lane modifies it using bitset0
6248 // so that we will get the next active lane for next iteration.
6249
6250 // Create Control flow for loop
6251 // Split MI's Machine Basic block into For loop
6252 auto [ComputeLoop, ComputeEnd] = splitBlockForLoop(MI, BB, true);
6253
6254 Register LoopIterator = MRI.createVirtualRegister(WaveMaskRegClass);
6255 Register IdentityValReg = MRI.createVirtualRegister(DstRegClass);
6256 Register AccumulatorReg = MRI.createVirtualRegister(DstRegClass);
6257 Register ActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6258 Register NewActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6259 Register FF1Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6260 Register LaneValueReg = MRI.createVirtualRegister(DstRegClass);
6261
6262 // Create initial values of induction variable from Exec, Accumulator and
6263 // insert branch instr to newly created ComputeBlock
6264 BuildMI(BB, I, DL, TII->get(MovOpcForExec), LoopIterator).addReg(ExecReg);
6265 uint64_t IdentityValue =
6266 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6267 ? 0x0 // +0.0 for double sub reduction
6269 BuildMI(BB, I, DL,
6270 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6271 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6272 IdentityValReg)
6273 .addImm(IdentityValue);
6274 // clang-format off
6275 BuildMI(BB, I, DL, TII->get(AMDGPU::S_BRANCH))
6276 .addMBB(ComputeLoop);
6277 // clang-format on
6278
6279 // Start constructing ComputeLoop
6280 I = ComputeLoop->begin();
6281 auto Accumulator =
6282 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), AccumulatorReg)
6283 .addReg(IdentityValReg)
6284 .addMBB(&BB);
6285 auto ActiveBits =
6286 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), ActiveBitsReg)
6287 .addReg(LoopIterator)
6288 .addMBB(&BB);
6289
6290 I = ComputeLoop->end();
6291 MachineInstr *NewAccumulator;
6292 // Perform the computations
6293 unsigned SFFOpc =
6294 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6295 BuildMI(*ComputeLoop, I, DL, TII->get(SFFOpc), FF1Reg)
6296 .addReg(ActiveBitsReg);
6297 if (is32BitOpc) {
6298 Register OpDstReg = DstReg;
6299 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6300 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6301 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6302 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6303 bool hasClamp =
6304 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1;
6305 bool hasOpSel =
6306 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel) != -1;
6307 bool hasOMod =
6308 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1;
6309 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6310 LaneValueReg)
6311 .addReg(SrcReg)
6312 .addReg(FF1Reg);
6313 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6314 // Get the Lane Value in VGPR to avoid the Constant Bus Restriction
6315 Register LaneValVgpr = MRI.createVirtualRegister(SrcRegClass);
6316 Register VgprResultReg = MRI.createVirtualRegister(SrcRegClass);
6317 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), LaneValVgpr)
6318 .addReg(LaneValueReg);
6319 OpDstReg = VgprResultReg;
6320 LaneValueReg = LaneValVgpr;
6321 }
6322 auto OpInstr = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), OpDstReg);
6323 if (hasSrc0Modifier)
6324 OpInstr.addImm(SISrcMods::NONE); // src0 modifier
6325 OpInstr.addReg(AccumulatorReg); // src0
6326 if (hasSrc1Modifier)
6327 OpInstr.addImm(SISrcMods::NONE); // src1 modifier
6328 OpInstr.addReg(LaneValueReg); // src1
6329 if (hasClamp)
6330 OpInstr.addImm(0); // clamp
6331 if (hasOpSel)
6332 OpInstr.addImm(0); // opsel
6333 if (hasOMod)
6334 OpInstr.addImm(0); // omod
6335 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6336 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6337 DstReg)
6338 .addReg(OpDstReg);
6339 }
6340 } else {
6341 Register LaneValueLoReg =
6342 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6343 Register LaneValueHiReg =
6344 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6345 Register LaneValReg =
6346 MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
6347 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6348 MRI.getRegClass(SrcReg), ST, MRI);
6349 // lane value input should be in an sgpr
6350 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6351 LaneValueLoReg)
6352 .addReg(Op1L)
6353 .addReg(FF1Reg);
6354 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6355 LaneValueHiReg)
6356 .addReg(Op1H)
6357 .addReg(FF1Reg);
6358 auto LaneValue = BuildRegSequence(*ComputeLoop, I, LaneValReg,
6359 LaneValueLoReg, LaneValueHiReg);
6360 switch (Opc) {
6361 case AMDGPU::S_OR_B64:
6362 case AMDGPU::S_AND_B64:
6363 case AMDGPU::S_XOR_B64: {
6364 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6365 .addReg(Accumulator->getOperand(0).getReg())
6366 .addReg(LaneValue->getOperand(0).getReg())
6367 .setOperandDead(3); // Dead scc
6368 break;
6369 }
6370 case AMDGPU::V_CMP_GT_I64_e64:
6371 case AMDGPU::V_CMP_GT_U64_e64:
6372 case AMDGPU::V_CMP_LT_I64_e64:
6373 case AMDGPU::V_CMP_LT_U64_e64: {
6374 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6375 Register ComparisonResultReg =
6376 MRI.createVirtualRegister(WaveMaskRegClass);
6377 int SrcIdx =
6378 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6379 const TargetRegisterClass *VregClass =
6380 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6381 Register AccumulatorVReg = MRI.createVirtualRegister(VregClass);
6382 auto [SrcReg0Sub0, SrcReg0Sub1] = ExtractSubRegs(
6383 MI, Accumulator->getOperand(0), VregClass, ST, MRI);
6384 BuildRegSequence(*ComputeLoop, I, AccumulatorVReg, SrcReg0Sub0,
6385 SrcReg0Sub1);
6386 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), LaneMaskReg)
6387 .addReg(LaneValue->getOperand(0).getReg())
6388 .addReg(AccumulatorVReg);
6389
6390 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6391 BuildMI(*ComputeLoop, I, DL, TII->get(AndOpc), ComparisonResultReg)
6392 .addReg(LaneMaskReg)
6393 .addReg(ActiveBitsReg);
6394
6395 NewAccumulator = BuildMI(*ComputeLoop, I, DL,
6396 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6397 .addReg(LaneValue->getOperand(0).getReg())
6398 .addReg(Accumulator->getOperand(0).getReg());
6399 break;
6400 }
6401 case AMDGPU::V_MIN_F64_e64:
6402 case AMDGPU::V_MIN_NUM_F64_e64:
6403 case AMDGPU::V_MAX_F64_e64:
6404 case AMDGPU::V_MAX_NUM_F64_e64:
6405 case AMDGPU::V_ADD_F64_e64:
6406 case AMDGPU::V_ADD_F64_pseudo_e64: {
6407 int SrcIdx =
6408 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6409 const TargetRegisterClass *VregRC =
6410 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6411 Register AccumulatorVReg = MRI.createVirtualRegister(VregRC);
6412 Register DstVreg = MRI.createVirtualRegister(VregRC);
6413 Register LaneValLo =
6414 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6415 Register LaneValHi =
6416 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6417 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), AccumulatorVReg)
6418 .addReg(Accumulator->getOperand(0).getReg());
6419 unsigned Modifier =
6420 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6423 auto DstVregInst =
6424 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstVreg)
6425 .addImm(Modifier) // src0 modifiers
6426 .addReg(LaneValue->getOperand(0).getReg())
6427 .addImm(SISrcMods::NONE) // src1 modifiers
6428 .addReg(AccumulatorVReg)
6429 .addImm(SISrcMods::NONE) // clamp
6430 .addImm(SISrcMods::NONE); // omod
6431 auto ReadLaneLo =
6432 BuildMI(*ComputeLoop, I, DL,
6433 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6434 auto ReadLaneHi =
6435 BuildMI(*ComputeLoop, I, DL,
6436 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6437 MachineBasicBlock::iterator Iters = *ReadLaneLo;
6438 auto [Op1L, Op1H] = ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6439 VregRC, ST, MRI);
6440 ReadLaneLo.addReg(Op1L);
6441 ReadLaneHi.addReg(Op1H);
6442 NewAccumulator =
6443 BuildRegSequence(*ComputeLoop, I, DstReg, LaneValLo, LaneValHi);
6444 break;
6445 }
6446 case AMDGPU::S_ADD_U64_PSEUDO:
6447 case AMDGPU::S_SUB_U64_PSEUDO: {
6448 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6449 .addReg(Accumulator->getOperand(0).getReg())
6450 .addReg(LaneValue->getOperand(0).getReg());
6451 ComputeLoop =
6452 expand64BitScalarArithmetic(*NewAccumulator, ComputeLoop);
6453 break;
6454 }
6455 }
6456 }
6457 // Manipulate the iterator to get the next active lane
6458 unsigned BITSETOpc =
6459 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6460 BuildMI(*ComputeLoop, I, DL, TII->get(BITSETOpc), NewActiveBitsReg)
6461 .addReg(FF1Reg)
6462 .addReg(ActiveBitsReg);
6463
6464 // Add phi nodes
6465 Accumulator.addReg(DstReg).addMBB(ComputeLoop);
6466 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6467
6468 // Creating branching
6469 MachineInstrBuilder SetSCCInstr;
6470 if (!ST.hasScalarCompareEq64()) {
6471 // For targets <= gfx7, use an S_OR_B32/B64 instruction to set SCC.
6472 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6473 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6474 SetSCCInstr =
6475 BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc), LaneMaskReg);
6476 } else {
6477 unsigned CMPOpc =
6478 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6479 SetSCCInstr = BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc));
6480 }
6481 SetSCCInstr.addReg(NewActiveBitsReg);
6482 if (ST.hasScalarCompareEq64())
6483 SetSCCInstr.addImm(0);
6484 else
6485 SetSCCInstr.addReg(NewActiveBitsReg);
6486 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
6487 .addMBB(ComputeLoop);
6488
6489 RetBB = ComputeEnd;
6490 } else {
6491 assert(ST.hasDPP() && "Sub Target does not support DPP Operations");
6492 MachineBasicBlock *CurrBB = &BB;
6493 Register SrcWithIdentity = MRI.createVirtualRegister(SrcRegClass);
6494 Register IdentityVGPR = MRI.createVirtualRegister(SrcRegClass);
6495 Register IdentitySGPR = MRI.createVirtualRegister(DstRegClass);
6496 Register DPPRowShr1 = MRI.createVirtualRegister(SrcRegClass);
6497 Register DPPRowShr2 = MRI.createVirtualRegister(SrcRegClass);
6498 Register DPPRowShr4 = MRI.createVirtualRegister(SrcRegClass);
6499 Register DPPRowShr8 = MRI.createVirtualRegister(SrcRegClass);
6500 Register RowBcast15 = MRI.createVirtualRegister(SrcRegClass);
6501 Register ReducedValSGPR = MRI.createVirtualRegister(DstRegClass);
6502 Register NegatedReducedVal = MRI.createVirtualRegister(DstRegClass);
6503 Register RowBcast31 = MRI.createVirtualRegister(SrcRegClass);
6504 Register UndefExec = MRI.createVirtualRegister(WaveMaskRegClass);
6505 Register FinalDPPResult;
6506 MachineInstr *SrcWithIdentityInstr;
6507 MachineInstr *LastBcastInstr;
6508 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6509
6511 BuildMI(*CurrBB, MI, DL,
6512 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6513 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6514 IdentitySGPR)
6515 .addImm(IdentityValue);
6516 auto IdentityCopyInstr =
6517 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::COPY), IdentityVGPR)
6518 .addReg(IdentitySGPR);
6519 auto DPPClampOpcPair = getDPPOpcForWaveReduction(Opc, ST);
6520 unsigned DPPOpc = std::get<0>(DPPClampOpcPair);
6521 unsigned ClampOpc = std::get<1>(DPPClampOpcPair);
6522 auto BuildSetInactiveInstr = [&](Register Dst, Register Src0,
6523 Register Src1) {
6524 return BuildMI(BB, MI, DL, TII->get(AMDGPU::V_SET_INACTIVE_B32),
6525 Dst)
6526 .addImm(0) // src0 modifiers
6527 .addReg(Src0) // src0
6528 .addImm(0) // src1 modifiers
6529 .addReg(Src1) // identity value for inactive lanes
6530 .addReg(UndefExec); // bool i1
6531 };
6532 auto BuildDPPMachineInstr = [&](Register Dst, Register Src,
6533 unsigned DPPCtrl) {
6534 auto DPPInstr =
6535 BuildMI(*CurrBB, MI, DL, TII->get(DPPOpc), Dst).addReg(Src); // old
6536 if (isFPOp && !NeedsMovDPP)
6537 DPPInstr.addImm(SISrcMods::NONE); // src0 modifier
6538 DPPInstr.addReg(Src); // src0
6539 if (isFPOp && !NeedsMovDPP)
6540 DPPInstr.addImm(SISrcMods::NONE); // src1 modifier
6541 if (!NeedsMovDPP)
6542 DPPInstr.addReg(Src); // src1
6543 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6544 DPPInstr.addImm(0); // clamp
6545 DPPInstr
6546 .addImm(DPPCtrl) // dpp-ctrl
6547 .addImm(0xf) // row-mask
6548 .addImm(0xf) // bank-mask
6549 .addImm(0); // bound-control
6550 };
6551 auto BuildClampInstr = [&](Register Dst, Register Src0, Register Src1,
6552 bool isAddSub = false,
6553 bool needsCarryIn = false,
6554 Register CarryIn = Register()) {
6555 unsigned InstrOpc = ClampOpc;
6556 Register CarryOutReg = MRI.createVirtualRegister(WaveMaskRegClass);
6557 if (needsCarryIn)
6558 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6559 auto ClampInstr = BuildMI(*CurrBB, MI, DL, TII->get(InstrOpc), Dst);
6560 if (isFPOp)
6561 ClampInstr.addImm(SISrcMods::NONE); // src0 mod
6562 if (isAddSub) {
6563 if (needsCarryIn)
6564 ClampInstr.addReg(CarryOutReg,
6566 RegState::Dead); // killed carry-out reg
6567 else
6568 ClampInstr.addReg(CarryOutReg, RegState::Define); // carry-out reg
6569 }
6570 ClampInstr.addReg(Src0); // src0
6571 if (isFPOp)
6572 ClampInstr.addImm(SISrcMods::NONE); // src1 mod
6573 ClampInstr.addReg(Src1); // src1
6574 if (needsCarryIn)
6575 ClampInstr.addReg(CarryIn, RegState::Kill); // carry-in reg
6576 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6577 ClampInstr.addImm(0); // clamp
6578 if (isFPOp)
6579 ClampInstr.addImm(0); // omod
6580 LastBcastInstr = ClampInstr;
6581 return CarryOutReg;
6582 };
6583 auto BuildPostDPPInstr = [&](Register Src0, Register Src1) {
6584 bool isAddSubOpc =
6585 Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO;
6586 bool isBitWiseOpc = Opc == AMDGPU::S_AND_B64 ||
6587 Opc == AMDGPU::S_OR_B64 || Opc == AMDGPU::S_XOR_B64;
6588 Register ReturnReg = MRI.createVirtualRegister(SrcRegClass);
6589 if (isAddSubOpc || isBitWiseOpc) {
6590 Register ResLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6591 Register ResHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6592 MachineOperand Src0Operand =
6593 MachineOperand::CreateReg(Src0, /*isDef=*/false);
6594 MachineOperand Src1Operand =
6595 MachineOperand::CreateReg(Src1, /*isDef=*/false);
6596 auto [Src0Lo, Src0Hi] =
6597 ExtractSubRegs(MI, Src0Operand, SrcRegClass, ST, MRI);
6598 auto [Src1Lo, Src1Hi] =
6599 ExtractSubRegs(MI, Src1Operand, SrcRegClass, ST, MRI);
6600 Register CarryReg = BuildClampInstr(
6601 ResLo, Src0Lo, Src1Lo, isAddSubOpc, /*needsCarryIn*/ false);
6602 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6603 /*needsCarryIn*/ isAddSubOpc, CarryReg);
6604 BuildRegSequence(*CurrBB, MI, ReturnReg, ResLo, ResHi);
6605 } else {
6606 if (isFPOp) {
6607 BuildMI(*CurrBB, MI, DL, TII->get(Opc), ReturnReg)
6608 .addImm(SISrcMods::NONE) // src0 modifiers
6609 .addReg(Src0)
6610 .addImm(SISrcMods::NONE) // src1 modifiers
6611 .addReg(Src1)
6612 .addImm(SISrcMods::NONE) // clamp
6613 .addImm(SISrcMods::NONE); // omod
6614 } else {
6615 Register CmpMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6616 BuildMI(*CurrBB, MI, DL, TII->get(Opc), CmpMaskReg)
6617 .addReg(Src0) // src0
6618 .addReg(Src1); // src1
6619 LastBcastInstr =
6620 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B64_PSEUDO),
6621 ReturnReg)
6622 .addReg(Src1) // src0
6623 .addReg(Src0) // src1
6624 .addReg(CmpMaskReg); // src2
6625 expand64BitV_CNDMASK(*LastBcastInstr, CurrBB);
6626 }
6627 }
6628 return ReturnReg;
6629 };
6630
6631 // Set inactive lanes to the identity value.
6632 if (is32BitOpc) {
6633 SrcWithIdentityInstr =
6634 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6635 } else {
6636 Register SrcWithIdentitylo =
6637 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6638 Register SrcWithIdentityhi =
6639 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6640 auto [Reg0Sub0, Reg0Sub1] = ExtractSubRegs(
6641 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST, MRI);
6642 auto [SrcReg0Sub0, SrcReg0Sub1] =
6643 ExtractSubRegs(MI, MI.getOperand(1), SrcRegClass, ST, MRI);
6644 MachineInstr *SetInactiveLoInstr =
6645 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6646 MachineInstr *SetInactiveHiInstr =
6647 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6648 SrcWithIdentityInstr =
6649 BuildRegSequence(*CurrBB, MI, SrcWithIdentity,
6650 SetInactiveLoInstr->getOperand(0).getReg(),
6651 SetInactiveHiInstr->getOperand(0).getReg());
6652 }
6653 // DPP reduction
6654 Register SrcWithIdentityReg =
6655 SrcWithIdentityInstr->getOperand(0).getReg();
6656 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6658 if (NeedsMovDPP)
6659 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6660
6661 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6663 if (NeedsMovDPP)
6664 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6665
6666 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6668 if (NeedsMovDPP)
6669 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6670
6671 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6673 if (NeedsMovDPP)
6674 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6675
6676 if (ST.hasDPPBroadcasts()) {
6677 BuildDPPMachineInstr(RowBcast15, DPPRowShr8, AMDGPU::DPP::BCAST15);
6678 if (NeedsMovDPP)
6679 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6680 } else {
6681 // magic constant: 0x1E0
6682 // To Set BIT_MODE : bit 15 = 0
6683 // XOR mask : bit [14:10] = 0
6684 // OR mask : bit [9:5] = 15
6685 // AND mask : bit [4:0] = 0
6686 if (is32BitOpc) {
6687 Register SwizzledValue =
6688 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6689 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6690 SwizzledValue)
6691 .addReg(DPPRowShr8) // addr
6692 .addImm(0x1E0) // swizzle offset (i16)
6693 .addImm(0x0); // gds (i1)
6694 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6695 } else {
6696 Register SwizzledValuelo =
6697 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6698 Register SwizzledValuehi =
6699 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6700 Register SwizzledValue64 = MRI.createVirtualRegister(SrcRegClass);
6701 MachineOperand DPPRowShr8Op =
6702 MachineOperand::CreateReg(DPPRowShr8, /*isDef=*/false);
6703 auto [Op1L, Op1H] =
6704 ExtractSubRegs(MI, DPPRowShr8Op, SrcRegClass, ST, MRI);
6705 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6706 SwizzledValuelo)
6707 .addReg(Op1L) // addr
6708 .addImm(0x1E0) // swizzle offset (i16)
6709 .addImm(0x0); // gds (i1)
6710 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6711 SwizzledValuehi)
6712 .addReg(Op1H) // addr
6713 .addImm(0x1E0) // swizzle offset (i16)
6714 .addImm(0x0); // gds (i1)
6715 BuildRegSequence(*CurrBB, MI, SwizzledValue64, SwizzledValuelo,
6716 SwizzledValuehi);
6717 if (NeedsMovDPP)
6718 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6719 else
6720 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6721 }
6722 }
6723 FinalDPPResult = RowBcast15;
6724 if (!IsWave32) {
6725 if (ST.hasDPPBroadcasts()) {
6726 BuildDPPMachineInstr(RowBcast31, RowBcast15, AMDGPU::DPP::BCAST31);
6727 if (NeedsMovDPP)
6728 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6729 } else {
6730 Register ShiftedThreadID =
6731 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6732 Register PermuteByteOffset =
6733 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6734 Register PermutedValue = MRI.createVirtualRegister(SrcRegClass);
6735 Register Lane32Offset =
6736 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6737 Register WordSizeConst =
6738 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6739 Register ThreadIDRegLo =
6740 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6741 Register ThreadIDReg =
6742 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6743 // Get the thread ID.
6744 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6745 ThreadIDRegLo)
6746 .addImm(-1)
6747 .addImm(0);
6748 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6749 ThreadIDReg)
6750 .addImm(-1)
6751 .addReg(ThreadIDRegLo);
6752 // shift each lane over by 32 positions, so value in 31st lane is
6753 // present in 63rd lane.
6754 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6755 .addImm(0x20);
6756 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_ADD_U32_e64),
6757 ShiftedThreadID)
6758 .addReg(ThreadIDReg)
6759 .addReg(Lane32Offset)
6760 .addImm(0); // clamp
6761 // multiply by reg size.
6762 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6763 .addImm(0x4);
6764 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MUL_LO_U32_e64),
6765 PermuteByteOffset)
6766 .addReg(WordSizeConst)
6767 .addReg(ShiftedThreadID);
6768 // Permute the lanes
6769 if (is32BitOpc) {
6770 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6771 PermutedValue)
6772 .addReg(PermuteByteOffset) // addr
6773 .addReg(RowBcast15) // data
6774 .addImm(0); // offset
6775 } else {
6776 Register PermutedValuelo =
6777 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6778 Register PermutedValuehi =
6779 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6780 MachineOperand RowBcast15Op =
6781 MachineOperand::CreateReg(RowBcast15, /*isDef=*/false);
6782 auto [RowBcast15Lo, RowBcast15Hi] =
6783 ExtractSubRegs(MI, RowBcast15Op, SrcRegClass, ST, MRI);
6784 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6785 PermutedValuelo)
6786 .addReg(PermuteByteOffset) // addr
6787 .addReg(RowBcast15Lo) // swizzle offset (i16)
6788 .addImm(0x0); // gds (i1)
6789 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6790 PermutedValuehi)
6791 .addReg(PermuteByteOffset) // addr
6792 .addReg(RowBcast15Hi) // swizzle offset (i16)
6793 .addImm(0x0); // gds (i1)
6794 BuildRegSequence(*CurrBB, MI, PermutedValue, PermutedValuelo,
6795 PermutedValuehi);
6796 }
6797 if (NeedsMovDPP)
6798 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6799 else
6800 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6801 }
6802 FinalDPPResult = RowBcast31;
6803 }
6804 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6805 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6806 Register NegatedValVGPR = MRI.createVirtualRegister(SrcRegClass);
6807 // Opc for f32 reduction is V_SUB_F32.
6808 // For f64, there is no equivalent V_SUB_F64 opcode, so use
6809 // V_ADD_F64/V_ADD_F64_pseudo, and negate the second operand.
6810 BuildMI(*CurrBB, MI, DL, TII->get(Opc),
6811 NegatedValVGPR)
6812 .addImm(SISrcMods::NONE) // src0 mods
6813 .addReg(IdentityVGPR) // src0
6814 .addImm(is32BitOpc ? SISrcMods::NONE : SISrcMods::NEG) // src1 mods
6815 .addReg(IsWave32 ? RowBcast15 : RowBcast31) // src1
6816 .addImm(SISrcMods::NONE) // clamp
6817 .addImm(SISrcMods::NONE); // omod
6818 FinalDPPResult = NegatedValVGPR;
6819 }
6820 // The final reduced value is in the last lane.
6821 if (is32BitOpc) {
6822 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6823 ReducedValSGPR)
6824 .addReg(FinalDPPResult)
6825 .addImm(ST.getWavefrontSize() - 1);
6826 } else {
6827 Register LaneValueLoReg =
6828 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6829 Register LaneValueHiReg =
6830 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6831 const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
6832 MachineOperand FinalDPPResultOperand =
6833 MachineOperand::CreateReg(FinalDPPResult, /*isDef=*/false);
6834 auto [Op1L, Op1H] =
6835 ExtractSubRegs(MI, FinalDPPResultOperand, SrcRC, ST, MRI);
6836 // lane value input should be in an sgpr
6837 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6838 LaneValueLoReg)
6839 .addReg(Op1L)
6840 .addImm(ST.getWavefrontSize() - 1);
6841 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6842 LaneValueHiReg)
6843 .addReg(Op1H)
6844 .addImm(ST.getWavefrontSize() - 1);
6845 BuildRegSequence(*CurrBB, MI, ReducedValSGPR, LaneValueLoReg,
6846 LaneValueHiReg);
6847 }
6848 if (Opc == AMDGPU::S_SUB_I32) {
6849 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6850 .addImm(0)
6851 .addReg(ReducedValSGPR);
6852 } else if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6853 auto NegatedValInstr =
6854 BuildMI(*CurrBB, MI, DL, TII->get(Opc), NegatedReducedVal)
6855 .addImm(0)
6856 .addReg(ReducedValSGPR);
6857 CurrBB = expand64BitScalarArithmetic(*NegatedValInstr, CurrBB);
6858 }
6859 // Mark the final result as a whole-wave-mode calculation.
6860 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::STRICT_WWM), DstReg)
6861 .addReg(Opc == AMDGPU::S_SUB_I32 || Opc == AMDGPU::S_SUB_U64_PSEUDO
6862 ? NegatedReducedVal
6863 : ReducedValSGPR);
6864 RetBB = CurrBB;
6865 }
6866 }
6867 MI.eraseFromParent();
6868 return RetBB;
6869}
6870
6873 MachineBasicBlock *BB) const {
6874 MachineFunction *MF = BB->getParent();
6876 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
6878 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
6879 MachineRegisterInfo &MRI = MF->getRegInfo();
6880 const DebugLoc &DL = MI.getDebugLoc();
6881
6882 switch (MI.getOpcode()) {
6883 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6884 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_U32);
6885 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6886 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_U64_e64);
6887 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6888 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_I32);
6889 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6890 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_I64_e64);
6891 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6892 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MIN_F32_e64);
6893 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6894 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6895 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6896 ? AMDGPU::V_MIN_NUM_F64_e64
6897 : AMDGPU::V_MIN_F64_e64);
6898 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6899 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_U32);
6900 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6901 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_U64_e64);
6902 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6903 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_I32);
6904 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6905 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_I64_e64);
6906 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6907 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MAX_F32_e64);
6908 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6909 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6910 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6911 ? AMDGPU::V_MAX_NUM_F64_e64
6912 : AMDGPU::V_MAX_F64_e64);
6913 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6914 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_I32);
6915 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6916 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_U64_PSEUDO);
6917 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6918 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_ADD_F32_e64);
6919 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
6920 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6921 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6922 ? AMDGPU::V_ADD_F64_pseudo_e64
6923 : AMDGPU::V_ADD_F64_e64);
6924 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
6925 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_I32);
6926 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
6927 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_U64_PSEUDO);
6928 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
6929 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_SUB_F32_e64);
6930 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
6931 // There is no S/V_SUB_F64 opcode. Double type subtraction is expanded as
6932 // fadd + neg, by setting the NEG bit in the instruction.
6933 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6934 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6935 ? AMDGPU::V_ADD_F64_pseudo_e64
6936 : AMDGPU::V_ADD_F64_e64);
6937 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
6938 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B32);
6939 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
6940 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B64);
6941 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
6942 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B32);
6943 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
6944 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B64);
6945 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
6946 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B32);
6947 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
6948 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B64);
6949 case AMDGPU::S_UADDO_PSEUDO:
6950 case AMDGPU::S_USUBO_PSEUDO: {
6951 MachineOperand &Dest0 = MI.getOperand(0);
6952 MachineOperand &Dest1 = MI.getOperand(1);
6953 MachineOperand &Src0 = MI.getOperand(2);
6954 MachineOperand &Src1 = MI.getOperand(3);
6955
6956 unsigned Opc = (MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
6957 ? AMDGPU::S_ADD_U32
6958 : AMDGPU::S_SUB_U32;
6959 // clang-format off
6960 BuildMI(*BB, MI, DL, TII->get(Opc), Dest0.getReg())
6961 .add(Src0)
6962 .add(Src1);
6963 // clang-format on
6964
6965 unsigned SelOpc =
6966 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
6967 BuildMI(*BB, MI, DL, TII->get(SelOpc), Dest1.getReg()).addImm(-1).addImm(0);
6968
6969 MI.eraseFromParent();
6970 return BB;
6971 }
6972 case AMDGPU::S_ADD_U64_PSEUDO:
6973 case AMDGPU::S_SUB_U64_PSEUDO: {
6974 return expand64BitScalarArithmetic(MI, BB);
6975 }
6976 case AMDGPU::V_ADD_U64_PSEUDO:
6977 case AMDGPU::V_SUB_U64_PSEUDO: {
6978 bool IsAdd = (MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
6979
6980 MachineOperand &Dest = MI.getOperand(0);
6981 MachineOperand &Src0 = MI.getOperand(1);
6982 MachineOperand &Src1 = MI.getOperand(2);
6983
6984 if (ST.hasAddSubU64Insts()) {
6985 auto I = BuildMI(*BB, MI, DL,
6986 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
6987 : AMDGPU::V_SUB_U64_e64),
6988 Dest.getReg())
6989 .add(Src0)
6990 .add(Src1)
6991 .addImm(0); // clamp
6992 TII->legalizeOperands(*I);
6993 MI.eraseFromParent();
6994 return BB;
6995 }
6996
6997 if (IsAdd && ST.hasLshlAddU64Inst()) {
6998 auto Add = BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_LSHL_ADD_U64_e64),
6999 Dest.getReg())
7000 .add(Src0)
7001 .addImm(0)
7002 .add(Src1);
7003 TII->legalizeOperands(*Add);
7004 MI.eraseFromParent();
7005 return BB;
7006 }
7007
7008 const auto *CarryRC = TRI->getWaveMaskRegClass();
7009
7010 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7011 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7012
7013 Register CarryReg = MRI.createVirtualRegister(CarryRC);
7014 Register DeadCarryReg = MRI.createVirtualRegister(CarryRC);
7015
7016 const TargetRegisterClass *Src0RC = Src0.isReg()
7017 ? MRI.getRegClass(Src0.getReg())
7018 : &AMDGPU::VReg_64RegClass;
7019 const TargetRegisterClass *Src1RC = Src1.isReg()
7020 ? MRI.getRegClass(Src1.getReg())
7021 : &AMDGPU::VReg_64RegClass;
7022
7023 const TargetRegisterClass *Src0SubRC =
7024 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
7025 const TargetRegisterClass *Src1SubRC =
7026 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
7027
7028 MachineOperand SrcReg0Sub0 = TII->buildExtractSubRegOrImm(
7029 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
7030 MachineOperand SrcReg1Sub0 = TII->buildExtractSubRegOrImm(
7031 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
7032
7033 MachineOperand SrcReg0Sub1 = TII->buildExtractSubRegOrImm(
7034 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
7035 MachineOperand SrcReg1Sub1 = TII->buildExtractSubRegOrImm(
7036 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
7037
7038 unsigned LoOpc =
7039 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7040 MachineInstr *LoHalf = BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0)
7041 .addReg(CarryReg, RegState::Define)
7042 .add(SrcReg0Sub0)
7043 .add(SrcReg1Sub0)
7044 .addImm(0); // clamp bit
7045
7046 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7047 MachineInstr *HiHalf =
7048 BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1)
7049 .addReg(DeadCarryReg, RegState::Define | RegState::Dead)
7050 .add(SrcReg0Sub1)
7051 .add(SrcReg1Sub1)
7052 .addReg(CarryReg, RegState::Kill)
7053 .addImm(0); // clamp bit
7054
7055 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
7056 .addReg(DestSub0)
7057 .addImm(AMDGPU::sub0)
7058 .addReg(DestSub1)
7059 .addImm(AMDGPU::sub1);
7060 TII->legalizeOperands(*LoHalf);
7061 TII->legalizeOperands(*HiHalf);
7062 MI.eraseFromParent();
7063 return BB;
7064 }
7065 case AMDGPU::S_ADD_CO_PSEUDO:
7066 case AMDGPU::S_SUB_CO_PSEUDO: {
7067 // This pseudo has a chance to be selected
7068 // only from uniform add/subcarry node. All the VGPR operands
7069 // therefore assumed to be splat vectors.
7071 MachineOperand &Dest = MI.getOperand(0);
7072 MachineOperand &CarryDest = MI.getOperand(1);
7073 MachineOperand &Src0 = MI.getOperand(2);
7074 MachineOperand &Src1 = MI.getOperand(3);
7075 MachineOperand &Src2 = MI.getOperand(4);
7076 if (Src0.isReg() && TRI->isVectorRegister(MRI, Src0.getReg())) {
7077 Register RegOp0 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7078 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7079 .addReg(Src0.getReg());
7080 Src0.setReg(RegOp0);
7081 }
7082 if (Src1.isReg() && TRI->isVectorRegister(MRI, Src1.getReg())) {
7083 Register RegOp1 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7084 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7085 .addReg(Src1.getReg());
7086 Src1.setReg(RegOp1);
7087 }
7088 Register RegOp2 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7089 if (TRI->isVectorRegister(MRI, Src2.getReg())) {
7090 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7091 .addReg(Src2.getReg());
7092 Src2.setReg(RegOp2);
7093 }
7094
7095 if (ST.isWave64()) {
7096 if (ST.hasScalarCompareEq64()) {
7097 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U64))
7098 .addReg(Src2.getReg())
7099 .addImm(0);
7100 } else {
7101 const TargetRegisterClass *Src2RC = MRI.getRegClass(Src2.getReg());
7102 const TargetRegisterClass *SubRC =
7103 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7104 MachineOperand Src2Sub0 = TII->buildExtractSubRegOrImm(
7105 MII, MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7106 MachineOperand Src2Sub1 = TII->buildExtractSubRegOrImm(
7107 MII, MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7108 Register Src2_32 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7109
7110 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_OR_B32), Src2_32)
7111 .add(Src2Sub0)
7112 .add(Src2Sub1);
7113
7114 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7115 .addReg(Src2_32, RegState::Kill)
7116 .addImm(0);
7117 }
7118 } else {
7119 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7120 .addReg(Src2.getReg())
7121 .addImm(0);
7122 }
7123
7124 unsigned Opc = MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7125 ? AMDGPU::S_ADDC_U32
7126 : AMDGPU::S_SUBB_U32;
7127
7128 BuildMI(*BB, MII, DL, TII->get(Opc), Dest.getReg()).add(Src0).add(Src1);
7129
7130 unsigned SelOpc =
7131 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7132
7133 BuildMI(*BB, MII, DL, TII->get(SelOpc), CarryDest.getReg())
7134 .addImm(-1)
7135 .addImm(0);
7136
7137 MI.eraseFromParent();
7138 return BB;
7139 }
7140 case AMDGPU::SI_INIT_M0: {
7141 MachineOperand &M0Init = MI.getOperand(0);
7142 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7143 TII->get(M0Init.isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7144 AMDGPU::M0)
7145 .add(M0Init);
7146 MI.eraseFromParent();
7147 return BB;
7148 }
7149 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7150 // Set SCC to true, in case the barrier instruction gets converted to a NOP.
7151 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7152 TII->get(AMDGPU::S_CMP_EQ_U32))
7153 .addImm(0)
7154 .addImm(0);
7155 return BB;
7156 }
7157 case AMDGPU::GET_GROUPSTATICSIZE: {
7158 assert(getTargetMachine().getTargetTriple().getOS() == Triple::AMDHSA ||
7159 getTargetMachine().getTargetTriple().getOS() == Triple::AMDPAL);
7160 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_MOV_B32))
7161 .add(MI.getOperand(0))
7162 .addImm(MFI->getLDSSize());
7163 MI.eraseFromParent();
7164 return BB;
7165 }
7166 case AMDGPU::GET_SHADERCYCLESHILO: {
7167 assert(MF->getSubtarget<GCNSubtarget>().hasShaderCyclesHiLoRegisters());
7168 // The algorithm is:
7169 //
7170 // hi1 = getreg(SHADER_CYCLES_HI)
7171 // lo1 = getreg(SHADER_CYCLES_LO)
7172 // hi2 = getreg(SHADER_CYCLES_HI)
7173 //
7174 // If hi1 == hi2 then there was no overflow and the result is hi2:lo1.
7175 // Otherwise there was overflow and the result is hi2:0. In both cases the
7176 // result should represent the actual time at some point during the sequence
7177 // of three getregs.
7178 using namespace AMDGPU::Hwreg;
7179 Register RegHi1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7180 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi1)
7181 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7182 Register RegLo1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7183 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegLo1)
7184 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7185 Register RegHi2 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7186 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi2)
7187 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7188 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CMP_EQ_U32))
7189 .addReg(RegHi1)
7190 .addReg(RegHi2);
7191 Register RegLo = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7192 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CSELECT_B32), RegLo)
7193 .addReg(RegLo1)
7194 .addImm(0);
7195 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE))
7196 .add(MI.getOperand(0))
7197 .addReg(RegLo)
7198 .addImm(AMDGPU::sub0)
7199 .addReg(RegHi2)
7200 .addImm(AMDGPU::sub1);
7201 MI.eraseFromParent();
7202 return BB;
7203 }
7204 case AMDGPU::SI_INDIRECT_SRC_V1:
7205 case AMDGPU::SI_INDIRECT_SRC_V2:
7206 case AMDGPU::SI_INDIRECT_SRC_V3:
7207 case AMDGPU::SI_INDIRECT_SRC_V4:
7208 case AMDGPU::SI_INDIRECT_SRC_V5:
7209 case AMDGPU::SI_INDIRECT_SRC_V6:
7210 case AMDGPU::SI_INDIRECT_SRC_V7:
7211 case AMDGPU::SI_INDIRECT_SRC_V8:
7212 case AMDGPU::SI_INDIRECT_SRC_V9:
7213 case AMDGPU::SI_INDIRECT_SRC_V10:
7214 case AMDGPU::SI_INDIRECT_SRC_V11:
7215 case AMDGPU::SI_INDIRECT_SRC_V12:
7216 case AMDGPU::SI_INDIRECT_SRC_V16:
7217 case AMDGPU::SI_INDIRECT_SRC_V32:
7218 return emitIndirectSrc(MI, *BB, *getSubtarget());
7219 case AMDGPU::SI_INDIRECT_DST_V1:
7220 case AMDGPU::SI_INDIRECT_DST_V2:
7221 case AMDGPU::SI_INDIRECT_DST_V3:
7222 case AMDGPU::SI_INDIRECT_DST_V4:
7223 case AMDGPU::SI_INDIRECT_DST_V5:
7224 case AMDGPU::SI_INDIRECT_DST_V6:
7225 case AMDGPU::SI_INDIRECT_DST_V7:
7226 case AMDGPU::SI_INDIRECT_DST_V8:
7227 case AMDGPU::SI_INDIRECT_DST_V9:
7228 case AMDGPU::SI_INDIRECT_DST_V10:
7229 case AMDGPU::SI_INDIRECT_DST_V11:
7230 case AMDGPU::SI_INDIRECT_DST_V12:
7231 case AMDGPU::SI_INDIRECT_DST_V16:
7232 case AMDGPU::SI_INDIRECT_DST_V32:
7233 return emitIndirectDst(MI, *BB, *getSubtarget());
7234 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7235 case AMDGPU::SI_KILL_I1_PSEUDO:
7236 return splitKillBlock(MI, BB);
7237 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7239 return BB;
7240 }
7241 case AMDGPU::SI_BR_UNDEF: {
7242 MachineInstr *Br = BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
7243 .add(MI.getOperand(0));
7244 Br->getOperand(1).setIsUndef(); // read undef SCC
7245 MI.eraseFromParent();
7246 return BB;
7247 }
7248 case AMDGPU::ADJCALLSTACKUP:
7249 case AMDGPU::ADJCALLSTACKDOWN: {
7251 MachineInstrBuilder MIB(*MF, &MI);
7252 MIB.addReg(Info->getStackPtrOffsetReg(), RegState::ImplicitDefine)
7253 .addReg(Info->getStackPtrOffsetReg(), RegState::Implicit);
7254 return BB;
7255 }
7256 case AMDGPU::SI_CALL_ISEL: {
7257 unsigned ReturnAddrReg = TII->getRegisterInfo().getReturnAddressReg(*MF);
7258
7260 MIB = BuildMI(*BB, MI, DL, TII->get(AMDGPU::SI_CALL), ReturnAddrReg);
7261
7262 for (const MachineOperand &MO : MI.operands())
7263 MIB.add(MO);
7264
7265 MIB.cloneMemRefs(MI);
7266 MI.eraseFromParent();
7267 return BB;
7268 }
7269 case AMDGPU::V_ADD_CO_U32_e32:
7270 case AMDGPU::V_SUB_CO_U32_e32:
7271 case AMDGPU::V_SUBREV_CO_U32_e32: {
7272 // TODO: Define distinct V_*_I32_Pseudo instructions instead.
7273 unsigned Opc = MI.getOpcode();
7274
7275 bool NeedClampOperand = false;
7276 if (TII->pseudoToMCOpcode(Opc) == -1) {
7278 NeedClampOperand = true;
7279 }
7280
7281 auto I = BuildMI(*BB, MI, DL, TII->get(Opc), MI.getOperand(0).getReg());
7282 if (TII->isVOP3(*I)) {
7283 I.addReg(TRI->getVCC(), RegState::Define);
7284 }
7285 I.add(MI.getOperand(1)).add(MI.getOperand(2));
7286 if (NeedClampOperand)
7287 I.addImm(0); // clamp bit for e64 encoding
7288
7289 TII->legalizeOperands(*I);
7290
7291 MI.eraseFromParent();
7292 return BB;
7293 }
7294 case AMDGPU::V_ADDC_U32_e32:
7295 case AMDGPU::V_SUBB_U32_e32:
7296 case AMDGPU::V_SUBBREV_U32_e32:
7297 // These instructions have an implicit use of vcc which counts towards the
7298 // constant bus limit.
7299 TII->legalizeOperands(MI);
7300 return BB;
7301 case AMDGPU::DS_GWS_INIT:
7302 case AMDGPU::DS_GWS_SEMA_BR:
7303 case AMDGPU::DS_GWS_BARRIER:
7304 case AMDGPU::DS_GWS_SEMA_V:
7305 case AMDGPU::DS_GWS_SEMA_P:
7306 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7307 // A s_waitcnt 0 is required to be the instruction immediately following.
7308 if (getSubtarget()->hasGWSAutoReplay()) {
7310 return BB;
7311 }
7312
7313 return emitGWSMemViolTestLoop(MI, BB);
7314 case AMDGPU::S_SETREG_B32: {
7315 // Try to optimize cases that only set the denormal mode or rounding mode.
7316 //
7317 // If the s_setreg_b32 fully sets all of the bits in the rounding mode or
7318 // denormal mode to a constant, we can use s_round_mode or s_denorm_mode
7319 // instead.
7320 //
7321 // FIXME: This could be predicates on the immediate, but tablegen doesn't
7322 // allow you to have a no side effect instruction in the output of a
7323 // sideeffecting pattern.
7324 auto [ID, Offset, Width] =
7325 AMDGPU::Hwreg::HwregEncoding::decode(MI.getOperand(1).getImm());
7326 if (ID != AMDGPU::Hwreg::ID_MODE)
7327 return BB;
7328
7329 const unsigned WidthMask = maskTrailingOnes<unsigned>(Width);
7330 const unsigned SetMask = WidthMask << Offset;
7331
7332 if (getSubtarget()->hasDenormModeInst()) {
7333 unsigned SetDenormOp = 0;
7334 unsigned SetRoundOp = 0;
7335
7336 // The dedicated instructions can only set the whole denorm or round mode
7337 // at once, not a subset of bits in either.
7338 if (SetMask ==
7340 // If this fully sets both the round and denorm mode, emit the two
7341 // dedicated instructions for these.
7342 SetRoundOp = AMDGPU::S_ROUND_MODE;
7343 SetDenormOp = AMDGPU::S_DENORM_MODE;
7344 } else if (SetMask == AMDGPU::Hwreg::FP_ROUND_MASK) {
7345 SetRoundOp = AMDGPU::S_ROUND_MODE;
7346 } else if (SetMask == AMDGPU::Hwreg::FP_DENORM_MASK) {
7347 SetDenormOp = AMDGPU::S_DENORM_MODE;
7348 }
7349
7350 if (SetRoundOp || SetDenormOp) {
7351 MachineInstr *Def = MRI.getVRegDef(MI.getOperand(0).getReg());
7352 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7353 unsigned ImmVal = Def->getOperand(1).getImm();
7354 if (SetRoundOp) {
7355 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetRoundOp))
7356 .addImm(ImmVal & 0xf);
7357
7358 // If we also have the denorm mode, get just the denorm mode bits.
7359 ImmVal >>= 4;
7360 }
7361
7362 if (SetDenormOp) {
7363 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetDenormOp))
7364 .addImm(ImmVal & 0xf);
7365 }
7366
7367 MI.eraseFromParent();
7368 return BB;
7369 }
7370 }
7371 }
7372
7373 // If only FP bits are touched, used the no side effects pseudo.
7374 if ((SetMask & (AMDGPU::Hwreg::FP_ROUND_MASK |
7375 AMDGPU::Hwreg::FP_DENORM_MASK)) == SetMask)
7376 MI.setDesc(TII->get(AMDGPU::S_SETREG_B32_mode));
7377
7378 return BB;
7379 }
7380 case AMDGPU::S_INVERSE_BALLOT_U32:
7381 case AMDGPU::S_INVERSE_BALLOT_U64:
7382 // These opcodes only exist to let SIFixSGPRCopies insert a readfirstlane if
7383 // necessary. After that they are equivalent to a COPY.
7384 MI.setDesc(TII->get(AMDGPU::COPY));
7385 return BB;
7386 case AMDGPU::ENDPGM_TRAP: {
7387 if (BB->succ_empty() && std::next(MI.getIterator()) == BB->end()) {
7388 MI.setDesc(TII->get(AMDGPU::S_ENDPGM));
7389 MI.addOperand(MachineOperand::CreateImm(0));
7390 return BB;
7391 }
7392
7393 // We need a block split to make the real endpgm a terminator. We also don't
7394 // want to break phis in successor blocks, so we can't just delete to the
7395 // end of the block.
7396
7397 MachineBasicBlock *SplitBB = BB->splitAt(MI, false /*UpdateLiveIns*/);
7399 MF->push_back(TrapBB);
7400 // clang-format off
7401 BuildMI(*TrapBB, TrapBB->end(), DL, TII->get(AMDGPU::S_ENDPGM))
7402 .addImm(0);
7403 BuildMI(*BB, &MI, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
7404 .addMBB(TrapBB);
7405 // clang-format on
7406
7407 BB->addSuccessor(TrapBB);
7408 MI.eraseFromParent();
7409 return SplitBB;
7410 }
7411 case AMDGPU::SIMULATED_TRAP: {
7412 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7413 MachineBasicBlock *SplitBB =
7414 TII->insertSimulatedTrap(MRI, *BB, MI, MI.getDebugLoc());
7415 MI.eraseFromParent();
7416 return SplitBB;
7417 }
7418 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7419 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7421
7422 // During ISel, it's difficult to propagate the original EXEC mask to use as
7423 // an input to SI_WHOLE_WAVE_FUNC_RETURN. Set it up here instead.
7424 MachineInstr *Setup = TII->getWholeWaveFunctionSetup(*BB->getParent());
7425 assert(Setup && "Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7426 Register OriginalExec = Setup->getOperand(0).getReg();
7427 MF->getRegInfo().clearKillFlags(OriginalExec);
7428 MI.getOperand(0).setReg(OriginalExec);
7429 return BB;
7430 }
7431 case AMDGPU::V_DOT2_F32_F16:
7432 case AMDGPU::V_DOT2_F32_BF16: {
7433 // Hint RA to assign dst and src2 the same physical register.
7434 // For targets without VOP2, but with VOPD, variant of the instruction this
7435 // is one of the conditions to attempt converting VOP3P to VOPD.
7436 MRI.setSimpleHint(MI.getOperand(0).getReg(), MI.getOperand(6).getReg());
7437 return BB;
7438 }
7439 default:
7440 if (TII->isImage(MI) || TII->isMUBUF(MI)) {
7441 if (!MI.mayStore())
7443 return BB;
7444 }
7446 }
7447}
7448
7450 // This currently forces unfolding various combinations of fsub into fma with
7451 // free fneg'd operands. As long as we have fast FMA (controlled by
7452 // isFMAFasterThanFMulAndFAdd), we should perform these.
7453
7454 // When fma is quarter rate, for f64 where add / sub are at best half rate,
7455 // most of these combines appear to be cycle neutral but save on instruction
7456 // count / code size.
7457 return true;
7458}
7459
7461
7463 EVT VT) const {
7464 if (!VT.isVector()) {
7465 return MVT::i1;
7466 }
7467 return EVT::getVectorVT(Ctx, MVT::i1, VT.getVectorNumElements());
7468}
7469
7471 // TODO: Should i16 be used always if legal? For now it would force VALU
7472 // shifts.
7473 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7474}
7475
7477 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7478 ? Ty.changeElementSize(16)
7479 : Ty.changeElementSize(32);
7480}
7481
7482// Answering this is somewhat tricky and depends on the specific device which
7483// have different rates for fma or all f64 operations.
7484//
7485// v_fma_f64 and v_mul_f64 always take the same number of cycles as each other
7486// regardless of which device (although the number of cycles differs between
7487// devices), so it is always profitable for f64.
7488//
7489// v_fma_f32 takes 4 or 16 cycles depending on the device, so it is profitable
7490// only on full rate devices. Normally, we should prefer selecting v_mad_f32
7491// which we can always do even without fused FP ops since it returns the same
7492// result as the separate operations and since it is always full
7493// rate. Therefore, we lie and report that it is not faster for f32. v_mad_f32
7494// however does not support denormals, so we do report fma as faster if we have
7495// a fast fma device and require denormals.
7496//
7498 DenormalFPEnv FPEnv) const {
7499 VT = VT.getScalarType();
7500 if (!VT.isSimple())
7501 return false;
7502
7503 switch (VT.getSimpleVT().SimpleTy) {
7504 case MVT::f32: {
7505 // If mad is not available this depends only on if f32 fma is full rate.
7506 if (!Subtarget->hasMadMacF32Insts())
7507 return Subtarget->hasFastFMAF32();
7508
7509 // Otherwise f32 mad is always full rate and returns the same result as
7510 // the separate operations so should be preferred over fma.
7511 // However does not support denormals.
7513 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7514
7515 // If the subtarget has v_fmac_f32, that's just as good as v_mac_f32.
7516 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7517 }
7518 case MVT::f64:
7519 return true;
7520 case MVT::f16:
7521 case MVT::bf16:
7522 return Subtarget->has16BitInsts() &&
7524 default:
7525 break;
7526 }
7527
7528 return false;
7529}
7530
7535
7537 Type *Ty) const {
7539 getValueType(F.getDataLayout(), Ty, /*AllowUnknown=*/true),
7540 F.getDenormalFPEnv());
7541}
7542
7544 LLT Ty) const {
7545 switch (Ty.getScalarSizeInBits()) {
7546 case 16:
7547 return isFMAFasterThanFMulAndFAdd(MF, MVT::f16);
7548 case 32:
7549 return isFMAFasterThanFMulAndFAdd(MF, MVT::f32);
7550 case 64:
7551 return isFMAFasterThanFMulAndFAdd(MF, MVT::f64);
7552 default:
7553 break;
7554 }
7555
7556 return false;
7557}
7558
7560 // TODO: Check future ftz flag
7561 // v_mad_f32/v_mac_f32 do not support denormals.
7562 if (VT == MVT::f32)
7563 return Subtarget->hasMadMacF32Insts() &&
7565 if (VT == MVT::f16)
7566 return Subtarget->hasMadF16() &&
7568
7569 return false;
7570}
7571
7573 if (!Ty.isScalar())
7574 return false;
7575
7576 DenormalFPEnv FPEnv = getDenormalFPEnv(*MI.getMF());
7577 if (Ty.getScalarSizeInBits() == 16)
7578 return isFMADLegal(MVT::f16, FPEnv);
7579 if (Ty.getScalarSizeInBits() == 32)
7580 return isFMADLegal(MVT::f32, FPEnv);
7581
7582 return false;
7583}
7584
7586 const SDNode *N) const {
7587 return isFMADLegal(N->getValueType(0),
7589}
7590
7592 return isFMADLegal(getValueType(F.getDataLayout(), Ty->getScalarType(),
7593 /*AllowUnknown=*/true),
7594 F.getDenormalFPEnv());
7595}
7596
7597//===----------------------------------------------------------------------===//
7598// Custom DAG Lowering Operations
7599//===----------------------------------------------------------------------===//
7600
7601// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7602// wider vector type is legal.
7604 SelectionDAG &DAG) const {
7605 unsigned Opc = Op.getOpcode();
7606 EVT VT = Op.getValueType();
7608
7609 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
7610 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VT);
7611
7612 SDLoc SL(Op);
7613
7614 // Forward any trailing scalar operands unchanged to both halves.
7615 SmallVector<SDValue, 2> LoOps = {Lo};
7616 SmallVector<SDValue, 2> HiOps = {Hi};
7617 auto TrailingOps = drop_begin(Op->ops());
7618 LoOps.append(TrailingOps.begin(), TrailingOps.end());
7619 HiOps.append(TrailingOps.begin(), TrailingOps.end());
7620
7621 SDValue OpLo = DAG.getNode(Opc, SL, LoVT, LoOps, Op->getFlags());
7622 SDValue OpHi = DAG.getNode(Opc, SL, HiVT, HiOps, Op->getFlags());
7623
7624 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7625}
7626
7627// Enable lowering of ROTR for vxi32 types. This is a workaround for a
7628// regression whereby extra unnecessary instructions were added to codegen
7629// for rotr operations, casued by legalising v2i32 or. This resulted in extra
7630// instructions to extract the result from the vector.
7632 [[maybe_unused]] EVT VT = Op.getValueType();
7633
7634 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7635 VT == MVT::v16i32) &&
7636 "Unexpected ValueType.");
7637
7638 return DAG.UnrollVectorOp(Op.getNode());
7639}
7640
7641// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7642// wider vector type is legal.
7644 SelectionDAG &DAG) const {
7645 unsigned Opc = Op.getOpcode();
7646 EVT VT = Op.getValueType();
7648
7649 auto [Lo0, Hi0] = DAG.SplitVectorOperand(Op.getNode(), 0);
7650 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7651
7652 SDLoc SL(Op);
7653
7654 SDValue OpLo =
7655 DAG.getNode(Opc, SL, Lo0.getValueType(), Lo0, Lo1, Op->getFlags());
7656 SDValue OpHi =
7657 DAG.getNode(Opc, SL, Hi0.getValueType(), Hi0, Hi1, Op->getFlags());
7658
7659 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7660}
7661
7663 SelectionDAG &DAG) const {
7664 unsigned Opc = Op.getOpcode();
7665 EVT VT = Op.getValueType();
7667
7668 SDValue Op0 = Op.getOperand(0);
7669 SDValue Lo0, Hi0;
7670 if (Op0.getValueType().isVector())
7671 std::tie(Lo0, Hi0) = DAG.SplitVectorOperand(Op.getNode(), 0);
7672 else
7673 Lo0 = Hi0 = DAG.getFreeze(Op0);
7674
7675 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7676 auto [Lo2, Hi2] = DAG.SplitVectorOperand(Op.getNode(), 2);
7677
7678 SDLoc SL(Op);
7679 auto ResVT = DAG.GetSplitDestVTs(VT);
7680
7681 SDValue OpLo =
7682 DAG.getNode(Opc, SL, ResVT.first, Lo0, Lo1, Lo2, Op->getFlags());
7683 SDValue OpHi =
7684 DAG.getNode(Opc, SL, ResVT.second, Hi0, Hi1, Hi2, Op->getFlags());
7685
7686 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7687}
7688
7690 switch (Op.getOpcode()) {
7691 default:
7693 case ISD::BRCOND:
7694 return LowerBRCOND(Op, DAG);
7695 case ISD::RETURNADDR:
7696 return LowerRETURNADDR(Op, DAG);
7697 case ISD::SPONENTRY:
7698 return LowerSPONENTRY(Op, DAG);
7699 case ISD::LOAD: {
7700 SDValue Result = LowerLOAD(Op, DAG);
7701 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7702 "Load should return a value and a chain");
7703 return Result;
7704 }
7705 case ISD::FSQRT: {
7706 EVT VT = Op.getValueType();
7707 if (VT == MVT::f32)
7708 return lowerFSQRTF32(Op, DAG);
7709 if (VT == MVT::f64)
7710 return lowerFSQRTF64(Op, DAG);
7711 return SDValue();
7712 }
7713 case ISD::FSIN:
7714 case ISD::FCOS:
7715 return LowerTrig(Op, DAG);
7716 case ISD::SELECT:
7717 return LowerSELECT(Op, DAG);
7718 case ISD::FDIV:
7719 return LowerFDIV(Op, DAG);
7720 case ISD::FFREXP:
7721 return LowerFFREXP(Op, DAG);
7723 return LowerATOMIC_CMP_SWAP(Op, DAG);
7724 case ISD::STORE:
7725 return LowerSTORE(Op, DAG);
7726 case ISD::GlobalAddress: {
7729 return LowerGlobalAddress(MFI, Op, DAG);
7730 }
7731 case ISD::BlockAddress:
7732 return LowerBlockAddress(Op, DAG);
7734 return LowerExternalSymbol(Op, DAG);
7736 return LowerINTRINSIC_WO_CHAIN(Op, DAG);
7738 return LowerCONVERT_FROM_ARBITRARY_FP(Op, DAG);
7740 return LowerCONVERT_TO_ARBITRARY_FP(Op, DAG);
7742 return LowerINTRINSIC_W_CHAIN(Op, DAG);
7744 return LowerINTRINSIC_VOID(Op, DAG);
7745 case ISD::ADDRSPACECAST:
7746 return lowerADDRSPACECAST(Op, DAG);
7748 return lowerINSERT_SUBVECTOR(Op, DAG);
7750 return lowerINSERT_VECTOR_ELT(Op, DAG);
7752 return lowerEXTRACT_VECTOR_ELT(Op, DAG);
7754 return lowerVECTOR_SHUFFLE(Op, DAG);
7756 return lowerSCALAR_TO_VECTOR(Op, DAG);
7757 case ISD::BUILD_VECTOR:
7758 return lowerBUILD_VECTOR(Op, DAG);
7759 case ISD::FP_ROUND:
7761 return lowerFP_ROUND(Op, DAG);
7762 case ISD::TRAP:
7763 return lowerTRAP(Op, DAG);
7764 case ISD::DEBUGTRAP:
7765 return lowerDEBUGTRAP(Op, DAG);
7766 case ISD::ABS:
7767 case ISD::FABS:
7768 case ISD::FNEG:
7769 case ISD::FCANONICALIZE:
7770 case ISD::BSWAP:
7771 return splitUnaryVectorOp(Op, DAG);
7774 if (Op.getValueType().isVector() && Op.getValueType() != MVT::v2i16 &&
7775 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7776 return splitUnaryVectorOp(Op, DAG);
7777 return LowerFP_TO_INT_SAT(Op, DAG);
7778 case ISD::FSUB:
7779 if (Op.getValueType() == MVT::bf16) {
7780 // Custom expansion:
7781 // fsub bf16 %a, %b -> fadd v2bf16(widen %a), fneg v2bf16(widen %b)
7782 // Then extract back to bf16.
7783 //
7784 // We create fneg on v2bf16 (not bf16) so the instruction selector can
7785 // fold the negation into the packed add's neg_lo/neg_hi modifiers,
7786 // generating a single v_pk_add_bf16 instruction. If we negate bf16 first,
7787 // it becomes a separate v_xor instruction before widening.
7788 SDLoc DL(Op);
7789 SDValue Op0 = Op.getOperand(0);
7790 SDValue Op1 = Op.getOperand(1);
7791
7792 // Widen both operands to v2bf16
7793 SDValue Vec0 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op0);
7794 SDValue Vec1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op1);
7795
7796 // Create FNEG v2bf16 for the second operand
7797 SDValue NegVec1 = DAG.getNode(ISD::FNEG, DL, MVT::v2bf16, Vec1);
7798
7799 // Perform FADD v2bf16
7800 SDValue Result = DAG.getNode(ISD::FADD, DL, MVT::v2bf16, Vec0, NegVec1);
7801
7802 // Extract element 0 back to bf16
7803 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::bf16, Result,
7804 DAG.getConstant(0, DL, MVT::i32));
7805 }
7806 return SDValue();
7807 case ISD::FMINNUM:
7808 case ISD::FMAXNUM:
7809 return lowerFMINNUM_FMAXNUM(Op, DAG);
7810 case ISD::FMINIMUMNUM:
7811 case ISD::FMAXIMUMNUM:
7812 return lowerFMINIMUMNUM_FMAXIMUMNUM(Op, DAG);
7813 case ISD::FLDEXP:
7814 case ISD::STRICT_FLDEXP:
7815 return lowerFLDEXP(Op, DAG);
7816 case ISD::FMA:
7817 return splitTernaryVectorOp(Op, DAG);
7818 case ISD::FP_TO_SINT:
7819 case ISD::FP_TO_UINT:
7820 if (Subtarget->hasVCvtPkIU16F32() && Op.getValueType() == MVT::i16 &&
7821 Op.getOperand(0).getValueType() == MVT::f32) {
7822 // Make f32->i16 legal so we can select V_CVT_PK_[IU]16_F32.
7823 return Op;
7824 }
7825 return LowerFP_TO_INT(Op, DAG);
7826 case ISD::SHL:
7827 case ISD::SRA:
7828 case ISD::SRL:
7829 case ISD::ADD:
7830 case ISD::SUB:
7831 case ISD::SMIN:
7832 case ISD::SMAX:
7833 case ISD::UMIN:
7834 case ISD::UMAX:
7835 case ISD::FMINNUM_IEEE:
7836 case ISD::FMAXNUM_IEEE:
7837 case ISD::FMINIMUM:
7838 case ISD::FMAXIMUM:
7839 case ISD::UADDSAT:
7840 case ISD::USUBSAT:
7841 case ISD::SADDSAT:
7842 case ISD::SSUBSAT:
7843 case ISD::FADD:
7844 case ISD::FMUL:
7845 return splitBinaryVectorOp(Op, DAG);
7846 case ISD::FCOPYSIGN:
7847 return lowerFCOPYSIGN(Op, DAG);
7848 case ISD::MUL:
7849 return lowerMUL(Op, DAG);
7850 case ISD::SMULO:
7851 case ISD::UMULO:
7852 return lowerXMULO(Op, DAG);
7853 case ISD::SMUL_LOHI:
7854 case ISD::UMUL_LOHI:
7855 return lowerXMUL_LOHI(Op, DAG);
7857 return LowerDYNAMIC_STACKALLOC(Op, DAG);
7858 case ISD::STACKSAVE:
7859 return LowerSTACKSAVE(Op, DAG);
7860 case ISD::GET_ROUNDING:
7861 return lowerGET_ROUNDING(Op, DAG);
7862 case ISD::SET_ROUNDING:
7863 return lowerSET_ROUNDING(Op, DAG);
7864 case ISD::PREFETCH:
7865 return lowerPREFETCH(Op, DAG);
7866 case ISD::FP_EXTEND:
7868 return lowerFP_EXTEND(Op, DAG);
7869 case ISD::GET_FPENV:
7870 return lowerGET_FPENV(Op, DAG);
7871 case ISD::SET_FPENV:
7872 return lowerSET_FPENV(Op, DAG);
7873 case ISD::ROTR:
7874 return lowerROTR(Op, DAG);
7875 case ISD::INLINEASM:
7876 return LowerINLINEASM(Op, DAG);
7877 }
7878 return SDValue();
7879}
7880
7881// Used for D16: Casts the result of an instruction into the right vector,
7882// packs values if loads return unpacked values.
7884 const SDLoc &DL, SelectionDAG &DAG,
7885 bool Unpacked) {
7886 if (!LoadVT.isVector())
7887 return Result;
7888
7889 // Cast back to the original packed type or to a larger type that is a
7890 // multiple of 32 bit for D16. Widening the return type is a required for
7891 // legalization.
7892 EVT FittingLoadVT = LoadVT;
7893 if ((LoadVT.getVectorNumElements() % 2) == 1) {
7894 FittingLoadVT =
7896 LoadVT.getVectorNumElements() + 1);
7897 }
7898
7899 if (Unpacked) { // From v2i32/v4i32 back to v2f16/v4f16.
7900 // Truncate to v2i16/v4i16.
7901 EVT IntLoadVT = FittingLoadVT.changeTypeToInteger();
7902
7903 // Workaround legalizer not scalarizing truncate after vector op
7904 // legalization but not creating intermediate vector trunc.
7906 DAG.ExtractVectorElements(Result, Elts);
7907 for (SDValue &Elt : Elts)
7908 Elt = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Elt);
7909
7910 // Pad illegal v1i16/v3fi6 to v4i16
7911 if ((LoadVT.getVectorNumElements() % 2) == 1)
7912 Elts.push_back(DAG.getPOISON(MVT::i16));
7913
7914 Result = DAG.getBuildVector(IntLoadVT, DL, Elts);
7915
7916 // Bitcast to original type (v2f16/v4f16).
7917 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
7918 }
7919
7920 // Cast back to the original packed type.
7921 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
7922}
7923
7924SDValue SITargetLowering::adjustLoadValueType(unsigned Opcode, MemSDNode *M,
7925 SelectionDAG &DAG,
7927 bool IsIntrinsic) const {
7928 SDLoc DL(M);
7929
7930 bool Unpacked = Subtarget->hasUnpackedD16VMem();
7931 EVT LoadVT = M->getValueType(0);
7932
7933 EVT EquivLoadVT = LoadVT;
7934 if (LoadVT.isVector()) {
7935 if (Unpacked) {
7936 EquivLoadVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
7937 LoadVT.getVectorNumElements());
7938 } else if ((LoadVT.getVectorNumElements() % 2) == 1) {
7939 // Widen v3f16 to legal type
7940 EquivLoadVT =
7942 LoadVT.getVectorNumElements() + 1);
7943 }
7944 }
7945
7946 // Change from v4f16/v2f16 to EquivLoadVT.
7947 SDVTList VTList = DAG.getVTList(EquivLoadVT, MVT::Other);
7948
7950 IsIntrinsic ? (unsigned)ISD::INTRINSIC_W_CHAIN : Opcode, DL, VTList, Ops,
7951 M->getMemoryVT(), M->getMemOperand());
7952
7953 SDValue Adjusted = adjustLoadValueTypeImpl(Load, LoadVT, DL, DAG, Unpacked);
7954
7955 return DAG.getMergeValues({Adjusted, Load.getValue(1)}, DL);
7956}
7957
7958SDValue SITargetLowering::lowerIntrinsicLoad(MemSDNode *M, bool IsFormat,
7959 SelectionDAG &DAG,
7960 ArrayRef<SDValue> Ops) const {
7961 SDLoc DL(M);
7962 EVT LoadVT = M->getValueType(0);
7963 EVT EltType = LoadVT.getScalarType();
7964 EVT IntVT = LoadVT.changeTypeToInteger();
7965
7966 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
7967
7968 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
7969 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
7971 "unsupported sub-dword format buffer load", DL.getDebugLoc()));
7972 return DAG.getMergeValues({DAG.getPOISON(LoadVT), M->getOperand(0)}, DL);
7973 }
7974
7975 assert(M->getNumValues() == 2 || M->getNumValues() == 3);
7976 bool IsTFE = M->getNumValues() == 3;
7977
7978 unsigned Opc = IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
7979 : AMDGPUISD::BUFFER_LOAD_FORMAT)
7980 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
7981 : AMDGPUISD::BUFFER_LOAD;
7982
7983 if (IsD16) {
7984 return adjustLoadValueType(AMDGPUISD::BUFFER_LOAD_FORMAT_D16, M, DAG, Ops);
7985 }
7986
7987 // Handle BUFFER_LOAD_BYTE/UBYTE/SHORT/USHORT overloaded intrinsics
7988 if (!IsD16 && !LoadVT.isVector() && EltType.getSizeInBits() < 32)
7989 return handleByteShortBufferLoads(DAG, LoadVT, DL, Ops, M->getMemOperand(),
7990 IsTFE);
7991
7992 if (isTypeLegal(LoadVT)) {
7993 return getMemIntrinsicNode(Opc, DL, M->getVTList(), Ops, IntVT,
7994 M->getMemOperand(), DAG);
7995 }
7996
7997 EVT CastVT = getEquivalentMemType(*DAG.getContext(), LoadVT);
7998 SDVTList VTList = DAG.getVTList(CastVT, MVT::Other);
7999 SDValue MemNode = getMemIntrinsicNode(Opc, DL, VTList, Ops, CastVT,
8000 M->getMemOperand(), DAG);
8001 return DAG.getMergeValues(
8002 {DAG.getNode(ISD::BITCAST, DL, LoadVT, MemNode), MemNode.getValue(1)},
8003 DL);
8004}
8005
8007 SelectionDAG &DAG) {
8008 EVT VT = N->getValueType(0);
8009 SDValue Src = N->getOperand(1);
8010 SDLoc SL(N);
8011
8012 if (Src.getOpcode() == ISD::SETCC) {
8013 SDValue Op0 = Src.getOperand(0);
8014 SDValue Op1 = Src.getOperand(1);
8015 // Need to expand bfloat to float for comparison (setcc).
8016 if (Op0.getValueType() == MVT::bf16) {
8017 Op0 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op0);
8018 Op1 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op1);
8019 }
8020 // (ballot (ISD::SETCC ...)) -> (AMDGPUISD::SETCC ...)
8021 return DAG.getNode(AMDGPUISD::SETCC, SL, VT, Op0, Op1, Src.getOperand(2));
8022 }
8023 if (const ConstantSDNode *Arg = dyn_cast<ConstantSDNode>(Src)) {
8024 // (ballot 0) -> 0
8025 if (Arg->isZero())
8026 return DAG.getConstant(0, SL, VT);
8027
8028 // (ballot 1) -> EXEC/EXEC_LO
8029 if (Arg->isOne()) {
8030 Register Exec;
8031 if (VT.getScalarSizeInBits() == 32)
8032 Exec = AMDGPU::EXEC_LO;
8033 else if (VT.getScalarSizeInBits() == 64)
8034 Exec = AMDGPU::EXEC;
8035 else
8036 return SDValue();
8037
8038 return DAG.getCopyFromReg(DAG.getEntryNode(), SL, Exec, VT);
8039 }
8040 }
8041
8042 // (ballot (i1 $src)) -> (AMDGPUISD::SETCC (i32 (zext $src)) (i32 0)
8043 // ISD::SETNE)
8044 return DAG.getNode(
8045 AMDGPUISD::SETCC, SL, VT, DAG.getZExtOrTrunc(Src, SL, MVT::i32),
8046 DAG.getConstant(0, SL, MVT::i32), DAG.getCondCode(ISD::SETNE));
8047}
8048
8050 Intrinsic::ID IntrinsicID) {
8051 bool Signed = IntrinsicID == Intrinsic::amdgcn_sbfe;
8052 SDLoc DL(Op);
8053 EVT VT = Op.getValueType();
8054 SDValue Src = Op.getOperand(1);
8055 SDValue Offset = Op.getOperand(2);
8056 SDValue Width = Op.getOperand(3);
8057
8058 if (VT != MVT::i32) {
8061 Twine(Intrinsic::getBaseName(IntrinsicID)) + " only supports i32",
8062 DL.getDebugLoc()));
8063 return DAG.getPOISON(VT);
8064 }
8065
8066 return DAG.getNode(Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32, DL, VT,
8067 Src, Offset, Width);
8068}
8069
8071 EVT VT);
8072
8074 SelectionDAG &DAG) {
8075 EVT VT = N->getValueType(0);
8076 unsigned ValSize = VT.getSizeInBits();
8077 unsigned IID = N->getConstantOperandVal(0);
8078 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8079 IID == Intrinsic::amdgcn_permlanex16;
8080 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8081 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8082 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8083 IID == Intrinsic::amdgcn_permlane_up ||
8084 IID == Intrinsic::amdgcn_permlane_down ||
8085 IID == Intrinsic::amdgcn_permlane_xor;
8086 SDLoc SL(N);
8087 MVT IntVT = MVT::getIntegerVT(ValSize);
8088 const GCNSubtarget *ST = TLI.getSubtarget();
8089
8090 unsigned SplitSize = 32;
8091 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8092 ST->hasDPALU_DPP() &&
8093 AMDGPU::isLegalDPALU_DPPControl(*ST, N->getConstantOperandVal(3)))
8094 SplitSize = 64;
8095
8096 auto createLaneOp = [&DAG, &SL, N, IID](SDValue Src0, SDValue Src1,
8097 SDValue Src2, MVT ValT) -> SDValue {
8099 switch (IID) {
8100 case Intrinsic::amdgcn_permlane16:
8101 case Intrinsic::amdgcn_permlanex16:
8102 case Intrinsic::amdgcn_update_dpp:
8103 Operands.push_back(N->getOperand(6));
8104 Operands.push_back(N->getOperand(5));
8105 Operands.push_back(N->getOperand(4));
8106 [[fallthrough]];
8107 case Intrinsic::amdgcn_writelane:
8108 case Intrinsic::amdgcn_permlane_bcast:
8109 case Intrinsic::amdgcn_permlane_up:
8110 case Intrinsic::amdgcn_permlane_down:
8111 case Intrinsic::amdgcn_permlane_xor:
8112 Operands.push_back(Src2);
8113 [[fallthrough]];
8114 case Intrinsic::amdgcn_readlane:
8115 case Intrinsic::amdgcn_set_inactive:
8116 case Intrinsic::amdgcn_set_inactive_chain_arg:
8117 case Intrinsic::amdgcn_mov_dpp8:
8118 Operands.push_back(Src1);
8119 [[fallthrough]];
8120 case Intrinsic::amdgcn_readfirstlane:
8121 case Intrinsic::amdgcn_permlane64:
8122 Operands.push_back(Src0);
8123 break;
8124 default:
8125 llvm_unreachable("unhandled lane op");
8126 }
8127
8128 Operands.push_back(DAG.getTargetConstant(IID, SL, MVT::i32));
8129 std::reverse(Operands.begin(), Operands.end());
8130
8131 if (SDNode *GL = N->getGluedNode()) {
8132 assert(GL->getOpcode() == ISD::CONVERGENCECTRL_GLUE);
8133 GL = GL->getOperand(0).getNode();
8134 Operands.push_back(DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8135 SDValue(GL, 0)));
8136 }
8137
8138 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, ValT, Operands);
8139 };
8140
8141 SDValue Src0 = N->getOperand(1);
8142 SDValue Src1, Src2;
8143 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8144 IID == Intrinsic::amdgcn_mov_dpp8 ||
8145 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8146 IsPermlaneShuffle) {
8147 Src1 = N->getOperand(2);
8148 if (IID == Intrinsic::amdgcn_writelane ||
8149 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8150 IsPermlaneShuffle)
8151 Src2 = N->getOperand(3);
8152 }
8153
8154 if (ValSize == SplitSize) {
8155 // Already legal
8156 return SDValue();
8157 }
8158
8159 if (ValSize < 32) {
8160 bool IsFloat = VT.isFloatingPoint();
8161 Src0 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src0) : Src0,
8162 SL, MVT::i32);
8163
8164 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8165 Src1 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src1) : Src1,
8166 SL, MVT::i32);
8167 }
8168
8169 if (IID == Intrinsic::amdgcn_writelane) {
8170 Src2 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src2) : Src2,
8171 SL, MVT::i32);
8172 }
8173
8174 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8175 SDValue Trunc = DAG.getAnyExtOrTrunc(LaneOp, SL, IntVT);
8176 return IsFloat ? DAG.getBitcast(VT, Trunc) : Trunc;
8177 }
8178
8179 if (ValSize % SplitSize != 0)
8180 return SDValue();
8181
8182 auto unrollLaneOp = [&DAG, &SL](SDNode *N) -> SDValue {
8183 EVT VT = N->getValueType(0);
8184 unsigned NE = VT.getVectorNumElements();
8185 EVT EltVT = VT.getVectorElementType();
8187 unsigned NumOperands = N->getNumOperands();
8188 SmallVector<SDValue, 4> Operands(NumOperands);
8189 SDNode *GL = N->getGluedNode();
8190
8191 // only handle convergencectrl_glue
8193
8194 for (unsigned i = 0; i != NE; ++i) {
8195 for (unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8196 ++j) {
8197 SDValue Operand = N->getOperand(j);
8198 EVT OperandVT = Operand.getValueType();
8199 if (OperandVT.isVector()) {
8200 // A vector operand; extract a single element.
8201 EVT OperandEltVT = OperandVT.getVectorElementType();
8202 Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, OperandEltVT,
8203 Operand, DAG.getVectorIdxConstant(i, SL));
8204 } else {
8205 // A scalar operand; just use it as is.
8206 Operands[j] = Operand;
8207 }
8208 }
8209
8210 if (GL)
8211 Operands[NumOperands - 1] =
8212 DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8213 SDValue(GL->getOperand(0).getNode(), 0));
8214
8215 Scalars.push_back(DAG.getNode(N->getOpcode(), SL, EltVT, Operands));
8216 }
8217
8218 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NE);
8219 return DAG.getBuildVector(VecVT, SL, Scalars);
8220 };
8221
8222 if (VT.isVector()) {
8223 switch (MVT::SimpleValueType EltTy =
8225 case MVT::i32:
8226 case MVT::f32:
8227 if (SplitSize == 32) {
8228 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VT.getSimpleVT());
8229 return unrollLaneOp(LaneOp.getNode());
8230 }
8231 [[fallthrough]];
8232 case MVT::i16:
8233 case MVT::f16:
8234 case MVT::bf16: {
8235 unsigned SubVecNumElt =
8236 SplitSize / VT.getVectorElementType().getSizeInBits();
8237 MVT SubVecVT = MVT::getVectorVT(EltTy, SubVecNumElt);
8239 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8240 for (unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8241 Src0SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src0,
8242 DAG.getConstant(EltIdx, SL, MVT::i32));
8243
8244 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8245 IsPermLane16) {
8246 Src1SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src1,
8247 DAG.getConstant(EltIdx, SL, MVT::i32));
8248
8249 Pieces.push_back(
8250 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8251 } else if (IID == Intrinsic::amdgcn_writelane) {
8252 Src2SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src2,
8253 DAG.getConstant(EltIdx, SL, MVT::i32));
8254 Pieces.push_back(
8255 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8256 } else {
8257 Pieces.push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8258 }
8259
8260 EltIdx += SubVecNumElt;
8261 }
8262 return DAG.getNode(ISD::CONCAT_VECTORS, SL, VT, Pieces);
8263 }
8264 default:
8265 // Handle all other cases by bitcasting to i32 vectors
8266 break;
8267 }
8268 }
8269
8270 MVT VecVT =
8271 MVT::getVectorVT(MVT::getIntegerVT(SplitSize), ValSize / SplitSize);
8272 Src0 = DAG.getBitcast(VecVT, Src0);
8273
8274 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8275 Src1 = DAG.getBitcast(VecVT, Src1);
8276
8277 if (IID == Intrinsic::amdgcn_writelane)
8278 Src2 = DAG.getBitcast(VecVT, Src2);
8279
8280 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8281 SDValue UnrolledLaneOp = unrollLaneOp(LaneOp.getNode());
8282 return DAG.getBitcast(VT, UnrolledLaneOp);
8283}
8284
8286 SelectionDAG &DAG) {
8287 EVT VT = N->getValueType(0);
8288
8289 if (VT.getSizeInBits() != 32)
8290 return SDValue();
8291
8292 SDLoc SL(N);
8293
8294 SDValue Value = N->getOperand(1);
8295 SDValue Index = N->getOperand(2);
8296
8297 // ds_bpermute requires index to be multiplied by 4
8298 SDValue ShiftAmount = DAG.getShiftAmountConstant(2, MVT::i32, SL);
8299 SDValue ShiftedIndex =
8300 DAG.getNode(ISD::SHL, SL, Index.getValueType(), Index, ShiftAmount);
8301
8302 // Intrinsics will require i32 to operate on
8303 SDValue ValueI32 = DAG.getBitcast(MVT::i32, Value);
8304
8305 auto MakeIntrinsic = [&DAG, &SL](unsigned IID, MVT RetVT,
8306 SmallVector<SDValue> IntrinArgs) -> SDValue {
8308 Operands[0] = DAG.getTargetConstant(IID, SL, MVT::i32);
8309 Operands.append(IntrinArgs);
8310 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, RetVT, Operands);
8311 };
8312
8313 // If we can bpermute across the whole wave, then just do that
8315 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8316 {ShiftedIndex, ValueI32});
8317 return DAG.getBitcast(VT, BPermute);
8318 }
8319
8320 assert(TLI.getSubtarget()->isWave64());
8321
8322 // Otherwise, we need to make use of whole wave mode
8323 SDValue PoisonVal = DAG.getPOISON(ValueI32->getValueType(0));
8324
8325 // Set inactive lanes to poison
8326 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8327 {ValueI32, PoisonVal});
8328 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8329 {ShiftedIndex, PoisonVal});
8330
8331 SDValue Swapped =
8332 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8333
8334 // Get permutation of each half, then we'll select which one to use
8335 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8336 {WWMIndex, WWMValue});
8337 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8338 MVT::i32, {WWMIndex, Swapped});
8339 SDValue BPermOtherHalfWWM =
8340 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8341
8342 // Select which side to take the permute from
8343 SDValue ThreadIDMask = DAG.getAllOnesConstant(SL, MVT::i32);
8344 // We can get away with only using mbcnt_lo here since we're only
8345 // trying to detect which side of 32 each lane is on, and mbcnt_lo
8346 // returns 32 for lanes 32-63.
8347 SDValue ThreadID =
8348 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8349 {ThreadIDMask, DAG.getTargetConstant(0, SL, MVT::i32)});
8350
8351 SDValue SameOrOtherHalf =
8352 DAG.getNode(ISD::AND, SL, MVT::i32,
8353 DAG.getNode(ISD::XOR, SL, MVT::i32, ThreadID, Index),
8354 DAG.getTargetConstant(32, SL, MVT::i32));
8355 SDValue UseSameHalf =
8356 DAG.getSetCC(SL, MVT::i1, SameOrOtherHalf,
8357 DAG.getConstant(0, SL, MVT::i32), ISD::SETEQ);
8358 SDValue Result = DAG.getSelect(SL, MVT::i32, UseSameHalf, BPermSameHalf,
8359 BPermOtherHalfWWM);
8360 return DAG.getBitcast(VT, Result);
8361}
8362
8365 SelectionDAG &DAG) const {
8366 switch (N->getOpcode()) {
8368 if (SDValue Res = lowerINSERT_VECTOR_ELT(SDValue(N, 0), DAG))
8369 Results.push_back(Res);
8370 return;
8371 }
8373 if (SDValue Res = lowerEXTRACT_VECTOR_ELT(SDValue(N, 0), DAG))
8374 Results.push_back(Res);
8375 return;
8376 }
8378 if (SDValue Res = LowerCONVERT_TO_ARBITRARY_FP(SDValue(N, 0), DAG))
8379 Results.push_back(Res);
8380 return;
8381 }
8383 unsigned IID = N->getConstantOperandVal(0);
8384 switch (IID) {
8385 case Intrinsic::amdgcn_wave_reduce_min:
8386 case Intrinsic::amdgcn_wave_reduce_umin:
8387 case Intrinsic::amdgcn_wave_reduce_max:
8388 case Intrinsic::amdgcn_wave_reduce_umax:
8389 case Intrinsic::amdgcn_wave_reduce_add:
8390 case Intrinsic::amdgcn_wave_reduce_sub:
8391 case Intrinsic::amdgcn_wave_reduce_and:
8392 case Intrinsic::amdgcn_wave_reduce_or:
8393 case Intrinsic::amdgcn_wave_reduce_xor: {
8394 EVT VT = N->getValueType(0);
8395 if (isTypeLegal(VT))
8396 return;
8397 SDLoc SL(N);
8398 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8399 IID == Intrinsic::amdgcn_wave_reduce_max ||
8400 IID == Intrinsic::amdgcn_wave_reduce_add ||
8401 IID == Intrinsic::amdgcn_wave_reduce_sub;
8402 unsigned ExtOpc = NeedsSignExt ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
8403 SDValue ExtSrc = DAG.getNode(ExtOpc, SL, MVT::i32, N->getOperand(1));
8404 SDValue Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
8405 N->getOperand(0), ExtSrc, N->getOperand(2));
8406 Results.push_back(DAG.getNode(ISD::TRUNCATE, SL, VT, Result));
8407 return;
8408 }
8409 case Intrinsic::amdgcn_make_buffer_rsrc:
8410 Results.push_back(lowerPointerAsRsrcIntrin(N, DAG));
8411 return;
8412 case Intrinsic::amdgcn_cvt_pkrtz: {
8413 SDValue Src0 = N->getOperand(1);
8414 SDValue Src1 = N->getOperand(2);
8415 SDLoc SL(N);
8416 SDValue Cvt =
8417 DAG.getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8418 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Cvt));
8419 return;
8420 }
8421 case Intrinsic::amdgcn_cvt_pknorm_i16:
8422 case Intrinsic::amdgcn_cvt_pknorm_u16:
8423 case Intrinsic::amdgcn_cvt_pk_i16:
8424 case Intrinsic::amdgcn_cvt_pk_u16: {
8425 SDValue Src0 = N->getOperand(1);
8426 SDValue Src1 = N->getOperand(2);
8427 SDLoc SL(N);
8428 unsigned Opcode;
8429
8430 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8431 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8432 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8433 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8434 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8435 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8436 else
8437 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8438
8439 EVT VT = N->getValueType(0);
8440 if (isTypeLegal(VT))
8441 Results.push_back(DAG.getNode(Opcode, SL, VT, Src0, Src1));
8442 else {
8443 SDValue Cvt = DAG.getNode(Opcode, SL, MVT::i32, Src0, Src1);
8444 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, Cvt));
8445 }
8446 return;
8447 }
8448 case Intrinsic::amdgcn_s_buffer_load: {
8449 // Lower llvm.amdgcn.s.buffer.load.(i8, u8) intrinsics. First, we generate
8450 // s_buffer_load_u8 for signed and unsigned load instructions. Next, DAG
8451 // combiner tries to merge the s_buffer_load_u8 with a sext instruction
8452 // (performSignExtendInRegCombine()) and it replaces s_buffer_load_u8 with
8453 // s_buffer_load_i8.
8454 if (!Subtarget->hasScalarSubwordLoads())
8455 return;
8456 SDValue Op = SDValue(N, 0);
8457 SDValue Rsrc = Op.getOperand(1);
8458 SDValue Offset = Op.getOperand(2);
8459 SDValue CachePolicy = Op.getOperand(3);
8460 EVT VT = Op.getValueType();
8461 assert(VT == MVT::i8 && "Expected 8-bit s_buffer_load intrinsics.\n");
8462 SDLoc DL(Op);
8464 const DataLayout &DataLayout = DAG.getDataLayout();
8465 Align Alignment =
8471 VT.getStoreSize(), Alignment);
8472 SDValue LoadVal;
8473 if (!Offset->isDivergent()) {
8474 SDValue Ops[] = {DAG.getEntryNode(), // Chain
8475 Rsrc, // source register
8476 Offset, CachePolicy};
8477 SDValue BufferLoad = DAG.getMemIntrinsicNode(
8478 AMDGPUISD::SBUFFER_LOAD_UBYTE, DL,
8479 DAG.getVTList(MVT::i32, MVT::Other), Ops, VT, MMO);
8480 LoadVal = DAG.getNode(ISD::TRUNCATE, DL, VT, BufferLoad);
8481 } else {
8482 SDValue Ops[] = {
8483 DAG.getEntryNode(), // Chain
8484 Rsrc, // rsrc
8485 DAG.getConstant(0, DL, MVT::i32), // vindex
8486 {}, // voffset
8487 {}, // soffset
8488 {}, // offset
8489 CachePolicy, // cachepolicy
8490 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
8491 };
8492 setBufferOffsets(Offset, DAG, &Ops[3], Align(4));
8493 LoadVal = handleByteShortBufferLoads(DAG, VT, DL, Ops, MMO);
8494 }
8495 Results.push_back(LoadVal);
8496 return;
8497 }
8498 case Intrinsic::amdgcn_dead: {
8499 for (unsigned I = 0, E = N->getNumValues(); I < E; ++I)
8500 Results.push_back(DAG.getPOISON(N->getValueType(I)));
8501 return;
8502 }
8503 }
8504 break;
8505 }
8507 if (SDValue Res = LowerINTRINSIC_W_CHAIN(SDValue(N, 0), DAG)) {
8508 if (Res.getOpcode() == ISD::MERGE_VALUES) {
8509 // FIXME: Hacky
8510 for (unsigned I = 0; I < Res.getNumOperands(); I++) {
8511 Results.push_back(Res.getOperand(I));
8512 }
8513 } else {
8514 Results.push_back(Res);
8515 Results.push_back(Res.getValue(1));
8516 }
8517 return;
8518 }
8519
8520 break;
8521 }
8522 case ISD::SELECT: {
8523 SDLoc SL(N);
8524 EVT VT = N->getValueType(0);
8525 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
8526 SDValue LHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(1));
8527 SDValue RHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(2));
8528
8529 EVT SelectVT = NewVT;
8530 if (NewVT.bitsLT(MVT::i32)) {
8531 LHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, LHS);
8532 RHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, RHS);
8533 SelectVT = MVT::i32;
8534 }
8535
8536 SDValue NewSelect =
8537 DAG.getNode(ISD::SELECT, SL, SelectVT, N->getOperand(0), LHS, RHS);
8538
8539 if (NewVT != SelectVT)
8540 NewSelect = DAG.getNode(ISD::TRUNCATE, SL, NewVT, NewSelect);
8541 Results.push_back(DAG.getNode(ISD::BITCAST, SL, VT, NewSelect));
8542 return;
8543 }
8544 case ISD::FNEG: {
8545 if (N->getValueType(0) != MVT::v2f16)
8546 break;
8547
8548 SDLoc SL(N);
8549 SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::i32, N->getOperand(0));
8550
8551 SDValue Op = DAG.getNode(ISD::XOR, SL, MVT::i32, BC,
8552 DAG.getConstant(0x80008000, SL, MVT::i32));
8553 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8554 return;
8555 }
8556 case ISD::FABS: {
8557 if (N->getValueType(0) != MVT::v2f16)
8558 break;
8559
8560 SDLoc SL(N);
8561 SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::i32, N->getOperand(0));
8562
8563 SDValue Op = DAG.getNode(ISD::AND, SL, MVT::i32, BC,
8564 DAG.getConstant(0x7fff7fff, SL, MVT::i32));
8565 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8566 return;
8567 }
8568 case ISD::FSQRT: {
8569 if (N->getValueType(0) != MVT::f16)
8570 break;
8571 Results.push_back(lowerFSQRTF16(SDValue(N, 0), DAG));
8572 break;
8573 }
8574 default:
8576 break;
8577 }
8578}
8579
8580/// Helper function for LowerBRCOND
8581static SDNode *findUser(SDValue Value, unsigned Opcode) {
8582
8583 for (SDUse &U : Value->uses()) {
8584 if (U.get() != Value)
8585 continue;
8586
8587 if (U.getUser()->getOpcode() == Opcode)
8588 return U.getUser();
8589 }
8590 return nullptr;
8591}
8592
8593unsigned SITargetLowering::isCFIntrinsic(const SDNode *Intr) const {
8594 if (Intr->getOpcode() == ISD::INTRINSIC_W_CHAIN) {
8595 switch (Intr->getConstantOperandVal(1)) {
8596 case Intrinsic::amdgcn_if:
8597 return AMDGPUISD::IF;
8598 case Intrinsic::amdgcn_else:
8599 return AMDGPUISD::ELSE;
8600 case Intrinsic::amdgcn_loop:
8601 return AMDGPUISD::LOOP;
8602 case Intrinsic::amdgcn_end_cf:
8603 llvm_unreachable("should not occur");
8604 default:
8605 return 0;
8606 }
8607 }
8608
8609 // break, if_break, else_break are all only used as inputs to loop, not
8610 // directly as branch conditions.
8611 return 0;
8612}
8613
8620
8622 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8623 return false;
8624
8625 // FIXME: Either avoid relying on address space here or change the default
8626 // address space for functions to avoid the explicit check.
8627 return (GV->getValueType()->isFunctionTy() ||
8630}
8631
8633 return !shouldEmitFixup(GV) && !shouldEmitGOTReloc(GV);
8634}
8635
8637 if (!GV->hasExternalLinkage())
8638 return true;
8639
8640 // With object linking, external LDS declarations need relocations so the
8641 // linker can assign their offsets.
8643 if (const auto *GVar = dyn_cast<GlobalVariable>(GV)) {
8644 if (GVar->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
8645 GVar->getAddressSpace() == AMDGPUAS::BARRIER) {
8646 assert(GVar->isDeclaration() &&
8647 "AS 3 & 13 GVs should be declaration here "
8648 "when object linking is enabled");
8649 return false;
8650 }
8651 }
8652 }
8653
8654 const auto OS = getTargetMachine().getTargetTriple().getOS();
8655 return OS == Triple::AMDHSA || OS == Triple::AMDPAL;
8656}
8657
8658/// This transforms the control flow intrinsics to get the branch destination as
8659/// last parameter, also switches branch target with BR if the need arise
8660SDValue SITargetLowering::LowerBRCOND(SDValue BRCOND, SelectionDAG &DAG) const {
8661 SDLoc DL(BRCOND);
8662
8663 SDNode *Intr = BRCOND.getOperand(1).getNode();
8664 SDValue Target = BRCOND.getOperand(2);
8665 SDNode *BR = nullptr;
8666 SDNode *SetCC = nullptr;
8667
8668 switch (Intr->getOpcode()) {
8669 case ISD::SETCC: {
8670 // As long as we negate the condition everything is fine
8671 SetCC = Intr;
8672 Intr = SetCC->getOperand(0).getNode();
8673 break;
8674 }
8675 case ISD::XOR: {
8676 // Similar to SETCC, if we have (xor c, -1), we will be fine.
8677 SDValue LHS = Intr->getOperand(0);
8678 SDValue RHS = Intr->getOperand(1);
8679 if (auto *C = dyn_cast<ConstantSDNode>(RHS); C && C->getZExtValue()) {
8680 Intr = LHS.getNode();
8681 break;
8682 }
8683 [[fallthrough]];
8684 }
8685 default: {
8686 // Get the target from BR if we don't negate the condition
8687 BR = findUser(BRCOND, ISD::BR);
8688 assert(BR && "brcond missing unconditional branch user");
8689 Target = BR->getOperand(1);
8690 }
8691 }
8692
8693 unsigned CFNode = isCFIntrinsic(Intr);
8694 if (CFNode == 0) {
8695 // This is a uniform branch so we don't need to legalize.
8696 return BRCOND;
8697 }
8698
8699 bool HaveChain = Intr->getOpcode() == ISD::INTRINSIC_VOID ||
8701
8702 assert(!SetCC ||
8703 (SetCC->getConstantOperandVal(1) == 1 &&
8704 cast<CondCodeSDNode>(SetCC->getOperand(2).getNode())->get() ==
8705 ISD::SETNE));
8706
8707 // operands of the new intrinsic call
8709 if (HaveChain)
8710 Ops.push_back(BRCOND.getOperand(0));
8711
8712 Ops.append(Intr->op_begin() + (HaveChain ? 2 : 1), Intr->op_end());
8713 Ops.push_back(Target);
8714
8715 ArrayRef<EVT> Res(Intr->value_begin() + 1, Intr->value_end());
8716
8717 // build the new intrinsic call
8718 SDNode *Result = DAG.getNode(CFNode, DL, DAG.getVTList(Res), Ops).getNode();
8719
8720 if (!HaveChain) {
8721 SDValue Ops[] = {SDValue(Result, 0), BRCOND.getOperand(0)};
8722
8724 }
8725
8726 if (BR) {
8727 // Give the branch instruction our target
8728 SDValue Ops[] = {BR->getOperand(0), BRCOND.getOperand(2)};
8729 SDValue NewBR = DAG.getNode(ISD::BR, DL, BR->getVTList(), Ops);
8730 DAG.ReplaceAllUsesWith(BR, NewBR.getNode());
8731 }
8732
8733 SDValue Chain = SDValue(Result, Result->getNumValues() - 1);
8734
8735 // Copy the intrinsic results to registers
8736 for (unsigned i = 1, e = Intr->getNumValues() - 1; i != e; ++i) {
8737 SDNode *CopyToReg = findUser(SDValue(Intr, i), ISD::CopyToReg);
8738 if (!CopyToReg)
8739 continue;
8740
8741 Chain = DAG.getCopyToReg(Chain, DL, CopyToReg->getOperand(1),
8742 SDValue(Result, i - 1), SDValue());
8743
8744 DAG.ReplaceAllUsesWith(SDValue(CopyToReg, 0), CopyToReg->getOperand(0));
8745 }
8746
8747 // Remove the old intrinsic from the chain
8748 DAG.ReplaceAllUsesOfValueWith(SDValue(Intr, Intr->getNumValues() - 1),
8749 Intr->getOperand(0));
8750
8751 return Chain;
8752}
8753
8754SDValue SITargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
8755 MVT VT = Op.getSimpleValueType();
8756 SDLoc DL(Op);
8757 // Checking the depth
8758 if (Op.getConstantOperandVal(0) != 0)
8759 return DAG.getConstant(0, DL, VT);
8760
8762 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8763 // Check for kernel and shader functions
8764 if (Info->isEntryFunction())
8765 return DAG.getConstant(0, DL, VT);
8766
8767 MachineFrameInfo &MFI = MF.getFrameInfo();
8768 // There is a call to @llvm.returnaddress in this function
8769 MFI.setReturnAddressIsTaken(true);
8770
8771 const SIRegisterInfo *TRI = getSubtarget()->getRegisterInfo();
8772 // Get the return address reg and mark it as an implicit live-in
8773 Register Reg = MF.addLiveIn(TRI->getReturnAddressReg(MF),
8774 getRegClassFor(VT, Op.getNode()->isDivergent()));
8775
8776 return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT);
8777}
8778
8779SDValue SITargetLowering::LowerSPONENTRY(SDValue Op, SelectionDAG &DAG) const {
8781 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
8782
8783 // For functions that set up their own stack, select the GET_STACK_BASE
8784 // pseudo.
8785 if (MFI->isBottomOfStack())
8786 return Op;
8787
8788 // For everything else, create a dummy stack object.
8789 int FI = MF.getFrameInfo().CreateFixedObject(1, 0, /*IsImmutable=*/false);
8790 return DAG.getFrameIndex(FI, Op.getValueType());
8791}
8792
8793SDValue SITargetLowering::getFPExtOrFPRound(SelectionDAG &DAG, SDValue Op,
8794 const SDLoc &DL, EVT VT) const {
8795 return Op.getValueType().bitsLE(VT)
8796 ? DAG.getNode(ISD::FP_EXTEND, DL, VT, Op)
8797 : DAG.getNode(ISD::FP_ROUND, DL, VT, Op,
8798 DAG.getTargetConstant(0, DL, MVT::i32));
8799}
8800
8801SDValue SITargetLowering::splitFP_ROUNDVectorOp(SDValue Op,
8802 SelectionDAG &DAG) const {
8803 EVT DstVT = Op.getValueType();
8804 unsigned NumElts = DstVT.getVectorNumElements();
8805 assert(NumElts > 2 && isPowerOf2_32(NumElts));
8806
8807 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
8808
8809 SDLoc DL(Op);
8810 unsigned Opc = Op.getOpcode();
8811 SDValue Flags = Op.getOperand(1);
8812 EVT HalfDstVT =
8813 EVT::getVectorVT(*DAG.getContext(), DstVT.getScalarType(), NumElts / 2);
8814 SDValue OpLo = DAG.getNode(Opc, DL, HalfDstVT, Lo, Flags);
8815 SDValue OpHi = DAG.getNode(Opc, DL, HalfDstVT, Hi, Flags);
8816
8817 return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, OpLo, OpHi);
8818}
8819
8820SDValue SITargetLowering::lowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const {
8821 bool IsStrict = Op->isStrictFPOpcode();
8822 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
8823 EVT SrcVT = Src.getValueType();
8824 EVT DstVT = Op.getValueType();
8825
8826 if (DstVT.isVectorOf(MVT::f16)) {
8827 assert(Subtarget->hasCvtPkF16F32Inst() && "support v_cvt_pk_f16_f32");
8828 if (SrcVT.getScalarType() != MVT::f32)
8829 return SDValue();
8830 return SrcVT == MVT::v2f32 ? Op : splitFP_ROUNDVectorOp(Op, DAG);
8831 }
8832
8833 if (SrcVT.getScalarType() != MVT::f64)
8834 return Op;
8835
8836 SDLoc DL(Op);
8837 if (DstVT == MVT::f16) {
8838 // TODO: Handle strictfp
8839 if (Op.getOpcode() != ISD::FP_ROUND)
8840 return Op;
8841
8842 if (!Subtarget->has16BitInsts()) {
8843 SDValue FpToFp16 = DAG.getNode(ISD::FP_TO_FP16, DL, MVT::i32, Src);
8844 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8845 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8846 }
8847 if (Op->getFlags().hasApproximateFuncs()) {
8848 SDValue Flags = Op.getOperand(1);
8849 SDValue Src32 = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, Src, Flags);
8850 return DAG.getNode(ISD::FP_ROUND, DL, MVT::f16, Src32, Flags);
8851 }
8852 SDValue FpToFp16 = LowerF64ToF16Safe(Src, DL, DAG);
8853 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8854 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8855 }
8856
8857 assert(DstVT.getScalarType() == MVT::bf16 &&
8858 "custom lower FP_ROUND for f16 or bf16");
8859 assert(Subtarget->hasBF16ConversionInsts() && "f32 -> bf16 is legal");
8860
8861 // Round-inexact-to-odd f64 to f32, then do the final rounding using the
8862 // hardware f32 -> bf16 instruction.
8863 EVT F32VT = SrcVT.changeElementType(*DAG.getContext(), MVT::f32);
8864 SDValue Rod = expandRoundInexactToOdd(F32VT, Src, DL, DAG);
8865 if (IsStrict) {
8866 return DAG.getNode(
8867 ISD::STRICT_FP_ROUND, DL, {DstVT, MVT::Other},
8868 {Op.getOperand(0), Rod, DAG.getTargetConstant(0, DL, MVT::i32)});
8869 }
8870 return DAG.getNode(ISD::FP_ROUND, DL, DstVT, Rod,
8871 DAG.getTargetConstant(0, DL, MVT::i32));
8872}
8873
8874SDValue SITargetLowering::lowerFMINNUM_FMAXNUM(SDValue Op,
8875 SelectionDAG &DAG) const {
8876 EVT VT = Op.getValueType();
8877 const MachineFunction &MF = DAG.getMachineFunction();
8878 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8879 bool IsIEEEMode = Info->getMode().IEEE;
8880
8881 // FIXME: Assert during selection that this is only selected for
8882 // ieee_mode. Currently a combine can produce the ieee version for non-ieee
8883 // mode functions, but this happens to be OK since it's only done in cases
8884 // where there is known no sNaN.
8885 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8886 return expandFMINNUM_FMAXNUM(Op.getNode(), DAG);
8887
8888 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8889 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8890 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8891 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8892 return splitBinaryVectorOp(Op, DAG);
8893 return Op;
8894}
8895
8896SDValue
8897SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(SDValue Op,
8898 SelectionDAG &DAG) const {
8899 EVT VT = Op.getValueType();
8900 const MachineFunction &MF = DAG.getMachineFunction();
8901 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8902 bool IsIEEEMode = Info->getMode().IEEE;
8903
8904 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8905 return expandFMINIMUMNUM_FMAXIMUMNUM(Op.getNode(), DAG);
8906
8907 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8908 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8909 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8910 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8911 return splitBinaryVectorOp(Op, DAG);
8912 return Op;
8913}
8914
8915SDValue SITargetLowering::lowerFLDEXP(SDValue Op, SelectionDAG &DAG) const {
8916 bool IsStrict = Op.getOpcode() == ISD::STRICT_FLDEXP;
8917 EVT VT = Op.getValueType();
8918 assert(VT == MVT::f16);
8919
8920 SDValue Exp = Op.getOperand(IsStrict ? 2 : 1);
8921 EVT ExpVT = Exp.getValueType();
8922 if (ExpVT == MVT::i16)
8923 return Op;
8924
8925 SDLoc DL(Op);
8926
8927 // Correct the exponent type for f16 to i16.
8928 // Clamp the range of the exponent to the instruction's range.
8929
8930 // TODO: This should be a generic narrowing legalization, and can easily be
8931 // for GlobalISel.
8932
8933 SDValue MinExp = DAG.getSignedConstant(minIntN(16), DL, ExpVT);
8934 SDValue ClampMin = DAG.getNode(ISD::SMAX, DL, ExpVT, Exp, MinExp);
8935
8936 SDValue MaxExp = DAG.getSignedConstant(maxIntN(16), DL, ExpVT);
8937 SDValue Clamp = DAG.getNode(ISD::SMIN, DL, ExpVT, ClampMin, MaxExp);
8938
8939 SDValue TruncExp = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Clamp);
8940
8941 if (IsStrict) {
8942 return DAG.getNode(ISD::STRICT_FLDEXP, DL, {VT, MVT::Other},
8943 {Op.getOperand(0), Op.getOperand(1), TruncExp});
8944 }
8945
8946 return DAG.getNode(ISD::FLDEXP, DL, VT, Op.getOperand(0), TruncExp);
8947}
8948
8950 switch (Op->getOpcode()) {
8951 case ISD::ABS:
8952 case ISD::SRA:
8953 case ISD::SMIN:
8954 case ISD::SMAX:
8955 return ISD::SIGN_EXTEND;
8956 case ISD::SRL:
8957 case ISD::UMIN:
8958 case ISD::UMAX:
8959 case ISD::USUBSAT:
8960 case ISD::UADDSAT:
8961 return ISD::ZERO_EXTEND;
8962 case ISD::ADD:
8963 case ISD::SUB:
8964 case ISD::AND:
8965 case ISD::OR:
8966 case ISD::XOR:
8967 case ISD::SHL:
8968 case ISD::SELECT:
8969 case ISD::MUL:
8970 // operation result won't be influenced by garbage high bits.
8971 // TODO: are all of those cases correct, and are there more?
8972 return ISD::ANY_EXTEND;
8973 case ISD::SETCC: {
8974 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
8976 }
8977 default:
8978 llvm_unreachable("unexpected opcode!");
8979 }
8980}
8981
8982SDValue
8983SITargetLowering::promoteUniformUnaryOpToI32(SDValue Op,
8984 DAGCombinerInfo &DCI) const {
8985 EVT OpTy = Op.getValueType();
8986 SelectionDAG &DAG = DCI.DAG;
8987 EVT ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
8988
8989 if (isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
8990 return SDValue();
8991
8992 SDLoc DL(Op);
8993 SDValue Input = Op.getOperand(0);
8994 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
8995 Input = DAG.getNode(ExtOp, DL, ExtTy, Input);
8996
8997 SDValue NewVal = DAG.getNode(Op.getOpcode(), DL, ExtTy, Input);
8998
8999 return DAG.getNode(ISD::TRUNCATE, DL, OpTy, NewVal);
9000}
9001
9002SDValue SITargetLowering::promoteUniformOpToI32(SDValue Op,
9003 DAGCombinerInfo &DCI) const {
9004 const unsigned Opc = Op.getOpcode();
9005 assert(Opc == ISD::ADD || Opc == ISD::SUB || Opc == ISD::SHL ||
9006 Opc == ISD::SRL || Opc == ISD::SRA || Opc == ISD::AND ||
9007 Opc == ISD::OR || Opc == ISD::XOR || Opc == ISD::MUL ||
9008 Opc == ISD::SETCC || Opc == ISD::SELECT || Opc == ISD::SMIN ||
9009 Opc == ISD::SMAX || Opc == ISD::UMIN || Opc == ISD::UMAX ||
9010 Opc == ISD::USUBSAT || Opc == ISD::UADDSAT);
9011
9012 EVT OpTy = (Opc != ISD::SETCC) ? Op.getValueType()
9013 : Op->getOperand(0).getValueType();
9014 auto &DAG = DCI.DAG;
9015 auto ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
9016
9017 if (DCI.isBeforeLegalizeOps() ||
9018 isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
9019 return SDValue();
9020
9021 SDLoc DL(Op);
9022 SDValue LHS;
9023 SDValue RHS;
9024 if (Opc == ISD::SELECT) {
9025 LHS = Op->getOperand(1);
9026 RHS = Op->getOperand(2);
9027 } else {
9028 LHS = Op->getOperand(0);
9029 RHS = Op->getOperand(1);
9030 }
9031
9032 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
9033 LHS = DAG.getNode(ExtOp, DL, ExtTy, {LHS});
9034
9035 // Special case: for shifts, the RHS always needs a zext.
9036 if (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA)
9037 RHS = DAG.getNode(ISD::ZERO_EXTEND, DL, ExtTy, {RHS});
9038 else
9039 RHS = DAG.getNode(ExtOp, DL, ExtTy, {RHS});
9040
9041 // setcc always return i1/i1 vec so no need to truncate after.
9042 if (Opc == ISD::SETCC) {
9043 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
9044 return DAG.getSetCC(DL, Op.getValueType(), LHS, RHS, CC);
9045 }
9046
9047 // For other ops, we extend the operation's return type as well so we need to
9048 // truncate back to the original type.
9049 SDValue NewVal;
9050 if (Opc == ISD::SELECT)
9051 NewVal = DAG.getNode(ISD::SELECT, DL, ExtTy, {Op->getOperand(0), LHS, RHS});
9052 else if (Opc == ISD::UADDSAT) {
9053 SDValue Sum = DAG.getNode(ISD::ADD, DL, ExtTy, LHS, RHS);
9054 SDValue MaxVal = DAG.getConstant(
9055 APInt::getMaxValue(OpTy.getScalarSizeInBits()).zext(32), DL, ExtTy);
9056 NewVal = DAG.getNode(ISD::UMIN, DL, ExtTy, Sum, MaxVal);
9057 } else
9058 NewVal = DAG.getNode(Opc, DL, ExtTy, {LHS, RHS});
9059
9060 return DAG.getZExtOrTrunc(NewVal, DL, OpTy);
9061}
9062
9063SDValue SITargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
9064 SDValue Mag = Op.getOperand(0);
9065 EVT MagVT = Mag.getValueType();
9066
9067 if (MagVT.getVectorNumElements() > 2)
9068 return splitBinaryVectorOp(Op, DAG);
9069
9070 SDValue Sign = Op.getOperand(1);
9071 EVT SignVT = Sign.getValueType();
9072
9073 if (MagVT == SignVT)
9074 return Op;
9075
9076 // fcopysign v2f16:mag, v2f32:sign ->
9077 // fcopysign v2f16:mag,
9078 // bitcast (trunc (srl (bitcast sign to v2i32), 16) to v2i16)
9079
9080 SDLoc SL(Op);
9081 SDValue SignAsInt32 = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Sign);
9082 SDValue ShiftAmt = DAG.getShiftAmountConstant(16, MVT::v2i32, SL);
9083 SDValue SignShifted =
9084 DAG.getNode(ISD::SRL, SL, MVT::v2i32, SignAsInt32, ShiftAmt);
9085 SDValue SignAsInt16 = DAG.getNode(ISD::TRUNCATE, SL, MVT::v2i16, SignShifted);
9086
9087 SDValue SignAsHalf16 = DAG.getNode(ISD::BITCAST, SL, MagVT, SignAsInt16);
9088
9089 return DAG.getNode(ISD::FCOPYSIGN, SL, MagVT, Mag, SignAsHalf16);
9090}
9091
9092// Custom lowering for vector multiplications and s_mul_u64.
9093SDValue SITargetLowering::lowerMUL(SDValue Op, SelectionDAG &DAG) const {
9094 EVT VT = Op.getValueType();
9095
9096 // Split vector operands.
9097 if (VT.isVector())
9098 return splitBinaryVectorOp(Op, DAG);
9099
9100 assert(VT == MVT::i64 && "The following code is a special for s_mul_u64");
9101
9102 // There are four ways to lower s_mul_u64:
9103 //
9104 // 1. If all the operands are uniform, then we lower it as it is.
9105 //
9106 // 2. If the operands are divergent, then we have to split s_mul_u64 in 32-bit
9107 // multiplications because there is not a vector equivalent of s_mul_u64.
9108 //
9109 // 3. If the cost model decides that it is more efficient to use vector
9110 // registers, then we have to split s_mul_u64 in 32-bit multiplications.
9111 // This happens in splitScalarSMULU64() in SIInstrInfo.cpp .
9112 //
9113 // 4. If the cost model decides to use vector registers and both of the
9114 // operands are zero-extended/sign-extended from 32-bits, then we split the
9115 // s_mul_u64 in two 32-bit multiplications. The problem is that it is not
9116 // possible to check if the operands are zero-extended or sign-extended in
9117 // SIInstrInfo.cpp. For this reason, here, we replace s_mul_u64 with
9118 // s_mul_u64_u32_pseudo if both operands are zero-extended and we replace
9119 // s_mul_u64 with s_mul_i64_i32_pseudo if both operands are sign-extended.
9120 // If the cost model decides that we have to use vector registers, then
9121 // splitScalarSMulPseudo() (in SIInstrInfo.cpp) split s_mul_u64_u32/
9122 // s_mul_i64_i32_pseudo in two vector multiplications. If the cost model
9123 // decides that we should use scalar registers, then s_mul_u64_u32_pseudo/
9124 // s_mul_i64_i32_pseudo is lowered as s_mul_u64 in expandPostRAPseudo() in
9125 // SIInstrInfo.cpp .
9126
9127 if (Op->isDivergent())
9128 return SDValue();
9129
9130 SDValue Op0 = Op.getOperand(0);
9131 SDValue Op1 = Op.getOperand(1);
9132 // If all the operands are zero-enteted to 32-bits, then we replace s_mul_u64
9133 // with s_mul_u64_u32_pseudo. If all the operands are sign-extended to
9134 // 32-bits, then we replace s_mul_u64 with s_mul_i64_i32_pseudo.
9135 KnownBits Op0KnownBits = DAG.computeKnownBits(Op0);
9136 unsigned Op0LeadingZeros = Op0KnownBits.countMinLeadingZeros();
9137 KnownBits Op1KnownBits = DAG.computeKnownBits(Op1);
9138 unsigned Op1LeadingZeros = Op1KnownBits.countMinLeadingZeros();
9139 SDLoc SL(Op);
9140 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9141 return SDValue(
9142 DAG.getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9143 unsigned Op0SignBits = DAG.ComputeNumSignBits(Op0);
9144 unsigned Op1SignBits = DAG.ComputeNumSignBits(Op1);
9145 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9146 return SDValue(
9147 DAG.getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9148 // If all the operands are uniform, then we lower s_mul_u64 as it is.
9149 return Op;
9150}
9151
9152SDValue SITargetLowering::lowerXMULO(SDValue Op, SelectionDAG &DAG) const {
9153 EVT VT = Op.getValueType();
9154 SDLoc SL(Op);
9155 SDValue LHS = Op.getOperand(0);
9156 SDValue RHS = Op.getOperand(1);
9157 bool isSigned = Op.getOpcode() == ISD::SMULO;
9158
9159 if (ConstantSDNode *RHSC = isConstOrConstSplat(RHS)) {
9160 const APInt &C = RHSC->getAPIntValue();
9161 // mulo(X, 1 << S) -> { X << S, (X << S) >> S != X }
9162 if (C.isPowerOf2()) {
9163 // smulo(x, signed_min) is same as umulo(x, signed_min).
9164 bool UseArithShift = isSigned && !C.isMinSignedValue();
9165 SDValue ShiftAmt = DAG.getConstant(C.logBase2(), SL, MVT::i32);
9166 SDValue Result = DAG.getNode(ISD::SHL, SL, VT, LHS, ShiftAmt);
9167 SDValue Overflow =
9168 DAG.getSetCC(SL, MVT::i1,
9169 DAG.getNode(UseArithShift ? ISD::SRA : ISD::SRL, SL, VT,
9170 Result, ShiftAmt),
9171 LHS, ISD::SETNE);
9172 return DAG.getMergeValues({Result, Overflow}, SL);
9173 }
9174 }
9175
9176 SDValue Result = DAG.getNode(ISD::MUL, SL, VT, LHS, RHS);
9177 SDValue Top =
9178 DAG.getNode(isSigned ? ISD::MULHS : ISD::MULHU, SL, VT, LHS, RHS);
9179
9180 SDValue Sign = isSigned
9181 ? DAG.getNode(ISD::SRA, SL, VT, Result,
9182 DAG.getConstant(VT.getScalarSizeInBits() - 1,
9183 SL, MVT::i32))
9184 : DAG.getConstant(0, SL, VT);
9185 SDValue Overflow = DAG.getSetCC(SL, MVT::i1, Top, Sign, ISD::SETNE);
9186
9187 return DAG.getMergeValues({Result, Overflow}, SL);
9188}
9189
9190SDValue SITargetLowering::lowerXMUL_LOHI(SDValue Op, SelectionDAG &DAG) const {
9191 if (Op->isDivergent()) {
9192 // Select to V_MAD_[IU]64_[IU]32.
9193 return Op;
9194 }
9195 if (Subtarget->hasSMulHi()) {
9196 // Expand to S_MUL_I32 + S_MUL_HI_[IU]32.
9197 return SDValue();
9198 }
9199 // The multiply is uniform but we would have to use V_MUL_HI_[IU]32 to
9200 // calculate the high part, so we might as well do the whole thing with
9201 // V_MAD_[IU]64_[IU]32.
9202 return Op;
9203}
9204
9205SDValue SITargetLowering::lowerTRAP(SDValue Op, SelectionDAG &DAG) const {
9206 if (!Subtarget->hasTrapHandler() ||
9207 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA)
9208 return lowerTrapEndpgm(Op, DAG);
9209
9210 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(Op, DAG)
9211 : lowerTrapHsaQueuePtr(Op, DAG);
9212}
9213
9214SDValue SITargetLowering::lowerTrapEndpgm(SDValue Op, SelectionDAG &DAG) const {
9215 SDLoc SL(Op);
9216 SDValue Chain = Op.getOperand(0);
9217 return DAG.getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9218}
9219
9220SDValue
9221SITargetLowering::loadImplicitKernelArgument(SelectionDAG &DAG, MVT VT,
9222 const SDLoc &DL, Align Alignment,
9223 ImplicitParameter Param) const {
9226 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, DAG.getEntryNode(), Offset);
9227 MachinePointerInfo PtrInfo =
9229 return DAG.getLoad(
9230 VT, DL, DAG.getEntryNode(), Ptr, PtrInfo.getWithOffset(Offset), Alignment,
9232}
9233
9234SDValue SITargetLowering::lowerTrapHsaQueuePtr(SDValue Op,
9235 SelectionDAG &DAG) const {
9236 SDLoc SL(Op);
9237 SDValue Chain = Op.getOperand(0);
9238
9239 SDValue QueuePtr;
9240 // For code object version 5, QueuePtr is passed through implicit kernarg.
9241 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9243 QueuePtr =
9244 loadImplicitKernelArgument(DAG, MVT::i64, SL, Align(8), QUEUE_PTR);
9245 } else {
9247 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9248 Register UserSGPR = Info->getQueuePtrUserSGPR();
9249
9250 if (UserSGPR == AMDGPU::NoRegister) {
9251 // We probably are in a function incorrectly marked with
9252 // amdgpu-no-queue-ptr. This is undefined. We don't want to delete the
9253 // trap, so just use a null pointer.
9254 QueuePtr = DAG.getConstant(0, SL, MVT::i64);
9255 } else {
9256 QueuePtr = CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR,
9257 MVT::i64);
9258 }
9259 }
9260
9261 SDValue SGPR01 = DAG.getRegister(AMDGPU::SGPR0_SGPR1, MVT::i64);
9262 SDValue ToReg = DAG.getCopyToReg(Chain, SL, SGPR01, QueuePtr, SDValue());
9263
9265 SDValue Ops[] = {ToReg, DAG.getTargetConstant(TrapID, SL, MVT::i16), SGPR01,
9266 ToReg.getValue(1)};
9267 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9268}
9269
9270SDValue SITargetLowering::lowerTrapHsa(SDValue Op, SelectionDAG &DAG) const {
9271 SDLoc SL(Op);
9272 SDValue Chain = Op.getOperand(0);
9273
9274 // We need to simulate the 's_trap 2' instruction on targets that run in
9275 // PRIV=1 (where it is treated as a nop).
9276 if (Subtarget->hasPrivEnabledTrap2NopBug())
9277 return DAG.getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9278
9280 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9281 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9282}
9283
9284SDValue SITargetLowering::lowerDEBUGTRAP(SDValue Op, SelectionDAG &DAG) const {
9285 SDLoc SL(Op);
9286 SDValue Chain = Op.getOperand(0);
9288
9289 if (!Subtarget->hasTrapHandler() ||
9290 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA) {
9291 LLVMContext &Ctx = MF.getFunction().getContext();
9292 Ctx.diagnose(DiagnosticInfoUnsupported(MF.getFunction(),
9293 "debugtrap handler not supported",
9294 Op.getDebugLoc(), DS_Warning));
9295 return Chain;
9296 }
9297
9298 uint64_t TrapID =
9300 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9301 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9302}
9303
9304/// When a divergent value (in VGPR) is passed to an inline asm with an SGPR
9305/// constraint ('s'), we need to insert v_readfirstlane to move the value from
9306/// VGPR to SGPR. This is done by modifying the CopyToReg nodes in the glue
9307/// chain that feed into the INLINEASM node.
9308SDValue SITargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
9309 unsigned NumOps = Op.getNumOperands();
9310
9311 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
9312 SmallSet<Register, 8> SGPRInputRegs;
9313
9314 unsigned NumVals = 0;
9315 for (unsigned I = InlineAsm::Op_FirstOperand; I < NumOps - 1;
9316 I += 1 + NumVals) {
9317 const InlineAsm::Flag Flags(Op.getConstantOperandVal(I));
9318 NumVals = Flags.getNumOperandRegisters();
9319
9320 unsigned RCID;
9321 bool IsSGPRInput = Flags.getKind() == InlineAsm::Kind::RegUse &&
9322 NumVals > 0 && Flags.hasRegClassConstraint(RCID) &&
9323 TRI->isSGPRClass(TRI->getRegClass(RCID));
9324
9325 for (unsigned J = 0; J < NumVals; ++J) {
9326 SDValue Val = Op.getOperand(I + 1 + J);
9327 if (const RegisterSDNode *RegNode =
9329 Register Reg = RegNode->getReg();
9330 if (IsSGPRInput || (Reg.isPhysical() && TRI->isSGPRPhysReg(Reg)))
9331 SGPRInputRegs.insert(Reg);
9332 }
9333 }
9334 }
9335
9336 if (SGPRInputRegs.empty())
9337 return Op;
9338
9339 // Walk the glue chain and insert readfirstlane for divergent SGPR inputs.
9340 SDLoc DL(Op);
9341 SDNode *N = Op.getOperand(NumOps - 1).getNode();
9342
9343 while (N && N->getOpcode() == ISD::CopyToReg) {
9344 Register Reg = cast<RegisterSDNode>(N->getOperand(1))->getReg();
9345 SDValue SrcVal = N->getOperand(2);
9346
9347 // Insert readfirstlane if copying a divergent value to an SGPR input.
9348 if (SrcVal->isDivergent() && SGPRInputRegs.count(Reg)) {
9349 SDValue ReadFirstLaneID =
9350 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
9351 SDValue ReadFirstLane =
9353 ReadFirstLaneID, SrcVal);
9354
9355 SmallVector<SDValue, 4> Ops = {N->getOperand(0), N->getOperand(1),
9356 ReadFirstLane};
9357 if (N->getNumOperands() > 3)
9358 Ops.push_back(N->getOperand(3)); // Glue input
9359
9360 DAG.UpdateNodeOperands(N, Ops);
9361 }
9362
9363 // Follow glue chain to next CopyToReg.
9364 SDNode *Next = nullptr;
9365 for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I) {
9366 if (N->getOperand(I).getValueType() == MVT::Glue) {
9367 Next = N->getOperand(I).getNode();
9368 break;
9369 }
9370 }
9371 N = Next;
9372 }
9373
9374 return Op;
9375}
9376
9377SDValue SITargetLowering::getSegmentAperture(unsigned AS, const SDLoc &DL,
9378 SelectionDAG &DAG) const {
9379 unsigned BaseAS = AS;
9380 unsigned SANum = AMDGPU::getSyntheticApertureNumber(AS);
9382 BaseAS = AMDGPUAS::LOCAL_ADDRESS;
9383
9384 SDValue Aperture = getBaseSegmentAperture(BaseAS, DL, DAG);
9385
9386 if (SANum != AMDGPU::SyntheticAperture::None) {
9387 SDValue Tag = DAG.getConstant(SANum, DL, MVT::i32);
9388 return DAG.getNode(ISD::OR, DL, MVT::i32, Aperture, Tag);
9389 }
9390
9391 return Aperture;
9392}
9393
9394SDValue SITargetLowering::getBaseSegmentAperture(unsigned AS, const SDLoc &DL,
9395 SelectionDAG &DAG) const {
9396 const bool IsLDS = (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::BARRIER);
9397
9398 if (Subtarget->hasApertureRegs()) {
9399 const unsigned ApertureRegNo =
9400 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
9401 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9402 !Subtarget->hasGloballyAddressableScratch()) &&
9403 "Cannot use src_private_base with globally addressable scratch!");
9404 // Note: this feature (register) is broken. When used as a 32-bit operand,
9405 // it returns a wrong value (all zeroes?). The real value is in the upper 32
9406 // bits.
9407 //
9408 // To work around the issue, emit a 64 bit copy from this register
9409 // then extract the high bits. Note that this shouldn't even result in a
9410 // shift being emitted and simply become a pair of registers (e.g.):
9411 // s_mov_b64 s[6:7], src_shared_base
9412 // v_mov_b32_e32 v1, s7
9413 SDValue Copy =
9414 DAG.getCopyFromReg(DAG.getEntryNode(), DL, ApertureRegNo, MVT::v2i32);
9415 return DAG.getExtractVectorElt(DL, MVT::i32, Copy, 1);
9416 }
9417
9418 // For code object version 5, private_base and shared_base are passed through
9419 // implicit kernargs.
9420 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9423 return loadImplicitKernelArgument(DAG, MVT::i32, DL, Align(4), Param);
9424 }
9425
9427 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9428 Register UserSGPR = Info->getQueuePtrUserSGPR();
9429 if (UserSGPR == AMDGPU::NoRegister) {
9430 // We probably are in a function incorrectly marked with
9431 // amdgpu-no-queue-ptr. This is undefined.
9432 return DAG.getPOISON(MVT::i32);
9433 }
9434
9435 SDValue QueuePtr =
9436 CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR, MVT::i64);
9437
9438 // Offset into amd_queue_t for group_segment_aperture_base_hi /
9439 // private_segment_aperture_base_hi.
9440 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
9441
9442 SDValue Ptr =
9443 DAG.getObjectPtrOffset(DL, QueuePtr, TypeSize::getFixed(StructOffset));
9444
9445 // TODO: Use custom target PseudoSourceValue.
9446 // TODO: We should use the value from the IR intrinsic call, but it might not
9447 // be available and how do we get it?
9448 MachinePointerInfo PtrInfo(AMDGPUAS::CONSTANT_ADDRESS);
9449 return DAG.getLoad(MVT::i32, DL, QueuePtr.getValue(1), Ptr, PtrInfo,
9450 commonAlignment(Align(64), StructOffset),
9453}
9454
9455/// Return true if the value is a known valid address, such that a null check is
9456/// not necessary.
9458 const AMDGPUTargetMachine &TM, unsigned AddrSpace) {
9460 return true;
9461
9462 if (auto *ConstVal = dyn_cast<ConstantSDNode>(Val))
9463 return ConstVal->getSExtValue() != AMDGPU::getNullPointerValue(AddrSpace);
9464
9465 // TODO: Search through arithmetic, handle arguments and loads
9466 // marked nonnull.
9467 return false;
9468}
9469
9470SDValue SITargetLowering::lowerADDRSPACECAST(SDValue Op,
9471 SelectionDAG &DAG) const {
9472 SDLoc SL(Op);
9473
9474 const AMDGPUTargetMachine &TM =
9475 static_cast<const AMDGPUTargetMachine &>(getTargetMachine());
9476
9477 const auto *ASC = cast<AddrSpaceCastSDNode>(Op);
9478 unsigned SrcAS = ASC->getSrcAddressSpace();
9479 SDValue Src = ASC->getOperand(0);
9480 unsigned DestAS = ASC->getDestAddressSpace();
9481 bool IsNonNull = ASC->getFlags().hasNonNull();
9482
9483 SDValue FlatNullPtr = DAG.getConstant(0, SL, MVT::i64);
9484
9485 // flat -> local/private/barrier
9486 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
9487 if (DestAS == AMDGPUAS::LOCAL_ADDRESS ||
9488 DestAS == AMDGPUAS::PRIVATE_ADDRESS || DestAS == AMDGPUAS::BARRIER) {
9489 SDValue Ptr = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9490
9491 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
9492 Subtarget->hasGloballyAddressableScratch()) {
9493 // flat -> private with globally addressable scratch: subtract
9494 // src_flat_scratch_base_lo.
9495 SDValue FlatScratchBaseLo(
9496 DAG.getMachineNode(
9497 AMDGPU::S_MOV_B32, SL, MVT::i32,
9498 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9499 0);
9500 Ptr = DAG.getNode(ISD::SUB, SL, MVT::i32, Ptr, FlatScratchBaseLo);
9501 }
9502
9503 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9504 return Ptr;
9505
9506 unsigned NullVal = AMDGPU::getNullPointerValue(DestAS);
9507 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9508 SDValue NonNull = DAG.getSetCC(SL, MVT::i1, Src, FlatNullPtr, ISD::SETNE);
9509
9510 return DAG.getNode(ISD::SELECT, SL, MVT::i32, NonNull, Ptr,
9511 SegmentNullPtr);
9512 }
9513 }
9514
9515 // local/private/barrier -> flat
9516 if (DestAS == AMDGPUAS::FLAT_ADDRESS) {
9517 if (SrcAS == AMDGPUAS::LOCAL_ADDRESS ||
9518 SrcAS == AMDGPUAS::PRIVATE_ADDRESS || SrcAS == AMDGPUAS::BARRIER) {
9519 SDValue CvtPtr;
9520 if (SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
9521 Subtarget->hasGloballyAddressableScratch()) {
9522 // For wave32: Addr = (TID[4:0] << 52) + FLAT_SCRATCH_BASE + privateAddr
9523 // For wave64: Addr = (TID[5:0] << 51) + FLAT_SCRATCH_BASE + privateAddr
9524 SDValue AllOnes = DAG.getSignedTargetConstant(-1, SL, MVT::i32);
9525 SDValue ThreadID = DAG.getConstant(0, SL, MVT::i32);
9526 ThreadID = DAG.getNode(
9527 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9528 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_lo, SL, MVT::i32),
9529 AllOnes, ThreadID);
9530 if (Subtarget->isWave64())
9531 ThreadID = DAG.getNode(
9532 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9533 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_hi, SL, MVT::i32),
9534 AllOnes, ThreadID);
9535 SDValue ShAmt = DAG.getShiftAmountConstant(
9536 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9537 SDValue SrcHi = DAG.getNode(ISD::SHL, SL, MVT::i32, ThreadID, ShAmt);
9538 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, SrcHi);
9539 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9540 // Accessing src_flat_scratch_base_lo as a 64-bit operand gives the full
9541 // 64-bit hi:lo value.
9542 SDValue FlatScratchBase = {
9543 DAG.getMachineNode(
9544 AMDGPU::S_MOV_B64, SL, MVT::i64,
9545 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9546 0};
9547 CvtPtr = DAG.getNode(ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9548 } else {
9549 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9550
9551 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Aperture);
9552 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9553 }
9554
9555 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9556 return CvtPtr;
9557
9558 unsigned NullVal = AMDGPU::getNullPointerValue(SrcAS);
9559 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9560
9561 SDValue NonNull =
9562 DAG.getSetCC(SL, MVT::i1, Src, SegmentNullPtr, ISD::SETNE);
9563
9564 return DAG.getNode(ISD::SELECT, SL, MVT::i64, NonNull, CvtPtr,
9565 FlatNullPtr);
9566 }
9567 }
9568
9569 if (SrcAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9570 Op.getValueType() == MVT::i64) {
9571 const SIMachineFunctionInfo *Info =
9572 DAG.getMachineFunction().getInfo<SIMachineFunctionInfo>();
9573 if (Info->get32BitAddressHighBits() == 0)
9574 return DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i64, Src);
9575
9576 SDValue Hi = DAG.getConstant(Info->get32BitAddressHighBits(), SL, MVT::i32);
9577 SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Hi);
9578 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
9579 }
9580
9581 if (DestAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9582 Src.getValueType() == MVT::i64)
9583 return DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9584
9585 // global <-> flat are no-ops and never emitted.
9586
9587 // Invalid casts are poison.
9588 return DAG.getPOISON(Op->getValueType(0));
9589}
9590
9591// This lowers an INSERT_SUBVECTOR by extracting the individual elements from
9592// the small vector and inserting them into the big vector. That is better than
9593// the default expansion of doing it via a stack slot. Even though the use of
9594// the stack slot would be optimized away afterwards, the stack slot itself
9595// remains.
9596SDValue SITargetLowering::lowerINSERT_SUBVECTOR(SDValue Op,
9597 SelectionDAG &DAG) const {
9598 SDValue Vec = Op.getOperand(0);
9599 SDValue Ins = Op.getOperand(1);
9600 SDValue Idx = Op.getOperand(2);
9601 EVT VecVT = Vec.getValueType();
9602 EVT InsVT = Ins.getValueType();
9603 EVT EltVT = VecVT.getVectorElementType();
9604 unsigned InsNumElts = InsVT.getVectorNumElements();
9605 unsigned IdxVal = Idx->getAsZExtVal();
9606 SDLoc SL(Op);
9607
9608 if (EltVT.getScalarSizeInBits() == 16 && IdxVal % 2 == 0) {
9609 // Insert 32-bit registers at a time.
9610 assert(InsNumElts % 2 == 0 && "expect legal vector types");
9611
9612 unsigned VecNumElts = VecVT.getVectorNumElements();
9613 EVT NewVecVT =
9614 EVT::getVectorVT(*DAG.getContext(), MVT::i32, VecNumElts / 2);
9615 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9617 MVT::i32, InsNumElts / 2);
9618
9619 Vec = DAG.getNode(ISD::BITCAST, SL, NewVecVT, Vec);
9620 Ins = DAG.getNode(ISD::BITCAST, SL, NewInsVT, Ins);
9621
9622 for (unsigned I = 0; I != InsNumElts / 2; ++I) {
9623 SDValue Elt;
9624 if (InsNumElts == 2) {
9625 Elt = Ins;
9626 } else {
9627 Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Ins,
9628 DAG.getConstant(I, SL, MVT::i32));
9629 }
9630 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, NewVecVT, Vec, Elt,
9631 DAG.getConstant(IdxVal / 2 + I, SL, MVT::i32));
9632 }
9633
9634 return DAG.getNode(ISD::BITCAST, SL, VecVT, Vec);
9635 }
9636
9637 for (unsigned I = 0; I != InsNumElts; ++I) {
9638 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Ins,
9639 DAG.getConstant(I, SL, MVT::i32));
9640 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, VecVT, Vec, Elt,
9641 DAG.getConstant(IdxVal + I, SL, MVT::i32));
9642 }
9643 return Vec;
9644}
9645
9646SDValue SITargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,
9647 SelectionDAG &DAG) const {
9648 SDValue Vec = Op.getOperand(0);
9649 SDValue InsVal = Op.getOperand(1);
9650 SDValue Idx = Op.getOperand(2);
9651 EVT VecVT = Vec.getValueType();
9652 EVT EltVT = VecVT.getVectorElementType();
9653 unsigned VecSize = VecVT.getSizeInBits();
9654 unsigned EltSize = EltVT.getSizeInBits();
9655 SDLoc SL(Op);
9656
9657 // Specially handle the case of v4i16 with static indexing.
9658 unsigned NumElts = VecVT.getVectorNumElements();
9659 auto *KIdx = dyn_cast<ConstantSDNode>(Idx);
9660 if (NumElts == 4 && EltSize == 16 && KIdx) {
9661 SDValue BCVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Vec);
9662
9663 SDValue LoHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9664 DAG.getConstant(0, SL, MVT::i32));
9665 SDValue HiHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9666 DAG.getConstant(1, SL, MVT::i32));
9667
9668 SDValue LoVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, LoHalf);
9669 SDValue HiVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, HiHalf);
9670
9671 unsigned Idx = KIdx->getZExtValue();
9672 bool InsertLo = Idx < 2;
9673 SDValue InsHalf = DAG.getNode(
9674 ISD::INSERT_VECTOR_ELT, SL, MVT::v2i16, InsertLo ? LoVec : HiVec,
9675 DAG.getNode(ISD::BITCAST, SL, MVT::i16, InsVal),
9676 DAG.getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9677
9678 InsHalf = DAG.getNode(ISD::BITCAST, SL, MVT::i32, InsHalf);
9679
9680 SDValue Concat =
9681 InsertLo ? DAG.getBuildVector(MVT::v2i32, SL, {InsHalf, HiHalf})
9682 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9683
9684 return DAG.getNode(ISD::BITCAST, SL, VecVT, Concat);
9685 }
9686
9687 // Static indexing does not lower to stack access, and hence there is no need
9688 // for special custom lowering to avoid stack access.
9689 if (isa<ConstantSDNode>(Idx))
9690 return SDValue();
9691
9692 // Avoid stack access for dynamic indexing by custom lowering to
9693 // v_bfi_b32 (v_bfm_b32 16, (shl idx, 16)), val, vec
9694
9695 assert(VecSize <= 64 && "Expected target vector size to be <= 64 bits");
9696
9697 MVT IntVT = MVT::getIntegerVT(VecSize);
9698
9699 // Convert vector index to bit-index and get the required bit mask.
9700 assert(isPowerOf2_32(EltSize));
9701 const auto EltMask = maskTrailingOnes<uint64_t>(EltSize);
9702 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9703 SDValue ScaledIdx = DAG.getNode(ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9704 SDValue BFM = DAG.getNode(ISD::SHL, SL, IntVT,
9705 DAG.getConstant(EltMask, SL, IntVT), ScaledIdx);
9706
9707 // 1. Create a congruent vector with the target value in each element.
9708 SDValue ExtVal = DAG.getNode(ISD::BITCAST, SL, IntVT,
9709 DAG.getSplatBuildVector(VecVT, SL, InsVal));
9710
9711 // 2. Mask off all other indices except the required index within (1).
9712 SDValue LHS = DAG.getNode(ISD::AND, SL, IntVT, BFM, ExtVal);
9713
9714 // 3. Mask off the required index within the target vector.
9715 SDValue BCVec = DAG.getNode(ISD::BITCAST, SL, IntVT, Vec);
9716 SDValue RHS =
9717 DAG.getNode(ISD::AND, SL, IntVT, DAG.getNOT(SL, BFM, IntVT), BCVec);
9718
9719 // 4. Get (2) and (3) ORed into the target vector.
9720 SDValue BFI =
9721 DAG.getNode(ISD::OR, SL, IntVT, LHS, RHS, SDNodeFlags::Disjoint);
9722
9723 return DAG.getNode(ISD::BITCAST, SL, VecVT, BFI);
9724}
9725
9726SDValue SITargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op,
9727 SelectionDAG &DAG) const {
9728 SDLoc SL(Op);
9729
9730 EVT ResultVT = Op.getValueType();
9731 SDValue Vec = Op.getOperand(0);
9732 SDValue Idx = Op.getOperand(1);
9733 EVT VecVT = Vec.getValueType();
9734 unsigned VecSize = VecVT.getSizeInBits();
9735 EVT EltVT = VecVT.getVectorElementType();
9736
9737 DAGCombinerInfo DCI(DAG, AfterLegalizeVectorOps, true, nullptr);
9738
9739 // Make sure we do any optimizations that will make it easier to fold
9740 // source modifiers before obscuring it with bit operations.
9741
9742 // XXX - Why doesn't this get called when vector_shuffle is expanded?
9743 if (SDValue Combined = performExtractVectorEltCombine(Op.getNode(), DCI))
9744 return Combined;
9745
9746 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9747 SDValue Lo, Hi;
9748 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VecVT);
9749
9750 if (VecSize == 128) {
9751 SDValue V2 = DAG.getBitcast(MVT::v2i64, Vec);
9752 Lo = DAG.getBitcast(LoVT,
9753 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9754 DAG.getConstant(0, SL, MVT::i32)));
9755 Hi = DAG.getBitcast(HiVT,
9756 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9757 DAG.getConstant(1, SL, MVT::i32)));
9758 } else if (VecSize == 256) {
9759 SDValue V2 = DAG.getBitcast(MVT::v4i64, Vec);
9760 SDValue Parts[4];
9761 for (unsigned P = 0; P < 4; ++P) {
9762 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9763 DAG.getConstant(P, SL, MVT::i32));
9764 }
9765
9766 Lo = DAG.getBitcast(LoVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9767 Parts[0], Parts[1]));
9768 Hi = DAG.getBitcast(HiVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9769 Parts[2], Parts[3]));
9770 } else {
9771 assert(VecSize == 512);
9772
9773 SDValue V2 = DAG.getBitcast(MVT::v8i64, Vec);
9774 SDValue Parts[8];
9775 for (unsigned P = 0; P < 8; ++P) {
9776 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9777 DAG.getConstant(P, SL, MVT::i32));
9778 }
9779
9780 Lo = DAG.getBitcast(LoVT,
9781 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9782 Parts[0], Parts[1], Parts[2], Parts[3]));
9783 Hi = DAG.getBitcast(HiVT,
9784 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9785 Parts[4], Parts[5], Parts[6], Parts[7]));
9786 }
9787
9788 EVT IdxVT = Idx.getValueType();
9789 unsigned NElem = VecVT.getVectorNumElements();
9790 assert(isPowerOf2_32(NElem));
9791 SDValue IdxMask = DAG.getConstant(NElem / 2 - 1, SL, IdxVT);
9792 SDValue NewIdx = DAG.getNode(ISD::AND, SL, IdxVT, Idx, IdxMask);
9793 SDValue Half = DAG.getSelectCC(SL, Idx, IdxMask, Hi, Lo, ISD::SETUGT);
9794 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Half, NewIdx);
9795 }
9796
9797 assert(VecSize <= 64);
9798
9799 MVT IntVT = MVT::getIntegerVT(VecSize);
9800
9801 // If Vec is just a SCALAR_TO_VECTOR, then use the scalar integer directly.
9802 SDValue VecBC = peekThroughBitcasts(Vec);
9803 if (VecBC.getOpcode() == ISD::SCALAR_TO_VECTOR) {
9804 SDValue Src = VecBC.getOperand(0);
9805 Src = DAG.getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9806 Vec = DAG.getAnyExtOrTrunc(Src, SL, IntVT);
9807 }
9808
9809 unsigned EltSize = EltVT.getSizeInBits();
9810 assert(isPowerOf2_32(EltSize));
9811
9812 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9813
9814 // Convert vector index to bit-index (* EltSize)
9815 SDValue ScaledIdx = DAG.getNode(ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9816
9817 SDValue BC = DAG.getNode(ISD::BITCAST, SL, IntVT, Vec);
9818 SDValue Elt = DAG.getNode(ISD::SRL, SL, IntVT, BC, ScaledIdx);
9819
9820 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9821 SDValue Result = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Elt);
9822 return DAG.getNode(ISD::BITCAST, SL, ResultVT, Result);
9823 }
9824
9825 return DAG.getAnyExtOrTrunc(Elt, SL, ResultVT);
9826}
9827
9828static bool elementPairIsContiguous(ArrayRef<int> Mask, int Elt) {
9829 assert(Elt % 2 == 0);
9830 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9831}
9832
9833static bool elementPairIsOddToEven(ArrayRef<int> Mask, int Elt) {
9834 assert(Elt % 2 == 0);
9835 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9836 !(Mask[Elt + 1] & 1);
9837}
9838
9839SDValue SITargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
9840 SelectionDAG &DAG) const {
9841 SDLoc SL(Op);
9842 EVT ResultVT = Op.getValueType();
9843 ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
9844 MVT EltVT = ResultVT.getVectorElementType().getSimpleVT();
9845 const int NewSrcNumElts = 2;
9846 MVT PackVT = MVT::getVectorVT(EltVT, NewSrcNumElts);
9847 int SrcNumElts = Op.getOperand(0).getValueType().getVectorNumElements();
9848
9849 // Break up the shuffle into registers sized pieces.
9850 //
9851 // We're trying to form sub-shuffles that the register allocation pipeline
9852 // won't be able to figure out, like how to use v_pk_mov_b32 to do a register
9853 // blend or 16-bit op_sel. It should be able to figure out how to reassemble a
9854 // pair of copies into a consecutive register copy, so use the ordinary
9855 // extract_vector_elt lowering unless we can use the shuffle.
9856 //
9857 // TODO: This is a bit of hack, and we should probably always use
9858 // extract_subvector for the largest possible subvector we can (or at least
9859 // use it for PackVT aligned pieces). However we have worse support for
9860 // combines on them don't directly treat extract_subvector / insert_subvector
9861 // as legal. The DAG scheduler also ends up doing a worse job with the
9862 // extract_subvectors.
9863 const bool ShouldUseConsecutiveExtract = EltVT.getSizeInBits() == 16;
9864
9865 // vector_shuffle <0,1,6,7> lhs, rhs
9866 // -> concat_vectors (extract_subvector lhs, 0), (extract_subvector rhs, 2)
9867 //
9868 // vector_shuffle <6,7,2,3> lhs, rhs
9869 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 2)
9870 //
9871 // vector_shuffle <6,7,0,1> lhs, rhs
9872 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 0)
9873
9874 // Avoid scalarizing when both halves are reading from consecutive elements.
9875
9876 // If we're treating 2 element shuffles as legal, also create odd-to-even
9877 // shuffles of neighboring pairs.
9878 //
9879 // vector_shuffle <3,2,7,6> lhs, rhs
9880 // -> concat_vectors vector_shuffle <1, 0> (extract_subvector lhs, 0)
9881 // vector_shuffle <1, 0> (extract_subvector rhs, 2)
9882
9884 for (int I = 0, N = ResultVT.getVectorNumElements(); I != N; I += 2) {
9885 if (ShouldUseConsecutiveExtract &&
9887 const int Idx = SVN->getMaskElt(I);
9888 int VecIdx = Idx < SrcNumElts ? 0 : 1;
9889 int EltIdx = Idx < SrcNumElts ? Idx : Idx - SrcNumElts;
9890 SDValue SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT,
9891 SVN->getOperand(VecIdx),
9892 DAG.getConstant(EltIdx, SL, MVT::i32));
9893 Pieces.push_back(SubVec);
9894 } else if (elementPairIsOddToEven(SVN->getMask(), I) &&
9896 int Idx0 = SVN->getMaskElt(I);
9897 int Idx1 = SVN->getMaskElt(I + 1);
9898
9899 SDValue SrcOp0 = SVN->getOperand(0);
9900 SDValue SrcOp1 = SrcOp0;
9901 if (Idx0 >= SrcNumElts) {
9902 SrcOp0 = SVN->getOperand(1);
9903 Idx0 -= SrcNumElts;
9904 }
9905
9906 if (Idx1 >= SrcNumElts) {
9907 SrcOp1 = SVN->getOperand(1);
9908 Idx1 -= SrcNumElts;
9909 }
9910
9911 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
9912 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
9913
9914 // Extract nearest even aligned piece.
9915 SDValue SubVec0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp0,
9916 DAG.getConstant(AlignedIdx0, SL, MVT::i32));
9917 SDValue SubVec1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp1,
9918 DAG.getConstant(AlignedIdx1, SL, MVT::i32));
9919
9920 int NewMaskIdx0 = Idx0 - AlignedIdx0;
9921 int NewMaskIdx1 = Idx1 - AlignedIdx1;
9922
9923 SDValue Result0 = SubVec0;
9924 SDValue Result1 = SubVec0;
9925
9926 if (SubVec0 != SubVec1) {
9927 NewMaskIdx1 += NewSrcNumElts;
9928 Result1 = SubVec1;
9929 } else {
9930 Result1 = DAG.getPOISON(PackVT);
9931 }
9932
9933 SDValue Shuf = DAG.getVectorShuffle(PackVT, SL, Result0, Result1,
9934 {NewMaskIdx0, NewMaskIdx1});
9935 Pieces.push_back(Shuf);
9936 } else {
9937 const int Idx0 = SVN->getMaskElt(I);
9938 const int Idx1 = SVN->getMaskElt(I + 1);
9939 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
9940 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
9941 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
9942 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
9943
9944 SDValue Vec0 = SVN->getOperand(VecIdx0);
9945 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec0,
9946 DAG.getSignedConstant(EltIdx0, SL, MVT::i32));
9947
9948 SDValue Vec1 = SVN->getOperand(VecIdx1);
9949 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec1,
9950 DAG.getSignedConstant(EltIdx1, SL, MVT::i32));
9951 Pieces.push_back(DAG.getBuildVector(PackVT, SL, {Elt0, Elt1}));
9952 }
9953 }
9954
9955 return DAG.getNode(ISD::CONCAT_VECTORS, SL, ResultVT, Pieces);
9956}
9957
9958SDValue SITargetLowering::lowerSCALAR_TO_VECTOR(SDValue Op,
9959 SelectionDAG &DAG) const {
9960 SDValue SVal = Op.getOperand(0);
9961 EVT ResultVT = Op.getValueType();
9962 EVT SValVT = SVal.getValueType();
9963 SDValue UndefVal = DAG.getPOISON(SValVT);
9964 SDLoc SL(Op);
9965
9967 VElts.push_back(SVal);
9968 for (int I = 1, E = ResultVT.getVectorNumElements(); I < E; ++I)
9969 VElts.push_back(UndefVal);
9970
9971 return DAG.getBuildVector(ResultVT, SL, VElts);
9972}
9973
9974SDValue SITargetLowering::lowerBUILD_VECTOR(SDValue Op,
9975 SelectionDAG &DAG) const {
9976 SDLoc SL(Op);
9977 EVT VT = Op.getValueType();
9978
9979 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
9980 assert(!Subtarget->hasVOP3PInsts() && "this should be legal");
9981
9982 SDValue Lo = Op.getOperand(0);
9983 SDValue Hi = Op.getOperand(1);
9984
9985 // Avoid adding defined bits with the zero_extend.
9986 if (Hi.isUndef()) {
9987 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
9988 SDValue ExtLo = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Lo);
9989 return DAG.getNode(ISD::BITCAST, SL, VT, ExtLo);
9990 }
9991
9992 Hi = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Hi);
9993 Hi = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Hi);
9994
9995 SDValue ShlHi = DAG.getNode(ISD::SHL, SL, MVT::i32, Hi,
9996 DAG.getConstant(16, SL, MVT::i32));
9997 if (Lo.isUndef())
9998 return DAG.getNode(ISD::BITCAST, SL, VT, ShlHi);
9999
10000 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
10001 Lo = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Lo);
10002
10003 SDValue Or =
10004 DAG.getNode(ISD::OR, SL, MVT::i32, Lo, ShlHi, SDNodeFlags::Disjoint);
10005 return DAG.getNode(ISD::BITCAST, SL, VT, Or);
10006 }
10007
10008 // Split into 2-element chunks.
10009 const unsigned NumParts = VT.getVectorNumElements() / 2;
10010 EVT PartVT = MVT::getVectorVT(VT.getVectorElementType().getSimpleVT(), 2);
10011 MVT PartIntVT = MVT::getIntegerVT(PartVT.getSizeInBits());
10012
10014 for (unsigned P = 0; P < NumParts; ++P) {
10015 SDValue Vec = DAG.getBuildVector(
10016 PartVT, SL, {Op.getOperand(P * 2), Op.getOperand(P * 2 + 1)});
10017 Casts.push_back(DAG.getNode(ISD::BITCAST, SL, PartIntVT, Vec));
10018 }
10019
10020 SDValue Blend =
10021 DAG.getBuildVector(MVT::getVectorVT(PartIntVT, NumParts), SL, Casts);
10022 return DAG.getNode(ISD::BITCAST, SL, VT, Blend);
10023}
10024
10026 const GlobalAddressSDNode *GA) const {
10027 // Named barriers have fixed, non-relocated LDS addresses, so a constant
10028 // offset into an array of them can be folded into the address.
10030 const auto *GV = dyn_cast<GlobalVariable>(GA->getGlobal());
10031 return GV && AMDGPU::isNamedBarrier(*GV);
10032 }
10033
10034 // OSes that use ELF REL relocations (instead of RELA) can only store a
10035 // 32-bit addend in the instruction, so it is not safe to allow offset folding
10036 // which can create arbitrary 64-bit addends. (This is only a problem for
10037 // R_AMDGPU_*32_HI relocations since other relocation types are unaffected by
10038 // the high 32 bits of the addend.)
10039 //
10040 // This should be kept in sync with how HasRelocationAddend is initialized in
10041 // the constructor of ELFAMDGPUAsmBackend.
10042 if (!Subtarget->isAmdHsaOS())
10043 return false;
10044
10045 // We can fold offsets for anything that doesn't require a GOT relocation.
10046 return (GA->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS ||
10050}
10051
10052static SDValue
10054 const SDLoc &DL, int64_t Offset, EVT PtrVT,
10055 unsigned GAFlags = SIInstrInfo::MO_NONE) {
10056 assert(isInt<32>(Offset + 4) && "32-bit offset is expected!");
10057 // In order to support pc-relative addressing, the PC_ADD_REL_OFFSET SDNode is
10058 // lowered to the following code sequence:
10059 //
10060 // For constant address space:
10061 // s_getpc_b64 s[0:1]
10062 // s_add_u32 s0, s0, $symbol
10063 // s_addc_u32 s1, s1, 0
10064 //
10065 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10066 // a fixup or relocation is emitted to replace $symbol with a literal
10067 // constant, which is a pc-relative offset from the encoding of the $symbol
10068 // operand to the global variable.
10069 //
10070 // For global address space:
10071 // s_getpc_b64 s[0:1]
10072 // s_add_u32 s0, s0, $symbol@{gotpc}rel32@lo
10073 // s_addc_u32 s1, s1, $symbol@{gotpc}rel32@hi
10074 //
10075 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10076 // fixups or relocations are emitted to replace $symbol@*@lo and
10077 // $symbol@*@hi with lower 32 bits and higher 32 bits of a literal constant,
10078 // which is a 64-bit pc-relative offset from the encoding of the $symbol
10079 // operand to the global variable.
10080 if (((const GCNSubtarget &)DAG.getSubtarget()).has64BitLiterals()) {
10081 assert(GAFlags != SIInstrInfo::MO_NONE);
10082
10083 SDValue Ptr =
10084 DAG.getTargetGlobalAddress(GV, DL, MVT::i64, Offset, GAFlags + 2);
10085 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET64, DL, PtrVT, Ptr);
10086 }
10087
10088 SDValue PtrLo = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags);
10089 SDValue PtrHi;
10090 if (GAFlags == SIInstrInfo::MO_NONE)
10091 PtrHi = DAG.getTargetConstant(0, DL, MVT::i32);
10092 else
10093 PtrHi = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags + 1);
10094 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET, DL, PtrVT, PtrLo, PtrHi);
10095}
10096
10097SDValue SITargetLowering::LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI,
10098 SDValue Op,
10099 SelectionDAG &DAG) const {
10100 GlobalAddressSDNode *GSD = cast<GlobalAddressSDNode>(Op);
10101 SDLoc DL(GSD);
10102 EVT PtrVT = Op.getValueType();
10103
10104 const GlobalValue *GV = GSD->getGlobal();
10105 const unsigned AS = GSD->getAddressSpace();
10106 if (((AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::BARRIER) &&
10109 if (AS == AMDGPUAS::LOCAL_ADDRESS && GV->hasExternalLinkage()) {
10110 const GlobalVariable &GVar = *cast<GlobalVariable>(GV);
10111 // HIP uses an unsized array `extern __shared__ T s[]` or similar
10112 // zero-sized type in other languages to declare the dynamic shared
10113 // memory which size is not known at the compile time. They will be
10114 // allocated by the runtime and placed directly after the static
10115 // allocated ones. They all share the same offset.
10116 if (GVar.getGlobalSize(GVar.getDataLayout()) == 0) {
10117 assert(PtrVT == MVT::i32 && "32-bit pointer is expected.");
10118 // Adjust alignment for that dynamic shared memory array.
10120 MFI->setDynLDSAlign(F, GVar);
10121 MFI->setUsesDynamicLDS(true);
10122 return SDValue(
10123 DAG.getMachineNode(AMDGPU::GET_GROUPSTATICSIZE, DL, PtrVT), 0);
10124 }
10125 }
10127 }
10128
10129 if (AS == AMDGPUAS::BARRIER) {
10130 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, GSD->getOffset(),
10132 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0);
10133 }
10134
10135 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
10136 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, GSD->getOffset(),
10138 return DAG.getNode(AMDGPUISD::LDS, DL, MVT::i32, GA);
10139 }
10140
10141 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10142 if (Subtarget->has64BitLiterals()) {
10144 GV, DL, MVT::i64, GSD->getOffset(), SIInstrInfo::MO_ABS64);
10145 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B64, DL, MVT::i64, Addr),
10146 0);
10147 }
10148
10149 SDValue AddrLo = DAG.getTargetGlobalAddress(
10150 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_LO);
10151 AddrLo = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrLo), 0};
10152
10153 SDValue AddrHi = DAG.getTargetGlobalAddress(
10154 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_HI);
10155 AddrHi = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrHi), 0};
10156
10157 return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, AddrLo, AddrHi);
10158 }
10159
10160 if (shouldEmitFixup(GV))
10161 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT);
10162
10163 if (shouldEmitPCReloc(GV))
10164 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT,
10166
10167 SDValue GOTAddr = buildPCRelGlobalAddress(DAG, GV, DL, 0, PtrVT,
10169 PointerType *PtrTy =
10171 const DataLayout &DataLayout = DAG.getDataLayout();
10172 Align Alignment = DataLayout.getABITypeAlign(PtrTy);
10173 MachinePointerInfo PtrInfo =
10175
10176 return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), GOTAddr, PtrInfo, Alignment,
10179}
10180
10181SDValue SITargetLowering::LowerExternalSymbol(SDValue Op,
10182 SelectionDAG &DAG) const {
10183 // TODO: Handle this. It should be mostly the same as LowerGlobalAddress.
10184 const Function &Fn = DAG.getMachineFunction().getFunction();
10185 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10186 Fn, "unsupported external symbol", Op.getDebugLoc()));
10187 return DAG.getPOISON(Op.getValueType());
10188}
10189
10191 const SDLoc &DL, SDValue V) const {
10192 // We can't use S_MOV_B32 directly, because there is no way to specify m0 as
10193 // the destination register.
10194 //
10195 // We can't use CopyToReg, because MachineCSE won't combine COPY instructions,
10196 // so we will end up with redundant moves to m0.
10197 //
10198 // We use a pseudo to ensure we emit s_mov_b32 with m0 as the direct result.
10199
10200 // A Null SDValue creates a glue result.
10201 SDNode *M0 = DAG.getMachineNode(AMDGPU::SI_INIT_M0, DL, MVT::Other, MVT::Glue,
10202 V, Chain);
10203 return SDValue(M0, 0);
10204}
10205
10206SDValue SITargetLowering::lowerImplicitZextParam(SelectionDAG &DAG, SDValue Op,
10207 MVT VT,
10208 unsigned Offset) const {
10209 SDLoc SL(Op);
10210 SDValue Param = lowerKernargMemParameter(
10211 DAG, MVT::i32, MVT::i32, SL, DAG.getEntryNode(), Offset, Align(4), false);
10212 // The local size values will have the hi 16-bits as zero.
10213 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Param,
10214 DAG.getValueType(VT));
10215}
10216
10218 EVT VT) {
10221 "non-hsa intrinsic with hsa target", DL.getDebugLoc()));
10222 return DAG.getPOISON(VT);
10223}
10224
10226 EVT VT) {
10229 "intrinsic not supported on subtarget", DL.getDebugLoc()));
10230 return DAG.getPOISON(VT);
10231}
10232
10234 ArrayRef<SDValue> Elts) {
10235 assert(!Elts.empty());
10236 MVT Type;
10237 unsigned NumElts = Elts.size();
10238
10239 if (NumElts <= 12) {
10240 Type = MVT::getVectorVT(MVT::f32, NumElts);
10241 } else {
10242 assert(Elts.size() <= 16);
10243 Type = MVT::v16f32;
10244 NumElts = 16;
10245 }
10246
10247 SmallVector<SDValue, 16> VecElts(NumElts);
10248 for (unsigned i = 0; i < Elts.size(); ++i) {
10249 SDValue Elt = Elts[i];
10250 if (Elt.getValueType() != MVT::f32)
10251 Elt = DAG.getBitcast(MVT::f32, Elt);
10252 VecElts[i] = Elt;
10253 }
10254 for (unsigned i = Elts.size(); i < NumElts; ++i)
10255 VecElts[i] = DAG.getPOISON(MVT::f32);
10256
10257 if (NumElts == 1)
10258 return VecElts[0];
10259 return DAG.getBuildVector(Type, DL, VecElts);
10260}
10261
10262static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT,
10263 SDValue Src, int ExtraElts) {
10264 EVT SrcVT = Src.getValueType();
10265
10267
10268 if (SrcVT.isVector())
10269 DAG.ExtractVectorElements(Src, Elts);
10270 else
10271 Elts.push_back(Src);
10272
10273 SDValue Undef = DAG.getPOISON(SrcVT.getScalarType());
10274 while (ExtraElts--)
10275 Elts.push_back(Undef);
10276
10277 return DAG.getBuildVector(CastVT, DL, Elts);
10278}
10279
10280// Re-construct the required return value for a image load intrinsic.
10281// This is more complicated due to the optional use TexFailCtrl which means the
10282// required return type is an aggregate
10284 ArrayRef<EVT> ResultTypes, bool IsTexFail,
10285 bool Unpacked, bool IsD16, int DMaskPop,
10286 int NumVDataDwords, bool IsAtomicPacked16Bit,
10287 const SDLoc &DL) {
10288 // Determine the required return type. This is the same regardless of
10289 // IsTexFail flag
10290 EVT ReqRetVT = ResultTypes[0];
10291 int ReqRetNumElts = ReqRetVT.isVector() ? ReqRetVT.getVectorNumElements() : 1;
10292 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10293 ? (ReqRetNumElts + 1) / 2
10294 : ReqRetNumElts;
10295
10296 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10297
10298 MVT DataDwordVT =
10299 NumDataDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, NumDataDwords);
10300
10301 MVT MaskPopVT =
10302 MaskPopDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, MaskPopDwords);
10303
10304 SDValue Data(Result, 0);
10305 SDValue TexFail;
10306
10307 if (DMaskPop > 0 && Data.getValueType() != MaskPopVT) {
10308 SDValue ZeroIdx = DAG.getConstant(0, DL, MVT::i32);
10309 if (MaskPopVT.isVector()) {
10310 Data = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, MaskPopVT,
10311 SDValue(Result, 0), ZeroIdx);
10312 } else {
10313 Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MaskPopVT,
10314 SDValue(Result, 0), ZeroIdx);
10315 }
10316 }
10317
10318 if (DataDwordVT.isVector() && !IsAtomicPacked16Bit)
10319 Data = padEltsToUndef(DAG, DL, DataDwordVT, Data,
10320 NumDataDwords - MaskPopDwords);
10321
10322 if (IsD16)
10323 Data = adjustLoadValueTypeImpl(Data, ReqRetVT, DL, DAG, Unpacked);
10324
10325 EVT LegalReqRetVT = ReqRetVT;
10326 if (!ReqRetVT.isVector()) {
10327 if (!Data.getValueType().isInteger())
10328 Data = DAG.getNode(ISD::BITCAST, DL,
10329 Data.getValueType().changeTypeToInteger(), Data);
10330 Data = DAG.getNode(ISD::TRUNCATE, DL, ReqRetVT.changeTypeToInteger(), Data);
10331 } else {
10332 // We need to widen the return vector to a legal type
10333 if ((ReqRetVT.getVectorNumElements() % 2) == 1 &&
10334 ReqRetVT.getVectorElementType().getSizeInBits() == 16) {
10335 LegalReqRetVT =
10337 ReqRetVT.getVectorNumElements() + 1);
10338 }
10339 }
10340 Data = DAG.getNode(ISD::BITCAST, DL, LegalReqRetVT, Data);
10341
10342 if (IsTexFail) {
10343 TexFail =
10344 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, SDValue(Result, 0),
10345 DAG.getConstant(MaskPopDwords, DL, MVT::i32));
10346
10347 return DAG.getMergeValues({Data, TexFail, SDValue(Result, 1)}, DL);
10348 }
10349
10350 if (Result->getNumValues() == 1)
10351 return Data;
10352
10353 return DAG.getMergeValues({Data, SDValue(Result, 1)}, DL);
10354}
10355
10356static bool parseTexFail(SDValue TexFailCtrl, SelectionDAG &DAG, SDValue *TFE,
10357 SDValue *LWE, bool &IsTexFail) {
10358 auto *TexFailCtrlConst = cast<ConstantSDNode>(TexFailCtrl.getNode());
10359
10360 uint64_t Value = TexFailCtrlConst->getZExtValue();
10361 if (Value) {
10362 IsTexFail = true;
10363 }
10364
10365 SDLoc DL(TexFailCtrlConst);
10366 *TFE = DAG.getTargetConstant((Value & 0x1) ? 1 : 0, DL, MVT::i32);
10367 Value &= ~(uint64_t)0x1;
10368 *LWE = DAG.getTargetConstant((Value & 0x2) ? 1 : 0, DL, MVT::i32);
10369 Value &= ~(uint64_t)0x2;
10370
10371 return Value == 0;
10372}
10373
10375 MVT PackVectorVT,
10376 SmallVectorImpl<SDValue> &PackedAddrs,
10377 unsigned DimIdx, unsigned EndIdx,
10378 unsigned NumGradients) {
10379 SDLoc DL(Op);
10380 for (unsigned I = DimIdx; I < EndIdx; I++) {
10381 SDValue Addr = Op.getOperand(I);
10382
10383 // Gradients are packed with undef for each coordinate.
10384 // In <hi 16 bit>,<lo 16 bit> notation, the registers look like this:
10385 // 1D: undef,dx/dh; undef,dx/dv
10386 // 2D: dy/dh,dx/dh; dy/dv,dx/dv
10387 // 3D: dy/dh,dx/dh; undef,dz/dh; dy/dv,dx/dv; undef,dz/dv
10388 if (((I + 1) >= EndIdx) ||
10389 ((NumGradients / 2) % 2 == 1 && (I == DimIdx + (NumGradients / 2) - 1 ||
10390 I == DimIdx + NumGradients - 1))) {
10391 if (Addr.getValueType() != MVT::i16)
10392 Addr = DAG.getBitcast(MVT::i16, Addr);
10393 Addr = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Addr);
10394 } else {
10395 Addr = DAG.getBuildVector(PackVectorVT, DL, {Addr, Op.getOperand(I + 1)});
10396 I++;
10397 }
10398 Addr = DAG.getBitcast(MVT::f32, Addr);
10399 PackedAddrs.push_back(Addr);
10400 }
10401}
10402
10403/// Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and
10404/// return poison values of \p ResultTypes, preserving the chain if present.
10406 ArrayRef<EVT> ResultTypes,
10407 const SDLoc &DL, const Twine &Msg) {
10409 DAG.getMachineFunction().getFunction(), Msg, DL.getDebugLoc()));
10410 return DAG.getErrorMergeValues(ResultTypes, Op.getOperand(0), DL);
10411}
10412
10413SDValue SITargetLowering::lowerImage(SDValue Op,
10415 SelectionDAG &DAG, bool WithChain) const {
10416 SDLoc DL(Op);
10418 const GCNSubtarget *ST = &MF.getSubtarget<GCNSubtarget>();
10419 unsigned IntrOpcode = Intr->BaseOpcode;
10420 // For image atomic: use no-return opcode if result is unused.
10421 if (Intr->AtomicNoRetBaseOpcode != Intr->BaseOpcode &&
10422 !Op.getNode()->hasAnyUseOfValue(0))
10423 IntrOpcode = Intr->AtomicNoRetBaseOpcode;
10424 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10426 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfo(Intr->Dim);
10427 bool IsGFX10Plus = AMDGPU::isGFX10Plus(*Subtarget);
10428 bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
10429 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
10430 bool IsGFX13 = AMDGPU::isGFX13(*Subtarget);
10431
10432 SmallVector<EVT, 3> ResultTypes(Op->values());
10433 SmallVector<EVT, 3> OrigResultTypes(Op->values());
10434 if (BaseOpcode->NoReturn && BaseOpcode->Atomic)
10435 ResultTypes.erase(&ResultTypes[0]);
10436
10437 bool IsD16 = false;
10438 bool IsG16 = false;
10439 bool IsA16 = false;
10440 SDValue VData;
10441 int NumVDataDwords = 0;
10442 bool AdjustRetType = false;
10443 bool IsAtomicPacked16Bit = false;
10444
10445 // Offset of intrinsic arguments
10446 const unsigned ArgOffset = WithChain ? 2 : 1;
10447
10448 unsigned DMask;
10449 unsigned DMaskLanes = 0;
10450
10451 if (BaseOpcode->Atomic) {
10452 VData = Op.getOperand(2);
10453
10454 IsAtomicPacked16Bit =
10455 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10456 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10457 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10458 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10459
10460 if (!IsAtomicPacked16Bit && VData.getValueSizeInBits() != 32 &&
10461 VData.getValueSizeInBits() != 64) {
10462 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10463 "unsupported image atomic data type");
10464 }
10465
10466 bool Is64Bit = VData.getValueSizeInBits() == 64;
10467 if (BaseOpcode->AtomicX2) {
10468 SDValue VData2 = Op.getOperand(3);
10469 VData = DAG.getBuildVector(Is64Bit ? MVT::v2i64 : MVT::v2i32, DL,
10470 {VData, VData2});
10471 if (Is64Bit)
10472 VData = DAG.getBitcast(MVT::v4i32, VData);
10473
10474 if (!BaseOpcode->NoReturn)
10475 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10476
10477 DMask = Is64Bit ? 0xf : 0x3;
10478 NumVDataDwords = Is64Bit ? 4 : 2;
10479 } else {
10480 DMask = Is64Bit ? 0x3 : 0x1;
10481 NumVDataDwords = Is64Bit ? 2 : 1;
10482 }
10483 } else {
10484 DMask = Op->getConstantOperandVal(ArgOffset + Intr->DMaskIndex);
10485 DMaskLanes = BaseOpcode->Gather4 ? 4 : llvm::popcount(DMask);
10486
10487 if (BaseOpcode->Store) {
10488 VData = Op.getOperand(2);
10489
10490 MVT StoreVT = VData.getSimpleValueType();
10491 MVT StoreScalarVT = StoreVT.getScalarType();
10492 if (StoreScalarVT != MVT::f16 && StoreScalarVT.getSizeInBits() != 32 &&
10493 StoreScalarVT.getSizeInBits() != 64) {
10494 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10495 "unsupported image store data type");
10496 }
10497 if (StoreScalarVT == MVT::f16) {
10498 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10499 return Op; // D16 is unsupported for this instruction
10500
10501 IsD16 = true;
10502 VData = handleD16VData(VData, DAG, true);
10503 }
10504
10505 NumVDataDwords = (VData.getValueType().getSizeInBits() + 31) / 32;
10506 } else if (!BaseOpcode->NoReturn) {
10507 // Work out the num dwords based on the dmask popcount and underlying type
10508 // and whether packing is supported.
10509 MVT LoadVT = ResultTypes[0].getSimpleVT();
10510 MVT LoadScalarVT = LoadVT.getScalarType();
10511 if (LoadScalarVT != MVT::f16 && LoadScalarVT.getSizeInBits() != 32 &&
10512 LoadScalarVT.getSizeInBits() != 64) {
10513 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10514 "unsupported image load data type");
10515 }
10516 if (LoadScalarVT == MVT::f16) {
10517 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10518 return Op; // D16 is unsupported for this instruction
10519
10520 IsD16 = true;
10521 }
10522
10523 // Confirm that the return type is large enough for the dmask specified
10524 if ((LoadVT.isVector() && LoadVT.getVectorNumElements() < DMaskLanes) ||
10525 (!LoadVT.isVector() && DMaskLanes > 1))
10526 return Op;
10527
10528 // The sq block of gfx8 and gfx9 do not estimate register use correctly
10529 // for d16 image_gather4, image_gather4_l, and image_gather4_lz
10530 // instructions.
10531 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10532 !(BaseOpcode->Gather4 && Subtarget->hasImageGather4D16Bug()))
10533 NumVDataDwords = (DMaskLanes + 1) / 2;
10534 else
10535 NumVDataDwords = DMaskLanes;
10536
10537 AdjustRetType = true;
10538 }
10539 }
10540
10541 unsigned VAddrEnd = ArgOffset + Intr->VAddrEnd;
10543
10544 // Check for 16 bit addresses or derivatives and pack if true.
10545 MVT VAddrVT =
10546 Op.getOperand(ArgOffset + Intr->GradientStart).getSimpleValueType();
10547 MVT VAddrScalarVT = VAddrVT.getScalarType();
10548 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10549 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10550
10551 VAddrVT = Op.getOperand(ArgOffset + Intr->CoordStart).getSimpleValueType();
10552 VAddrScalarVT = VAddrVT.getScalarType();
10553 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10554 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10555
10556 // Push back extra arguments.
10557 for (unsigned I = Intr->VAddrStart; I < Intr->GradientStart; I++) {
10558 if (IsA16 && (Op.getOperand(ArgOffset + I).getValueType() == MVT::f16)) {
10559 assert(I == Intr->BiasIndex && "Got unexpected 16-bit extra argument");
10560 // Special handling of bias when A16 is on. Bias is of type half but
10561 // occupies full 32-bit.
10562 SDValue Bias = DAG.getBuildVector(
10563 MVT::v2f16, DL,
10564 {Op.getOperand(ArgOffset + I), DAG.getPOISON(MVT::f16)});
10565 VAddrs.push_back(Bias);
10566 } else {
10567 assert((!IsA16 || Intr->NumBiasArgs == 0 || I != Intr->BiasIndex) &&
10568 "Bias needs to be converted to 16 bit in A16 mode");
10569 VAddrs.push_back(Op.getOperand(ArgOffset + I));
10570 }
10571 }
10572
10573 if (BaseOpcode->Gradients && !ST->hasG16() && (IsA16 != IsG16)) {
10574 // 16 bit gradients are supported, but are tied to the A16 control
10575 // so both gradients and addresses must be 16 bit
10576 LLVM_DEBUG(
10577 dbgs() << "Failed to lower image intrinsic: 16 bit addresses "
10578 "require 16 bit args for both gradients and addresses");
10579 return Op;
10580 }
10581
10582 if (IsA16) {
10583 if (!ST->hasA16()) {
10584 LLVM_DEBUG(dbgs() << "Failed to lower image intrinsic: Target does not "
10585 "support 16 bit addresses\n");
10586 return Op;
10587 }
10588 }
10589
10590 // We've dealt with incorrect input so we know that if IsA16, IsG16
10591 // are set then we have to compress/pack operands (either address,
10592 // gradient or both)
10593 // In the case where a16 and gradients are tied (no G16 support) then we
10594 // have already verified that both IsA16 and IsG16 are true
10595 if (BaseOpcode->Gradients && IsG16 && ST->hasG16()) {
10596 // Activate g16
10597 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10599 IntrOpcode = G16MappingInfo->G16; // set new opcode to variant with _g16
10600 }
10601
10602 // Add gradients (packed or unpacked)
10603 if (IsG16) {
10604 // Pack the gradients
10605 // const int PackEndIdx = IsA16 ? VAddrEnd : (ArgOffset + Intr->CoordStart);
10606 packImage16bitOpsToDwords(DAG, Op, GradPackVectorVT, VAddrs,
10607 ArgOffset + Intr->GradientStart,
10608 ArgOffset + Intr->CoordStart, Intr->NumGradients);
10609 } else {
10610 for (unsigned I = ArgOffset + Intr->GradientStart;
10611 I < ArgOffset + Intr->CoordStart; I++)
10612 VAddrs.push_back(Op.getOperand(I));
10613 }
10614
10615 // Add addresses (packed or unpacked)
10616 if (IsA16) {
10617 packImage16bitOpsToDwords(DAG, Op, AddrPackVectorVT, VAddrs,
10618 ArgOffset + Intr->CoordStart, VAddrEnd,
10619 0 /* No gradients */);
10620 } else {
10621 // Add uncompressed address
10622 for (unsigned I = ArgOffset + Intr->CoordStart; I < VAddrEnd; I++)
10623 VAddrs.push_back(Op.getOperand(I));
10624 }
10625
10626 // If the register allocator cannot place the address registers contiguously
10627 // without introducing moves, then using the non-sequential address encoding
10628 // is always preferable, since it saves VALU instructions and is usually a
10629 // wash in terms of code size or even better.
10630 //
10631 // However, we currently have no way of hinting to the register allocator that
10632 // MIMG addresses should be placed contiguously when it is possible to do so,
10633 // so force non-NSA for the common 2-address case as a heuristic.
10634 //
10635 // SIShrinkInstructions will convert NSA encodings to non-NSA after register
10636 // allocation when possible.
10637 //
10638 // Partial NSA is allowed on GFX11+ where the final register is a contiguous
10639 // set of the remaining addresses.
10640 const unsigned NSAMaxSize = ST->getNSAMaxSize(BaseOpcode->Sampler);
10641 const bool HasPartialNSAEncoding = ST->hasPartialNSAEncoding();
10642 const bool UseNSA = ST->hasNSAEncoding() &&
10643 VAddrs.size() >= ST->getNSAThreshold(MF) &&
10644 (VAddrs.size() <= NSAMaxSize || HasPartialNSAEncoding);
10645 const bool UsePartialNSA =
10646 UseNSA && HasPartialNSAEncoding && VAddrs.size() > NSAMaxSize;
10647
10648 SDValue VAddr;
10649 if (UsePartialNSA) {
10650 VAddr = getBuildDwordsVector(DAG, DL,
10651 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10652 } else if (!UseNSA) {
10653 VAddr = getBuildDwordsVector(DAG, DL, VAddrs);
10654 }
10655
10656 SDValue True = DAG.getTargetConstant(1, DL, MVT::i1);
10657 SDValue False = DAG.getTargetConstant(0, DL, MVT::i1);
10658 SDValue Unorm;
10659 if (!BaseOpcode->Sampler) {
10660 Unorm = True;
10661 } else {
10662 uint64_t UnormConst =
10663 Op.getConstantOperandVal(ArgOffset + Intr->UnormIndex);
10664
10665 Unorm = UnormConst ? True : False;
10666 }
10667
10668 SDValue TFE;
10669 SDValue LWE;
10670 SDValue TexFail = Op.getOperand(ArgOffset + Intr->TexFailCtrlIndex);
10671 bool IsTexFail = false;
10672 if (!parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10673 return Op;
10674
10675 if (IsTexFail) {
10676 if (!DMaskLanes) {
10677 // Expecting to get an error flag since TFC is on - and dmask is 0
10678 // Force dmask to be at least 1 otherwise the instruction will fail
10679 DMask = 0x1;
10680 DMaskLanes = 1;
10681 NumVDataDwords = 1;
10682 }
10683 NumVDataDwords += 1;
10684 AdjustRetType = true;
10685 }
10686
10687 // Has something earlier tagged that the return type needs adjusting
10688 // This happens if the instruction is a load or has set TexFailCtrl flags
10689 if (AdjustRetType) {
10690 // NumVDataDwords reflects the true number of dwords required in the return
10691 // type
10692 if (DMaskLanes == 0 && !BaseOpcode->Store) {
10693 // This is a no-op load. This can be eliminated
10694 SDValue Undef = DAG.getPOISON(Op.getValueType());
10695 if (isa<MemSDNode>(Op))
10696 return DAG.getMergeValues({Undef, Op.getOperand(0)}, DL);
10697 return Undef;
10698 }
10699
10700 EVT NewVT = NumVDataDwords > 1 ? EVT::getVectorVT(*DAG.getContext(),
10701 MVT::i32, NumVDataDwords)
10702 : MVT::i32;
10703
10704 ResultTypes[0] = NewVT;
10705 if (ResultTypes.size() == 3) {
10706 // Original result was aggregate type used for TexFailCtrl results
10707 // The actual instruction returns as a vector type which has now been
10708 // created. Remove the aggregate result.
10709 ResultTypes.erase(&ResultTypes[1]);
10710 }
10711 }
10712
10713 unsigned CPol = Op.getConstantOperandVal(ArgOffset + Intr->CachePolicyIndex);
10714 // Keep GLC only when the atomic's result is actually used.
10715 if (BaseOpcode->Atomic && !BaseOpcode->NoReturn)
10717 if (CPol & ~((IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12) |
10719 return Op;
10720
10722 if (BaseOpcode->Store || BaseOpcode->Atomic)
10723 Ops.push_back(VData); // vdata
10724 if (UsePartialNSA) {
10725 append_range(Ops, ArrayRef(VAddrs).take_front(NSAMaxSize - 1));
10726 Ops.push_back(VAddr);
10727 } else if (UseNSA)
10728 append_range(Ops, VAddrs);
10729 else
10730 Ops.push_back(VAddr);
10731 SDValue Rsrc = Op.getOperand(ArgOffset + Intr->RsrcIndex);
10732 EVT RsrcVT = Rsrc.getValueType();
10733 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32)
10734 return Op;
10735 Ops.push_back(Rsrc);
10736 if (BaseOpcode->Sampler) {
10737 SDValue Samp = Op.getOperand(ArgOffset + Intr->SampIndex);
10738 if (Samp.getValueType() != MVT::v4i32)
10739 return Op;
10740 Ops.push_back(Samp);
10741 }
10742 Ops.push_back(DAG.getTargetConstant(DMask, DL, MVT::i32));
10743 if (IsGFX10Plus)
10744 Ops.push_back(DAG.getTargetConstant(DimInfo->Encoding, DL, MVT::i32));
10745 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10746 Ops.push_back(Unorm);
10747 Ops.push_back(DAG.getTargetConstant(CPol, DL, MVT::i32));
10748 Ops.push_back(IsA16 && // r128, a16 for gfx9
10749 ST->hasFeature(AMDGPU::FeatureR128A16)
10750 ? True
10751 : False);
10752 if (IsGFX10Plus)
10753 Ops.push_back(IsA16 ? True : False);
10754
10755 if (!Subtarget->hasGFX90AInsts())
10756 Ops.push_back(TFE); // tfe
10757 else if (TFE->getAsZExtVal()) {
10758 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10760 "TFE is not supported on this GPU", DL.getDebugLoc()));
10761 }
10762
10763 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10764 Ops.push_back(LWE); // lwe
10765 if (!IsGFX10Plus)
10766 Ops.push_back(DimInfo->DA ? True : False);
10767 if (BaseOpcode->HasD16)
10768 Ops.push_back(IsD16 ? True : False);
10769 if (isa<MemSDNode>(Op))
10770 Ops.push_back(Op.getOperand(0)); // chain
10771
10772 int NumVAddrDwords =
10773 UseNSA ? VAddrs.size() : VAddr.getValueType().getSizeInBits() / 32;
10774 int Opcode = -1;
10775
10776 if (IsGFX13) {
10777 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx13,
10778 NumVDataDwords, NumVAddrDwords);
10779 } else if (IsGFX12Plus) {
10780 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx12,
10781 NumVDataDwords, NumVAddrDwords);
10782 } else if (IsGFX11Plus) {
10783 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10784 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10785 : AMDGPU::MIMGEncGfx11Default,
10786 NumVDataDwords, NumVAddrDwords);
10787 } else if (IsGFX10Plus) {
10788 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10789 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10790 : AMDGPU::MIMGEncGfx10Default,
10791 NumVDataDwords, NumVAddrDwords);
10792 } else {
10793 if (Subtarget->hasGFX90AInsts()) {
10794 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx90a,
10795 NumVDataDwords, NumVAddrDwords);
10796 if (Opcode == -1) {
10798 DAG, Op, OrigResultTypes, DL,
10799 "requested image instruction is not supported on this GPU");
10800 }
10801 }
10802 if (Opcode == -1 &&
10803 Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10804 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx8,
10805 NumVDataDwords, NumVAddrDwords);
10806 if (Opcode == -1)
10807 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx6,
10808 NumVDataDwords, NumVAddrDwords);
10809 }
10810 if (Opcode == -1)
10811 return Op;
10812
10813 MachineSDNode *NewNode = DAG.getMachineNode(Opcode, DL, ResultTypes, Ops);
10814 if (auto *MemOp = dyn_cast<MemSDNode>(Op)) {
10815 MachineMemOperand *MemRef = MemOp->getMemOperand();
10816 DAG.setNodeMemRefs(NewNode, {MemRef});
10817 }
10818
10819 if (BaseOpcode->NoReturn) {
10820 if (BaseOpcode->Atomic)
10821 return DAG.getMergeValues(
10822 {DAG.getPOISON(OrigResultTypes[0]), SDValue(NewNode, 0)}, DL);
10823
10824 return SDValue(NewNode, 0);
10825 }
10826
10827 if (BaseOpcode->AtomicX2) {
10829 DAG.ExtractVectorElements(SDValue(NewNode, 0), Elt, 0, 1);
10830 return DAG.getMergeValues({Elt[0], SDValue(NewNode, 1)}, DL);
10831 }
10832
10833 return constructRetValue(DAG, NewNode, OrigResultTypes, IsTexFail,
10834 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10835 NumVDataDwords, IsAtomicPacked16Bit, DL);
10836}
10837
10838SDValue SITargetLowering::lowerSBuffer(EVT VT, EVT MemVT, SDLoc DL,
10839 SDValue Chain, SDValue Rsrc,
10840 SDValue Offset, SDValue CachePolicy,
10841 SelectionDAG &DAG,
10842 MachineMemOperand *MMO) const {
10844 bool HasChainResult = MMO != nullptr;
10845
10846 if (!HasChainResult) {
10847 const DataLayout &DataLayout = DAG.getDataLayout();
10849 DataLayout.getABITypeAlign(MemVT.getTypeForEVT(*DAG.getContext()));
10850
10851 MMO = MF.getMachineMemOperand(MachinePointerInfo(),
10855 MemVT.getStoreSize(), Alignment);
10856 }
10857
10858 if (!Offset->isDivergent()) {
10859 SDValue Ops[] = {Chain, Rsrc, Offset, CachePolicy};
10860
10861 // Lower llvm.amdgcn.*s.buffer.load.{i,u}N intrinsics. First, generate
10862 // s_buffer_load_u* for signed and unsigned load instructions. Next, DAG
10863 // combiner tries to merge the s_buffer_load_uN with a sext instruction
10864 // (performSignExtendInRegCombine()) and it replaces s_buffer_load_uN with
10865 // s_buffer_load_iN.
10866 auto HandleScalarSubwordLoads = [&](unsigned Opcode) -> SDValue {
10867 SDValue BufferLoad = DAG.getMemIntrinsicNode(
10868 Opcode, DL, DAG.getVTList(MVT::i32, MVT::Other), Ops, MemVT, MMO);
10869 SDValue LoadVal = DAG.getAnyExtOrTrunc(
10870 DAG.getNode(ISD::TRUNCATE, DL, MemVT, BufferLoad), DL, VT);
10871 if (HasChainResult)
10872 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
10873 return LoadVal;
10874 };
10875 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10876 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10877
10878 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10879 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10880
10881 // Widen vec3 load to vec4.
10882 if (VT.isVector() && VT.getVectorNumElements() == 3 &&
10883 !Subtarget->hasScalarDwordx3Loads()) {
10884 EVT WidenedVT =
10886 auto WidenedOp = DAG.getMemIntrinsicNode(
10887 AMDGPUISD::SBUFFER_LOAD, DL, DAG.getVTList(WidenedVT, MVT::Other),
10888 Ops, WidenedVT,
10889 MF.getMachineMemOperand(MMO, 0, WidenedVT.getStoreSize()));
10890 auto Subvector = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, WidenedOp,
10891 DAG.getVectorIdxConstant(0, DL));
10892 if (HasChainResult)
10893 return DAG.getMergeValues({Subvector, WidenedOp.getValue(1)}, DL);
10894 return Subvector;
10895 }
10896
10897 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_LOAD, DL,
10898 DAG.getVTList(VT, MVT::Other), Ops, MemVT,
10899 MMO);
10900 }
10901
10902 // We have a divergent offset. Emit a MUBUF buffer load instead. We can
10903 // assume that the buffer is unswizzled.
10904 SDValue Ops[] = {
10905 Chain, // Chain
10906 Rsrc, // rsrc
10907 DAG.getConstant(0, DL, MVT::i32), // vindex
10908 {}, // voffset
10909 {}, // soffset
10910 {}, // offset
10911 CachePolicy, // cachepolicy
10912 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
10913 };
10914 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10915 Subtarget->hasScalarSubwordLoads()) {
10916 setBufferOffsets(Offset, DAG, &Ops[3], Align(4));
10917 SDValue Load = handleByteShortBufferLoads(DAG, MemVT, DL, Ops, MMO);
10918 SDValue LoadVal = DAG.getAnyExtOrTrunc(Load.getOperand(0), DL, VT);
10919 if (HasChainResult)
10920 return DAG.getMergeValues({LoadVal, Load.getOperand(1)}, DL);
10921 return LoadVal;
10922 }
10923
10925 unsigned NumLoads = 1;
10926 MVT LoadVT = VT.getSimpleVT();
10927 unsigned NumElts = LoadVT.isVector() ? LoadVT.getVectorNumElements() : 1;
10928 assert((LoadVT.getScalarType() == MVT::i32 ||
10929 LoadVT.getScalarType() == MVT::f32));
10930
10931 if (NumElts == 8 || NumElts == 16) {
10932 NumLoads = NumElts / 4;
10933 LoadVT = MVT::getVectorVT(LoadVT.getScalarType(), 4);
10934 }
10935
10936 SDVTList VTList = DAG.getVTList({LoadVT, MVT::Other});
10937
10938 // Use the alignment to ensure that the required offsets will fit into the
10939 // immediate offsets.
10940 setBufferOffsets(Offset, DAG, &Ops[3],
10941 NumLoads > 1 ? Align(16 * NumLoads) : Align(4));
10942
10943 uint64_t InstOffset = Ops[5]->getAsZExtVal();
10944 unsigned LoadSize = LoadVT.getStoreSize();
10945 for (unsigned i = 0; i < NumLoads; ++i) {
10946 Ops[5] = DAG.getTargetConstant(InstOffset + 16 * i, DL, MVT::i32);
10947 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(MMO, 16 * i, LoadSize);
10948 Loads.push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD, DL, VTList, Ops,
10949 LoadVT, LoadMMO, DAG));
10950 }
10951
10952 if (NumElts == 8 || NumElts == 16) {
10953 SDValue LoadVal = DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Loads);
10954 if (HasChainResult) {
10955 SmallVector<SDValue, 4> LoadChains;
10956 for (SDValue Load : Loads)
10957 LoadChains.push_back(Load.getValue(1));
10958 SDValue Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, LoadChains);
10959 return DAG.getMergeValues({LoadVal, Chain}, DL);
10960 }
10961 return LoadVal;
10962 }
10963
10964 return Loads[0];
10965}
10966
10967SDValue SITargetLowering::lowerWaveID(SelectionDAG &DAG, SDValue Op) const {
10968 // With architected SGPRs, waveIDinGroup is in TTMP8[29:25].
10969 if (!Subtarget->hasArchitectedSGPRs())
10970 return {};
10971 SDLoc SL(Op);
10972 MVT VT = MVT::i32;
10973 SDValue TTMP8 = DAG.getCopyFromReg(DAG.getEntryNode(), SL, AMDGPU::TTMP8, VT);
10974 return DAG.getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
10975 DAG.getConstant(25, SL, VT), DAG.getConstant(5, SL, VT));
10976}
10977
10978SDValue SITargetLowering::lowerConstHwRegRead(SelectionDAG &DAG, SDValue Op,
10979 AMDGPU::Hwreg::Id HwReg,
10980 unsigned LowBit,
10981 unsigned Width) const {
10982 SDLoc SL(Op);
10983 using namespace AMDGPU::Hwreg;
10984 return {DAG.getMachineNode(
10985 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
10986 DAG.getTargetConstant(HwregEncoding::encode(HwReg, LowBit, Width),
10987 SL, MVT::i32)),
10988 0};
10989}
10990
10991SDValue SITargetLowering::lowerWorkitemID(SelectionDAG &DAG, SDValue Op,
10992 unsigned Dim,
10993 const ArgDescriptor &Arg) const {
10994 SDLoc SL(Op);
10996 unsigned MaxID = Subtarget->getMaxWorkitemID(MF.getFunction(), Dim);
10997 if (MaxID == 0)
10998 return DAG.getConstant(0, SL, MVT::i32);
10999
11000 // It's undefined behavior if a function marked with the amdgpu-no-*
11001 // attributes uses the corresponding intrinsic.
11002 if (!Arg)
11003 return DAG.getPOISON(Op->getValueType(0));
11004
11005 SDValue Val = loadInputValue(DAG, &AMDGPU::VGPR_32RegClass, MVT::i32,
11006 SDLoc(DAG.getEntryNode()), Arg);
11007
11008 // Don't bother inserting AssertZext for packed IDs since we're emitting the
11009 // masking operations anyway.
11010 //
11011 // TODO: We could assert the top bit is 0 for the source copy.
11012 if (Arg.isMasked())
11013 return Val;
11014
11015 // Preserve the known bits after expansion to a copy.
11016 EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), llvm::bit_width(MaxID));
11017 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Val,
11018 DAG.getValueType(SmallVT));
11019}
11020
11021SDValue SITargetLowering::lowerFromFP8(SDValue Op, bool IsBF8,
11022 SelectionDAG &DAG) const {
11023 SDLoc SL(Op);
11024 SDValue Src = Op.getOperand(0);
11025 EVT DstVT = Op.getValueType();
11026 bool IsF16 = DstVT.getVectorElementType() == MVT::f16;
11027 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
11028 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11029
11030 unsigned Opc;
11031 if (IsF16)
11032 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11033 else
11034 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11035
11036 // Pack the two i8 lanes into the integer type the packed HW node reads. The
11037 // f16 form takes i16 and the f32 form takes i32. v2i8 bitcasts to i16
11038 // directly and the f32 node reads the low half of an any-extended i32.
11039 EVT PackedVT =
11041 SDValue AsI16 = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
11042 SDValue Packed = DAG.getAnyExtOrTrunc(AsI16, SL, PackedVT);
11043 return DAG.getNode(Opc, SL, DstVT, Packed);
11044}
11045
11046SDValue
11047SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(SDValue Op,
11048 SelectionDAG &DAG) const {
11049 // Handle the OCP FP8 formats (E4M3FN, E5M2) and unsigned E5M3 on subtargets
11050 // with matching HW conversions. Other formats use the generic expansion.
11051 APFloatBase::Semantics FPSemantic =
11052 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11053 const bool IsFP8 = FPSemantic == APFloatBase::S_Float8E4M3FN;
11054 const bool IsBF8 = FPSemantic == APFloatBase::S_Float8E5M2;
11055 const bool IsE5M3 = FPSemantic == APFloatBase::S_Float8E5M3FNU;
11056 const bool HasE5M3ConversionInsts =
11057 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11058 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11059 if (!IsSupported)
11060 return SDValue();
11061
11062 EVT DstVT = Op.getValueType();
11063 if (IsE5M3) {
11064 if (DstVT.getScalarType() != MVT::f32)
11065 return SDValue();
11066
11067 SDLoc SL(Op);
11068 SDValue Src = Op.getOperand(0);
11069 assert((!DstVT.isVector() || DstVT == MVT::v2f32) &&
11070 "only the v2f32 vector result is custom lowered");
11071
11072 if (DstVT.isVector())
11073 Src = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
11074 Src = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
11075
11076 auto ConvertByte = [&](unsigned ByteSel) {
11077 return DAG.getNode(AMDGPUISD::CVT_F32_FP8_E5M3, SL, MVT::f32, Src,
11078 DAG.getTargetConstant(ByteSel, SL, MVT::i32));
11079 };
11080
11081 if (!DstVT.isVector())
11082 return ConvertByte(0);
11083 return DAG.getBuildVector(DstVT, SL, {ConvertByte(0), ConvertByte(1)});
11084 }
11085
11086 if (!DstVT.isVector()) {
11087 SDValue Src = Op.getOperand(0);
11088 if (Src.getValueType() != MVT::i32) {
11089 SDLoc SL(Op);
11090 SDValue SrcI32 = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
11091 return DAG.getNode(ISD::CONVERT_FROM_ARBITRARY_FP, SL, DstVT, SrcI32,
11092 Op.getOperand(1));
11093 }
11094 return Op;
11095 }
11096
11097 EVT EltVT = DstVT.getVectorElementType();
11098 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11099 return lowerFromFP8(Op, IsBF8, DAG);
11100 return SDValue();
11101}
11102
11103SDValue SITargetLowering::lowerToFP8(SDValue Op, bool IsBF8, bool IsE5M3,
11104 SelectionDAG &DAG) const {
11105 SDLoc SL(Op);
11106 SDValue Src = Op.getOperand(0);
11107 EVT ResVT = Op.getValueType();
11108 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11109 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11110 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11111 assert((!ResVT.isVector() || ResVT == MVT::v2i8) &&
11112 "only the v2i8 vector result is custom lowered");
11113
11114 if (IsF16) {
11115 unsigned Opc =
11116 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11117 SDValue Bytes = DAG.getNode(Opc, SL, MVT::i16, Src);
11118 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11119 }
11120
11121 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32
11122 : IsE5M3 ? AMDGPUISD::CVT_PK_FP8_F32_E5M3
11123 : AMDGPUISD::CVT_PK_FP8_F32;
11124 SDValue PoisonI32 = DAG.getPOISON(MVT::i32);
11125 SDValue WordSel = DAG.getTargetConstant(0, SL, MVT::i1);
11126
11127 if (!ResVT.isVector()) {
11128 // Convert one lane, the second is unused. Feed it the same source so the
11129 // instruction does not read an undefined register.
11130 SDValue Packed =
11131 DAG.getNode(Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11132 return DAG.getAnyExtOrTrunc(Packed, SL, ResVT);
11133 }
11134
11135 SDValue A = DAG.getExtractVectorElt(SL, MVT::f32, Src, 0);
11136 SDValue B = DAG.getExtractVectorElt(SL, MVT::f32, Src, 1);
11137 SDValue Packed = DAG.getNode(Opc, SL, MVT::i32, A, B, PoisonI32, WordSel);
11138 SDValue Bytes = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Packed);
11139 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11140}
11141
11142SDValue
11143SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(SDValue Op,
11144 SelectionDAG &DAG) const {
11145 // The OCP FP8 formats (E4M3FN, E5M2) and unsigned E5M3 map to HW conversions
11146 // on subtargets that support them. Everything else uses generic expansion.
11148 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11149 const bool IsFP8 = Sem == APFloatBase::S_Float8E4M3FN;
11150 const bool IsBF8 = Sem == APFloatBase::S_Float8E5M2;
11151 const bool IsE5M3 = Sem == APFloatBase::S_Float8E5M3FNU;
11152 const bool HasE5M3ConversionInsts =
11153 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11154 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11155 if (!IsSupported)
11156 return SDValue();
11157
11158 // The HW conversions only support nearest-even. The OCP conversions do not
11159 // saturate. The unsigned E5M3 conversion always clamps out-of-range inputs,
11160 // which also refines the non-saturating form where those inputs are poison.
11161 if (static_cast<RoundingMode>(Op.getConstantOperandVal(2)) !=
11163 return SDValue();
11164 if (!IsE5M3 && Op.getConstantOperandVal(3) != 0)
11165 return SDValue();
11166
11167 EVT SrcEltVT = Op.getOperand(0).getValueType().getScalarType();
11168 // The f32 form is built here rather than by a tablegen pattern because the
11169 // HW result is i32 while the node result is i16 after the i8 promotion.
11170 if (SrcEltVT == MVT::f32)
11171 return lowerToFP8(Op, IsBF8, IsE5M3, DAG);
11172 if (!IsE5M3 && SrcEltVT == MVT::f16 &&
11173 Subtarget->hasF16FP8ConversionInsts()) {
11174 // A scalar conversion is selected from the generic node by tablegen, only
11175 // the illegal v2i8 result type needs lowering here.
11176 if (!Op.getValueType().isVector())
11177 return Op;
11178 return lowerToFP8(Op, IsBF8, false, DAG);
11179 }
11180 return SDValue();
11181}
11182
11183SDValue SITargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
11184 SelectionDAG &DAG) const {
11186 auto *MFI = MF.getInfo<SIMachineFunctionInfo>();
11187
11188 EVT VT = Op.getValueType();
11189 SDLoc DL(Op);
11190 unsigned IntrinsicID = Op.getConstantOperandVal(0);
11191
11192 // TODO: Should this propagate fast-math-flags?
11193
11194 switch (IntrinsicID) {
11195 case Intrinsic::amdgcn_wave_reduce_min:
11196 case Intrinsic::amdgcn_wave_reduce_umin:
11197 case Intrinsic::amdgcn_wave_reduce_fmin:
11198 case Intrinsic::amdgcn_wave_reduce_max:
11199 case Intrinsic::amdgcn_wave_reduce_umax:
11200 case Intrinsic::amdgcn_wave_reduce_fmax:
11201 case Intrinsic::amdgcn_wave_reduce_add:
11202 case Intrinsic::amdgcn_wave_reduce_fadd:
11203 case Intrinsic::amdgcn_wave_reduce_sub:
11204 case Intrinsic::amdgcn_wave_reduce_fsub:
11205 case Intrinsic::amdgcn_wave_reduce_and:
11206 case Intrinsic::amdgcn_wave_reduce_or:
11207 case Intrinsic::amdgcn_wave_reduce_xor: {
11208 EVT SrcVT = Op.getOperand(1).getValueType();
11209 if (SrcVT.getFixedSizeInBits() == 16) {
11210 bool IsFPOp = SrcVT.isFloatingPoint();
11211 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11212 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11213 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11214 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11215 unsigned ExtOpc = IsFPOp ? ISD::FP_EXTEND
11216 : NeedsSignExt ? ISD::SIGN_EXTEND
11218 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11219 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11220 SDValue ExtendedSrc = DAG.getNode(ExtOpc, DL, ExtType, Op.getOperand(1));
11221 SDValue Strategy = Op.getOperand(2);
11223 Op.getOperand(0), ExtendedSrc, Strategy);
11224 if (IsFPOp)
11225 return DAG.getNode(ISD::FP_ROUND, DL, SrcType, Result,
11226 DAG.getTargetConstant(1, DL, MVT::i32));
11227 else
11228 return DAG.getNode(ISD::TRUNCATE, DL, SrcType, Result);
11229 }
11230 return SDValue();
11231 }
11232 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11233 if (getSubtarget()->isAmdHsaOrMesa(MF.getFunction()))
11234 return emitNonHSAIntrinsicError(DAG, DL, VT);
11235 return getPreloadedValue(DAG, *MFI, VT,
11237 }
11238 case Intrinsic::amdgcn_dispatch_ptr:
11239 case Intrinsic::amdgcn_queue_ptr: {
11240 if (!Subtarget->isAmdHsaOrMesa(MF.getFunction())) {
11241 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11242 MF.getFunction(), "unsupported hsa intrinsic without hsa target",
11243 DL.getDebugLoc()));
11244 return DAG.getPOISON(VT);
11245 }
11246
11247 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11250 return getPreloadedValue(DAG, *MFI, VT, RegID);
11251 }
11252 case Intrinsic::amdgcn_implicitarg_ptr: {
11253 if (MFI->isEntryFunction())
11254 return getImplicitArgPtr(DAG, DL);
11255 return getPreloadedValue(DAG, *MFI, VT,
11257 }
11258 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11259 if (!AMDGPU::isKernel(MF.getFunction())) {
11260 // This only makes sense to call in a kernel, so just lower to null.
11261 return DAG.getConstant(0, DL, VT);
11262 }
11263
11264 return getPreloadedValue(DAG, *MFI, VT,
11266 }
11267 case Intrinsic::amdgcn_dispatch_id: {
11268 return getPreloadedValue(DAG, *MFI, VT, AMDGPUFunctionArgInfo::DISPATCH_ID);
11269 }
11270 case Intrinsic::amdgcn_rcp:
11271 return DAG.getNode(AMDGPUISD::RCP, DL, VT, Op.getOperand(1));
11272 case Intrinsic::amdgcn_rsq:
11273 return DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11274 case Intrinsic::amdgcn_rsq_legacy:
11275 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11276 return emitRemovedIntrinsicError(DAG, DL, VT);
11277 return SDValue();
11278 case Intrinsic::amdgcn_rcp_legacy:
11279 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11280 return emitRemovedIntrinsicError(DAG, DL, VT);
11281 return DAG.getNode(AMDGPUISD::RCP_LEGACY, DL, VT, Op.getOperand(1));
11282 case Intrinsic::amdgcn_fma_legacy:
11283 case Intrinsic::amdgcn_sudot4:
11284 case Intrinsic::amdgcn_sudot8:
11285 case Intrinsic::amdgcn_tanh:
11286 return SDValue();
11287 case Intrinsic::amdgcn_rsq_clamp: {
11288 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11289 return DAG.getNode(AMDGPUISD::RSQ_CLAMP, DL, VT, Op.getOperand(1));
11290
11291 Type *Type = VT.getTypeForEVT(*DAG.getContext());
11292 APFloat Max = APFloat::getLargest(Type->getFltSemantics());
11293 APFloat Min = APFloat::getLargest(Type->getFltSemantics(), true);
11294
11295 SDValue Rsq = DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11296 SDValue Tmp =
11297 DAG.getNode(ISD::FMINNUM, DL, VT, Rsq, DAG.getConstantFP(Max, DL, VT));
11298 return DAG.getNode(ISD::FMAXNUM, DL, VT, Tmp,
11299 DAG.getConstantFP(Min, DL, VT));
11300 }
11301 case Intrinsic::r600_read_ngroups_x:
11302 if (Subtarget->isAmdHsaOS())
11303 return emitNonHSAIntrinsicError(DAG, DL, VT);
11304
11305 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11307 false);
11308 case Intrinsic::r600_read_ngroups_y:
11309 if (Subtarget->isAmdHsaOS())
11310 return emitNonHSAIntrinsicError(DAG, DL, VT);
11311
11312 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11314 false);
11315 case Intrinsic::r600_read_ngroups_z:
11316 if (Subtarget->isAmdHsaOS())
11317 return emitNonHSAIntrinsicError(DAG, DL, VT);
11318
11319 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11321 false);
11322 case Intrinsic::r600_read_local_size_x:
11323 if (Subtarget->isAmdHsaOS())
11324 return emitNonHSAIntrinsicError(DAG, DL, VT);
11325
11326 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11328 case Intrinsic::r600_read_local_size_y:
11329 if (Subtarget->isAmdHsaOS())
11330 return emitNonHSAIntrinsicError(DAG, DL, VT);
11331
11332 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11334 case Intrinsic::r600_read_local_size_z:
11335 if (Subtarget->isAmdHsaOS())
11336 return emitNonHSAIntrinsicError(DAG, DL, VT);
11337
11338 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11340 case Intrinsic::amdgcn_workgroup_id_x:
11341 return lowerWorkGroupId(DAG, *MFI, VT,
11345 case Intrinsic::amdgcn_workgroup_id_y:
11346 return lowerWorkGroupId(DAG, *MFI, VT,
11350 case Intrinsic::amdgcn_workgroup_id_z:
11351 return lowerWorkGroupId(DAG, *MFI, VT,
11355 case Intrinsic::amdgcn_cluster_id_x:
11356 return Subtarget->hasClusters()
11357 ? getPreloadedValue(DAG, *MFI, VT,
11359 : DAG.getPOISON(VT);
11360 case Intrinsic::amdgcn_cluster_id_y:
11361 return Subtarget->hasClusters()
11362 ? getPreloadedValue(DAG, *MFI, VT,
11364 : DAG.getPOISON(VT);
11365 case Intrinsic::amdgcn_cluster_id_z:
11366 return Subtarget->hasClusters()
11367 ? getPreloadedValue(DAG, *MFI, VT,
11369 : DAG.getPOISON(VT);
11370 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11371 return Subtarget->hasClusters()
11372 ? getPreloadedValue(
11373 DAG, *MFI, VT,
11375 : DAG.getPOISON(VT);
11376 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11377 return Subtarget->hasClusters()
11378 ? getPreloadedValue(
11379 DAG, *MFI, VT,
11381 : DAG.getPOISON(VT);
11382 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11383 return Subtarget->hasClusters()
11384 ? getPreloadedValue(
11385 DAG, *MFI, VT,
11387 : DAG.getPOISON(VT);
11388 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11389 return Subtarget->hasClusters()
11390 ? lowerConstHwRegRead(DAG, Op, AMDGPU::Hwreg::ID_IB_STS2, 21, 4)
11391 : SDValue();
11392 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11393 return Subtarget->hasClusters()
11394 ? getPreloadedValue(
11395 DAG, *MFI, VT,
11397 : DAG.getPOISON(VT);
11398 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11399 return Subtarget->hasClusters()
11400 ? getPreloadedValue(
11401 DAG, *MFI, VT,
11403 : DAG.getPOISON(VT);
11404 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11405 return Subtarget->hasClusters()
11406 ? getPreloadedValue(
11407 DAG, *MFI, VT,
11409 : DAG.getPOISON(VT);
11410 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11411 return Subtarget->hasClusters()
11412 ? getPreloadedValue(
11413 DAG, *MFI, VT,
11415 : DAG.getPOISON(VT);
11416 case Intrinsic::amdgcn_wave_id:
11417 return lowerWaveID(DAG, Op);
11418 case Intrinsic::amdgcn_lds_kernel_id: {
11419 if (MFI->isEntryFunction())
11420 return getLDSKernelId(DAG, DL);
11421 return getPreloadedValue(DAG, *MFI, VT,
11423 }
11424 case Intrinsic::amdgcn_workitem_id_x:
11425 return lowerWorkitemID(DAG, Op, 0, MFI->getArgInfo().WorkItemIDX);
11426 case Intrinsic::amdgcn_workitem_id_y:
11427 return lowerWorkitemID(DAG, Op, 1, MFI->getArgInfo().WorkItemIDY);
11428 case Intrinsic::amdgcn_workitem_id_z:
11429 return lowerWorkitemID(DAG, Op, 2, MFI->getArgInfo().WorkItemIDZ);
11430 case Intrinsic::amdgcn_wavefrontsize:
11431 return DAG.getConstant(MF.getSubtarget<GCNSubtarget>().getWavefrontSize(),
11432 SDLoc(Op), MVT::i32);
11433 case Intrinsic::amdgcn_s_buffer_load: {
11434 unsigned CPol = Op.getConstantOperandVal(3);
11435 // s_buffer_load, because of how it's optimized, can't be volatile
11436 // so reject ones with the volatile bit set.
11437 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
11440 return Op;
11441 return lowerSBuffer(VT, VT, DL, DAG.getEntryNode(), Op.getOperand(1),
11442 Op.getOperand(2), Op.getOperand(3), DAG);
11443 }
11444 case Intrinsic::amdgcn_fdiv_fast:
11445 return lowerFDIV_FAST(Op, DAG);
11446 case Intrinsic::amdgcn_sin:
11447 return DAG.getNode(AMDGPUISD::SIN_HW, DL, VT, Op.getOperand(1));
11448
11449 case Intrinsic::amdgcn_cos:
11450 return DAG.getNode(AMDGPUISD::COS_HW, DL, VT, Op.getOperand(1));
11451
11452 case Intrinsic::amdgcn_mul_u24:
11453 return DAG.getNode(AMDGPUISD::MUL_U24, DL, VT, Op.getOperand(1),
11454 Op.getOperand(2));
11455 case Intrinsic::amdgcn_mul_i24:
11456 return DAG.getNode(AMDGPUISD::MUL_I24, DL, VT, Op.getOperand(1),
11457 Op.getOperand(2));
11458
11459 case Intrinsic::amdgcn_log_clamp: {
11460 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11461 return SDValue();
11462
11463 return emitRemovedIntrinsicError(DAG, DL, VT);
11464 }
11465 case Intrinsic::amdgcn_fract:
11466 return DAG.getNode(AMDGPUISD::FRACT, DL, VT, Op.getOperand(1));
11467
11468 case Intrinsic::amdgcn_class: {
11469 SDValue Src = Op.getOperand(1);
11470 EVT SrcVT = Src.getValueType();
11471 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11472 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11473 if (!IsLegal) {
11474 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11476 "llvm.amdgcn.class only supports f16, f32, and f64",
11477 DL.getDebugLoc()));
11478 return DAG.getPOISON(VT);
11479 }
11480 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, VT, Src, Op.getOperand(2));
11481 }
11482 case Intrinsic::amdgcn_div_fmas:
11483 return DAG.getNode(AMDGPUISD::DIV_FMAS, DL, VT, Op.getOperand(1),
11484 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11485
11486 case Intrinsic::amdgcn_div_fixup:
11487 return DAG.getNode(AMDGPUISD::DIV_FIXUP, DL, VT, Op.getOperand(1),
11488 Op.getOperand(2), Op.getOperand(3));
11489
11490 case Intrinsic::amdgcn_div_scale: {
11491 const ConstantSDNode *Param = cast<ConstantSDNode>(Op.getOperand(3));
11492
11493 // Translate to the operands expected by the machine instruction. The
11494 // first parameter must be the same as the first instruction.
11495 SDValue Numerator = Op.getOperand(1);
11496 SDValue Denominator = Op.getOperand(2);
11497
11498 // Note this order is opposite of the machine instruction's operations,
11499 // which is s0.f = Quotient, s1.f = Denominator, s2.f = Numerator. The
11500 // intrinsic has the numerator as the first operand to match a normal
11501 // division operation.
11502
11503 SDValue Src0 = Param->isAllOnes() ? Numerator : Denominator;
11504
11505 return DAG.getNode(AMDGPUISD::DIV_SCALE, DL, Op->getVTList(), Src0,
11506 Denominator, Numerator);
11507 }
11508 case Intrinsic::amdgcn_ballot:
11509 return lowerBALLOTIntrinsic(*this, Op.getNode(), DAG);
11510 case Intrinsic::amdgcn_fmed3:
11511 return DAG.getNode(AMDGPUISD::FMED3, DL, VT, Op.getOperand(1),
11512 Op.getOperand(2), Op.getOperand(3), Op->getFlags());
11513 case Intrinsic::amdgcn_fdot2:
11514 return DAG.getNode(AMDGPUISD::FDOT2, DL, VT, Op.getOperand(1),
11515 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11516 case Intrinsic::amdgcn_fmul_legacy:
11517 return DAG.getNode(AMDGPUISD::FMUL_LEGACY, DL, VT, Op.getOperand(1),
11518 Op.getOperand(2));
11519 case Intrinsic::amdgcn_sbfe:
11520 case Intrinsic::amdgcn_ubfe:
11521 return lowerBFEIntrinsic(Op, DAG, IntrinsicID);
11522 case Intrinsic::amdgcn_cvt_pkrtz:
11523 case Intrinsic::amdgcn_cvt_pknorm_i16:
11524 case Intrinsic::amdgcn_cvt_pknorm_u16:
11525 case Intrinsic::amdgcn_cvt_pk_i16:
11526 case Intrinsic::amdgcn_cvt_pk_u16: {
11527 // FIXME: Stop adding cast if v2f16/v2i16 are legal.
11528 EVT VT = Op.getValueType();
11529 unsigned Opcode;
11530
11531 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11532 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11533 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11534 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11535 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11536 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11537 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11538 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11539 else
11540 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11541
11542 if (isTypeLegal(VT))
11543 return DAG.getNode(Opcode, DL, VT, Op.getOperand(1), Op.getOperand(2));
11544
11545 SDValue Node =
11546 DAG.getNode(Opcode, DL, MVT::i32, Op.getOperand(1), Op.getOperand(2));
11547 return DAG.getNode(ISD::BITCAST, DL, VT, Node);
11548 }
11549 case Intrinsic::amdgcn_fmad_ftz:
11550 return DAG.getNode(AMDGPUISD::FMAD_FTZ, DL, VT, Op.getOperand(1),
11551 Op.getOperand(2), Op.getOperand(3));
11552
11553 case Intrinsic::amdgcn_if_break:
11554 return SDValue(DAG.getMachineNode(AMDGPU::SI_IF_BREAK, DL, VT,
11555 Op->getOperand(1), Op->getOperand(2)),
11556 0);
11557
11558 case Intrinsic::amdgcn_groupstaticsize: {
11560 if (OS == Triple::AMDHSA || OS == Triple::AMDPAL)
11561 return Op;
11562
11563 const Module *M = MF.getFunction().getParent();
11564 const GlobalValue *GV =
11565 Intrinsic::getDeclarationIfExists(M, Intrinsic::amdgcn_groupstaticsize);
11566 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, 0,
11568 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11569 }
11570 case Intrinsic::amdgcn_is_shared:
11571 case Intrinsic::amdgcn_is_private: {
11572 SDLoc SL(Op);
11573 SDValue SrcVec =
11574 DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
11575 SDValue SrcHi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, SrcVec,
11576 DAG.getConstant(1, SL, MVT::i32));
11577
11578 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11580 : AMDGPUAS::PRIVATE_ADDRESS;
11581 if (AS == AMDGPUAS::PRIVATE_ADDRESS &&
11582 Subtarget->hasGloballyAddressableScratch()) {
11583 SDValue FlatScratchBaseHi(
11584 DAG.getMachineNode(
11585 AMDGPU::S_MOV_B32, DL, MVT::i32,
11586 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11587 0);
11588 // Test bits 63..58 against the aperture address.
11589 return DAG.getSetCC(
11590 SL, MVT::i1,
11591 DAG.getNode(ISD::XOR, SL, MVT::i32, SrcHi, FlatScratchBaseHi),
11592 DAG.getConstant(1u << 26, SL, MVT::i32), ISD::SETULT);
11593 }
11594
11595 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11596 return DAG.getSetCC(SL, MVT::i1, SrcHi, Aperture, ISD::SETEQ);
11597 }
11598 case Intrinsic::amdgcn_perm:
11599 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op.getOperand(1),
11600 Op.getOperand(2), Op.getOperand(3));
11601 case Intrinsic::amdgcn_reloc_constant: {
11602 Module *M = MF.getFunction().getParent();
11603 const MDNode *Metadata = cast<MDNodeSDNode>(Op.getOperand(1))->getMD();
11604 auto SymbolName = cast<MDString>(Metadata->getOperand(0))->getString();
11605 auto *RelocSymbol = cast<GlobalVariable>(
11606 M->getOrInsertGlobal(SymbolName, Type::getInt32Ty(M->getContext())));
11607 SDValue GA = DAG.getTargetGlobalAddress(RelocSymbol, DL, MVT::i32, 0,
11609 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11610 }
11611 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11612 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11613 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11614 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11615 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11616 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11617 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11618 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11619 if (Op.getOperand(4).getValueType() == MVT::i32)
11620 return SDValue();
11621
11622 SDLoc SL(Op);
11623 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i32);
11624 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11625 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11626 Op.getOperand(3), IndexKeyi32);
11627 }
11628 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11629 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11630 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11631 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11632 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11633 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11634 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11635 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11636 if (Op.getOperand(4).getValueType() == MVT::i64)
11637 return SDValue();
11638
11639 SDLoc SL(Op);
11640 auto IndexKeyi64 =
11641 Op.getOperand(4).getValueType() == MVT::v2i32
11642 ? DAG.getBitcast(MVT::i64, Op.getOperand(4))
11643 : DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i64);
11644 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11645 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11646 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11647 Op.getOperand(6)});
11648 }
11649 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11650 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11651 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11652 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11653 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11654 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11655 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11656 ? MVT::i64
11657 : MVT::i32;
11658 if (Op.getOperand(6).getValueType() == IndexKeyTy)
11659 return SDValue();
11660
11661 SDLoc SL(Op);
11662 auto IndexKey =
11663 Op.getOperand(6).getValueType().isVector()
11664 ? DAG.getBitcast(IndexKeyTy, Op.getOperand(6))
11665 : DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, IndexKeyTy);
11667 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11668 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11669 IndexKey, Op.getOperand(7), Op.getOperand(8)};
11670 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11671 Args.push_back(Op.getOperand(9));
11672 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(), Args);
11673 }
11674 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11675 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11676 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11677 if (Op.getOperand(6).getValueType() == MVT::i32)
11678 return SDValue();
11679
11680 SDLoc SL(Op);
11681 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, MVT::i32);
11682 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11683 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11684 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11685 IndexKeyi32, Op.getOperand(7)});
11686 }
11687 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11688 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11689 unsigned AFmt = (unsigned)Op.getConstantOperandVal(1);
11690 unsigned BFmt = (unsigned)Op.getConstantOperandVal(3);
11691 unsigned AScaleFmt = (unsigned)Op.getConstantOperandVal(8);
11692 unsigned BScaleFmt = (unsigned)Op.getConstantOperandVal(11);
11693 if (!AMDGPU::isValidWMMAScaleFmtCombination(AFmt, AScaleFmt, BFmt,
11694 BScaleFmt)) {
11696 "invalid matrix and scale format combination in wmma call");
11697 Op->print(errs());
11698 errs() << '\n';
11699 }
11700 return SDValue();
11701 }
11702 case Intrinsic::amdgcn_readlane:
11703 case Intrinsic::amdgcn_readfirstlane:
11704 case Intrinsic::amdgcn_writelane:
11705 case Intrinsic::amdgcn_permlane16:
11706 case Intrinsic::amdgcn_permlanex16:
11707 case Intrinsic::amdgcn_permlane64:
11708 case Intrinsic::amdgcn_set_inactive:
11709 case Intrinsic::amdgcn_set_inactive_chain_arg:
11710 case Intrinsic::amdgcn_mov_dpp8:
11711 case Intrinsic::amdgcn_update_dpp:
11712 case Intrinsic::amdgcn_permlane_bcast:
11713 case Intrinsic::amdgcn_permlane_up:
11714 case Intrinsic::amdgcn_permlane_down:
11715 case Intrinsic::amdgcn_permlane_xor:
11716 return lowerLaneOp(*this, Op.getNode(), DAG);
11717 case Intrinsic::amdgcn_dead: {
11719 for (const EVT ValTy : Op.getNode()->values())
11720 Poisons.push_back(DAG.getPOISON(ValTy));
11721 return DAG.getMergeValues(Poisons, SDLoc(Op));
11722 }
11723 case Intrinsic::amdgcn_wave_shuffle:
11724 return lowerWaveShuffle(*this, Op.getNode(), DAG);
11725 default:
11726 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11728 return lowerImage(Op, ImageDimIntr, DAG, false);
11729
11730 return Op;
11731 }
11732}
11733
11734// On targets not supporting constant in soffset field, turn zero to
11735// SGPR_NULL to avoid generating an extra s_mov with zero.
11737 const GCNSubtarget *Subtarget) {
11738 if (Subtarget->hasRestrictedSOffset() && isNullConstant(SOffset))
11739 return DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11740 return SOffset;
11741}
11742
11743SDValue SITargetLowering::lowerRawBufferAtomicIntrin(SDValue Op,
11744 SelectionDAG &DAG,
11745 unsigned NewOpcode) const {
11746 SDLoc DL(Op);
11747
11748 SDValue VData = Op.getOperand(2);
11749 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11750 SmallVector<EVT, 2> ResultTypes(Op->values());
11751 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11752 "unsupported buffer atomic data type");
11753 }
11754 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11755 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
11756 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
11757 SDValue Ops[] = {
11758 Op.getOperand(0), // Chain
11759 VData, // vdata
11760 Rsrc, // rsrc
11761 DAG.getConstant(0, DL, MVT::i32), // vindex
11762 VOffset, // voffset
11763 SOffset, // soffset
11764 Offset, // offset
11765 Op.getOperand(6), // cachepolicy
11766 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11767 };
11768
11769 auto *M = cast<MemSDNode>(Op);
11770
11771 EVT MemVT = VData.getValueType();
11772 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11773 M->getMemOperand());
11774}
11775
11776SDValue
11777SITargetLowering::lowerStructBufferAtomicIntrin(SDValue Op, SelectionDAG &DAG,
11778 unsigned NewOpcode) const {
11779 SDLoc DL(Op);
11780
11781 SDValue VData = Op.getOperand(2);
11782 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11783 SmallVector<EVT, 2> ResultTypes(Op->values());
11784 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11785 "unsupported buffer atomic data type");
11786 }
11787 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11788 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
11789 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
11790 SDValue Ops[] = {
11791 Op.getOperand(0), // Chain
11792 VData, // vdata
11793 Rsrc, // rsrc
11794 Op.getOperand(4), // vindex
11795 VOffset, // voffset
11796 SOffset, // soffset
11797 Offset, // offset
11798 Op.getOperand(7), // cachepolicy
11799 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
11800 };
11801
11802 auto *M = cast<MemSDNode>(Op);
11803
11804 EVT MemVT = VData.getValueType();
11805 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11806 M->getMemOperand());
11807}
11808
11810 SDLoc DL) {
11811 SDNode *N = Op.getNode();
11812 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
11813 unsigned NumOperands = N->getNumOperands();
11814 if (N->getOperand(NumOperands - 1) == Zero)
11815 return;
11817 Ops[NumOperands - 1] = Zero; // M0 = 0
11818 DAG.UpdateNodeOperands(N, Ops);
11819}
11820
11821SDValue SITargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
11822 SelectionDAG &DAG) const {
11823 unsigned IntrID = Op.getConstantOperandVal(1);
11824 SDLoc DL(Op);
11825
11826 switch (IntrID) {
11827 case Intrinsic::amdgcn_cluster_load_b32:
11828 case Intrinsic::amdgcn_cluster_load_b64:
11829 case Intrinsic::amdgcn_cluster_load_b128: {
11830 if (Subtarget->hasGFX1250_STRICT())
11832 return SDValue();
11833 }
11834 case Intrinsic::amdgcn_ds_ordered_add:
11835 case Intrinsic::amdgcn_ds_ordered_swap: {
11836 MemSDNode *M = cast<MemSDNode>(Op);
11837 SDValue Chain = M->getOperand(0);
11838 SDValue M0 = M->getOperand(2);
11839 SDValue Value = M->getOperand(3);
11840 unsigned IndexOperand = M->getConstantOperandVal(7);
11841 unsigned WaveRelease = M->getConstantOperandVal(8);
11842 unsigned WaveDone = M->getConstantOperandVal(9);
11843
11844 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11845 IndexOperand &= ~0x3f;
11846 unsigned CountDw = 0;
11847
11848 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10) {
11849 CountDw = (IndexOperand >> 24) & 0xf;
11850 IndexOperand &= ~(0xf << 24);
11851
11852 if (CountDw < 1 || CountDw > 4) {
11853 const Function &Fn = DAG.getMachineFunction().getFunction();
11854 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11855 Fn, "ds_ordered_count: dword count must be between 1 and 4",
11856 DL.getDebugLoc()));
11857 CountDw = 1;
11858 }
11859 }
11860
11861 if (IndexOperand) {
11862 const Function &Fn = DAG.getMachineFunction().getFunction();
11863 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11864 Fn, "ds_ordered_count: bad index operand", DL.getDebugLoc()));
11865 }
11866
11867 if (WaveDone && !WaveRelease) {
11868 // TODO: Move this to IR verifier
11869 const Function &Fn = DAG.getMachineFunction().getFunction();
11870 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11871 Fn, "ds_ordered_count: wave_done requires wave_release",
11872 DL.getDebugLoc()));
11873 }
11874
11875 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
11876 unsigned ShaderType =
11878 unsigned Offset0 = OrderedCountIndex << 2;
11879 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
11880
11881 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10)
11882 Offset1 |= (CountDw - 1) << 6;
11883
11884 if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX11)
11885 Offset1 |= ShaderType << 2;
11886
11887 unsigned Offset = Offset0 | (Offset1 << 8);
11888
11889 SDValue Ops[] = {
11890 Chain, Value, DAG.getTargetConstant(Offset, DL, MVT::i16),
11891 copyToM0(DAG, Chain, DL, M0).getValue(1), // Glue
11892 };
11893 return DAG.getMemIntrinsicNode(AMDGPUISD::DS_ORDERED_COUNT, DL,
11894 M->getVTList(), Ops, M->getMemoryVT(),
11895 M->getMemOperand());
11896 }
11897 case Intrinsic::amdgcn_ptr_s_buffer_load: {
11898 unsigned CPol = Op.getConstantOperandVal(4);
11899 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
11902 return Op;
11903
11904 MemSDNode *M = cast<MemSDNode>(Op);
11905 return lowerSBuffer(
11906 Op.getValueType(), M->getMemoryVT(), DL, Op.getOperand(0),
11907 bufferRsrcPtrToVector(Op.getOperand(2), DAG), Op.getOperand(3),
11908 Op.getOperand(4), DAG, M->getMemOperand());
11909 }
11910 case Intrinsic::amdgcn_raw_buffer_load:
11911 case Intrinsic::amdgcn_raw_ptr_buffer_load:
11912 case Intrinsic::amdgcn_raw_atomic_buffer_load:
11913 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
11914 case Intrinsic::amdgcn_raw_buffer_load_format:
11915 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
11916 const bool IsFormat =
11917 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
11918 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
11919
11920 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
11921 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
11922 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
11923 SDValue Ops[] = {
11924 Op.getOperand(0), // Chain
11925 Rsrc, // rsrc
11926 DAG.getConstant(0, DL, MVT::i32), // vindex
11927 VOffset, // voffset
11928 SOffset, // soffset
11929 Offset, // offset
11930 Op.getOperand(5), // cachepolicy, swizzled buffer
11931 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11932 };
11933
11934 auto *M = cast<MemSDNode>(Op);
11935 return lowerIntrinsicLoad(M, IsFormat, DAG, Ops);
11936 }
11937 case Intrinsic::amdgcn_struct_buffer_load:
11938 case Intrinsic::amdgcn_struct_ptr_buffer_load:
11939 case Intrinsic::amdgcn_struct_buffer_load_format:
11940 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
11941 case Intrinsic::amdgcn_struct_atomic_buffer_load:
11942 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
11943 const bool IsFormat =
11944 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
11945 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
11946
11947 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
11948 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
11949 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
11950 SDValue Ops[] = {
11951 Op.getOperand(0), // Chain
11952 Rsrc, // rsrc
11953 Op.getOperand(3), // vindex
11954 VOffset, // voffset
11955 SOffset, // soffset
11956 Offset, // offset
11957 Op.getOperand(6), // cachepolicy, swizzled buffer
11958 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
11959 };
11960
11961 return lowerIntrinsicLoad(cast<MemSDNode>(Op), IsFormat, DAG, Ops);
11962 }
11963 case Intrinsic::amdgcn_raw_tbuffer_load:
11964 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
11965 MemSDNode *M = cast<MemSDNode>(Op);
11966 EVT LoadVT = Op.getValueType();
11967 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
11968 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
11969 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
11970
11971 SDValue Ops[] = {
11972 Op.getOperand(0), // Chain
11973 Rsrc, // rsrc
11974 DAG.getConstant(0, DL, MVT::i32), // vindex
11975 VOffset, // voffset
11976 SOffset, // soffset
11977 Offset, // offset
11978 Op.getOperand(5), // format
11979 Op.getOperand(6), // cachepolicy, swizzled buffer
11980 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11981 };
11982
11983 if (LoadVT.getScalarSizeInBits() == 16)
11984 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
11985 Ops);
11986 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
11987 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
11988 DAG);
11989 }
11990 case Intrinsic::amdgcn_struct_tbuffer_load:
11991 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
11992 MemSDNode *M = cast<MemSDNode>(Op);
11993 EVT LoadVT = Op.getValueType();
11994 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
11995 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
11996 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
11997
11998 SDValue Ops[] = {
11999 Op.getOperand(0), // Chain
12000 Rsrc, // rsrc
12001 Op.getOperand(3), // vindex
12002 VOffset, // voffset
12003 SOffset, // soffset
12004 Offset, // offset
12005 Op.getOperand(6), // format
12006 Op.getOperand(7), // cachepolicy, swizzled buffer
12007 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12008 };
12009
12010 if (LoadVT.getScalarSizeInBits() == 16)
12011 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12012 Ops);
12013 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
12014 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
12015 DAG);
12016 }
12017 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
12018 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
12019 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
12020 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
12021 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
12022 return lowerStructBufferAtomicIntrin(Op, DAG,
12023 AMDGPUISD::BUFFER_ATOMIC_FADD);
12024 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
12025 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
12026 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
12027 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
12028 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
12029 return lowerStructBufferAtomicIntrin(Op, DAG,
12030 AMDGPUISD::BUFFER_ATOMIC_FMIN);
12031 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
12032 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
12033 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
12034 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
12035 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
12036 return lowerStructBufferAtomicIntrin(Op, DAG,
12037 AMDGPUISD::BUFFER_ATOMIC_FMAX);
12038 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
12039 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
12040 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
12041 case Intrinsic::amdgcn_raw_buffer_atomic_add:
12042 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
12043 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12044 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
12045 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
12046 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12047 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
12048 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
12049 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
12050 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
12051 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
12052 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
12053 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
12054 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
12055 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
12056 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
12057 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
12058 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
12059 case Intrinsic::amdgcn_raw_buffer_atomic_and:
12060 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
12061 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12062 case Intrinsic::amdgcn_raw_buffer_atomic_or:
12063 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
12064 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12065 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
12066 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
12067 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12068 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
12069 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
12070 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12071 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12072 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12073 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12074 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12075 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12076 return lowerStructBufferAtomicIntrin(Op, DAG,
12077 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12078 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12079 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12080 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12081 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12082 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12083 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12084 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12085 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12086 return lowerStructBufferAtomicIntrin(Op, DAG,
12087 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12088 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12089 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12090 return lowerStructBufferAtomicIntrin(Op, DAG,
12091 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12092 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12093 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12094 return lowerStructBufferAtomicIntrin(Op, DAG,
12095 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12096 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12097 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12098 return lowerStructBufferAtomicIntrin(Op, DAG,
12099 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12100 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12101 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12102 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12103 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12104 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12105 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12106 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12107 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12108 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12109 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12110 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12111 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12112 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12113 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12114 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12115 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12116 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12117 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12118 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12119 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12120 return lowerStructBufferAtomicIntrin(Op, DAG,
12121 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12122 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12123 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12124 return lowerRawBufferAtomicIntrin(Op, DAG,
12125 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12126 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12127 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12128 return lowerStructBufferAtomicIntrin(Op, DAG,
12129 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12130 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12131 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12132 SDValue Src = Op.getOperand(2);
12133 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12134 SmallVector<EVT, 2> ResultTypes(Op->values());
12135 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12136 "unsupported buffer atomic data type");
12137 }
12138 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(4), DAG);
12139 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12140 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12141 SDValue Ops[] = {
12142 Op.getOperand(0), // Chain
12143 Op.getOperand(2), // src
12144 Op.getOperand(3), // cmp
12145 Rsrc, // rsrc
12146 DAG.getConstant(0, DL, MVT::i32), // vindex
12147 VOffset, // voffset
12148 SOffset, // soffset
12149 Offset, // offset
12150 Op.getOperand(7), // cachepolicy
12151 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12152 };
12153 EVT VT = Op.getValueType();
12154 auto *M = cast<MemSDNode>(Op);
12155
12156 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12157 Op->getVTList(), Ops, VT,
12158 M->getMemOperand());
12159 }
12160 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12161 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12162 SDValue Src = Op.getOperand(2);
12163 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12164 SmallVector<EVT, 2> ResultTypes(Op->values());
12165 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12166 "unsupported buffer atomic data type");
12167 }
12168 SDValue Rsrc = bufferRsrcPtrToVector(Op->getOperand(4), DAG);
12169 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(6), DAG);
12170 auto SOffset = selectSOffset(Op.getOperand(7), DAG, Subtarget);
12171 SDValue Ops[] = {
12172 Op.getOperand(0), // Chain
12173 Op.getOperand(2), // src
12174 Op.getOperand(3), // cmp
12175 Rsrc, // rsrc
12176 Op.getOperand(5), // vindex
12177 VOffset, // voffset
12178 SOffset, // soffset
12179 Offset, // offset
12180 Op.getOperand(8), // cachepolicy
12181 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12182 };
12183 EVT VT = Op.getValueType();
12184 auto *M = cast<MemSDNode>(Op);
12185
12186 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12187 Op->getVTList(), Ops, VT,
12188 M->getMemOperand());
12189 }
12190 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12191 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12192 MemSDNode *M = cast<MemSDNode>(Op);
12193 SDValue NodePtr = M->getOperand(2);
12194 SDValue RayExtent = M->getOperand(3);
12195 SDValue InstanceMask = M->getOperand(4);
12196 SDValue RayOrigin = M->getOperand(5);
12197 SDValue RayDir = M->getOperand(6);
12198 SDValue Offsets = M->getOperand(7);
12199 SDValue TDescr = M->getOperand(8);
12200
12201 assert(NodePtr.getValueType() == MVT::i64);
12202 assert(RayDir.getValueType() == MVT::v3f32);
12203
12204 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12205 const unsigned NumVDataDwords = 10;
12206 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12207 int Opcode = AMDGPU::getMIMGOpcode(
12208 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12209 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12210 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12211 assert(Opcode != -1);
12212
12214 Ops.push_back(NodePtr);
12215 Ops.push_back(DAG.getBuildVector(
12216 MVT::v2i32, DL,
12217 {DAG.getBitcast(MVT::i32, RayExtent),
12218 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12219 Ops.push_back(RayOrigin);
12220 Ops.push_back(RayDir);
12221 Ops.push_back(Offsets);
12222 Ops.push_back(TDescr);
12223 Ops.push_back(M->getChain());
12224
12225 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12226 MachineMemOperand *MemRef = M->getMemOperand();
12227 DAG.setNodeMemRefs(NewNode, {MemRef});
12228 return SDValue(NewNode, 0);
12229 }
12230 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12231 MemSDNode *M = cast<MemSDNode>(Op);
12232 SDValue NodePtr = M->getOperand(2);
12233 SDValue RayExtent = M->getOperand(3);
12234 SDValue RayOrigin = M->getOperand(4);
12235 SDValue RayDir = M->getOperand(5);
12236 SDValue RayInvDir = M->getOperand(6);
12237 SDValue TDescr = M->getOperand(7);
12238
12239 assert(NodePtr.getValueType() == MVT::i32 ||
12240 NodePtr.getValueType() == MVT::i64);
12241 assert(RayDir.getValueType() == MVT::v3f16 ||
12242 RayDir.getValueType() == MVT::v3f32);
12243
12244 const bool IsGFX11 = AMDGPU::isGFX11(*Subtarget);
12245 const bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
12246 const bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
12247 const bool IsA16 = RayDir.getValueType().getVectorElementType() == MVT::f16;
12248 const bool Is64 = NodePtr.getValueType() == MVT::i64;
12249 const unsigned NumVDataDwords = 4;
12250 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12251 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12252 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12253 NumVAddrs <= Subtarget->getNSAMaxSize()) ||
12254 IsGFX12Plus;
12255 const unsigned BaseOpcodes[2][2] = {
12256 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12257 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12258 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12259 int Opcode;
12260 if (UseNSA) {
12261 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12262 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12263 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12264 : AMDGPU::MIMGEncGfx10NSA,
12265 NumVDataDwords, NumVAddrDwords);
12266 } else {
12267 assert(!IsGFX12Plus);
12268 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12269 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12270 : AMDGPU::MIMGEncGfx10Default,
12271 NumVDataDwords, NumVAddrDwords);
12272 }
12273 assert(Opcode != -1);
12274
12276
12277 auto packLanes = [&DAG, &Ops, &DL](SDValue Op, bool IsAligned) {
12279 DAG.ExtractVectorElements(Op, Lanes, 0, 3);
12280 if (Lanes[0].getValueSizeInBits() == 32) {
12281 for (unsigned I = 0; I < 3; ++I)
12282 Ops.push_back(DAG.getBitcast(MVT::i32, Lanes[I]));
12283 } else {
12284 if (IsAligned) {
12285 Ops.push_back(DAG.getBitcast(
12286 MVT::i32,
12287 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[0], Lanes[1]})));
12288 Ops.push_back(Lanes[2]);
12289 } else {
12290 SDValue Elt0 = Ops.pop_back_val();
12291 Ops.push_back(DAG.getBitcast(
12292 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL, {Elt0, Lanes[0]})));
12293 Ops.push_back(DAG.getBitcast(
12294 MVT::i32,
12295 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[1], Lanes[2]})));
12296 }
12297 }
12298 };
12299
12300 if (UseNSA && IsGFX11Plus) {
12301 Ops.push_back(NodePtr);
12302 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12303 Ops.push_back(RayOrigin);
12304 if (IsA16) {
12305 SmallVector<SDValue, 3> DirLanes, InvDirLanes, MergedLanes;
12306 DAG.ExtractVectorElements(RayDir, DirLanes, 0, 3);
12307 DAG.ExtractVectorElements(RayInvDir, InvDirLanes, 0, 3);
12308 for (unsigned I = 0; I < 3; ++I) {
12309 MergedLanes.push_back(DAG.getBitcast(
12310 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL,
12311 {DirLanes[I], InvDirLanes[I]})));
12312 }
12313 Ops.push_back(DAG.getBuildVector(MVT::v3i32, DL, MergedLanes));
12314 } else {
12315 Ops.push_back(RayDir);
12316 Ops.push_back(RayInvDir);
12317 }
12318 } else {
12319 if (Is64)
12320 DAG.ExtractVectorElements(DAG.getBitcast(MVT::v2i32, NodePtr), Ops, 0,
12321 2);
12322 else
12323 Ops.push_back(NodePtr);
12324
12325 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12326 packLanes(RayOrigin, true);
12327 packLanes(RayDir, true);
12328 packLanes(RayInvDir, false);
12329 }
12330
12331 if (!UseNSA) {
12332 // Build a single vector containing all the operands so far prepared.
12333 if (NumVAddrDwords > 12) {
12334 SDValue Undef = DAG.getPOISON(MVT::i32);
12335 Ops.append(16 - Ops.size(), Undef);
12336 }
12337 assert(Ops.size() >= 8 && Ops.size() <= 12);
12338 SDValue MergedOps =
12339 DAG.getBuildVector(MVT::getVectorVT(MVT::i32, Ops.size()), DL, Ops);
12340 Ops.clear();
12341 Ops.push_back(MergedOps);
12342 }
12343
12344 Ops.push_back(TDescr);
12345 Ops.push_back(DAG.getTargetConstant(IsA16, DL, MVT::i1));
12346 Ops.push_back(M->getChain());
12347
12348 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12349 MachineMemOperand *MemRef = M->getMemOperand();
12350 DAG.setNodeMemRefs(NewNode, {MemRef});
12351 return SDValue(NewNode, 0);
12352 }
12353 case Intrinsic::amdgcn_global_atomic_fmin_num:
12354 case Intrinsic::amdgcn_global_atomic_fmax_num:
12355 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12356 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12357 MemSDNode *M = cast<MemSDNode>(Op);
12358 SDValue Ops[] = {
12359 M->getOperand(0), // Chain
12360 M->getOperand(2), // Ptr
12361 M->getOperand(3) // Value
12362 };
12363 unsigned Opcode = 0;
12364 switch (IntrID) {
12365 case Intrinsic::amdgcn_global_atomic_fmin_num:
12366 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12367 Opcode = ISD::ATOMIC_LOAD_FMIN;
12368 break;
12369 }
12370 case Intrinsic::amdgcn_global_atomic_fmax_num:
12371 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12372 Opcode = ISD::ATOMIC_LOAD_FMAX;
12373 break;
12374 }
12375 default:
12376 llvm_unreachable("unhandled atomic opcode");
12377 }
12378 return DAG.getAtomic(Opcode, SDLoc(Op), M->getMemoryVT(), M->getVTList(),
12379 Ops, M->getMemOperand());
12380 }
12381 case Intrinsic::amdgcn_s_alloc_vgpr: {
12382 SDValue NumVGPRs = Op.getOperand(2);
12383 if (!NumVGPRs->isDivergent())
12384 return Op;
12385
12386 SDValue ReadFirstLaneID =
12387 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
12388 NumVGPRs = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
12389 ReadFirstLaneID, NumVGPRs);
12390
12391 return DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, Op->getVTList(),
12392 Op.getOperand(0), Op.getOperand(1), NumVGPRs);
12393 }
12394 case Intrinsic::amdgcn_s_get_barrier_state:
12395 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12396 SDValue Chain = Op->getOperand(0);
12398 unsigned Opc;
12399
12400 if (isa<ConstantSDNode>(Op->getOperand(2))) {
12401 uint64_t BarID = cast<ConstantSDNode>(Op->getOperand(2))->getZExtValue();
12402 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12403 BarID = BarID & 0x3F;
12404 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12405 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
12406 Ops.push_back(K);
12407 Ops.push_back(Chain);
12408 } else {
12409 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12410 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12411 SDValue M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, Op->getOperand(2),
12412 DAG.getConstant(0x3F, DL, MVT::i32));
12413 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
12414 } else
12415 Ops.push_back(copyToM0(DAG, Chain, DL, Op->getOperand(2)).getValue(0));
12416 }
12417
12418 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
12419 return SDValue(NewMI, 0);
12420 }
12421 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12422 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12423 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12424 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12425 SDValue Chain = Op->getOperand(0);
12426 SDValue Ptr = Op->getOperand(2);
12427 EVT VT = Op->getValueType(0);
12428 return DAG.getAtomicLoad(ISD::NON_EXTLOAD, DL, MII->getMemoryVT(), VT,
12429 Chain, Ptr, MII->getMemOperand());
12430 }
12431 case Intrinsic::amdgcn_av_load_b128: {
12432 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12433 SDValue Chain = Op->getOperand(0);
12434 SDValue Ptr = Op->getOperand(2);
12435 EVT VT = Op->getValueType(0);
12436 // Lower to a regular ISD::LOAD. The MachineMemOperand carries Monotonic
12437 // ordering and syncscope so that SIMemoryLegalizer sets cache policy bits.
12438 // Address space filtering in the load_global/load_flat PatFrags selects
12439 // the correct GLOBAL vs FLAT instruction.
12440 return DAG.getLoad(VT, DL, Chain, Ptr, MII->getMemOperand());
12441 }
12442 case Intrinsic::amdgcn_flat_load_monitor_b32:
12443 case Intrinsic::amdgcn_flat_load_monitor_b64:
12444 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12445 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12446 SDValue Chain = Op->getOperand(0);
12447 SDValue Ptr = Op->getOperand(2);
12448 return DAG.getMemIntrinsicNode(AMDGPUISD::FLAT_LOAD_MONITOR, DL,
12449 Op->getVTList(), {Chain, Ptr},
12450 MII->getMemoryVT(), MII->getMemOperand());
12451 }
12452 case Intrinsic::amdgcn_global_load_monitor_b32:
12453 case Intrinsic::amdgcn_global_load_monitor_b64:
12454 case Intrinsic::amdgcn_global_load_monitor_b128: {
12455 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12456 SDValue Chain = Op->getOperand(0);
12457 SDValue Ptr = Op->getOperand(2);
12458 return DAG.getMemIntrinsicNode(AMDGPUISD::GLOBAL_LOAD_MONITOR, DL,
12459 Op->getVTList(), {Chain, Ptr},
12460 MII->getMemoryVT(), MII->getMemOperand());
12461 }
12462 default:
12463
12464 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12466 return lowerImage(Op, ImageDimIntr, DAG, true);
12467
12468 return SDValue();
12469 }
12470}
12471
12472// Call DAG.getMemIntrinsicNode for a load, but first widen a dwordx3 type to
12473// dwordx4 if on SI and handle TFE loads.
12474SDValue SITargetLowering::getMemIntrinsicNode(unsigned Opcode, const SDLoc &DL,
12475 SDVTList VTList,
12476 ArrayRef<SDValue> Ops, EVT MemVT,
12477 MachineMemOperand *MMO,
12478 SelectionDAG &DAG) const {
12479 LLVMContext &C = *DAG.getContext();
12481 EVT VT = VTList.VTs[0];
12482
12483 assert(VTList.NumVTs == 2 || VTList.NumVTs == 3);
12484 bool IsTFE = VTList.NumVTs == 3;
12485 if (IsTFE) {
12486 unsigned NumValueDWords = divideCeil(VT.getSizeInBits(), 32);
12487 unsigned NumOpDWords = NumValueDWords + 1;
12488 EVT OpDWordsVT = EVT::getVectorVT(C, MVT::i32, NumOpDWords);
12489 SDVTList OpDWordsVTList = DAG.getVTList(OpDWordsVT, VTList.VTs[2]);
12490 MachineMemOperand *OpDWordsMMO =
12491 MF.getMachineMemOperand(MMO, 0, NumOpDWords * 4);
12492 SDValue Op = getMemIntrinsicNode(Opcode, DL, OpDWordsVTList, Ops,
12493 OpDWordsVT, OpDWordsMMO, DAG);
12494 SDValue Status = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
12495 DAG.getVectorIdxConstant(NumValueDWords, DL));
12496 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, DL);
12497 SDValue ValueDWords =
12498 NumValueDWords == 1
12499 ? DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op, ZeroIdx)
12501 EVT::getVectorVT(C, MVT::i32, NumValueDWords), Op,
12502 ZeroIdx);
12503 SDValue Value = DAG.getNode(ISD::BITCAST, DL, VT, ValueDWords);
12504 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
12505 }
12506
12507 if (!Subtarget->hasDwordx3LoadStores() &&
12508 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12509 EVT WidenedVT = EVT::getVectorVT(C, VT.getVectorElementType(), 4);
12510 EVT WidenedMemVT = EVT::getVectorVT(C, MemVT.getVectorElementType(), 4);
12511 MachineMemOperand *WidenedMMO = MF.getMachineMemOperand(MMO, 0, 16);
12512 SDVTList WidenedVTList = DAG.getVTList(WidenedVT, VTList.VTs[1]);
12513 SDValue Op = DAG.getMemIntrinsicNode(Opcode, DL, WidenedVTList, Ops,
12514 WidenedMemVT, WidenedMMO);
12516 DAG.getVectorIdxConstant(0, DL));
12517 return DAG.getMergeValues({Value, SDValue(Op.getNode(), 1)}, DL);
12518 }
12519
12520 return DAG.getMemIntrinsicNode(Opcode, DL, VTList, Ops, MemVT, MMO);
12521}
12522
12523SDValue SITargetLowering::handleD16VData(SDValue VData, SelectionDAG &DAG,
12524 bool ImageStore) const {
12525 EVT StoreVT = VData.getValueType();
12526
12527 // No change for f16 and legal vector D16 types.
12528 if (!StoreVT.isVector())
12529 return VData;
12530
12531 SDLoc DL(VData);
12532 unsigned NumElements = StoreVT.getVectorNumElements();
12533
12534 if (Subtarget->hasUnpackedD16VMem()) {
12535 // We need to unpack the packed data to store.
12536 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12537 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12538
12539 EVT EquivStoreVT =
12540 EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumElements);
12541 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, EquivStoreVT, IntVData);
12542 return DAG.UnrollVectorOp(ZExt.getNode());
12543 }
12544
12545 // The sq block of gfx8.1 does not estimate register use correctly for d16
12546 // image store instructions. The data operand is computed as if it were not a
12547 // d16 image instruction.
12548 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12549 // Bitcast to i16
12550 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12551 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12552
12553 // Decompose into scalars
12555 DAG.ExtractVectorElements(IntVData, Elts);
12556
12557 // Group pairs of i16 into v2i16 and bitcast to i32
12558 SmallVector<SDValue, 4> PackedElts;
12559 for (unsigned I = 0; I < Elts.size() / 2; I += 1) {
12560 SDValue Pair =
12561 DAG.getBuildVector(MVT::v2i16, DL, {Elts[I * 2], Elts[I * 2 + 1]});
12562 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12563 PackedElts.push_back(IntPair);
12564 }
12565 if ((NumElements % 2) == 1) {
12566 // Handle v3i16
12567 unsigned I = Elts.size() / 2;
12568 SDValue Pair = DAG.getBuildVector(MVT::v2i16, DL,
12569 {Elts[I * 2], DAG.getPOISON(MVT::i16)});
12570 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12571 PackedElts.push_back(IntPair);
12572 }
12573
12574 // Pad using UNDEF
12575 PackedElts.resize(Elts.size(), DAG.getPOISON(MVT::i32));
12576
12577 // Build final vector
12578 EVT VecVT =
12579 EVT::getVectorVT(*DAG.getContext(), MVT::i32, PackedElts.size());
12580 return DAG.getBuildVector(VecVT, DL, PackedElts);
12581 }
12582
12583 if (NumElements == 3) {
12584 EVT IntStoreVT =
12586 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12587
12588 EVT WidenedStoreVT = EVT::getVectorVT(
12589 *DAG.getContext(), StoreVT.getVectorElementType(), NumElements + 1);
12590 EVT WidenedIntVT = EVT::getIntegerVT(*DAG.getContext(),
12591 WidenedStoreVT.getStoreSizeInBits());
12592 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenedIntVT, IntVData);
12593 return DAG.getNode(ISD::BITCAST, DL, WidenedStoreVT, ZExt);
12594 }
12595
12596 assert(isTypeLegal(StoreVT));
12597 return VData;
12598}
12599
12600static bool isAsyncLDSDMA(Intrinsic::ID Intr) {
12601 switch (Intr) {
12602 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12603 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12604 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12605 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12606 case Intrinsic::amdgcn_load_async_to_lds:
12607 case Intrinsic::amdgcn_global_load_async_lds:
12608 return true;
12609 }
12610 return false;
12611}
12612
12613SDValue SITargetLowering::LowerINTRINSIC_VOID(SDValue Op,
12614 SelectionDAG &DAG) const {
12615 SDLoc DL(Op);
12616 SDValue Chain = Op.getOperand(0);
12617 unsigned IntrinsicID = Op.getConstantOperandVal(1);
12618
12619 switch (IntrinsicID) {
12620 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
12621 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
12622 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
12623 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
12624 if (Subtarget->hasGFX1250_STRICT())
12626 return SDValue();
12627 }
12628 case Intrinsic::amdgcn_exp_compr: {
12629 SDValue Src0 = Op.getOperand(4);
12630 SDValue Src1 = Op.getOperand(5);
12631 // Hack around illegal type on SI by directly selecting it.
12632 if (isTypeLegal(Src0.getValueType()))
12633 return SDValue();
12634
12635 const ConstantSDNode *Done = cast<ConstantSDNode>(Op.getOperand(6));
12636 SDValue Undef = DAG.getPOISON(MVT::f32);
12637 const SDValue Ops[] = {
12638 Op.getOperand(2), // tgt
12639 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src0), // src0
12640 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src1), // src1
12641 Undef, // src2
12642 Undef, // src3
12643 Op.getOperand(7), // vm
12644 DAG.getTargetConstant(1, DL, MVT::i1), // compr
12645 Op.getOperand(3), // en
12646 Op.getOperand(0) // Chain
12647 };
12648
12649 unsigned Opc = Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12650 return SDValue(DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops), 0);
12651 }
12652
12653 case Intrinsic::amdgcn_struct_tbuffer_store:
12654 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12655 SDValue VData = Op.getOperand(2);
12656 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12657 if (IsD16)
12658 VData = handleD16VData(VData, DAG);
12659 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12660 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12661 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12662 SDValue Ops[] = {
12663 Chain,
12664 VData, // vdata
12665 Rsrc, // rsrc
12666 Op.getOperand(4), // vindex
12667 VOffset, // voffset
12668 SOffset, // soffset
12669 Offset, // offset
12670 Op.getOperand(7), // format
12671 Op.getOperand(8), // cachepolicy, swizzled buffer
12672 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12673 };
12674 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12675 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12676 MemSDNode *M = cast<MemSDNode>(Op);
12677 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12678 M->getMemoryVT(), M->getMemOperand());
12679 }
12680
12681 case Intrinsic::amdgcn_raw_tbuffer_store:
12682 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12683 SDValue VData = Op.getOperand(2);
12684 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12685 if (IsD16)
12686 VData = handleD16VData(VData, DAG);
12687 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12688 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12689 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12690 SDValue Ops[] = {
12691 Chain,
12692 VData, // vdata
12693 Rsrc, // rsrc
12694 DAG.getConstant(0, DL, MVT::i32), // vindex
12695 VOffset, // voffset
12696 SOffset, // soffset
12697 Offset, // offset
12698 Op.getOperand(6), // format
12699 Op.getOperand(7), // cachepolicy, swizzled buffer
12700 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12701 };
12702 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12703 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12704 MemSDNode *M = cast<MemSDNode>(Op);
12705 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12706 M->getMemoryVT(), M->getMemOperand());
12707 }
12708
12709 case Intrinsic::amdgcn_raw_buffer_store:
12710 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12711 case Intrinsic::amdgcn_raw_buffer_store_format:
12712 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12713 const bool IsFormat =
12714 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12715 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12716
12717 SDValue VData = Op.getOperand(2);
12718 EVT VDataVT = VData.getValueType();
12719 EVT EltType = VDataVT.getScalarType();
12720 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12721
12722 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12723 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12725 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12726 return Chain;
12727 }
12728
12729 if (IsD16) {
12730 VData = handleD16VData(VData, DAG);
12731 VDataVT = VData.getValueType();
12732 }
12733
12734 if (!isTypeLegal(VDataVT)) {
12735 VData =
12736 DAG.getNode(ISD::BITCAST, DL,
12737 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12738 }
12739
12740 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12741 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12742 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12743 SDValue Ops[] = {
12744 Chain,
12745 VData,
12746 Rsrc,
12747 DAG.getConstant(0, DL, MVT::i32), // vindex
12748 VOffset, // voffset
12749 SOffset, // soffset
12750 Offset, // offset
12751 Op.getOperand(6), // cachepolicy, swizzled buffer
12752 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12753 };
12754 unsigned Opc =
12755 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12756 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12757 MemSDNode *M = cast<MemSDNode>(Op);
12758
12759 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12760 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12761 return handleByteShortBufferStores(DAG, VDataVT, DL, Ops, M);
12762
12763 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12764 M->getMemoryVT(), M->getMemOperand());
12765 }
12766
12767 case Intrinsic::amdgcn_struct_buffer_store:
12768 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12769 case Intrinsic::amdgcn_struct_buffer_store_format:
12770 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12771 const bool IsFormat =
12772 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12773 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12774
12775 SDValue VData = Op.getOperand(2);
12776 EVT VDataVT = VData.getValueType();
12777 EVT EltType = VDataVT.getScalarType();
12778 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12779
12780 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12781 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12783 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12784 return Chain;
12785 }
12786
12787 if (IsD16) {
12788 VData = handleD16VData(VData, DAG);
12789 VDataVT = VData.getValueType();
12790 }
12791
12792 if (!isTypeLegal(VDataVT)) {
12793 VData =
12794 DAG.getNode(ISD::BITCAST, DL,
12795 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12796 }
12797
12798 auto Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12799 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12800 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12801 SDValue Ops[] = {
12802 Chain,
12803 VData,
12804 Rsrc,
12805 Op.getOperand(4), // vindex
12806 VOffset, // voffset
12807 SOffset, // soffset
12808 Offset, // offset
12809 Op.getOperand(7), // cachepolicy, swizzled buffer
12810 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12811 };
12812 unsigned Opc =
12813 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12814 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12815 MemSDNode *M = cast<MemSDNode>(Op);
12816
12817 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12818 EVT VDataType = VData.getValueType().getScalarType();
12819 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12820 return handleByteShortBufferStores(DAG, VDataType, DL, Ops, M);
12821
12822 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12823 M->getMemoryVT(), M->getMemOperand());
12824 }
12825 case Intrinsic::amdgcn_raw_buffer_load_lds:
12826 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12827 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12828 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12829 case Intrinsic::amdgcn_struct_buffer_load_lds:
12830 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12831 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12832 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12833 unsigned Opc;
12834 bool HasVIndex =
12835 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12836 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12837 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12838 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12839 unsigned OpOffset = HasVIndex ? 1 : 0;
12840 SDValue VOffset = Op.getOperand(5 + OpOffset);
12841 bool HasVOffset = !isNullConstant(VOffset);
12842 unsigned Size = Op->getConstantOperandVal(4);
12843
12844 switch (Size) {
12845 default:
12846 return SDValue();
12847 case 1:
12848 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12849 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12850 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12851 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12852 break;
12853 case 2:
12854 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12855 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12856 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12857 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12858 break;
12859 case 4:
12860 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12861 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12862 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12863 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12864 break;
12865 case 12:
12866 if (!Subtarget->hasLDSLoadB96_B128())
12867 return SDValue();
12868 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
12869 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
12870 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
12871 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
12872 break;
12873 case 16:
12874 if (!Subtarget->hasLDSLoadB96_B128())
12875 return SDValue();
12876 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
12877 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
12878 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
12879 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
12880 break;
12881 }
12882
12883 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
12884
12886
12887 if (HasVIndex && HasVOffset)
12888 Ops.push_back(DAG.getBuildVector(MVT::v2i32, DL,
12889 {Op.getOperand(5), // VIndex
12890 VOffset}));
12891 else if (HasVIndex)
12892 Ops.push_back(Op.getOperand(5));
12893 else if (HasVOffset)
12894 Ops.push_back(VOffset);
12895
12896 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12897 Ops.push_back(Rsrc);
12898 Ops.push_back(Op.getOperand(6 + OpOffset)); // soffset
12899 Ops.push_back(Op.getOperand(7 + OpOffset)); // imm offset
12900 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
12901 unsigned Aux = Op.getConstantOperandVal(8 + OpOffset);
12902 Ops.push_back(DAG.getTargetConstant(
12903 Aux & (IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12),
12904 DL, MVT::i8)); // cpol
12905 Ops.push_back(DAG.getTargetConstant(
12906 Aux & (IsGFX12Plus ? AMDGPU::CPol::SWZ : AMDGPU::CPol::SWZ_pregfx12)
12907 ? 1
12908 : 0,
12909 DL, MVT::i8)); // swz
12910 Ops.push_back(
12911 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
12912 Ops.push_back(M0Val.getValue(0)); // Chain
12913 Ops.push_back(M0Val.getValue(1)); // Glue
12914
12915 auto *M = cast<MemSDNode>(Op);
12916 auto *Load = DAG.getMachineNode(Opc, DL, M->getVTList(), Ops);
12917 DAG.setNodeMemRefs(Load, M->memoperands());
12918
12919 return SDValue(Load, 0);
12920 }
12921 // Buffers are handled by LowerBufferFatPointers, and we're going to go
12922 // for "trust me" that the remaining cases are global pointers until
12923 // such time as we can put two mem operands on an intrinsic.
12924 case Intrinsic::amdgcn_load_to_lds:
12925 case Intrinsic::amdgcn_load_async_to_lds:
12926 case Intrinsic::amdgcn_global_load_lds:
12927 case Intrinsic::amdgcn_global_load_async_lds: {
12928 if (!Subtarget->hasVMemToLDSLoad())
12929 return SDValue();
12930
12931 unsigned Opc;
12932 unsigned Size = Op->getConstantOperandVal(4);
12933 switch (Size) {
12934 default:
12935 return SDValue();
12936 case 1:
12937 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
12938 break;
12939 case 2:
12940 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
12941 break;
12942 case 4:
12943 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
12944 break;
12945 case 12:
12946 if (!Subtarget->hasLDSLoadB96_B128())
12947 return SDValue();
12948 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
12949 break;
12950 case 16:
12951 if (!Subtarget->hasLDSLoadB96_B128())
12952 return SDValue();
12953 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
12954 break;
12955 }
12956
12957 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
12958
12960
12961 SDValue Addr = Op.getOperand(2); // Global ptr
12962 SDValue VOffset;
12963 // Try to split SAddr and VOffset. Global and LDS pointers share the same
12964 // immediate offset, so we cannot use a regular SelectGlobalSAddr().
12965 if (Addr->isDivergent() && Addr->isAnyAdd()) {
12966 SDValue LHS = Addr.getOperand(0);
12967 SDValue RHS = Addr.getOperand(1);
12968
12969 if (LHS->isDivergent())
12970 std::swap(LHS, RHS);
12971
12972 if (!LHS->isDivergent() && RHS.getOpcode() == ISD::ZERO_EXTEND &&
12973 RHS.getOperand(0).getValueType() == MVT::i32) {
12974 // add (i64 sgpr), (zero_extend (i32 vgpr))
12975 Addr = LHS;
12976 VOffset = RHS.getOperand(0);
12977 }
12978 }
12979
12980 Ops.push_back(Addr);
12981 if (!Addr->isDivergent()) {
12983 if (!VOffset)
12984 VOffset =
12985 SDValue(DAG.getMachineNode(AMDGPU::V_MOV_B32_e32, DL, MVT::i32,
12986 DAG.getTargetConstant(0, DL, MVT::i32)),
12987 0);
12988 Ops.push_back(VOffset);
12989 }
12990
12991 Ops.push_back(Op.getOperand(5)); // Offset
12992
12993 unsigned Aux = Op.getConstantOperandVal(6);
12994 Ops.push_back(DAG.getTargetConstant(Aux & ~AMDGPU::CPol::VIRTUAL_BITS, DL,
12995 MVT::i32)); // CPol
12996 Ops.push_back(
12997 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
12998
12999 Ops.push_back(M0Val.getValue(0)); // Chain
13000 Ops.push_back(M0Val.getValue(1)); // Glue
13001
13002 auto *M = cast<MemSDNode>(Op);
13003 auto *Load = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13004 DAG.setNodeMemRefs(Load, M->memoperands());
13005
13006 return SDValue(Load, 0);
13007 }
13008 case Intrinsic::amdgcn_end_cf:
13009 return SDValue(DAG.getMachineNode(AMDGPU::SI_END_CF, DL, MVT::Other,
13010 Op->getOperand(2), Chain),
13011 0);
13012 case Intrinsic::amdgcn_s_barrier_signal_var: {
13013 // Member count of 0 means to re-use a previous member count,
13014 // which, if the named barrier is statically chosen, means we can use
13015 // the immarg form. Otherwisee, fall through to constructiong M0 as for
13016 // s_barrier_init.
13017 SDValue CntOp = Op->getOperand(3);
13018 auto *CntC = dyn_cast<ConstantSDNode>(CntOp);
13019 if (CntC && CntC->isZero()) {
13020 SDValue Chain = Op->getOperand(0);
13021 SDValue BarOp = Op->getOperand(2);
13023
13024 std::optional<uint64_t> BarVal;
13025 if (auto *C = dyn_cast<ConstantSDNode>(BarOp))
13026 BarVal = C->getZExtValue();
13027 else if (auto *GA = dyn_cast<GlobalAddressSDNode>(BarOp))
13029 *GA->getGlobal(), AMDGPUAS::BARRIER))
13030 BarVal = *Addr + GA->getOffset();
13031
13032 if (BarVal) {
13033 unsigned BarID = *BarVal & 0x3F;
13034 Ops.push_back(DAG.getTargetConstant(BarID, DL, MVT::i32));
13035 Ops.push_back(Chain);
13036 auto *NewMI = DAG.getMachineNode(AMDGPU::S_BARRIER_SIGNAL_IMM, DL,
13037 Op->getVTList(), Ops);
13038 return SDValue(NewMI, 0);
13039 }
13040 }
13041 [[fallthrough]];
13042 }
13043 case Intrinsic::amdgcn_s_barrier_init: {
13044 // these two intrinsics have two operands: barrier pointer and member count
13045 SDValue Chain = Op->getOperand(0);
13047 SDValue BarOp = Op->getOperand(2);
13048 SDValue CntOp = Op->getOperand(3);
13049 SDValue M0Val;
13050 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
13051 ? AMDGPU::S_BARRIER_INIT_M0
13052 : AMDGPU::S_BARRIER_SIGNAL_M0;
13053 // extract the BarrierID from bits 0-5 of BarOp
13054 SDValue BarID = DAG.getNode(ISD::AND, DL, MVT::i32, BarOp,
13055 DAG.getConstant(0x3F, DL, MVT::i32));
13056 // Member count should be put into M0[ShAmt:+6]
13057 // Barrier ID should be put into M0[5:0]
13058 SDValue MemberCnt = DAG.getNode(ISD::AND, DL, MVT::i32, CntOp,
13059 DAG.getConstant(0x3F, DL, MVT::i32));
13060 constexpr unsigned ShAmt = 16;
13061 M0Val = DAG.getNode(ISD::SHL, DL, MVT::i32, MemberCnt,
13062 DAG.getShiftAmountConstant(ShAmt, MVT::i32, DL));
13063
13064 M0Val = DAG.getNode(ISD::OR, DL, MVT::i32, M0Val, BarID);
13065
13066 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
13067
13068 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13069 return SDValue(NewMI, 0);
13070 }
13071 case Intrinsic::amdgcn_s_wakeup_barrier: {
13072 if (!Subtarget->hasSWakeupBarrier())
13073 return SDValue();
13074 [[fallthrough]];
13075 }
13076 case Intrinsic::amdgcn_s_barrier_join: {
13077 // these three intrinsics have one operand: barrier pointer
13078 SDValue Chain = Op->getOperand(0);
13080 SDValue BarOp = Op->getOperand(2);
13081 unsigned Opc;
13082
13083 if (isa<ConstantSDNode>(BarOp)) {
13084 uint64_t BarVal = cast<ConstantSDNode>(BarOp)->getZExtValue();
13085 switch (IntrinsicID) {
13086 default:
13087 return SDValue();
13088 case Intrinsic::amdgcn_s_barrier_join:
13089 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13090 break;
13091 case Intrinsic::amdgcn_s_wakeup_barrier:
13092 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13093 break;
13094 }
13095 // extract the BarrierID from bits 0-5 of the immediate
13096 unsigned BarID = BarVal & 0x3F;
13097 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
13098 Ops.push_back(K);
13099 Ops.push_back(Chain);
13100 } else {
13101 switch (IntrinsicID) {
13102 default:
13103 return SDValue();
13104 case Intrinsic::amdgcn_s_barrier_join:
13105 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13106 break;
13107 case Intrinsic::amdgcn_s_wakeup_barrier:
13108 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13109 break;
13110 }
13111 // extract the BarrierID from bits 0-5 of BarOp, copy to M0[5:0]
13112 SDValue M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, BarOp,
13113 DAG.getConstant(0x3F, DL, MVT::i32));
13114 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
13115 }
13116
13117 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13118 return SDValue(NewMI, 0);
13119 }
13120 case Intrinsic::amdgcn_s_prefetch_data:
13121 case Intrinsic::amdgcn_s_prefetch_inst: {
13122 // For non-global address space preserve the chain and remove the call.
13124 return Op.getOperand(0);
13125 return Op;
13126 }
13127 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13128 SDValue Ops[] = {
13129 Chain, bufferRsrcPtrToVector(Op.getOperand(2), DAG),
13130 Op.getOperand(3), // offset
13131 Op.getOperand(4), // length
13132 };
13133
13134 MemSDNode *M = cast<MemSDNode>(Op);
13135 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_PREFETCH_DATA, DL,
13136 Op->getVTList(), Ops, M->getMemoryVT(),
13137 M->getMemOperand());
13138 }
13139 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13140 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13141 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13142 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13143 SDValue Chain = Op->getOperand(0);
13144 SDValue Ptr = Op->getOperand(2);
13145 SDValue Val = Op->getOperand(3);
13146 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MII->getMemoryVT(), Chain, Val,
13147 Ptr, MII->getMemOperand());
13148 }
13149 case Intrinsic::amdgcn_av_store_b128: {
13150 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13151 SDValue Chain = Op->getOperand(0);
13152 SDValue Ptr = Op->getOperand(2);
13153 SDValue Val = Op->getOperand(3);
13154 return DAG.getStore(Chain, DL, Val, Ptr, MII->getMemOperand());
13155 }
13156 default: {
13157 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13159 return lowerImage(Op, ImageDimIntr, DAG, true);
13160
13161 return Op;
13162 }
13163 }
13164}
13165
13166// Return whether the operation has NoUnsignedWrap property.
13167static bool isNoUnsignedWrap(SDValue Addr) {
13168 return (Addr.getOpcode() == ISD::ADD &&
13169 Addr->getFlags().hasNoUnsignedWrap()) ||
13170 Addr->getOpcode() == ISD::OR;
13171}
13172
13174 EVT PtrVT) const {
13175 return PtrVT == MVT::i64;
13176}
13177
13179 EVT PtrVT) const {
13180 return true;
13181}
13182
13183// The raw.(t)buffer and struct.(t)buffer intrinsics have two offset args:
13184// offset (the offset that is included in bounds checking and swizzling, to be
13185// split between the instruction's voffset and immoffset fields) and soffset
13186// (the offset that is excluded from bounds checking and swizzling, to go in
13187// the instruction's soffset field). This function takes the first kind of
13188// offset and figures out how to split it between voffset and immoffset.
13189std::pair<SDValue, SDValue>
13190SITargetLowering::splitBufferOffsets(SDValue Offset, SelectionDAG &DAG) const {
13191 SDLoc DL(Offset);
13192 const unsigned MaxImm = SIInstrInfo::getMaxMUBUFImmOffset(*Subtarget);
13193 SDValue N0 = Offset;
13194 ConstantSDNode *C1 = nullptr;
13195
13196 if ((C1 = dyn_cast<ConstantSDNode>(N0)))
13197 N0 = SDValue();
13198 else if (DAG.isBaseWithConstantOffset(N0)) {
13199 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13200 // being added, so we can only safely match a 32-bit addition with no
13201 // unsigned overflow.
13202 bool CheckNUW = Subtarget->hasGFX1250Insts();
13203 if (!CheckNUW || isNoUnsignedWrap(N0)) {
13204 C1 = cast<ConstantSDNode>(N0.getOperand(1));
13205 N0 = N0.getOperand(0);
13206 }
13207 }
13208
13209 if (C1) {
13210 unsigned ImmOffset = C1->getZExtValue();
13211 // If the immediate value is too big for the immoffset field, put only bits
13212 // that would normally fit in the immoffset field. The remaining value that
13213 // is copied/added for the voffset field is a large power of 2, and it
13214 // stands more chance of being CSEd with the copy/add for another similar
13215 // load/store.
13216 // However, do not do that rounding down if that is a negative
13217 // number, as it appears to be illegal to have a negative offset in the
13218 // vgpr, even if adding the immediate offset makes it positive.
13219 unsigned Overflow = ImmOffset & ~MaxImm;
13220 ImmOffset -= Overflow;
13221 if ((int32_t)Overflow < 0) {
13222 Overflow += ImmOffset;
13223 ImmOffset = 0;
13224 }
13225 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(ImmOffset, DL, MVT::i32));
13226 if (Overflow) {
13227 auto OverflowVal = DAG.getConstant(Overflow, DL, MVT::i32);
13228 if (!N0)
13229 N0 = OverflowVal;
13230 else {
13231 SDValue Ops[] = {N0, OverflowVal};
13232 N0 = DAG.getNode(ISD::ADD, DL, MVT::i32, Ops);
13233 }
13234 }
13235 }
13236 if (!N0)
13237 N0 = DAG.getConstant(0, DL, MVT::i32);
13238 if (!C1)
13239 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(0, DL, MVT::i32));
13240 return {N0, SDValue(C1, 0)};
13241}
13242
13243// Analyze a combined offset from an amdgcn_s_buffer_load intrinsic and store
13244// the three offsets (voffset, soffset and instoffset) into the SDValue[3] array
13245// pointed to by Offsets.
13246void SITargetLowering::setBufferOffsets(SDValue CombinedOffset,
13247 SelectionDAG &DAG, SDValue *Offsets,
13248 Align Alignment) const {
13249 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
13250 SDLoc DL(CombinedOffset);
13251 if (auto *C = dyn_cast<ConstantSDNode>(CombinedOffset)) {
13252 uint32_t Imm = C->getZExtValue();
13253 uint32_t SOffset, ImmOffset;
13254 if (TII->splitMUBUFOffset(Imm, SOffset, ImmOffset, Alignment)) {
13255 Offsets[0] = DAG.getConstant(0, DL, MVT::i32);
13256 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13257 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13258 return;
13259 }
13260 }
13261 if (DAG.isBaseWithConstantOffset(CombinedOffset)) {
13262 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13263 // being added, so we can only safely match a 32-bit addition with no
13264 // unsigned overflow.
13265 bool CheckNUW = Subtarget->hasGFX1250Insts();
13266 SDValue N0 = CombinedOffset.getOperand(0);
13267 SDValue N1 = CombinedOffset.getOperand(1);
13268 uint32_t SOffset, ImmOffset;
13269 int Offset = cast<ConstantSDNode>(N1)->getSExtValue();
13270 if (Offset >= 0 && (!CheckNUW || isNoUnsignedWrap(CombinedOffset)) &&
13271 TII->splitMUBUFOffset(Offset, SOffset, ImmOffset, Alignment)) {
13272 Offsets[0] = N0;
13273 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13274 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13275 return;
13276 }
13277 }
13278
13279 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13280 ? DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32)
13281 : DAG.getConstant(0, DL, MVT::i32);
13282
13283 Offsets[0] = CombinedOffset;
13284 Offsets[1] = SOffsetZero;
13285 Offsets[2] = DAG.getTargetConstant(0, DL, MVT::i32);
13286}
13287
13288SDValue SITargetLowering::bufferRsrcPtrToVector(SDValue MaybePointer,
13289 SelectionDAG &DAG) const {
13290 if (!MaybePointer.getValueType().isScalarInteger())
13291 return MaybePointer;
13292
13293 SDValue Rsrc = DAG.getBitcast(MVT::v4i32, MaybePointer);
13294 return Rsrc;
13295}
13296
13297// Wrap a global or flat pointer into a buffer intrinsic using the flags
13298// specified in the intrinsic.
13299SDValue SITargetLowering::lowerPointerAsRsrcIntrin(SDNode *Op,
13300 SelectionDAG &DAG) const {
13301 SDLoc Loc(Op);
13302
13303 SDValue Pointer = Op->getOperand(1);
13304 SDValue Stride = Op->getOperand(2);
13305 SDValue NumRecords = Op->getOperand(3);
13306 SDValue Flags = Op->getOperand(4);
13307
13308 SDValue ExtStride = DAG.getAnyExtOrTrunc(Stride, Loc, MVT::i32);
13309 SDValue Rsrc;
13310
13311 if (Subtarget->getBufferResourceNumRecordsWidth() == 45) {
13312 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i64);
13313 NumRecords = DAG.getNode(ISD::AND, Loc, MVT::i64, NumRecords,
13314 DAG.getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13315 SDValue Zero = DAG.getConstant(0, Loc, MVT::i32);
13316 // Build the lower 64-bit value, which has a 57-bit base and the lower 7-bit
13317 // num_records.
13318 SDValue ExtPointer = DAG.getAnyExtOrTrunc(Pointer, Loc, MVT::i64);
13319 SDValue NumRecordsLHS =
13320 DAG.getNode(ISD::SHL, Loc, MVT::i64, NumRecords,
13321 DAG.getShiftAmountConstant(57, MVT::i32, Loc));
13322 SDValue LowHalf =
13323 DAG.getNode(ISD::OR, Loc, MVT::i64, ExtPointer, NumRecordsLHS);
13324
13325 // Build the higher 64-bit value, which has the higher 38-bit num_records,
13326 // 6-bit zero (omit), 16-bit stride and scale and 4-bit flag.
13327 SDValue NumRecordsRHS =
13328 DAG.getNode(ISD::SRL, Loc, MVT::i64, NumRecords,
13329 DAG.getShiftAmountConstant(7, MVT::i32, Loc));
13330 SDValue ShiftedStride =
13331 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13332 DAG.getShiftAmountConstant(12, MVT::i32, Loc));
13333 SDValue ExtShiftedStrideVec =
13334 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedStride);
13335 SDValue ExtShiftedStride =
13336 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedStrideVec);
13337 SDValue ShiftedFlags =
13338 DAG.getNode(ISD::SHL, Loc, MVT::i32, Flags,
13339 DAG.getShiftAmountConstant(28, MVT::i32, Loc));
13340 SDValue ExtShiftedFlagsVec =
13341 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedFlags);
13342 SDValue ExtShiftedFlags =
13343 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedFlagsVec);
13344 SDValue CombinedFields =
13345 DAG.getNode(ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13346 SDValue HighHalf =
13347 DAG.getNode(ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13348
13349 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i64, LowHalf, HighHalf);
13350 } else {
13351 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i32);
13352 auto [LowHalf, HighHalf] =
13353 DAG.SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13354 SDValue Mask = DAG.getConstant(0x0000ffff, Loc, MVT::i32);
13355 SDValue Masked = DAG.getNode(ISD::AND, Loc, MVT::i32, HighHalf, Mask);
13356 SDValue ShiftedStride =
13357 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13358 DAG.getShiftAmountConstant(16, MVT::i32, Loc));
13359 SDValue NewHighHalf =
13360 DAG.getNode(ISD::OR, Loc, MVT::i32, Masked, ShiftedStride);
13361
13362 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v4i32, LowHalf, NewHighHalf,
13363 NumRecords, Flags);
13364 }
13365
13366 SDValue RsrcPtr = DAG.getNode(ISD::BITCAST, Loc, MVT::i128, Rsrc);
13367 return RsrcPtr;
13368}
13369
13370// Handle 8 bit and 16 bit buffer loads
13371SDValue SITargetLowering::handleByteShortBufferLoads(SelectionDAG &DAG,
13372 EVT LoadVT, SDLoc DL,
13374 MachineMemOperand *MMO,
13375 bool IsTFE) const {
13376 EVT IntVT = LoadVT.changeTypeToInteger();
13377
13378 if (IsTFE) {
13379 unsigned Opc = (LoadVT.getScalarType() == MVT::i8)
13380 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13381 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13383 MachineMemOperand *OpMMO = MF.getMachineMemOperand(MMO, 0, 8);
13384 SDVTList VTs = DAG.getVTList(MVT::v2i32, MVT::Other);
13385 SDValue Op = getMemIntrinsicNode(Opc, DL, VTs, Ops, MVT::v2i32, OpMMO, DAG);
13386 SDValue Status = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13387 DAG.getConstant(1, DL, MVT::i32));
13388 SDValue Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13389 DAG.getConstant(0, DL, MVT::i32));
13390 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Data);
13391 SDValue Value = DAG.getNode(ISD::BITCAST, DL, LoadVT, Trunc);
13392 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
13393 }
13394
13395 unsigned Opc = LoadVT.getScalarType() == MVT::i8
13396 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13397 : AMDGPUISD::BUFFER_LOAD_USHORT;
13398
13399 SDVTList ResList = DAG.getVTList(MVT::i32, MVT::Other);
13400 SDValue BufferLoad =
13401 DAG.getMemIntrinsicNode(Opc, DL, ResList, Ops, IntVT, MMO);
13402 SDValue LoadVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, BufferLoad);
13403 LoadVal = DAG.getNode(ISD::BITCAST, DL, LoadVT, LoadVal);
13404
13405 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
13406}
13407
13408// Handle 8 bit and 16 bit buffer stores
13409SDValue SITargetLowering::handleByteShortBufferStores(SelectionDAG &DAG,
13410 EVT VDataType, SDLoc DL,
13411 SDValue Ops[],
13412 MemSDNode *M) const {
13413 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13414 Ops[1] = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Ops[1]);
13415
13416 SDValue BufferStoreExt = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Ops[1]);
13417 Ops[1] = BufferStoreExt;
13418 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13419 : AMDGPUISD::BUFFER_STORE_SHORT;
13420 ArrayRef<SDValue> OpsRef = ArrayRef(&Ops[0], 9);
13421 return DAG.getMemIntrinsicNode(Opc, DL, M->getVTList(), OpsRef, VDataType,
13422 M->getMemOperand());
13423}
13424
13426 SDValue Op, const SDLoc &SL, EVT VT) {
13427 if (VT.bitsLT(Op.getValueType()))
13428 return DAG.getNode(ISD::TRUNCATE, SL, VT, Op);
13429
13430 switch (ExtType) {
13431 case ISD::SEXTLOAD:
13432 return DAG.getNode(ISD::SIGN_EXTEND, SL, VT, Op);
13433 case ISD::ZEXTLOAD:
13434 return DAG.getNode(ISD::ZERO_EXTEND, SL, VT, Op);
13435 case ISD::EXTLOAD:
13436 return DAG.getNode(ISD::ANY_EXTEND, SL, VT, Op);
13437 case ISD::NON_EXTLOAD:
13438 return Op;
13439 }
13440
13441 llvm_unreachable("invalid ext type");
13442}
13443
13444// Try to turn 8 and 16-bit scalar loads into SMEM eligible 32-bit loads.
13445// TODO: Skip this on GFX12 which does have scalar sub-dword loads.
13446SDValue SITargetLowering::widenLoad(LoadSDNode *Ld,
13447 DAGCombinerInfo &DCI) const {
13448 SelectionDAG &DAG = DCI.DAG;
13449 if (Ld->getAlign() < Align(4) || Ld->isDivergent())
13450 return SDValue();
13451
13452 // FIXME: Constant loads should all be marked invariant.
13453 unsigned AS = Ld->getAddressSpace();
13454 if (AS != AMDGPUAS::CONSTANT_ADDRESS &&
13456 (AS != AMDGPUAS::GLOBAL_ADDRESS || !Ld->isInvariant()))
13457 return SDValue();
13458
13459 // Don't do this early, since it may interfere with adjacent load merging for
13460 // illegal types. We can avoid losing alignment information for exotic types
13461 // pre-legalize.
13462 EVT MemVT = Ld->getMemoryVT();
13463 if ((MemVT.isSimple() && !DCI.isAfterLegalizeDAG()) ||
13464 MemVT.getSizeInBits() >= 32)
13465 return SDValue();
13466
13467 SDLoc SL(Ld);
13468
13469 assert((!MemVT.isVector() || Ld->getExtensionType() == ISD::NON_EXTLOAD) &&
13470 "unexpected vector extload");
13471
13472 // TODO: Drop only high part of range.
13473 SDValue Ptr = Ld->getBasePtr();
13474 SDValue NewLoad = DAG.getLoad(
13475 ISD::UNINDEXED, ISD::NON_EXTLOAD, MVT::i32, SL, Ld->getChain(), Ptr,
13476 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13477 Ld->getMemOperand()->getFlags(), Ld->getAAInfo()); // Drop ranges
13478
13479 EVT TruncVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
13480 if (MemVT.isFloatingPoint()) {
13481 assert(Ld->getExtensionType() == ISD::NON_EXTLOAD &&
13482 "unexpected fp extload");
13483 TruncVT = MemVT.changeTypeToInteger();
13484 }
13485
13486 SDValue Cvt = NewLoad;
13487 if (Ld->getExtensionType() == ISD::SEXTLOAD) {
13488 Cvt = DAG.getNode(ISD::SIGN_EXTEND_INREG, SL, MVT::i32, NewLoad,
13489 DAG.getValueType(TruncVT));
13490 } else if (Ld->getExtensionType() == ISD::ZEXTLOAD ||
13491 Ld->getExtensionType() == ISD::NON_EXTLOAD) {
13492 Cvt = DAG.getZeroExtendInReg(NewLoad, SL, TruncVT);
13493 } else {
13494 assert(Ld->getExtensionType() == ISD::EXTLOAD);
13495 }
13496
13497 EVT VT = Ld->getValueType(0);
13498 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
13499
13500 DCI.AddToWorklist(Cvt.getNode());
13501
13502 // We may need to handle exotic cases, such as i16->i64 extloads, so insert
13503 // the appropriate extension from the 32-bit load.
13504 Cvt = getLoadExtOrTrunc(DAG, Ld->getExtensionType(), Cvt, SL, IntVT);
13505 DCI.AddToWorklist(Cvt.getNode());
13506
13507 // Handle conversion back to floating point if necessary.
13508 Cvt = DAG.getNode(ISD::BITCAST, SL, VT, Cvt);
13509
13510 return DAG.getMergeValues({Cvt, NewLoad.getValue(1)}, SL);
13511}
13512
13514 const SIMachineFunctionInfo &Info) {
13515 // TODO: Should check if the address can definitely not access stack.
13516 if (Info.isEntryFunction())
13517 return Info.getUserSGPRInfo().hasFlatScratchInit();
13518 return true;
13519}
13520
13521SDValue SITargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
13522 SDLoc DL(Op);
13523 LoadSDNode *Load = cast<LoadSDNode>(Op);
13524 ISD::LoadExtType ExtType = Load->getExtensionType();
13525 EVT MemVT = Load->getMemoryVT();
13526 MachineMemOperand *MMO = Load->getMemOperand();
13527
13528 if (ExtType == ISD::NON_EXTLOAD && MemVT.getSizeInBits() < 32) {
13529 if (MemVT == MVT::i16 && isTypeLegal(MVT::i16))
13530 return SDValue();
13531
13532 // FIXME: Copied from PPC
13533 // First, load into 32 bits, then truncate to 1 bit.
13534
13535 SDValue Chain = Load->getChain();
13536 SDValue BasePtr = Load->getBasePtr();
13537
13538 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13539
13540 SDValue NewLD = DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, BasePtr,
13541 RealMemVT, MMO);
13542
13543 if (!MemVT.isVector()) {
13544 SDValue Ops[] = {DAG.getNode(ISD::TRUNCATE, DL, MemVT, NewLD),
13545 NewLD.getValue(1)};
13546
13547 return DAG.getMergeValues(Ops, DL);
13548 }
13549
13551 for (unsigned I = 0, N = MemVT.getVectorNumElements(); I != N; ++I) {
13552 SDValue Elt = DAG.getNode(ISD::SRL, DL, MVT::i32, NewLD,
13553 DAG.getConstant(I, DL, MVT::i32));
13554
13555 Elts.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Elt));
13556 }
13557
13558 SDValue Ops[] = {DAG.getBuildVector(MemVT, DL, Elts), NewLD.getValue(1)};
13559
13560 return DAG.getMergeValues(Ops, DL);
13561 }
13562
13563 if (!MemVT.isVector())
13564 return SDValue();
13565
13566 assert(Op.getValueType().getVectorElementType() == MVT::i32 &&
13567 "Custom lowering for non-i32 vectors hasn't been implemented.");
13568
13569 Align Alignment = Load->getAlign();
13570 unsigned AS = Load->getAddressSpace();
13571 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13572 AS == AMDGPUAS::FLAT_ADDRESS &&
13573 Alignment.value() < MemVT.getStoreSize() && MemVT.getSizeInBits() > 32) {
13574 return SplitVectorLoad(Op, DAG);
13575 }
13576
13578 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
13579 // If there is a possibility that flat instruction access scratch memory
13580 // then we need to use the same legalization rules we use for private.
13581 if (AS == AMDGPUAS::FLAT_ADDRESS &&
13582 !Subtarget->hasMultiDwordFlatScratchAddressing())
13583 AS = addressMayBeAccessedAsPrivate(Load->getMemOperand(), *MFI)
13586
13587 unsigned NumElements = MemVT.getVectorNumElements();
13588
13589 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13591 (AS == AMDGPUAS::GLOBAL_ADDRESS &&
13592 Subtarget->getScalarizeGlobalBehavior() && Load->isSimple() &&
13593 (Load->isInvariant() || isMemOpHasNoClobberedMemOperand(Load)))) {
13594 if ((!Op->isDivergent() || AMDGPU::isUniformMMO(MMO)) &&
13595 Alignment >= Align(4) && NumElements < 32) {
13596 if (MemVT.isPow2VectorType() ||
13597 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13598 return SDValue();
13599 return WidenOrSplitVectorLoad(Op, DAG);
13600 }
13601 // Non-uniform loads will be selected to MUBUF instructions, so they
13602 // have the same legalization requirements as global and private
13603 // loads.
13604 //
13605 }
13606 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13609 if (NumElements > 4)
13610 return SplitVectorLoad(Op, DAG);
13611 // v3 loads not supported on SI.
13612 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13613 return WidenOrSplitVectorLoad(Op, DAG);
13614
13615 // v3 and v4 loads are supported for private and global memory.
13616 return SDValue();
13617 }
13618 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
13619 // Depending on the setting of the private_element_size field in the
13620 // resource descriptor, we can only make private accesses up to a certain
13621 // size.
13622 switch (Subtarget->getMaxPrivateElementSize()) {
13623 case 4: {
13624 auto [Op0, Op1] = scalarizeVectorLoad(Load, DAG);
13625 return DAG.getMergeValues({Op0, Op1}, DL);
13626 }
13627 case 8:
13628 if (NumElements > 2)
13629 return SplitVectorLoad(Op, DAG);
13630 return SDValue();
13631 case 16:
13632 // Same as global/flat
13633 if (NumElements > 4)
13634 return SplitVectorLoad(Op, DAG);
13635 // v3 loads not supported on SI.
13636 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13637 return WidenOrSplitVectorLoad(Op, DAG);
13638
13639 return SDValue();
13640 default:
13641 llvm_unreachable("unsupported private_element_size");
13642 }
13643 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
13644 unsigned Fast = 0;
13645 auto Flags = Load->getMemOperand()->getFlags();
13647 Load->getAlign(), Flags, &Fast) &&
13648 Fast > 1)
13649 return SDValue();
13650
13651 if (MemVT.isVector())
13652 return SplitVectorLoad(Op, DAG);
13653 }
13654
13656 MemVT, *Load->getMemOperand())) {
13657 auto [Op0, Op1] = expandUnalignedLoad(Load, DAG);
13658 return DAG.getMergeValues({Op0, Op1}, DL);
13659 }
13660
13661 return SDValue();
13662}
13663
13664SDValue SITargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
13665 EVT VT = Op.getValueType();
13666 if (VT.getSizeInBits() == 128 || VT.getSizeInBits() == 256 ||
13667 VT.getSizeInBits() == 512)
13668 return splitTernaryVectorOp(Op, DAG);
13669
13670 assert(VT.getSizeInBits() == 64);
13671
13672 SDLoc DL(Op);
13673 SDValue Cond = DAG.getFreeze(Op.getOperand(0));
13674
13675 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
13676 SDValue One = DAG.getConstant(1, DL, MVT::i32);
13677
13678 SDValue LHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
13679 SDValue RHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(2));
13680
13681 SDValue Lo0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, Zero);
13682 SDValue Lo1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, Zero);
13683
13684 SDValue Lo = DAG.getSelect(DL, MVT::i32, Cond, Lo0, Lo1);
13685
13686 SDValue Hi0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, One);
13687 SDValue Hi1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, One);
13688
13689 SDValue Hi = DAG.getSelect(DL, MVT::i32, Cond, Hi0, Hi1);
13690
13691 SDValue Res = DAG.getBuildVector(MVT::v2i32, DL, {Lo, Hi});
13692 return DAG.getNode(ISD::BITCAST, DL, VT, Res);
13693}
13694
13695// Catch division cases where we can use shortcuts with rcp and rsq
13696// instructions.
13697SDValue SITargetLowering::lowerFastUnsafeFDIV(SDValue Op,
13698 SelectionDAG &DAG) const {
13699 SDLoc SL(Op);
13700 SDValue LHS = Op.getOperand(0);
13701 SDValue RHS = Op.getOperand(1);
13702 EVT VT = Op.getValueType();
13703 const SDNodeFlags Flags = Op->getFlags();
13704
13705 bool AllowInaccurateRcp = Flags.hasApproximateFuncs();
13706
13707 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
13708 // Without !fpmath accuracy information, we can't do more because we don't
13709 // know exactly whether rcp is accurate enough to meet !fpmath requirement.
13710 // f16 is always accurate enough
13711 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13712 return SDValue();
13713
13714 if (CLHS->isOne()) {
13715 // v_rcp_f32 and v_rsq_f32 do not support denormals, and according to
13716 // the CI documentation has a worst case error of 1 ulp.
13717 // OpenCL requires <= 2.5 ulp for 1.0 / x, so it should always be OK to
13718 // use it as long as we aren't trying to use denormals.
13719 //
13720 // v_rcp_f16 and v_rsq_f16 DO support denormals and 0.51ulp.
13721
13722 // 1.0 / sqrt(x) -> rsq(x)
13723
13724 // XXX - Is afn sufficient to do this for f64? The maximum ULP
13725 // error seems really high at 2^29 ULP.
13726 // 1.0 / x -> rcp(x)
13727 return DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13728 }
13729
13730 // Same as for 1.0, but expand the sign out of the constant.
13731 if (CLHS->isMinusOne()) {
13732 // -1.0 / x -> rcp (fneg x)
13733 SDValue FNegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
13734 return DAG.getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13735 }
13736 }
13737
13738 // For f16 and bf16 require afn or arcp.
13739 // For f32 require afn.
13740 if (!AllowInaccurateRcp &&
13741 ((VT != MVT::f16 && VT != MVT::bf16) || !Flags.hasAllowReciprocal()))
13742 return SDValue();
13743
13744 // Turn into multiply by the reciprocal.
13745 // x / y -> x * (1.0 / y)
13746 SDValue Recip = DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13747 return DAG.getNode(ISD::FMUL, SL, VT, LHS, Recip, Flags);
13748}
13749
13750SDValue SITargetLowering::lowerFastUnsafeFDIV64(SDValue Op,
13751 SelectionDAG &DAG) const {
13752 SDLoc SL(Op);
13753 SDValue X = Op.getOperand(0);
13754 SDValue Y = Op.getOperand(1);
13755 EVT VT = Op.getValueType();
13756 const SDNodeFlags Flags = Op->getFlags();
13757
13758 bool AllowInaccurateDiv = Flags.hasApproximateFuncs();
13759 if (!AllowInaccurateDiv)
13760 return SDValue();
13761
13762 const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(X);
13763 bool IsNegRcp = CLHS && CLHS->isMinusOne();
13764
13765 // Pull out the negation so it folds for free into the source modifiers.
13766 if (IsNegRcp)
13767 X = DAG.getConstantFP(1.0, SL, VT);
13768
13769 SDValue NegY = IsNegRcp ? Y : DAG.getNode(ISD::FNEG, SL, VT, Y);
13770 SDValue One = DAG.getConstantFP(1.0, SL, VT);
13771
13772 SDValue R = DAG.getNode(AMDGPUISD::RCP, SL, VT, Y);
13773 if (IsNegRcp)
13774 R = DAG.getNode(ISD::FNEG, SL, VT, R);
13775
13776 SDValue Tmp0 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13777
13778 R = DAG.getNode(ISD::FMA, SL, VT, Tmp0, R, R);
13779 SDValue Tmp1 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13780 R = DAG.getNode(ISD::FMA, SL, VT, Tmp1, R, R);
13781
13782 // Skip the last 2 correction terms for reciprocal.
13783 if (IsNegRcp || (CLHS && CLHS->isOne()))
13784 return R;
13785
13786 SDValue Ret = DAG.getNode(ISD::FMUL, SL, VT, X, R);
13787 SDValue Tmp2 = DAG.getNode(ISD::FMA, SL, VT, NegY, Ret, X);
13788 return DAG.getNode(ISD::FMA, SL, VT, Tmp2, R, Ret);
13789}
13790
13791static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13792 EVT VT, SDValue A, SDValue B, SDValue GlueChain,
13793 SDNodeFlags Flags) {
13794 if (GlueChain->getNumValues() <= 1) {
13795 return DAG.getNode(Opcode, SL, VT, A, B, Flags);
13796 }
13797
13798 assert(GlueChain->getNumValues() == 3);
13799
13800 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13801 switch (Opcode) {
13802 default:
13803 llvm_unreachable("no chain equivalent for opcode");
13804 case ISD::FMUL:
13805 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13806 break;
13807 }
13808
13809 return DAG.getNode(Opcode, SL, VTList,
13810 {GlueChain.getValue(1), A, B, GlueChain.getValue(2)},
13811 Flags);
13812}
13813
13814static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13815 EVT VT, SDValue A, SDValue B, SDValue C,
13816 SDValue GlueChain, SDNodeFlags Flags) {
13817 if (GlueChain->getNumValues() <= 1) {
13818 return DAG.getNode(Opcode, SL, VT, {A, B, C}, Flags);
13819 }
13820
13821 assert(GlueChain->getNumValues() == 3);
13822
13823 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13824 switch (Opcode) {
13825 default:
13826 llvm_unreachable("no chain equivalent for opcode");
13827 case ISD::FMA:
13828 Opcode = AMDGPUISD::FMA_W_CHAIN;
13829 break;
13830 }
13831
13832 return DAG.getNode(Opcode, SL, VTList,
13833 {GlueChain.getValue(1), A, B, C, GlueChain.getValue(2)},
13834 Flags);
13835}
13836
13837SDValue SITargetLowering::LowerFDIV16(SDValue Op, SelectionDAG &DAG) const {
13838 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
13839 return FastLowered;
13840
13841 SDLoc SL(Op);
13842 EVT VT = Op.getValueType();
13843 SDValue LHS = Op.getOperand(0);
13844 SDValue RHS = Op.getOperand(1);
13845
13846 SDValue LHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, LHS);
13847 SDValue RHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, RHS);
13848
13849 if (VT == MVT::bf16) {
13850 SDValue ExtDiv =
13851 DAG.getNode(ISD::FDIV, SL, MVT::f32, LHSExt, RHSExt, Op->getFlags());
13852 return DAG.getNode(ISD::FP_ROUND, SL, MVT::bf16, ExtDiv,
13853 DAG.getTargetConstant(0, SL, MVT::i32));
13854 }
13855
13856 assert(VT == MVT::f16);
13857
13858 // a32.u = opx(V_CVT_F32_F16, a.u); // CVT to F32
13859 // b32.u = opx(V_CVT_F32_F16, b.u); // CVT to F32
13860 // r32.u = opx(V_RCP_F32, b32.u); // rcp = 1 / d
13861 // q32.u = opx(V_MUL_F32, a32.u, r32.u); // q = n * rcp
13862 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
13863 // q32.u = opx(V_MAD_F32, e32.u, r32.u, q32.u); // q = n * rcp
13864 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
13865 // tmp.u = opx(V_MUL_F32, e32.u, r32.u);
13866 // tmp.u = opx(V_AND_B32, tmp.u, 0xff800000)
13867 // q32.u = opx(V_ADD_F32, tmp.u, q32.u);
13868 // q16.u = opx(V_CVT_F16_F32, q32.u);
13869 // q16.u = opx(V_DIV_FIXUP_F16, q16.u, b.u, a.u); // q = touchup(q, d, n)
13870
13871 // We will use ISD::FMA on targets that don't support ISD::FMAD.
13872 unsigned FMADOpCode =
13874 SDValue NegRHSExt = DAG.getNode(ISD::FNEG, SL, MVT::f32, RHSExt);
13875 SDValue Rcp =
13876 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt, Op->getFlags());
13877 SDValue Quot =
13878 DAG.getNode(ISD::FMUL, SL, MVT::f32, LHSExt, Rcp, Op->getFlags());
13879 SDValue Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13880 Op->getFlags());
13881 Quot = DAG.getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot, Op->getFlags());
13882 Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13883 Op->getFlags());
13884 SDValue Tmp = DAG.getNode(ISD::FMUL, SL, MVT::f32, Err, Rcp, Op->getFlags());
13885 SDValue TmpCast = DAG.getNode(ISD::BITCAST, SL, MVT::i32, Tmp);
13886 TmpCast = DAG.getNode(ISD::AND, SL, MVT::i32, TmpCast,
13887 DAG.getConstant(0xff800000, SL, MVT::i32));
13888 Tmp = DAG.getNode(ISD::BITCAST, SL, MVT::f32, TmpCast);
13889 Quot = DAG.getNode(ISD::FADD, SL, MVT::f32, Tmp, Quot, Op->getFlags());
13890 SDValue RDst = DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Quot,
13891 DAG.getTargetConstant(0, SL, MVT::i32));
13892 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst, RHS, LHS,
13893 Op->getFlags());
13894}
13895
13896// Faster 2.5 ULP division that does not support denormals.
13897SDValue SITargetLowering::lowerFDIV_FAST(SDValue Op, SelectionDAG &DAG) const {
13898 SDNodeFlags Flags = Op->getFlags();
13899 SDLoc SL(Op);
13900 SDValue LHS = Op.getOperand(1);
13901 SDValue RHS = Op.getOperand(2);
13902
13903 // TODO: The combiner should probably handle elimination of redundant fabs.
13905 ? RHS
13906 : DAG.getNode(ISD::FABS, SL, MVT::f32, RHS, Flags);
13907
13908 const APFloat K0Val(0x1p+96f);
13909 const SDValue K0 = DAG.getConstantFP(K0Val, SL, MVT::f32);
13910
13911 const APFloat K1Val(0x1p-32f);
13912 const SDValue K1 = DAG.getConstantFP(K1Val, SL, MVT::f32);
13913
13914 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
13915
13916 EVT SetCCVT =
13917 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
13918
13919 SDValue r2 = DAG.getSetCC(SL, SetCCVT, r1, K0, ISD::SETOGT);
13920
13921 SDValue r3 = DAG.getNode(ISD::SELECT, SL, MVT::f32, r2, K1, One, Flags);
13922
13923 r1 = DAG.getNode(ISD::FMUL, SL, MVT::f32, RHS, r3, Flags);
13924
13925 // rcp does not support denormals.
13926 SDValue r0 = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, r1, Flags);
13927
13928 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f32, LHS, r0, Flags);
13929
13930 return DAG.getNode(ISD::FMUL, SL, MVT::f32, r3, Mul, Flags);
13931}
13932
13933// Returns immediate value for setting the F32 denorm mode when using the
13934// S_DENORM_MODE instruction.
13936 const SIMachineFunctionInfo *Info,
13937 const GCNSubtarget *ST) {
13938 assert(ST->hasDenormModeInst() && "Requires S_DENORM_MODE");
13939 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
13940 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
13941 return DAG.getTargetConstant(Mode, SDLoc(), MVT::i32);
13942}
13943
13944SDValue SITargetLowering::LowerFDIV32(SDValue Op, SelectionDAG &DAG) const {
13945 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
13946 return FastLowered;
13947
13948 // The selection matcher assumes anything with a chain selecting to a
13949 // mayRaiseFPException machine instruction. Since we're introducing a chain
13950 // here, we need to explicitly report nofpexcept for the regular fdiv
13951 // lowering.
13952 SDNodeFlags Flags = Op->getFlags();
13953 Flags.setNoFPExcept(true);
13954
13955 SDLoc SL(Op);
13956 SDValue LHS = Op.getOperand(0);
13957 SDValue RHS = Op.getOperand(1);
13958
13959 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
13960
13961 SDVTList ScaleVT = DAG.getVTList(MVT::f32, MVT::i1);
13962
13963 SDValue DenominatorScaled =
13964 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {RHS, RHS, LHS}, Flags);
13965 SDValue NumeratorScaled =
13966 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {LHS, RHS, LHS}, Flags);
13967
13968 // Denominator is scaled to not be denormal, so using rcp is ok.
13969 SDValue ApproxRcp =
13970 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
13971 SDValue NegDivScale0 =
13972 DAG.getNode(ISD::FNEG, SL, MVT::f32, DenominatorScaled, Flags);
13973
13974 using namespace AMDGPU::Hwreg;
13975 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
13976 const SDValue BitField = DAG.getTargetConstant(Denorm32Reg, SL, MVT::i32);
13977
13978 const MachineFunction &MF = DAG.getMachineFunction();
13979 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
13980 const DenormalMode DenormMode = Info->getMode().FP32Denormals;
13981
13982 const bool PreservesDenormals = DenormMode == DenormalMode::getIEEE();
13983 const bool HasDynamicDenormals =
13984 (DenormMode.Input == DenormalMode::Dynamic) ||
13985 (DenormMode.Output == DenormalMode::Dynamic);
13986
13987 SDValue SavedDenormMode;
13988
13989 if (!PreservesDenormals) {
13990 // Note we can't use the STRICT_FMA/STRICT_FMUL for the non-strict FDIV
13991 // lowering. The chain dependence is insufficient, and we need glue. We do
13992 // not need the glue variants in a strictfp function.
13993
13994 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
13995
13996 SDValue Glue = DAG.getEntryNode();
13997 if (HasDynamicDenormals) {
13998 SDNode *GetReg = DAG.getMachineNode(AMDGPU::S_GETREG_B32, SL,
13999 DAG.getVTList(MVT::i32, MVT::Glue),
14000 {BitField, Glue});
14001 SavedDenormMode = SDValue(GetReg, 0);
14002
14003 Glue = DAG.getMergeValues(
14004 {DAG.getEntryNode(), SDValue(GetReg, 0), SDValue(GetReg, 1)}, SL);
14005 }
14006
14007 SDNode *EnableDenorm;
14008 if (Subtarget->hasDenormModeInst()) {
14009 const SDValue EnableDenormValue =
14010 getSPDenormModeValue(FP_DENORM_FLUSH_NONE, DAG, Info, Subtarget);
14011
14012 EnableDenorm = DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
14013 EnableDenormValue)
14014 .getNode();
14015 } else {
14016 const SDValue EnableDenormValue =
14017 DAG.getConstant(FP_DENORM_FLUSH_NONE, SL, MVT::i32);
14018 EnableDenorm = DAG.getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
14019 {EnableDenormValue, BitField, Glue});
14020 }
14021
14022 SDValue Ops[3] = {NegDivScale0, SDValue(EnableDenorm, 0),
14023 SDValue(EnableDenorm, 1)};
14024
14025 NegDivScale0 = DAG.getMergeValues(Ops, SL);
14026 }
14027
14028 SDValue Fma0 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0,
14029 ApproxRcp, One, NegDivScale0, Flags);
14030
14031 SDValue Fma1 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma0, ApproxRcp,
14032 ApproxRcp, Fma0, Flags);
14033
14034 SDValue Mul = getFPBinOp(DAG, ISD::FMUL, SL, MVT::f32, NumeratorScaled, Fma1,
14035 Fma1, Flags);
14036
14037 SDValue Fma2 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Mul,
14038 NumeratorScaled, Mul, Flags);
14039
14040 SDValue Fma3 =
14041 getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma2, Fma1, Mul, Fma2, Flags);
14042
14043 SDValue Fma4 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Fma3,
14044 NumeratorScaled, Fma3, Flags);
14045
14046 if (!PreservesDenormals) {
14047 SDNode *DisableDenorm;
14048 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
14049 const SDValue DisableDenormValue = getSPDenormModeValue(
14050 FP_DENORM_FLUSH_IN_FLUSH_OUT, DAG, Info, Subtarget);
14051
14052 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
14053 DisableDenorm =
14054 DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
14055 Fma4.getValue(1), DisableDenormValue, Fma4.getValue(2))
14056 .getNode();
14057 } else {
14058 assert(HasDynamicDenormals == (bool)SavedDenormMode);
14059 const SDValue DisableDenormValue =
14060 HasDynamicDenormals
14061 ? SavedDenormMode
14062 : DAG.getConstant(FP_DENORM_FLUSH_IN_FLUSH_OUT, SL, MVT::i32);
14063
14064 DisableDenorm = DAG.getMachineNode(
14065 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14066 {DisableDenormValue, BitField, Fma4.getValue(1), Fma4.getValue(2)});
14067 }
14068
14069 SDValue OutputChain = DAG.getNode(ISD::TokenFactor, SL, MVT::Other,
14070 SDValue(DisableDenorm, 0), DAG.getRoot());
14071 DAG.setRoot(OutputChain);
14072 }
14073
14074 SDValue Scale = NumeratorScaled.getValue(1);
14075 SDValue Fmas = DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f32,
14076 {Fma4, Fma1, Fma3, Scale}, Flags);
14077
14078 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas, RHS, LHS, Flags);
14079}
14080
14081SDValue SITargetLowering::LowerFDIV64(SDValue Op, SelectionDAG &DAG) const {
14082 if (SDValue FastLowered = lowerFastUnsafeFDIV64(Op, DAG))
14083 return FastLowered;
14084
14085 SDLoc SL(Op);
14086 SDValue X = Op.getOperand(0);
14087 SDValue Y = Op.getOperand(1);
14088
14089 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f64);
14090
14091 SDVTList ScaleVT = DAG.getVTList(MVT::f64, MVT::i1);
14092
14093 SDValue DivScale0 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, Y, Y, X);
14094
14095 SDValue NegDivScale0 = DAG.getNode(ISD::FNEG, SL, MVT::f64, DivScale0);
14096
14097 SDValue Rcp = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14098
14099 SDValue Fma0 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Rcp, One);
14100
14101 SDValue Fma1 = DAG.getNode(ISD::FMA, SL, MVT::f64, Rcp, Fma0, Rcp);
14102
14103 SDValue Fma2 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Fma1, One);
14104
14105 SDValue DivScale1 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, X, Y, X);
14106
14107 SDValue Fma3 = DAG.getNode(ISD::FMA, SL, MVT::f64, Fma1, Fma2, Fma1);
14108 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f64, DivScale1, Fma3);
14109
14110 SDValue Fma4 =
14111 DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Mul, DivScale1);
14112
14113 SDValue Scale;
14114
14115 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14116 // Workaround a hardware bug on SI where the condition output from div_scale
14117 // is not usable.
14118
14119 const SDValue Hi = DAG.getConstant(1, SL, MVT::i32);
14120
14121 // Figure out if the scale to use for div_fmas.
14122 SDValue NumBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, X);
14123 SDValue DenBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Y);
14124 SDValue Scale0BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale0);
14125 SDValue Scale1BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale1);
14126
14127 SDValue NumHi =
14128 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, NumBC, Hi);
14129 SDValue DenHi =
14130 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, DenBC, Hi);
14131
14132 SDValue Scale0Hi =
14133 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale0BC, Hi);
14134 SDValue Scale1Hi =
14135 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale1BC, Hi);
14136
14137 SDValue CmpDen = DAG.getSetCC(SL, MVT::i1, DenHi, Scale0Hi, ISD::SETEQ);
14138 SDValue CmpNum = DAG.getSetCC(SL, MVT::i1, NumHi, Scale1Hi, ISD::SETEQ);
14139 Scale = DAG.getNode(ISD::XOR, SL, MVT::i1, CmpNum, CmpDen);
14140 } else {
14141 Scale = DivScale1.getValue(1);
14142 }
14143
14144 SDValue Fmas =
14145 DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3, Mul, Scale);
14146
14147 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas, Y, X);
14148}
14149
14150SDValue SITargetLowering::LowerFDIV(SDValue Op, SelectionDAG &DAG) const {
14151 EVT VT = Op.getValueType();
14152
14153 if (VT == MVT::f32)
14154 return LowerFDIV32(Op, DAG);
14155
14156 if (VT == MVT::f64)
14157 return LowerFDIV64(Op, DAG);
14158
14159 if (VT == MVT::f16 || VT == MVT::bf16)
14160 return LowerFDIV16(Op, DAG);
14161
14162 llvm_unreachable("Unexpected type for fdiv");
14163}
14164
14165SDValue SITargetLowering::LowerFFREXP(SDValue Op, SelectionDAG &DAG) const {
14166 SDLoc dl(Op);
14167 SDValue Val = Op.getOperand(0);
14168 EVT VT = Val.getValueType();
14169 EVT ResultExpVT = Op->getValueType(1);
14170 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14171
14172 SDValue Mant = DAG.getNode(
14174 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_mant, dl, MVT::i32), Val);
14175
14176 SDValue Exp = DAG.getNode(
14177 ISD::INTRINSIC_WO_CHAIN, dl, InstrExpVT,
14178 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_exp, dl, MVT::i32), Val);
14179
14180 if (Subtarget->hasFractBug()) {
14181 SDValue Fabs = DAG.getNode(ISD::FABS, dl, VT, Val);
14182 SDValue Inf =
14184
14185 SDValue IsFinite = DAG.getSetCC(dl, MVT::i1, Fabs, Inf, ISD::SETOLT);
14186 SDValue Zero = DAG.getConstant(0, dl, InstrExpVT);
14187 Exp = DAG.getNode(ISD::SELECT, dl, InstrExpVT, IsFinite, Exp, Zero);
14188 Mant = DAG.getNode(ISD::SELECT, dl, VT, IsFinite, Mant, Val);
14189 }
14190
14191 SDValue CastExp = DAG.getSExtOrTrunc(Exp, dl, ResultExpVT);
14192 return DAG.getMergeValues({Mant, CastExp}, dl);
14193}
14194
14195SDValue SITargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const {
14196 SDLoc DL(Op);
14197 StoreSDNode *Store = cast<StoreSDNode>(Op);
14198 EVT VT = Store->getMemoryVT();
14199
14200 if (VT == MVT::i1) {
14201 return DAG.getTruncStore(
14202 Store->getChain(), DL,
14203 DAG.getSExtOrTrunc(Store->getValue(), DL, MVT::i32),
14204 Store->getBasePtr(), MVT::i1, Store->getMemOperand());
14205 }
14206
14207 assert(VT.isVector() &&
14208 Store->getValue().getValueType().getScalarType() == MVT::i32);
14209
14210 unsigned AS = Store->getAddressSpace();
14211 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14212 AS == AMDGPUAS::FLAT_ADDRESS &&
14213 Store->getAlign().value() < VT.getStoreSize() &&
14214 VT.getSizeInBits() > 32) {
14215 return SplitVectorStore(Op, DAG);
14216 }
14217
14219 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
14220 // If there is a possibility that flat instruction access scratch memory
14221 // then we need to use the same legalization rules we use for private.
14222 if (AS == AMDGPUAS::FLAT_ADDRESS &&
14223 !Subtarget->hasMultiDwordFlatScratchAddressing())
14224 AS = addressMayBeAccessedAsPrivate(Store->getMemOperand(), *MFI)
14227
14228 unsigned NumElements = VT.getVectorNumElements();
14230 if (NumElements > 4)
14231 return SplitVectorStore(Op, DAG);
14232 // v3 stores not supported on SI.
14233 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14234 return SplitVectorStore(Op, DAG);
14235
14237 VT, *Store->getMemOperand()))
14238 return expandUnalignedStore(Store, DAG);
14239
14240 return SDValue();
14241 }
14242 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
14243 switch (Subtarget->getMaxPrivateElementSize()) {
14244 case 4:
14245 return scalarizeVectorStore(Store, DAG);
14246 case 8:
14247 if (NumElements > 2)
14248 return SplitVectorStore(Op, DAG);
14249 return SDValue();
14250 case 16:
14251 if (NumElements > 4 ||
14252 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14253 return SplitVectorStore(Op, DAG);
14254 return SDValue();
14255 default:
14256 llvm_unreachable("unsupported private_element_size");
14257 }
14258 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
14259 unsigned Fast = 0;
14260 auto Flags = Store->getMemOperand()->getFlags();
14262 Store->getAlign(), Flags, &Fast) &&
14263 Fast > 1)
14264 return SDValue();
14265
14266 if (VT.isVector())
14267 return SplitVectorStore(Op, DAG);
14268
14269 return expandUnalignedStore(Store, DAG);
14270 }
14271
14272 // Probably an invalid store. If so we'll end up emitting a selection error.
14273 return SDValue();
14274}
14275
14276// Avoid the full correct expansion for f32 sqrt when promoting from f16.
14277SDValue SITargetLowering::lowerFSQRTF16(SDValue Op, SelectionDAG &DAG) const {
14278 SDLoc SL(Op);
14279 assert(!Subtarget->has16BitInsts());
14280 SDNodeFlags Flags = Op->getFlags();
14281 SDValue Ext =
14282 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op.getOperand(0), Flags);
14283
14284 SDValue SqrtID = DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, SL, MVT::i32);
14285 SDValue Sqrt =
14286 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::f32, SqrtID, Ext, Flags);
14287
14288 return DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Sqrt,
14289 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
14290}
14291
14292SDValue SITargetLowering::lowerFSQRTF32(SDValue Op, SelectionDAG &DAG) const {
14293 SDLoc DL(Op);
14294 SDNodeFlags Flags = Op->getFlags();
14295 MVT VT = Op.getValueType().getSimpleVT();
14296 const SDValue X = Op.getOperand(0);
14297
14298 if (allowApproxFunc(DAG, Flags)) {
14299 // Instruction is 1ulp but ignores denormals.
14300 return DAG.getNode(
14302 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32), X, Flags);
14303 }
14304
14305 SDValue ScaleThreshold = DAG.getConstantFP(0x1.0p-96f, DL, VT);
14306 SDValue NeedScale = DAG.getSetCC(DL, MVT::i1, X, ScaleThreshold, ISD::SETOLT);
14307
14308 SDValue ScaleUpFactor = DAG.getConstantFP(0x1.0p+32f, DL, VT);
14309
14310 SDValue ScaledX = DAG.getNode(ISD::FMUL, DL, VT, X, ScaleUpFactor, Flags);
14311
14312 SDValue SqrtX =
14313 DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledX, X, Flags);
14314
14315 SDValue SqrtS;
14316 if (needsDenormHandlingF32(DAG, X, Flags)) {
14317 SDValue SqrtID =
14318 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32);
14319 SqrtS = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, SqrtID, SqrtX, Flags);
14320
14321 SDValue SqrtSAsInt = DAG.getNode(ISD::BITCAST, DL, MVT::i32, SqrtS);
14322 SDValue SqrtSNextDownInt =
14323 DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14324 DAG.getAllOnesConstant(DL, MVT::i32));
14325 SDValue SqrtSNextDown = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextDownInt);
14326
14327 SDValue NegSqrtSNextDown =
14328 DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextDown, Flags);
14329
14330 SDValue SqrtVP =
14331 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
14332
14333 SDValue SqrtSNextUpInt = DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14334 DAG.getConstant(1, DL, MVT::i32));
14335 SDValue SqrtSNextUp = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextUpInt);
14336
14337 SDValue NegSqrtSNextUp = DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextUp, Flags);
14338 SDValue SqrtVS =
14339 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
14340
14341 SDValue Zero = DAG.getConstantFP(0.0f, DL, VT);
14342 SDValue SqrtVPLE0 = DAG.getSetCC(DL, MVT::i1, SqrtVP, Zero, ISD::SETOLE);
14343
14344 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPLE0, SqrtSNextDown, SqrtS,
14345 Flags);
14346
14347 SDValue SqrtVPVSGT0 = DAG.getSetCC(DL, MVT::i1, SqrtVS, Zero, ISD::SETOGT);
14348 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPVSGT0, SqrtSNextUp, SqrtS,
14349 Flags);
14350 } else {
14351 SDValue SqrtR = DAG.getNode(AMDGPUISD::RSQ, DL, VT, SqrtX, Flags);
14352
14353 SqrtS = DAG.getNode(ISD::FMUL, DL, VT, SqrtX, SqrtR, Flags);
14354
14355 SDValue Half = DAG.getConstantFP(0.5f, DL, VT);
14356 SDValue SqrtH = DAG.getNode(ISD::FMUL, DL, VT, SqrtR, Half, Flags);
14357 SDValue NegSqrtH = DAG.getNode(ISD::FNEG, DL, VT, SqrtH, Flags);
14358
14359 SDValue SqrtE = DAG.getNode(ISD::FMA, DL, VT, NegSqrtH, SqrtS, Half, Flags);
14360 SqrtH = DAG.getNode(ISD::FMA, DL, VT, SqrtH, SqrtE, SqrtH, Flags);
14361 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtS, SqrtE, SqrtS, Flags);
14362
14363 SDValue NegSqrtS = DAG.getNode(ISD::FNEG, DL, VT, SqrtS, Flags);
14364 SDValue SqrtD =
14365 DAG.getNode(ISD::FMA, DL, VT, NegSqrtS, SqrtS, SqrtX, Flags);
14366 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtD, SqrtH, SqrtS, Flags);
14367 }
14368
14369 SDValue ScaleDownFactor = DAG.getConstantFP(0x1.0p-16f, DL, VT);
14370
14371 SDValue ScaledDown =
14372 DAG.getNode(ISD::FMUL, DL, VT, SqrtS, ScaleDownFactor, Flags);
14373
14374 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledDown, SqrtS, Flags);
14375 SDValue IsZeroOrInf =
14376 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14377 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14378
14379 return DAG.getNode(ISD::SELECT, DL, VT, IsZeroOrInf, SqrtX, SqrtS, Flags);
14380}
14381
14382SDValue SITargetLowering::lowerFSQRTF64(SDValue Op, SelectionDAG &DAG) const {
14383 // For double type, the SQRT and RSQ instructions don't have required
14384 // precision, we apply Goldschmidt's algorithm to improve the result:
14385 //
14386 // y0 = rsq(x)
14387 // g0 = x * y0
14388 // h0 = 0.5 * y0
14389 //
14390 // r0 = 0.5 - h0 * g0
14391 // g1 = g0 * r0 + g0
14392 // h1 = h0 * r0 + h0
14393 //
14394 // r1 = 0.5 - h1 * g1 => d0 = x - g1 * g1
14395 // g2 = g1 * r1 + g1 g2 = d0 * h1 + g1
14396 // h2 = h1 * r1 + h1
14397 //
14398 // r2 = 0.5 - h2 * g2 => d1 = x - g2 * g2
14399 // g3 = g2 * r2 + g2 g3 = d1 * h1 + g2
14400 //
14401 // sqrt(x) = g3
14402
14403 SDNodeFlags Flags = Op->getFlags();
14404
14405 SDLoc DL(Op);
14406
14407 SDValue X = Op.getOperand(0);
14408 SDValue ZeroInt = DAG.getConstant(0, DL, MVT::i32);
14409
14410 SDValue SqrtX = X;
14411 SDValue Scaling;
14412 if (!Flags.hasApproximateFuncs()) {
14413 SDValue ScaleConstant = DAG.getConstantFP(0x1.0p-767, DL, MVT::f64);
14414 Scaling = DAG.getSetCC(DL, MVT::i1, X, ScaleConstant, ISD::SETOLT);
14415
14416 // Scale up input if it is too small.
14417 SDValue ScaleUpFactor = DAG.getConstant(256, DL, MVT::i32);
14418 SDValue ScaleUp =
14419 DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling, ScaleUpFactor, ZeroInt);
14420 SqrtX = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, X, ScaleUp, Flags);
14421 }
14422
14423 SDValue SqrtY = DAG.getNode(AMDGPUISD::RSQ, DL, MVT::f64, SqrtX);
14424
14425 SDValue SqrtS0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtX, SqrtY);
14426
14427 SDValue Half = DAG.getConstantFP(0.5, DL, MVT::f64);
14428 SDValue SqrtH0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtY, Half);
14429
14430 SDValue NegSqrtH0 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtH0);
14431 SDValue SqrtR0 = DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtH0, SqrtS0, Half);
14432
14433 SDValue SqrtH1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtH0, SqrtR0, SqrtH0);
14434
14435 SDValue SqrtS1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtS0, SqrtR0, SqrtS0);
14436
14437 SDValue NegSqrtS1 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS1);
14438 SDValue SqrtD0 =
14439 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS1, SqrtS1, SqrtX);
14440
14441 SDValue SqrtS2 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD0, SqrtH1, SqrtS1);
14442
14443 SDValue SqrtRet = SqrtS2;
14444 if (!Flags.hasApproximateFuncs()) {
14445 SDValue NegSqrtS2 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS2);
14446 SDValue SqrtD1 =
14447 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS2, SqrtS2, SqrtX);
14448
14449 SqrtRet = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD1, SqrtH1, SqrtS2);
14450
14451 SDValue ScaleDownFactor = DAG.getSignedConstant(-128, DL, MVT::i32);
14452 SDValue ScaleDown = DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling,
14453 ScaleDownFactor, ZeroInt);
14454 SqrtRet = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, SqrtRet, ScaleDown, Flags);
14455 }
14456
14457 // TODO: Check for DAZ and expand to subnormals
14458
14459 SDValue IsZeroOrInf;
14460 if (Flags.hasNoInfs()) {
14461 SDValue Zero = DAG.getConstantFP(0.0, DL, MVT::f64);
14462 IsZeroOrInf = DAG.getSetCC(DL, MVT::i1, SqrtX, Zero, ISD::SETOEQ);
14463 } else {
14464 IsZeroOrInf =
14465 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14466 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14467 }
14468
14469 // If x is +INF, +0, or -0, use its original value
14470 return DAG.getNode(ISD::SELECT, DL, MVT::f64, IsZeroOrInf, SqrtX, SqrtRet,
14471 Flags);
14472}
14473
14474SDValue SITargetLowering::LowerTrig(SDValue Op, SelectionDAG &DAG) const {
14475 SDLoc DL(Op);
14476 EVT VT = Op.getValueType();
14477 SDValue Arg = Op.getOperand(0);
14478 SDValue TrigVal;
14479
14480 // Propagate fast-math flags so that the multiply we introduce can be folded
14481 // if Arg is already the result of a multiply by constant.
14482 auto Flags = Op->getFlags();
14483
14484 // AMDGPUISD nodes of vector type must be unrolled here since
14485 // they will not be expanded elsewhere.
14486 auto UnrollIfVec = [&DAG](SDValue V) -> SDValue {
14487 if (!V.getValueType().isVector())
14488 return V;
14489
14490 return DAG.UnrollVectorOp(cast<SDNode>(V));
14491 };
14492
14493 SDValue OneOver2Pi = DAG.getConstantFP(0.5 * numbers::inv_pi, DL, VT);
14494
14495 if (Subtarget->hasTrigReducedRange()) {
14496 SDValue MulVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14497 TrigVal = UnrollIfVec(DAG.getNode(AMDGPUISD::FRACT, DL, VT, MulVal, Flags));
14498 } else {
14499 TrigVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14500 }
14501
14502 switch (Op.getOpcode()) {
14503 case ISD::FCOS:
14504 TrigVal = DAG.getNode(AMDGPUISD::COS_HW, SDLoc(Op), VT, TrigVal, Flags);
14505 break;
14506 case ISD::FSIN:
14507 TrigVal = DAG.getNode(AMDGPUISD::SIN_HW, SDLoc(Op), VT, TrigVal, Flags);
14508 break;
14509 default:
14510 llvm_unreachable("Wrong trig opcode");
14511 }
14512
14513 return UnrollIfVec(TrigVal);
14514}
14515
14516SDValue SITargetLowering::LowerATOMIC_CMP_SWAP(SDValue Op,
14517 SelectionDAG &DAG) const {
14518 AtomicSDNode *AtomicNode = cast<AtomicSDNode>(Op);
14519 assert(AtomicNode->isCompareAndSwap());
14520 unsigned AS = AtomicNode->getAddressSpace();
14521
14522 // No custom lowering required for local address space
14524 return Op;
14525
14526 // Non-local address space requires custom lowering for atomic compare
14527 // and swap; cmp and swap should be in a v2i32 or v2i64 in case of _X2
14528 SDLoc DL(Op);
14529 SDValue ChainIn = Op.getOperand(0);
14530 SDValue Addr = Op.getOperand(1);
14531 SDValue Old = Op.getOperand(2);
14532 SDValue New = Op.getOperand(3);
14533 EVT VT = Op.getValueType();
14534 MVT SimpleVT = VT.getSimpleVT();
14535 MVT VecType = MVT::getVectorVT(SimpleVT, 2);
14536
14537 SDValue NewOld = DAG.getBuildVector(VecType, DL, {New, Old});
14538 SDValue Ops[] = {ChainIn, Addr, NewOld};
14539
14540 return DAG.getMemIntrinsicNode(AMDGPUISD::ATOMIC_CMP_SWAP, DL,
14541 Op->getVTList(), Ops, VT,
14542 AtomicNode->getMemOperand());
14543}
14544
14545//===----------------------------------------------------------------------===//
14546// Custom DAG optimizations
14547//===----------------------------------------------------------------------===//
14548
14549SDValue
14550SITargetLowering::performUCharToFloatCombine(SDNode *N,
14551 DAGCombinerInfo &DCI) const {
14552 EVT VT = N->getValueType(0);
14553 EVT ScalarVT = VT.getScalarType();
14554 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14555 return SDValue();
14556
14557 SelectionDAG &DAG = DCI.DAG;
14558 SDLoc DL(N);
14559
14560 SDValue Src = N->getOperand(0);
14561 EVT SrcVT = Src.getValueType();
14562
14563 // TODO: We could try to match extracting the higher bytes, which would be
14564 // easier if i8 vectors weren't promoted to i32 vectors, particularly after
14565 // types are legalized. v4i8 -> v4f32 is probably the only case to worry
14566 // about in practice.
14567 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14568 if (DAG.MaskedValueIsZero(Src, APInt::getHighBitsSet(32, 24))) {
14569 SDValue Cvt = DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0, DL, MVT::f32, Src);
14570 DCI.AddToWorklist(Cvt.getNode());
14571
14572 // For the f16 case, fold to a cast to f32 and then cast back to f16.
14573 if (ScalarVT != MVT::f32) {
14574 Cvt = DAG.getNode(ISD::FP_ROUND, DL, VT, Cvt,
14575 DAG.getTargetConstant(0, DL, MVT::i32));
14576 }
14577 return Cvt;
14578 }
14579 }
14580
14581 return SDValue();
14582}
14583
14584SDValue SITargetLowering::performFCopySignCombine(SDNode *N,
14585 DAGCombinerInfo &DCI) const {
14586 SDValue MagnitudeOp = N->getOperand(0);
14587 SDValue SignOp = N->getOperand(1);
14588
14589 // The generic combine for fcopysign + fp cast is too conservative with
14590 // vectors, and also gets confused by the splitting we will perform here, so
14591 // peek through FP casts.
14592 if (SignOp.getOpcode() == ISD::FP_EXTEND ||
14593 SignOp.getOpcode() == ISD::FP_ROUND)
14594 SignOp = SignOp.getOperand(0);
14595
14596 SelectionDAG &DAG = DCI.DAG;
14597 SDLoc DL(N);
14598 EVT SignVT = SignOp.getValueType();
14599
14600 // f64 fcopysign is really an f32 copysign on the high bits, so replace the
14601 // lower half with a copy.
14602 // fcopysign f64:x, _:y -> x.lo32, (fcopysign (f32 x.hi32), _:y)
14603 EVT MagVT = MagnitudeOp.getValueType();
14604
14605 unsigned NumElts = MagVT.isVector() ? MagVT.getVectorNumElements() : 1;
14606
14607 if (MagVT.getScalarType() == MVT::f64) {
14608 EVT F32VT = MagVT.isVector()
14609 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14610 : MVT::v2f32;
14611
14612 SDValue MagAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, MagnitudeOp);
14613
14615 for (unsigned I = 0; I != NumElts; ++I) {
14616 SDValue MagLo =
14617 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14618 DAG.getConstant(2 * I, DL, MVT::i32));
14619 SDValue MagHi =
14620 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14621 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14622
14623 SDValue SignOpElt =
14624 MagVT.isVector()
14626 SignOp, DAG.getConstant(I, DL, MVT::i32))
14627 : SignOp;
14628
14629 SDValue HiOp =
14630 DAG.getNode(ISD::FCOPYSIGN, DL, MVT::f32, MagHi, SignOpElt);
14631
14632 SDValue Vector =
14633 DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v2f32, MagLo, HiOp);
14634
14635 SDValue NewElt = DAG.getNode(ISD::BITCAST, DL, MVT::f64, Vector);
14636 NewElts.push_back(NewElt);
14637 }
14638
14639 if (NewElts.size() == 1)
14640 return NewElts[0];
14641
14642 return DAG.getNode(ISD::BUILD_VECTOR, DL, MagVT, NewElts);
14643 }
14644
14645 if (SignVT.getScalarType() != MVT::f64)
14646 return SDValue();
14647
14648 // Reduce width of sign operand, we only need the highest bit.
14649 //
14650 // fcopysign f64:x, f64:y ->
14651 // fcopysign f64:x, (extract_vector_elt (bitcast f64:y to v2f32), 1)
14652 // TODO: In some cases it might make sense to go all the way to f16.
14653
14654 EVT F32VT = MagVT.isVector()
14655 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14656 : MVT::v2f32;
14657
14658 SDValue SignAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, SignOp);
14659
14660 SmallVector<SDValue, 8> F32Signs;
14661 for (unsigned I = 0; I != NumElts; ++I) {
14662 // Take sign from odd elements of cast vector
14663 SDValue SignAsF32 =
14664 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, SignAsVector,
14665 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14666 F32Signs.push_back(SignAsF32);
14667 }
14668
14669 SDValue NewSign =
14670 NumElts == 1
14671 ? F32Signs.back()
14673 EVT::getVectorVT(*DAG.getContext(), MVT::f32, NumElts),
14674 F32Signs);
14675
14676 return DAG.getNode(ISD::FCOPYSIGN, DL, N->getValueType(0), N->getOperand(0),
14677 NewSign);
14678}
14679
14680// (shl (add x, c1), c2) -> add (shl x, c2), (shl c1, c2)
14681// (shl (or x, c1), c2) -> add (shl x, c2), (shl c1, c2) iff x and c1 share no
14682// bits
14683
14684// This is a variant of
14685// (mul (add x, c1), c2) -> add (mul x, c2), (mul c1, c2),
14686//
14687// The normal DAG combiner will do this, but only if the add has one use since
14688// that would increase the number of instructions.
14689//
14690// This prevents us from seeing a constant offset that can be folded into a
14691// memory instruction's addressing mode. If we know the resulting add offset of
14692// a pointer can be folded into an addressing offset, we can replace the pointer
14693// operand with the add of new constant offset. This eliminates one of the uses,
14694// and may allow the remaining use to also be simplified.
14695//
14696SDValue SITargetLowering::performSHLPtrCombine(SDNode *N, unsigned AddrSpace,
14697 EVT MemVT,
14698 DAGCombinerInfo &DCI) const {
14699 SDValue N0 = N->getOperand(0);
14700 SDValue N1 = N->getOperand(1);
14701
14702 // We only do this to handle cases where it's profitable when there are
14703 // multiple uses of the add, so defer to the standard combine.
14704 if ((!N0->isAnyAdd() && N0.getOpcode() != ISD::OR) || N0->hasOneUse())
14705 return SDValue();
14706
14707 const ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(N1);
14708 if (!CN1)
14709 return SDValue();
14710
14711 const ConstantSDNode *CAdd = dyn_cast<ConstantSDNode>(N0.getOperand(1));
14712 if (!CAdd)
14713 return SDValue();
14714
14715 SelectionDAG &DAG = DCI.DAG;
14716
14717 if (N0->getOpcode() == ISD::OR &&
14718 !DAG.haveNoCommonBitsSet(N0.getOperand(0), N0.getOperand(1)))
14719 return SDValue();
14720
14721 // If the resulting offset is too large, we can't fold it into the
14722 // addressing mode offset.
14723 APInt Offset = CAdd->getAPIntValue() << CN1->getAPIntValue();
14724 Type *Ty = MemVT.getTypeForEVT(*DCI.DAG.getContext());
14725
14726 AddrMode AM;
14727 AM.HasBaseReg = true;
14728 AM.BaseOffs = Offset.getSExtValue();
14729 if (!isLegalAddressingMode(DCI.DAG.getDataLayout(), AM, Ty, AddrSpace))
14730 return SDValue();
14731
14732 SDLoc SL(N);
14733 EVT VT = N->getValueType(0);
14734
14735 SDValue ShlX = DAG.getNode(ISD::SHL, SL, VT, N0.getOperand(0), N1);
14736 SDValue COffset = DAG.getConstant(Offset, SL, VT);
14737
14738 SDNodeFlags Flags;
14739 Flags.setNoUnsignedWrap(
14740 N->getFlags().hasNoUnsignedWrap() &&
14741 (N0.getOpcode() == ISD::OR || N0->getFlags().hasNoUnsignedWrap()));
14742
14743 // Use ISD::ADD even if the original operation was ISD::PTRADD, since we can't
14744 // be sure that the new left operand is a proper base pointer.
14745 return DAG.getNode(ISD::ADD, SL, VT, ShlX, COffset, Flags);
14746}
14747
14748/// MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset
14749/// by the chain and intrinsic ID. Theoretically we would also need to check the
14750/// specific intrinsic, but they all place the pointer operand first.
14751static unsigned getBasePtrIndex(const MemSDNode *N) {
14752 switch (N->getOpcode()) {
14753 case ISD::STORE:
14756 return 2;
14757 default:
14758 return 1;
14759 }
14760}
14761
14762SDValue SITargetLowering::performMemSDNodeCombine(MemSDNode *N,
14763 DAGCombinerInfo &DCI) const {
14764 SelectionDAG &DAG = DCI.DAG;
14765
14766 unsigned PtrIdx = getBasePtrIndex(N);
14767 SDValue Ptr = N->getOperand(PtrIdx);
14768
14769 // TODO: We could also do this for multiplies.
14770 if (Ptr.getOpcode() == ISD::SHL) {
14771 SDValue NewPtr = performSHLPtrCombine(Ptr.getNode(), N->getAddressSpace(),
14772 N->getMemoryVT(), DCI);
14773 if (NewPtr) {
14774 SmallVector<SDValue, 8> NewOps(N->ops());
14775
14776 NewOps[PtrIdx] = NewPtr;
14777 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
14778 }
14779 }
14780
14781 return SDValue();
14782}
14783
14784static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val) {
14785 return (Opc == ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14786 (Opc == ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14787 (Opc == ISD::XOR && Val == 0);
14788}
14789
14790// Break up 64-bit bit operation of a constant into two 32-bit and/or/xor. This
14791// will typically happen anyway for a VALU 64-bit and. This exposes other 32-bit
14792// integer combine opportunities since most 64-bit operations are decomposed
14793// this way. TODO: We won't want this for SALU especially if it is an inline
14794// immediate.
14795SDValue SITargetLowering::splitBinaryBitConstantOp(
14796 DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS,
14797 const ConstantSDNode *CRHS) const {
14798 uint64_t Val = CRHS->getZExtValue();
14799 uint32_t ValLo = Lo_32(Val);
14800 uint32_t ValHi = Hi_32(Val);
14801 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
14802
14803 if ((bitOpWithConstantIsReducible(Opc, ValLo) ||
14805 (CRHS->hasOneUse() && !TII->isInlineConstant(CRHS->getAPIntValue()))) {
14806 // We have 64-bit scalar and/or/xor, but do not have vector forms.
14807 if (Subtarget->has64BitLiterals() && CRHS->hasOneUse() &&
14808 !CRHS->user_begin()->isDivergent())
14809 return SDValue();
14810
14811 // If we need to materialize a 64-bit immediate, it will be split up later
14812 // anyway. Avoid creating the harder to understand 64-bit immediate
14813 // materialization.
14814 return splitBinaryBitConstantOpImpl(DCI, SL, Opc, LHS, ValLo, ValHi);
14815 }
14816
14817 return SDValue();
14818}
14819
14821 if (V.getValueType() != MVT::i1)
14822 return false;
14823 switch (V.getOpcode()) {
14824 default:
14825 break;
14826 case ISD::SETCC:
14827 case ISD::IS_FPCLASS:
14828 case AMDGPUISD::FP_CLASS:
14829 return true;
14830 case ISD::AND:
14831 case ISD::OR:
14832 case ISD::XOR:
14833 return isBoolSGPR(V.getOperand(0)) && isBoolSGPR(V.getOperand(1));
14834 case ISD::SADDO:
14835 case ISD::UADDO:
14836 case ISD::SSUBO:
14837 case ISD::USUBO:
14838 case ISD::SMULO:
14839 case ISD::UMULO:
14840 return V.getResNo() == 1;
14842 unsigned IntrinsicID = V.getConstantOperandVal(0);
14843 switch (IntrinsicID) {
14844 case Intrinsic::amdgcn_is_shared:
14845 case Intrinsic::amdgcn_is_private:
14846 return true;
14847 default:
14848 return false;
14849 }
14850
14851 return false;
14852 }
14853 }
14854 return false;
14855}
14856
14857// If a constant has all zeroes or all ones within each byte return it.
14858// Otherwise return 0.
14860 // 0xff for any zero byte in the mask
14861 uint32_t ZeroByteMask = 0;
14862 if (!(C & 0x000000ff))
14863 ZeroByteMask |= 0x000000ff;
14864 if (!(C & 0x0000ff00))
14865 ZeroByteMask |= 0x0000ff00;
14866 if (!(C & 0x00ff0000))
14867 ZeroByteMask |= 0x00ff0000;
14868 if (!(C & 0xff000000))
14869 ZeroByteMask |= 0xff000000;
14870 uint32_t NonZeroByteMask = ~ZeroByteMask; // 0xff for any non-zero byte
14871 if ((NonZeroByteMask & C) != NonZeroByteMask)
14872 return 0; // Partial bytes selected.
14873 return C;
14874}
14875
14876// Check if a node selects whole bytes from its operand 0 starting at a byte
14877// boundary while masking the rest. Returns select mask as in the v_perm_b32
14878// or -1 if not succeeded.
14879// Note byte select encoding:
14880// value 0-3 selects corresponding source byte;
14881// value 0xc selects zero;
14882// value 0xff selects 0xff.
14884 assert(V.getValueSizeInBits() == 32);
14885
14886 if (V.getNumOperands() != 2)
14887 return ~0;
14888
14889 ConstantSDNode *N1 = dyn_cast<ConstantSDNode>(V.getOperand(1));
14890 if (!N1)
14891 return ~0;
14892
14893 uint32_t C = N1->getZExtValue();
14894
14895 switch (V.getOpcode()) {
14896 default:
14897 break;
14898 case ISD::AND:
14899 if (uint32_t ConstMask = getConstantPermuteMask(C))
14900 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
14901 break;
14902
14903 case ISD::OR:
14904 if (uint32_t ConstMask = getConstantPermuteMask(C))
14905 return (0x03020100 & ~ConstMask) | ConstMask;
14906 break;
14907
14908 case ISD::SHL:
14909 if (C % 8)
14910 return ~0;
14911
14912 return uint32_t((0x030201000c0c0c0cull << C) >> 32);
14913
14914 case ISD::SRL:
14915 if (C % 8)
14916 return ~0;
14917
14918 return uint32_t(0x0c0c0c0c03020100ull >> C);
14919 }
14920
14921 return ~0;
14922}
14923
14924SDValue SITargetLowering::performAndCombine(SDNode *N,
14925 DAGCombinerInfo &DCI) const {
14926 if (DCI.isBeforeLegalize())
14927 return SDValue();
14928
14929 SelectionDAG &DAG = DCI.DAG;
14930 EVT VT = N->getValueType(0);
14931 SDValue LHS = N->getOperand(0);
14932 SDValue RHS = N->getOperand(1);
14933
14934 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS);
14935 if (VT == MVT::i64 && CRHS) {
14936 if (SDValue Split =
14937 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::AND, LHS, CRHS))
14938 return Split;
14939 }
14940
14941 if (CRHS && VT == MVT::i32) {
14942 // and (srl x, c), mask => shl (bfe x, nb + c, mask >> nb), nb
14943 // nb = number of trailing zeroes in mask
14944 // It can be optimized out using SDWA for GFX8+ in the SDWA peephole pass,
14945 // given that we are selecting 8 or 16 bit fields starting at byte boundary.
14946 uint64_t Mask = CRHS->getZExtValue();
14947 unsigned Bits = llvm::popcount(Mask);
14948 if (getSubtarget()->hasSDWA() && LHS->getOpcode() == ISD::SRL &&
14949 (Bits == 8 || Bits == 16) && isShiftedMask_64(Mask) && !(Mask & 1)) {
14950 if (auto *CShift = dyn_cast<ConstantSDNode>(LHS->getOperand(1))) {
14951 unsigned Shift = CShift->getZExtValue();
14952 unsigned NB = CRHS->getAPIntValue().countr_zero();
14953 unsigned Offset = NB + Shift;
14954 if ((Offset & (Bits - 1)) == 0) { // Starts at a byte or word boundary.
14955 SDLoc SL(N);
14956 SDValue BFE =
14957 DAG.getNode(AMDGPUISD::BFE_U32, SL, MVT::i32, LHS->getOperand(0),
14958 DAG.getConstant(Offset, SL, MVT::i32),
14959 DAG.getConstant(Bits, SL, MVT::i32));
14960 EVT NarrowVT = EVT::getIntegerVT(*DAG.getContext(), Bits);
14961 SDValue Ext = DAG.getNode(ISD::AssertZext, SL, VT, BFE,
14962 DAG.getValueType(NarrowVT));
14963 SDValue Shl = DAG.getNode(ISD::SHL, SDLoc(LHS), VT, Ext,
14964 DAG.getConstant(NB, SDLoc(CRHS), MVT::i32));
14965 return Shl;
14966 }
14967 }
14968 }
14969
14970 // and (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
14971 if (LHS.hasOneUse() && LHS.getOpcode() == AMDGPUISD::PERM &&
14972 isa<ConstantSDNode>(LHS.getOperand(2))) {
14973 uint32_t Sel = getConstantPermuteMask(Mask);
14974 if (!Sel)
14975 return SDValue();
14976
14977 // Select 0xc for all zero bytes
14978 Sel = (LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
14979 SDLoc DL(N);
14980 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
14981 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
14982 }
14983 }
14984
14985 // (and (fcmp ord x, x), (fcmp une (fabs x), inf)) ->
14986 // fp_class x, ~(s_nan | q_nan | n_infinity | p_infinity)
14987 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == ISD::SETCC) {
14988 ISD::CondCode LCC = cast<CondCodeSDNode>(LHS.getOperand(2))->get();
14989 ISD::CondCode RCC = cast<CondCodeSDNode>(RHS.getOperand(2))->get();
14990
14991 SDValue X = LHS.getOperand(0);
14992 SDValue Y = RHS.getOperand(0);
14993 if (Y.getOpcode() != ISD::FABS || Y.getOperand(0) != X ||
14994 !isTypeLegal(X.getValueType()))
14995 return SDValue();
14996
14997 if (LCC == ISD::SETO) {
14998 if (X != LHS.getOperand(1))
14999 return SDValue();
15000
15001 if (RCC == ISD::SETUNE) {
15002 const ConstantFPSDNode *C1 =
15003 dyn_cast<ConstantFPSDNode>(RHS.getOperand(1));
15004 if (!C1 || !C1->isInfinity() || C1->isNegative())
15005 return SDValue();
15006
15007 const uint32_t Mask = SIInstrFlags::N_NORMAL |
15011
15012 static_assert(
15015 0x3ff) == Mask,
15016 "mask not equal");
15017
15018 SDLoc DL(N);
15019 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, X,
15020 DAG.getConstant(Mask, DL, MVT::i32));
15021 }
15022 }
15023 }
15024
15025 if (RHS.getOpcode() == ISD::SETCC && LHS.getOpcode() == AMDGPUISD::FP_CLASS)
15026 std::swap(LHS, RHS);
15027
15028 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15029 RHS.hasOneUse()) {
15030 ISD::CondCode LCC = cast<CondCodeSDNode>(LHS.getOperand(2))->get();
15031 // and (fcmp seto), (fp_class x, mask) -> fp_class x, mask & ~(p_nan |
15032 // n_nan) and (fcmp setuo), (fp_class x, mask) -> fp_class x, mask & (p_nan
15033 // | n_nan)
15034 const ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
15035 if ((LCC == ISD::SETO || LCC == ISD::SETUO) && Mask &&
15036 (RHS.getOperand(0) == LHS.getOperand(0) &&
15037 LHS.getOperand(0) == LHS.getOperand(1))) {
15038 const unsigned OrdMask = SIInstrFlags::S_NAN | SIInstrFlags::Q_NAN;
15039 unsigned NewMask = LCC == ISD::SETO ? Mask->getZExtValue() & ~OrdMask
15040 : Mask->getZExtValue() & OrdMask;
15041
15042 SDLoc DL(N);
15043 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, RHS.getOperand(0),
15044 DAG.getConstant(NewMask, DL, MVT::i32));
15045 }
15046 }
15047
15048 if (VT == MVT::i32 && (RHS.getOpcode() == ISD::SIGN_EXTEND ||
15049 LHS.getOpcode() == ISD::SIGN_EXTEND)) {
15050 // and x, (sext cc from i1) => select cc, x, 0
15051 if (RHS.getOpcode() != ISD::SIGN_EXTEND)
15052 std::swap(LHS, RHS);
15053 if (isBoolSGPR(RHS.getOperand(0)))
15054 return DAG.getSelect(SDLoc(N), MVT::i32, RHS.getOperand(0), LHS,
15055 DAG.getConstant(0, SDLoc(N), MVT::i32));
15056 }
15057
15058 // and (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
15059 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
15060 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
15061 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15062 uint32_t LHSMask = getPermuteMask(LHS);
15063 uint32_t RHSMask = getPermuteMask(RHS);
15064 if (LHSMask != ~0u && RHSMask != ~0u) {
15065 // Canonicalize the expression in an attempt to have fewer unique masks
15066 // and therefore fewer registers used to hold the masks.
15067 if (LHSMask > RHSMask) {
15068 std::swap(LHSMask, RHSMask);
15069 std::swap(LHS, RHS);
15070 }
15071
15072 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15073 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15074 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15075 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15076
15077 // Check of we need to combine values from two sources within a byte.
15078 if (!(LHSUsedLanes & RHSUsedLanes) &&
15079 // If we select high and lower word keep it for SDWA.
15080 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15081 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15082 // Each byte in each mask is either selector mask 0-3, or has higher
15083 // bits set in either of masks, which can be 0xff for 0xff or 0x0c for
15084 // zero. If 0x0c is in either mask it shall always be 0x0c. Otherwise
15085 // mask which is not 0xff wins. By anding both masks we have a correct
15086 // result except that 0x0c shall be corrected to give 0x0c only.
15087 uint32_t Mask = LHSMask & RHSMask;
15088 for (unsigned I = 0; I < 32; I += 8) {
15089 uint32_t ByteSel = 0xff << I;
15090 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15091 Mask &= (0x0c << I) & 0xffffffff;
15092 }
15093
15094 // Add 4 to each active LHS lane. It will not affect any existing 0xff
15095 // or 0x0c.
15096 uint32_t Sel = Mask | (LHSUsedLanes & 0x04040404);
15097 SDLoc DL(N);
15098
15099 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15100 RHS.getOperand(0),
15101 DAG.getConstant(Sel, DL, MVT::i32));
15102 }
15103 }
15104 }
15105
15106 return SDValue();
15107}
15108
15109// A key component of v_perm is a mapping between byte position of the src
15110// operands, and the byte position of the dest. To provide such, we need: 1. the
15111// node that provides x byte of the dest of the OR, and 2. the byte of the node
15112// used to provide that x byte. calculateByteProvider finds which node provides
15113// a certain byte of the dest of the OR, and calculateSrcByte takes that node,
15114// and finds an ultimate src and byte position For example: The supported
15115// LoadCombine pattern for vector loads is as follows
15116// t1
15117// or
15118// / \
15119// t2 t3
15120// zext shl
15121// | | \
15122// t4 t5 16
15123// or anyext
15124// / \ |
15125// t6 t7 t8
15126// srl shl or
15127// / | / \ / \
15128// t9 t10 t11 t12 t13 t14
15129// trunc* 8 trunc* 8 and and
15130// | | / | | \
15131// t15 t16 t17 t18 t19 t20
15132// trunc* 255 srl -256
15133// | / \
15134// t15 t15 16
15135//
15136// *In this example, the truncs are from i32->i16
15137//
15138// calculateByteProvider would find t6, t7, t13, and t14 for bytes 0-3
15139// respectively. calculateSrcByte would find (given node) -> ultimate src &
15140// byteposition: t6 -> t15 & 1, t7 -> t16 & 0, t13 -> t15 & 0, t14 -> t15 & 3.
15141// After finding the mapping, we can combine the tree into vperm t15, t16,
15142// 0x05000407
15143
15144// Find the source and byte position from a node.
15145// \p DestByte is the byte position of the dest of the or that the src
15146// ultimately provides. \p SrcIndex is the byte of the src that maps to this
15147// dest of the or byte. \p Depth tracks how many recursive iterations we have
15148// performed.
15149static const std::optional<ByteProvider<SDValue>>
15150calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex = 0,
15151 unsigned Depth = 0) {
15152 // We may need to recursively traverse a series of SRLs
15153 if (Depth >= 6)
15154 return std::nullopt;
15155
15156 if (Op.getValueSizeInBits() < 8)
15157 return std::nullopt;
15158
15159 if (Op.getValueType().isVector())
15160 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15161
15162 switch (Op->getOpcode()) {
15163 case ISD::TRUNCATE: {
15164 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15165 }
15166
15167 case ISD::ANY_EXTEND:
15168 case ISD::SIGN_EXTEND:
15169 case ISD::ZERO_EXTEND:
15171 SDValue NarrowOp = Op->getOperand(0);
15172 auto NarrowVT = NarrowOp.getValueType();
15173 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG) {
15174 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15175 NarrowVT = VTSign->getVT();
15176 }
15177 if (!NarrowVT.isByteSized())
15178 return std::nullopt;
15179 uint64_t NarrowByteWidth = NarrowVT.getStoreSize();
15180
15181 if (SrcIndex >= NarrowByteWidth)
15182 return std::nullopt;
15183 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15184 }
15185
15186 case ISD::SRA:
15187 case ISD::SRL: {
15188 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15189 if (!ShiftOp)
15190 return std::nullopt;
15191
15192 uint64_t BitShift = ShiftOp->getZExtValue();
15193
15194 if (BitShift % 8 != 0)
15195 return std::nullopt;
15196
15197 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15198 if (NewSrcIndex >= Op.getScalarValueSizeInBits() / 8)
15199 return std::nullopt;
15200
15201 return calculateSrcByte(Op->getOperand(0), DestByte, NewSrcIndex,
15202 Depth + 1);
15203 }
15204
15205 default: {
15206 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15207 }
15208 }
15209 llvm_unreachable("fully handled switch");
15210}
15211
15212// For a byte position in the result of an Or, traverse the tree and find the
15213// node (and the byte of the node) which ultimately provides this {Or,
15214// BytePosition}. \p Op is the operand we are currently examining. \p Index is
15215// the byte position of the Op that corresponds with the originally requested
15216// byte of the Or \p Depth tracks how many recursive iterations we have
15217// performed. \p StartingIndex is the originally requested byte of the Or
15218static const std::optional<ByteProvider<SDValue>>
15219calculateByteProvider(const SDValue &Op, unsigned Index, unsigned Depth,
15220 unsigned StartingIndex = 0) {
15221 // Finding Src tree of RHS of or typically requires at least 1 additional
15222 // depth
15223 if (Depth > 6)
15224 return std::nullopt;
15225
15226 unsigned BitWidth = Op.getScalarValueSizeInBits();
15227 if (BitWidth % 8 != 0)
15228 return std::nullopt;
15229 if (Index > BitWidth / 8 - 1)
15230 return std::nullopt;
15231
15232 bool IsVec = Op.getValueType().isVector();
15233 switch (Op.getOpcode()) {
15234 case ISD::OR: {
15235 if (IsVec)
15236 return std::nullopt;
15237
15238 auto RHS = calculateByteProvider(Op.getOperand(1), Index, Depth + 1,
15239 StartingIndex);
15240 if (!RHS)
15241 return std::nullopt;
15242 auto LHS = calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15243 StartingIndex);
15244 if (!LHS)
15245 return std::nullopt;
15246 // A well formed Or will have two ByteProviders for each byte, one of which
15247 // is constant zero
15248 if (!LHS->isConstantZero() && !RHS->isConstantZero())
15249 return std::nullopt;
15250 if (!LHS || LHS->isConstantZero())
15251 return RHS;
15252 if (!RHS || RHS->isConstantZero())
15253 return LHS;
15254 return std::nullopt;
15255 }
15256
15257 case ISD::AND: {
15258 if (IsVec)
15259 return std::nullopt;
15260
15261 auto *BitMaskOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15262 if (!BitMaskOp)
15263 return std::nullopt;
15264
15265 uint32_t BitMask = BitMaskOp->getZExtValue();
15266 // Bits we expect for our StartingIndex
15267 uint32_t IndexMask = 0xFF << (Index * 8);
15268
15269 if ((IndexMask & BitMask) != IndexMask) {
15270 // If the result of the and partially provides the byte, then it
15271 // is not well formatted
15272 if (IndexMask & BitMask)
15273 return std::nullopt;
15275 }
15276
15277 return calculateSrcByte(Op->getOperand(0), StartingIndex, Index);
15278 }
15279
15280 case ISD::FSHR: {
15281 if (IsVec)
15282 return std::nullopt;
15283
15284 // fshr(X,Y,Z): (X << (BW - (Z % BW))) | (Y >> (Z % BW))
15285 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15286 if (!ShiftOp || Op.getValueType().isVector())
15287 return std::nullopt;
15288
15289 uint64_t BitsProvided = Op.getValueSizeInBits();
15290 if (BitsProvided % 8 != 0)
15291 return std::nullopt;
15292
15293 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15294 if (BitShift % 8)
15295 return std::nullopt;
15296
15297 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15298 uint64_t ByteShift = BitShift / 8;
15299
15300 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15301 uint64_t BytesProvided = BitsProvided / 8;
15302 SDValue NextOp = Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15303 NewIndex %= BytesProvided;
15304 return calculateByteProvider(NextOp, NewIndex, Depth + 1, StartingIndex);
15305 }
15306
15307 case ISD::SRA:
15308 case ISD::SRL: {
15309 if (IsVec)
15310 return std::nullopt;
15311
15312 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15313 if (!ShiftOp)
15314 return std::nullopt;
15315
15316 uint64_t BitShift = ShiftOp->getZExtValue();
15317 if (BitShift % 8)
15318 return std::nullopt;
15319
15320 auto BitsProvided = Op.getScalarValueSizeInBits();
15321 if (BitsProvided % 8 != 0)
15322 return std::nullopt;
15323
15324 uint64_t BytesProvided = BitsProvided / 8;
15325 uint64_t ByteShift = BitShift / 8;
15326 if (Index + ByteShift < BytesProvided)
15327 return calculateSrcByte(Op->getOperand(0), StartingIndex,
15328 Index + ByteShift);
15329 // SRA's out-of-range bytes are sign bits, not constant zero.
15330 if (Op.getOpcode() == ISD::SRA)
15331 return std::nullopt;
15333 }
15334
15335 case ISD::SHL: {
15336 if (IsVec)
15337 return std::nullopt;
15338
15339 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15340 if (!ShiftOp)
15341 return std::nullopt;
15342
15343 uint64_t BitShift = ShiftOp->getZExtValue();
15344 if (BitShift % 8 != 0)
15345 return std::nullopt;
15346 uint64_t ByteShift = BitShift / 8;
15347
15348 // If we are shifting by an amount greater than (or equal to)
15349 // the index we are trying to provide, then it provides 0s. If not,
15350 // then this bytes are not definitively 0s, and the corresponding byte
15351 // of interest is Index - ByteShift of the src
15352 return Index < ByteShift
15354 : calculateByteProvider(Op.getOperand(0), Index - ByteShift,
15355 Depth + 1, StartingIndex);
15356 }
15357 case ISD::ANY_EXTEND:
15358 case ISD::SIGN_EXTEND:
15359 case ISD::ZERO_EXTEND:
15361 case ISD::AssertZext:
15362 case ISD::AssertSext: {
15363 if (IsVec)
15364 return std::nullopt;
15365
15366 SDValue NarrowOp = Op->getOperand(0);
15367 unsigned NarrowBitWidth = NarrowOp.getValueSizeInBits();
15368 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG ||
15369 Op->getOpcode() == ISD::AssertZext ||
15370 Op->getOpcode() == ISD::AssertSext) {
15371 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15372 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15373 }
15374 if (NarrowBitWidth % 8 != 0)
15375 return std::nullopt;
15376 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15377
15378 if (Index >= NarrowByteWidth)
15379 return Op.getOpcode() == ISD::ZERO_EXTEND
15380 ? std::optional<ByteProvider<SDValue>>(
15382 : std::nullopt;
15383 return calculateByteProvider(NarrowOp, Index, Depth + 1, StartingIndex);
15384 }
15385
15386 case ISD::TRUNCATE: {
15387 if (IsVec)
15388 return std::nullopt;
15389
15390 uint64_t NarrowByteWidth = BitWidth / 8;
15391
15392 if (NarrowByteWidth >= Index) {
15393 return calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15394 StartingIndex);
15395 }
15396
15397 return std::nullopt;
15398 }
15399
15400 case ISD::CopyFromReg: {
15401 if (BitWidth / 8 > Index)
15402 return calculateSrcByte(Op, StartingIndex, Index);
15403
15404 return std::nullopt;
15405 }
15406
15407 case ISD::LOAD: {
15408 auto *L = cast<LoadSDNode>(Op.getNode());
15409
15410 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15411 if (NarrowBitWidth % 8 != 0)
15412 return std::nullopt;
15413 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15414
15415 // If the width of the load does not reach byte we are trying to provide for
15416 // and it is not a ZEXTLOAD, then the load does not provide for the byte in
15417 // question
15418 if (Index >= NarrowByteWidth) {
15419 return L->getExtensionType() == ISD::ZEXTLOAD
15420 ? std::optional<ByteProvider<SDValue>>(
15422 : std::nullopt;
15423 }
15424
15425 if (NarrowByteWidth > Index) {
15426 return calculateSrcByte(Op, StartingIndex, Index);
15427 }
15428
15429 return std::nullopt;
15430 }
15431
15432 case ISD::BSWAP: {
15433 if (IsVec)
15434 return std::nullopt;
15435
15436 return calculateByteProvider(Op->getOperand(0), BitWidth / 8 - Index - 1,
15437 Depth + 1, StartingIndex);
15438 }
15439
15441 auto *IdxOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15442 if (!IdxOp)
15443 return std::nullopt;
15444 auto VecIdx = IdxOp->getZExtValue();
15445 auto ScalarSize = Op.getScalarValueSizeInBits();
15446 if (ScalarSize < 32)
15447 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15448 return calculateSrcByte(ScalarSize >= 32 ? Op : Op.getOperand(0),
15449 StartingIndex, Index);
15450 }
15451
15452 case AMDGPUISD::PERM: {
15453 if (IsVec)
15454 return std::nullopt;
15455
15456 auto *PermMask = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15457 if (!PermMask)
15458 return std::nullopt;
15459
15460 auto IdxMask =
15461 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15462 if (IdxMask > 0x07 && IdxMask != 0x0c)
15463 return std::nullopt;
15464
15465 auto NextOp = Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15466 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15467
15468 return IdxMask != 0x0c ? calculateSrcByte(NextOp, StartingIndex, NextIndex)
15471 }
15472
15473 default: {
15474 return std::nullopt;
15475 }
15476 }
15477
15478 llvm_unreachable("fully handled switch");
15479}
15480
15481// Returns true if the Operand is a scalar and is 16 bits
15482static bool isExtendedFrom16Bits(SDValue &Operand) {
15483
15484 switch (Operand.getOpcode()) {
15485 case ISD::ANY_EXTEND:
15486 case ISD::SIGN_EXTEND:
15487 case ISD::ZERO_EXTEND: {
15488 auto OpVT = Operand.getOperand(0).getValueType();
15489 return !OpVT.isVector() && OpVT.getSizeInBits() == 16;
15490 }
15491 case ISD::LOAD: {
15492 LoadSDNode *L = cast<LoadSDNode>(Operand.getNode());
15493 auto ExtType = cast<LoadSDNode>(L)->getExtensionType();
15494 if (ExtType == ISD::ZEXTLOAD || ExtType == ISD::SEXTLOAD ||
15495 ExtType == ISD::EXTLOAD) {
15496 auto MemVT = L->getMemoryVT();
15497 return !MemVT.isVector() && MemVT.getSizeInBits() == 16;
15498 }
15499 return L->getMemoryVT().getSizeInBits() == 16;
15500 }
15501 default:
15502 return false;
15503 }
15504}
15505
15506// Returns true if the mask matches consecutive bytes, and the first byte
15507// begins at a power of 2 byte offset from 0th byte
15508static bool addresses16Bits(int Mask) {
15509 int Low8 = Mask & 0xff;
15510 int Hi8 = (Mask & 0xff00) >> 8;
15511
15512 assert(Low8 < 8 && Hi8 < 8);
15513 // Are the bytes contiguous in the order of increasing addresses.
15514 bool IsConsecutive = (Hi8 - Low8 == 1);
15515 // Is the first byte at location that is aligned for 16 bit instructions.
15516 // A counter example is taking 2 consecutive bytes starting at the 8th bit.
15517 // In this case, we still need code to extract the 16 bit operand, so it
15518 // is better to use i8 v_perm
15519 bool Is16Aligned = !(Low8 % 2);
15520
15521 return IsConsecutive && Is16Aligned;
15522}
15523
15524// Do not lower into v_perm if the operands are actually 16 bit
15525// and the selected bits (based on PermMask) correspond with two
15526// easily addressable 16 bit operands.
15528 SDValue &OtherOp) {
15529 int Low16 = PermMask & 0xffff;
15530 int Hi16 = (PermMask & 0xffff0000) >> 16;
15531
15532 auto TempOp = peekThroughBitcasts(Op);
15533 auto TempOtherOp = peekThroughBitcasts(OtherOp);
15534
15535 auto OpIs16Bit =
15536 TempOp.getValueSizeInBits() == 16 || isExtendedFrom16Bits(TempOp);
15537 if (!OpIs16Bit)
15538 return true;
15539
15540 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15541 isExtendedFrom16Bits(TempOtherOp);
15542 if (!OtherOpIs16Bit)
15543 return true;
15544
15545 // Do we cleanly address both
15546 return !addresses16Bits(Low16) || !addresses16Bits(Hi16);
15547}
15548
15550 unsigned DWordOffset) {
15551 SDValue Ret;
15552
15553 auto TypeSize = Src.getValueSizeInBits().getFixedValue();
15554 // ByteProvider must be at least 8 bits
15555 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15556
15557 if (TypeSize <= 32)
15558 return DAG.getBitcastedAnyExtOrTrunc(Src, SL, MVT::i32);
15559
15560 if (Src.getValueType().isVector()) {
15561 auto ScalarTySize = Src.getScalarValueSizeInBits();
15562 auto ScalarTy = Src.getValueType().getScalarType();
15563 if (ScalarTySize == 32) {
15564 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Src,
15565 DAG.getConstant(DWordOffset, SL, MVT::i32));
15566 }
15567 if (ScalarTySize > 32) {
15568 Ret = DAG.getNode(
15569 ISD::EXTRACT_VECTOR_ELT, SL, ScalarTy, Src,
15570 DAG.getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15571 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15572 if (ShiftVal)
15573 Ret = DAG.getNode(ISD::SRL, SL, Ret.getValueType(), Ret,
15574 DAG.getConstant(ShiftVal, SL, MVT::i32));
15575 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15576 }
15577
15578 assert(ScalarTySize < 32);
15579 if (TypeSize % 32 == 0) {
15580 assert(DWordOffset < TypeSize / 32);
15581 SDValue Cast = DAG.getBitcast(
15582 EVT::getVectorVT(*DAG.getContext(), MVT::i32, TypeSize / 32), Src);
15583 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Cast,
15584 DAG.getConstant(DWordOffset, SL, MVT::i32));
15585 }
15586
15587 auto NumElements = TypeSize / ScalarTySize;
15588 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15589 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15590 auto NumElementsIn32 = 32 / ScalarTySize;
15591 auto NumAvailElements = DWordOffset < Trunc32Elements
15592 ? NumElementsIn32
15593 : NumElements - NormalizedTrunc;
15594
15596 DAG.ExtractVectorElements(Src, VecSrcs, DWordOffset * NumElementsIn32,
15597 NumAvailElements);
15598
15599 Ret = DAG.getBuildVector(
15600 MVT::getVectorVT(MVT::getIntegerVT(ScalarTySize), NumAvailElements), SL,
15601 VecSrcs);
15602 return Ret = DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15603 }
15604
15605 /// Scalar Type
15606 auto ShiftVal = 32 * DWordOffset;
15607 Ret = DAG.getNode(ISD::SRL, SL, Src.getValueType(), Src,
15608 DAG.getConstant(ShiftVal, SL, MVT::i32));
15609 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15610}
15611
15613 SelectionDAG &DAG = DCI.DAG;
15614 [[maybe_unused]] EVT VT = N->getValueType(0);
15616
15617 // VT is known to be MVT::i32, so we need to provide 4 bytes.
15618 assert(VT == MVT::i32);
15619 for (int i = 0; i < 4; i++) {
15620 // Find the ByteProvider that provides the ith byte of the result of OR
15621 std::optional<ByteProvider<SDValue>> P =
15622 calculateByteProvider(SDValue(N, 0), i, 0, /*StartingIndex = */ i);
15623 // TODO support constantZero
15624 if (!P || P->isConstantZero())
15625 return SDValue();
15626
15627 PermNodes.push_back(*P);
15628 }
15629 if (PermNodes.size() != 4)
15630 return SDValue();
15631
15632 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15633 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15634 uint64_t PermMask = 0x00000000;
15635 for (size_t i = 0; i < PermNodes.size(); i++) {
15636 auto PermOp = PermNodes[i];
15637 // Since the mask is applied to Src1:Src2, Src1 bytes must be offset
15638 // by sizeof(Src2) = 4
15639 int SrcByteAdjust = 4;
15640
15641 // If the Src uses a byte from a different DWORD, then it corresponds
15642 // with a difference source
15643 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15644 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15645 if (SecondSrc)
15646 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15647 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15648 return SDValue();
15649
15650 // Set the index of the second distinct Src node
15651 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15652 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15653 SrcByteAdjust = 0;
15654 }
15655 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15657 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15658 }
15659 SDLoc DL(N);
15660 SDValue Op = *PermNodes[FirstSrc.first].Src;
15661 Op = getDWordFromOffset(DAG, DL, Op, FirstSrc.second);
15662 assert(Op.getValueSizeInBits() == 32);
15663
15664 // Check that we are not just extracting the bytes in order from an op
15665 if (!SecondSrc) {
15666 int Low16 = PermMask & 0xffff;
15667 int Hi16 = (PermMask & 0xffff0000) >> 16;
15668
15669 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15670 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15671
15672 // The perm op would really just produce Op. So combine into Op
15673 if (WellFormedLow && WellFormedHi)
15674 return DAG.getBitcast(MVT::getIntegerVT(32), Op);
15675 }
15676
15677 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src : Op;
15678
15679 if (SecondSrc) {
15680 OtherOp = getDWordFromOffset(DAG, DL, OtherOp, SecondSrc->second);
15681 assert(OtherOp.getValueSizeInBits() == 32);
15682 }
15683
15684 // Check that we haven't just recreated the same FSHR node.
15685 if (N->getOpcode() == ISD::FSHR &&
15686 (N->getOperand(0) == Op || N->getOperand(0) == OtherOp) &&
15687 (N->getOperand(1) == Op || N->getOperand(1) == OtherOp))
15688 return SDValue();
15689
15690 if (hasNon16BitAccesses(PermMask, Op, OtherOp)) {
15691
15692 assert(Op.getValueType().isByteSized() &&
15693 OtherOp.getValueType().isByteSized());
15694
15695 // If the ultimate src is less than 32 bits, then we will only be
15696 // using bytes 0: Op.getValueSizeInBytes() - 1 in the or.
15697 // CalculateByteProvider would not have returned Op as source if we
15698 // used a byte that is outside its ValueType. Thus, we are free to
15699 // ANY_EXTEND as the extended bits are dont-cares.
15700 Op = DAG.getBitcastedAnyExtOrTrunc(Op, DL, MVT::i32);
15701 OtherOp = DAG.getBitcastedAnyExtOrTrunc(OtherOp, DL, MVT::i32);
15702
15703 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op, OtherOp,
15704 DAG.getConstant(PermMask, DL, MVT::i32));
15705 }
15706 return SDValue();
15707}
15708
15709SDValue SITargetLowering::performOrCombine(SDNode *N,
15710 DAGCombinerInfo &DCI) const {
15711 SelectionDAG &DAG = DCI.DAG;
15712 SDValue LHS = N->getOperand(0);
15713 SDValue RHS = N->getOperand(1);
15714
15715 EVT VT = N->getValueType(0);
15716 if (VT == MVT::i1) {
15717 // or (fp_class x, c1), (fp_class x, c2) -> fp_class x, (c1 | c2)
15718 if (LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15719 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15720 SDValue Src = LHS.getOperand(0);
15721 if (Src != RHS.getOperand(0))
15722 return SDValue();
15723
15724 const ConstantSDNode *CLHS = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
15725 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
15726 if (!CLHS || !CRHS)
15727 return SDValue();
15728
15729 // Only 10 bits are used.
15730 static const uint32_t MaxMask = 0x3ff;
15731
15732 uint32_t NewMask =
15733 (CLHS->getZExtValue() | CRHS->getZExtValue()) & MaxMask;
15734 SDLoc DL(N);
15735 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, Src,
15736 DAG.getConstant(NewMask, DL, MVT::i32));
15737 }
15738
15739 return SDValue();
15740 }
15741
15742 // or (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
15744 LHS.getOpcode() == AMDGPUISD::PERM &&
15745 isa<ConstantSDNode>(LHS.getOperand(2))) {
15746 uint32_t Sel = getConstantPermuteMask(N->getConstantOperandVal(1));
15747 if (!Sel)
15748 return SDValue();
15749
15750 Sel |= LHS.getConstantOperandVal(2);
15751 SDLoc DL(N);
15752 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15753 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
15754 }
15755
15756 // or (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
15757 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
15758 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
15759 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15760
15761 // If all the uses of an or need to extract the individual elements, do not
15762 // attempt to lower into v_perm
15763 auto usesCombinedOperand = [](SDNode *OrUse) {
15764 // If we have any non-vectorized use, then it is a candidate for v_perm
15765 if (OrUse->getOpcode() != ISD::BITCAST ||
15766 !OrUse->getValueType(0).isVector())
15767 return true;
15768
15769 // If we have any non-vectorized use, then it is a candidate for v_perm
15770 for (auto *VUser : OrUse->users()) {
15771 if (!VUser->getValueType(0).isVector())
15772 return true;
15773
15774 // If the use of a vector is a store, then combining via a v_perm
15775 // is beneficial.
15776 // TODO -- whitelist more uses
15777 for (auto VectorwiseOp : {ISD::STORE, ISD::CopyToReg, ISD::CopyFromReg})
15778 if (VUser->getOpcode() == VectorwiseOp)
15779 return true;
15780 }
15781 return false;
15782 };
15783
15784 if (!any_of(N->users(), usesCombinedOperand))
15785 return SDValue();
15786
15787 uint32_t LHSMask = getPermuteMask(LHS);
15788 uint32_t RHSMask = getPermuteMask(RHS);
15789
15790 if (LHSMask != ~0u && RHSMask != ~0u) {
15791 // Canonicalize the expression in an attempt to have fewer unique masks
15792 // and therefore fewer registers used to hold the masks.
15793 if (LHSMask > RHSMask) {
15794 std::swap(LHSMask, RHSMask);
15795 std::swap(LHS, RHS);
15796 }
15797
15798 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15799 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15800 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15801 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15802
15803 // Check of we need to combine values from two sources within a byte.
15804 if (!(LHSUsedLanes & RHSUsedLanes) &&
15805 // If we select high and lower word keep it for SDWA.
15806 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15807 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15808 // Kill zero bytes selected by other mask. Zero value is 0xc.
15809 LHSMask &= ~RHSUsedLanes;
15810 RHSMask &= ~LHSUsedLanes;
15811 // Add 4 to each active LHS lane
15812 LHSMask |= LHSUsedLanes & 0x04040404;
15813 // Combine masks
15814 uint32_t Sel = LHSMask | RHSMask;
15815 SDLoc DL(N);
15816
15817 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15818 RHS.getOperand(0),
15819 DAG.getConstant(Sel, DL, MVT::i32));
15820 }
15821 }
15822 if (LHSMask == ~0u || RHSMask == ~0u) {
15823 if (SDValue Perm = matchPERM(N, DCI))
15824 return Perm;
15825 }
15826 }
15827
15828 // Detect identity v2i32 OR and replace with identity source node.
15829 // Specifically an Or that has operands constructed from the same source node
15830 // via extract_vector_elt and build_vector. I.E.
15831 // v2i32 or(
15832 // v2i32 build_vector(
15833 // i32 extract_elt(%IdentitySrc, 0),
15834 // i32 0
15835 // ),
15836 // v2i32 build_vector(
15837 // i32 0,
15838 // i32 extract_elt(%IdentitySrc, 1)
15839 // ) )
15840 // =>
15841 // v2i32 %IdentitySrc
15842
15843 if (VT == MVT::v2i32 && LHS->getOpcode() == ISD::BUILD_VECTOR &&
15844 RHS->getOpcode() == ISD::BUILD_VECTOR) {
15845
15846 ConstantSDNode *LC = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
15847 ConstantSDNode *RC = dyn_cast<ConstantSDNode>(RHS->getOperand(0));
15848
15849 // Test for and normalise build vectors.
15850 if (LC && RC && LC->getZExtValue() == 0 && RC->getZExtValue() == 0) {
15851
15852 // Get the extract_vector_element operands.
15853 SDValue LEVE = LHS->getOperand(0);
15854 SDValue REVE = RHS->getOperand(1);
15855
15856 if (LEVE->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15858 // Check that different elements from the same vector are
15859 // extracted.
15860 if (LEVE->getOperand(0) == REVE->getOperand(0) &&
15861 LEVE->getOperand(1) != REVE->getOperand(1)) {
15862 SDValue IdentitySrc = LEVE.getOperand(0);
15863 return IdentitySrc;
15864 }
15865 }
15866 }
15867 }
15868
15869 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
15870 return SDValue();
15871
15872 // TODO: This could be a generic combine with a predicate for extracting the
15873 // high half of an integer being free.
15874
15875 // (or i64:x, (zero_extend i32:y)) ->
15876 // i64 (bitcast (v2i32 build_vector (or i32:y, lo_32(x)), hi_32(x)))
15877 if (LHS.getOpcode() == ISD::ZERO_EXTEND &&
15878 RHS.getOpcode() != ISD::ZERO_EXTEND)
15879 std::swap(LHS, RHS);
15880
15881 if (RHS.getOpcode() == ISD::ZERO_EXTEND) {
15882 SDValue ExtSrc = RHS.getOperand(0);
15883 EVT SrcVT = ExtSrc.getValueType();
15884 if (SrcVT == MVT::i32) {
15885 SDLoc SL(N);
15886 auto [LowLHS, HiBits] = split64BitValue(LHS, DAG);
15887 SDValue LowOr = DAG.getNode(ISD::OR, SL, MVT::i32, LowLHS, ExtSrc);
15888
15889 DCI.AddToWorklist(LowOr.getNode());
15890 DCI.AddToWorklist(HiBits.getNode());
15891
15892 SDValue Vec =
15893 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, LowOr, HiBits);
15894 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
15895 }
15896 }
15897
15898 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
15899 if (CRHS) {
15900 if (SDValue Split = splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::OR,
15901 N->getOperand(0), CRHS))
15902 return Split;
15903 }
15904
15905 return SDValue();
15906}
15907
15908SDValue SITargetLowering::performXorCombine(SDNode *N,
15909 DAGCombinerInfo &DCI) const {
15910 if (SDValue RV = reassociateScalarOps(N, DCI.DAG))
15911 return RV;
15912
15913 SDValue LHS = N->getOperand(0);
15914 SDValue RHS = N->getOperand(1);
15915
15916 const ConstantSDNode *CRHS = isConstOrConstSplat(RHS);
15917 SelectionDAG &DAG = DCI.DAG;
15918
15919 EVT VT = N->getValueType(0);
15920 if (CRHS && VT == MVT::i64) {
15921 if (SDValue Split =
15922 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::XOR, LHS, CRHS))
15923 return Split;
15924 }
15925
15926 // v2i32 (xor (vselect cc, x, y), K) ->
15927 // (v2i32 svelect cc, (xor x, K), (xor y, K)) This enables the xor to be
15928 // replaced with source modifiers when the select is lowered to CNDMASK.
15929 unsigned Opc = LHS.getOpcode();
15930 if (((Opc == ISD::VSELECT && VT == MVT::v2i32) ||
15931 (Opc == ISD::SELECT && VT == MVT::i64)) &&
15932 CRHS && CRHS->getAPIntValue().isSignMask()) {
15933 SDValue CC = LHS->getOperand(0);
15934 SDValue TRUE = LHS->getOperand(1);
15935 SDValue FALSE = LHS->getOperand(2);
15936 SDValue XTrue = DAG.getNode(ISD::XOR, SDLoc(N), VT, TRUE, RHS);
15937 SDValue XFalse = DAG.getNode(ISD::XOR, SDLoc(N), VT, FALSE, RHS);
15938 SDValue XSelect =
15939 DAG.getNode(ISD::VSELECT, SDLoc(N), VT, CC, XTrue, XFalse);
15940 return XSelect;
15941 }
15942
15943 // Make sure to apply the 64-bit constant splitting fold before trying to fold
15944 // fneg-like xors into 64-bit select.
15945 if (LHS.getOpcode() == ISD::SELECT && VT == MVT::i32) {
15946 // This looks like an fneg, try to fold as a source modifier.
15947 if (CRHS && CRHS->getAPIntValue().isSignMask() &&
15949 // xor (select c, a, b), 0x80000000 ->
15950 // bitcast (select c, (fneg (bitcast a)), (fneg (bitcast b)))
15951 SDLoc DL(N);
15952 SDValue CastLHS =
15953 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(1));
15954 SDValue CastRHS =
15955 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(2));
15956 SDValue FNegLHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastLHS);
15957 SDValue FNegRHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastRHS);
15958 SDValue NewSelect = DAG.getNode(ISD::SELECT, DL, MVT::f32,
15959 LHS->getOperand(0), FNegLHS, FNegRHS);
15960 return DAG.getNode(ISD::BITCAST, DL, VT, NewSelect);
15961 }
15962 }
15963
15964 return SDValue();
15965}
15966
15967SDValue
15968SITargetLowering::performZeroOrAnyExtendCombine(SDNode *N,
15969 DAGCombinerInfo &DCI) const {
15970 if (!Subtarget->has16BitInsts() ||
15971 DCI.getDAGCombineLevel() < AfterLegalizeTypes)
15972 return SDValue();
15973
15974 EVT VT = N->getValueType(0);
15975 if (VT != MVT::i32)
15976 return SDValue();
15977
15978 SDValue Src = N->getOperand(0);
15979 if (Src.getValueType() != MVT::i16)
15980 return SDValue();
15981
15982 if (!Src->hasOneUse())
15983 return SDValue();
15984
15985 // TODO: We bail out below if SrcOffset is not in the first dword (>= 4). It's
15986 // possible we're missing out on some combine opportunities, but we'd need to
15987 // weigh the cost of extracting the byte from the upper dwords.
15988
15989 std::optional<ByteProvider<SDValue>> BP0 =
15990 calculateByteProvider(SDValue(N, 0), 0, 0, 0);
15991 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
15992 return SDValue();
15993 SDValue V0 = *BP0->Src;
15994
15995 std::optional<ByteProvider<SDValue>> BP1 =
15996 calculateByteProvider(SDValue(N, 0), 1, 0, 1);
15997 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
15998 return SDValue();
15999
16000 SDValue V1 = *BP1->Src;
16001
16002 if (V0 == V1)
16003 return SDValue();
16004
16005 SelectionDAG &DAG = DCI.DAG;
16006 SDLoc DL(N);
16007 uint32_t PermMask = 0x0c0c0c0c;
16008 if (V0) {
16009 V0 = DAG.getBitcastedAnyExtOrTrunc(V0, DL, MVT::i32);
16010 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
16011 }
16012
16013 if (V1) {
16014 V1 = DAG.getBitcastedAnyExtOrTrunc(V1, DL, MVT::i32);
16015 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
16016 }
16017
16018 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, V0, V1,
16019 DAG.getConstant(PermMask, DL, MVT::i32));
16020}
16021
16022SDValue
16023SITargetLowering::performSignExtendInRegCombine(SDNode *N,
16024 DAGCombinerInfo &DCI) const {
16025 SDValue Src = N->getOperand(0);
16026 auto *VTSign = cast<VTSDNode>(N->getOperand(1));
16027
16028 // Combine s_buffer_load_u8 or s_buffer_load_u16 with sext and replace them
16029 // with s_buffer_load_i8 and s_buffer_load_i16 respectively.
16030 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
16031 VTSign->getVT() == MVT::i8) ||
16032 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
16033 VTSign->getVT() == MVT::i16))) {
16034 assert(Subtarget->hasScalarSubwordLoads() &&
16035 "s_buffer_load_{u8, i8} are supported "
16036 "in GFX12 (or newer) architectures.");
16037 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
16038 ? AMDGPUISD::SBUFFER_LOAD_BYTE
16039 : AMDGPUISD::SBUFFER_LOAD_SHORT;
16040 SDLoc DL(N);
16041 SDVTList ResList =
16042 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16043 SDValue Ops[] = {
16044 Src.getOperand(0), // Chain
16045 Src.getOperand(1), // source register
16046 Src.getOperand(2), // offset
16047 Src.getOperand(3) // cachePolicy
16048 };
16049 auto *M = cast<MemSDNode>(Src);
16050 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
16051 Opc, DL, ResList, Ops, M->getMemoryVT(), M->getMemOperand());
16052 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.getValue(1)}, DL);
16053 }
16054 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
16055 VTSign->getVT() == MVT::i8) ||
16056 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
16057 VTSign->getVT() == MVT::i16)) &&
16058 Src.hasOneUse()) {
16059 auto *M = cast<MemSDNode>(Src);
16060 SDValue Ops[] = {Src.getOperand(0), // Chain
16061 Src.getOperand(1), // rsrc
16062 Src.getOperand(2), // vindex
16063 Src.getOperand(3), // voffset
16064 Src.getOperand(4), // soffset
16065 Src.getOperand(5), // offset
16066 Src.getOperand(6), Src.getOperand(7)};
16067 // replace with BUFFER_LOAD_BYTE/SHORT
16068 SDVTList ResList =
16069 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16070 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
16071 ? AMDGPUISD::BUFFER_LOAD_BYTE
16072 : AMDGPUISD::BUFFER_LOAD_SHORT;
16073 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
16074 Opc, SDLoc(N), ResList, Ops, M->getMemoryVT(), M->getMemOperand());
16075 return DCI.DAG.getMergeValues(
16076 {BufferLoadSignExt, BufferLoadSignExt.getValue(1)}, SDLoc(N));
16077 }
16078 return SDValue();
16079}
16080
16081SDValue SITargetLowering::performClassCombine(SDNode *N,
16082 DAGCombinerInfo &DCI) const {
16083 SelectionDAG &DAG = DCI.DAG;
16084 SDValue Mask = N->getOperand(1);
16085
16086 // fp_class x, 0 -> false
16087 if (isNullConstant(Mask))
16088 return DAG.getConstant(0, SDLoc(N), MVT::i1);
16089
16090 if (N->getOperand(0).isUndef())
16091 return DAG.getUNDEF(MVT::i1);
16092
16093 return SDValue();
16094}
16095
16096SDValue SITargetLowering::performRcpCombine(SDNode *N,
16097 DAGCombinerInfo &DCI) const {
16098 EVT VT = N->getValueType(0);
16099 SDValue N0 = N->getOperand(0);
16100
16101 if (N0.isUndef()) {
16102 return DCI.DAG.getConstantFP(APFloat::getQNaN(VT.getFltSemantics()),
16103 SDLoc(N), VT);
16104 }
16105
16106 // TODO: Could handle f32 + amdgcn.sqrt but probably never reaches here.
16107 if ((VT == MVT::f16 && N0.getOpcode() == ISD::FSQRT) &&
16108 N->getFlags().hasAllowContract() && N0->getFlags().hasAllowContract()) {
16109 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(N), VT, N0.getOperand(0),
16110 N->getFlags());
16111 }
16112
16114}
16115
16117 SDNodeFlags UserFlags,
16118 unsigned MaxDepth) const {
16119 EVT VT = Op.getValueType();
16120 assert(VT.isFloatingPoint() &&
16121 "expected a floating-point value to query canonicality of");
16122 return isCanonicalized(DAG, Op, VT.getScalarType(), UserFlags, MaxDepth);
16123}
16124
16126 EVT QueryVT, SDNodeFlags UserFlags,
16127 unsigned MaxDepth) const {
16128 assert(QueryVT.isFloatingPoint() && !QueryVT.isVector() &&
16129 "QueryVT must be a floating-point scalar type");
16130 EVT VT = Op.getValueType();
16131 if (VT.isFloatingPoint() && VT.getScalarType() != QueryVT)
16132 return false;
16133
16134 unsigned Opcode = Op.getOpcode();
16135 if (Opcode == ISD::FCANONICALIZE)
16136 return true;
16137
16138 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16139 const auto &F = CFP->getValueAPF();
16140 if (F.isNaN() && F.isSignaling())
16141 return false;
16142 if (!F.isDenormal())
16143 return true;
16144
16145 DenormalMode Mode =
16146 DAG.getMachineFunction().getDenormalMode(F.getSemantics());
16147 return Mode == DenormalMode::getIEEE();
16148 }
16149
16150 // If source is a result of another standard FP operation it is already in
16151 // canonical form.
16152 if (MaxDepth == 0)
16153 return false;
16154
16155 switch (Opcode) {
16156 // These will flush denorms if required.
16157 case ISD::FADD:
16158 case ISD::FSUB:
16159 case ISD::FMUL:
16160 case ISD::FCEIL:
16161 case ISD::FFLOOR:
16162 case ISD::FMA:
16163 case ISD::FMAD:
16164 case ISD::FSQRT:
16165 case ISD::FDIV:
16166 case ISD::FREM:
16167 case ISD::FP_ROUND:
16168 case ISD::FP_EXTEND:
16169 case ISD::FP16_TO_FP:
16170 case ISD::FP_TO_FP16:
16171 case ISD::BF16_TO_FP:
16172 case ISD::FP_TO_BF16:
16173 case ISD::FLDEXP:
16174 case AMDGPUISD::FMUL_LEGACY:
16175 case AMDGPUISD::FMAD_FTZ:
16176 case AMDGPUISD::RCP:
16177 case AMDGPUISD::RSQ:
16178 case AMDGPUISD::RSQ_CLAMP:
16179 case AMDGPUISD::RCP_LEGACY:
16180 case AMDGPUISD::RCP_IFLAG:
16181 case AMDGPUISD::LOG:
16182 case AMDGPUISD::EXP:
16183 case AMDGPUISD::DIV_SCALE:
16184 case AMDGPUISD::DIV_FMAS:
16185 case AMDGPUISD::DIV_FIXUP:
16186 case AMDGPUISD::FRACT:
16187 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16188 case AMDGPUISD::CVT_F32_UBYTE0:
16189 case AMDGPUISD::CVT_F32_UBYTE1:
16190 case AMDGPUISD::CVT_F32_UBYTE2:
16191 case AMDGPUISD::CVT_F32_UBYTE3:
16192 case AMDGPUISD::FP_TO_FP16:
16193 case AMDGPUISD::SIN_HW:
16194 case AMDGPUISD::COS_HW:
16195 return true;
16196
16197 // It can/will be lowered or combined as a bit operation.
16198 // Need to check their input recursively to handle.
16199 case ISD::FNEG:
16200 case ISD::FABS:
16201 case ISD::FCOPYSIGN:
16202 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16203 MaxDepth - 1);
16204
16205 case ISD::AND:
16206 if (Op.getValueType() == MVT::i32) {
16207 // Be careful as we only know it is a bitcast floating point type. It
16208 // could be f32, v2f16, we have no way of knowing. Luckily the constant
16209 // value that we optimize for, which comes up in fp32 to bf16 conversions,
16210 // is valid to optimize for all types.
16211 if (auto *RHS = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
16212 if (RHS->getZExtValue() == 0xffff0000) {
16213 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16214 MaxDepth - 1);
16215 }
16216 }
16217 }
16218 break;
16219
16220 case ISD::FSIN:
16221 case ISD::FCOS:
16222 case ISD::FSINCOS:
16223 return Op.getValueType().getScalarType() != MVT::f16;
16224
16225 case ISD::FMINNUM:
16226 case ISD::FMAXNUM:
16227 case ISD::FMINNUM_IEEE:
16228 case ISD::FMAXNUM_IEEE:
16229 case ISD::FMINIMUM:
16230 case ISD::FMAXIMUM:
16231 case ISD::FMINIMUMNUM:
16232 case ISD::FMAXIMUMNUM:
16233 case AMDGPUISD::CLAMP:
16234 case AMDGPUISD::FMED3:
16235 case AMDGPUISD::FMAX3:
16236 case AMDGPUISD::FMIN3:
16237 case AMDGPUISD::FMAXIMUM3:
16238 case AMDGPUISD::FMINIMUM3: {
16239 // FIXME: Shouldn't treat the generic operations different based these.
16240 // However, we aren't really required to flush the result from
16241 // minnum/maxnum..
16242
16243 // snans will be quieted, so we only need to worry about denormals.
16244 if (Subtarget->supportsMinMaxDenormModes() ||
16245 // FIXME: denormalsEnabledForType is broken for dynamic
16246 denormalsEnabledForType(DAG, Op.getValueType()))
16247 return true;
16248
16249 // Flushing may be required.
16250 // In pre-GFX9 targets V_MIN_F32 and others do not flush denorms. For such
16251 // targets need to check their input recursively.
16252
16253 // FIXME: Does this apply with clamp? It's implemented with max.
16254 for (unsigned I = 0, E = Op.getNumOperands(); I != E; ++I) {
16255 if (!isCanonicalized(DAG, Op.getOperand(I), QueryVT, UserFlags,
16256 MaxDepth - 1))
16257 return false;
16258 }
16259
16260 return true;
16261 }
16262 case ISD::SELECT: {
16263 return isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16264 MaxDepth - 1) &&
16265 isCanonicalized(DAG, Op.getOperand(2), QueryVT, UserFlags,
16266 MaxDepth - 1);
16267 }
16268 case ISD::BUILD_VECTOR: {
16269 for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
16270 SDValue SrcOp = Op.getOperand(i);
16271 if (!isCanonicalized(DAG, SrcOp, QueryVT, UserFlags, MaxDepth - 1))
16272 return false;
16273 }
16274
16275 return true;
16276 }
16279 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16280 MaxDepth - 1);
16281 }
16283 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16284 MaxDepth - 1) &&
16285 isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16286 MaxDepth - 1);
16287 }
16288 case ISD::POISON:
16289 return true;
16290 case ISD::UNDEF:
16291 // Could be anything.
16292 return false;
16293
16294 case ISD::BITCAST: {
16295 // Carry QueryVT through the bitcast unchanged. The top-of-function guard
16296 // rejects a source whose FP format differs from the consumed type, so a
16297 // value canonical in one FP format is not assumed canonical in another.
16298 SDValue Src = peekThroughBitcasts(Op.getOperand(0));
16299 return isCanonicalized(DAG, Src, QueryVT, UserFlags, MaxDepth - 1);
16300 }
16301 case ISD::TRUNCATE: {
16302 // Hack round the mess we make when legalizing extract_vector_elt
16303 if (Op.getValueType() == MVT::i16) {
16304 SDValue TruncSrc = Op.getOperand(0);
16305 if (TruncSrc.getValueType() == MVT::i32 &&
16306 TruncSrc.getOpcode() == ISD::BITCAST &&
16307 TruncSrc.getOperand(0).getValueType() == MVT::v2f16) {
16308 return isCanonicalized(DAG, TruncSrc.getOperand(0), QueryVT, UserFlags,
16309 MaxDepth - 1);
16310 }
16311 }
16312 return false;
16313 }
16315 unsigned IntrinsicID = Op.getConstantOperandVal(0);
16316 // TODO: Handle more intrinsics
16317 switch (IntrinsicID) {
16318 case Intrinsic::amdgcn_cvt_pkrtz:
16319 case Intrinsic::amdgcn_cubeid:
16320 case Intrinsic::amdgcn_frexp_mant:
16321 case Intrinsic::amdgcn_fdot2:
16322 case Intrinsic::amdgcn_rcp:
16323 case Intrinsic::amdgcn_rsq:
16324 case Intrinsic::amdgcn_rsq_clamp:
16325 case Intrinsic::amdgcn_rcp_legacy:
16326 case Intrinsic::amdgcn_rsq_legacy:
16327 case Intrinsic::amdgcn_trig_preop:
16328 case Intrinsic::amdgcn_tanh:
16329 case Intrinsic::amdgcn_log:
16330 case Intrinsic::amdgcn_exp2:
16331 case Intrinsic::amdgcn_sqrt:
16332 return true;
16333 default:
16334 break;
16335 }
16336
16337 break;
16338 }
16339 default:
16340 break;
16341 }
16342
16343 // FIXME: denormalsEnabledForType is broken for dynamic
16344 return denormalsEnabledForType(DAG, Op.getValueType()) &&
16345 (UserFlags.hasNoNaNs() || DAG.isKnownNeverSNaN(Op));
16346}
16347
16349 unsigned MaxDepth) const {
16350 const MachineRegisterInfo &MRI = MF.getRegInfo();
16351 MachineInstr *MI = MRI.getVRegDef(Reg);
16352 unsigned Opcode = MI->getOpcode();
16353
16354 if (Opcode == AMDGPU::G_FCANONICALIZE)
16355 return true;
16356
16357 std::optional<FPValueAndVReg> FCR;
16358 // Constant splat (can be padded with undef) or scalar constant.
16359 if (mi_match(Reg, MRI, MIPatternMatch::m_GFCstOrSplat(FCR))) {
16360 if (FCR->Value.isSignaling())
16361 return false;
16362 if (!FCR->Value.isDenormal())
16363 return true;
16364
16365 DenormalMode Mode = MF.getDenormalMode(FCR->Value.getSemantics());
16366 return Mode == DenormalMode::getIEEE();
16367 }
16368
16369 if (MaxDepth == 0)
16370 return false;
16371
16372 switch (Opcode) {
16373 case AMDGPU::G_FADD:
16374 case AMDGPU::G_FSUB:
16375 case AMDGPU::G_FMUL:
16376 case AMDGPU::G_FCEIL:
16377 case AMDGPU::G_FFLOOR:
16378 case AMDGPU::G_FRINT:
16379 case AMDGPU::G_FNEARBYINT:
16380 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16381 case AMDGPU::G_INTRINSIC_TRUNC:
16382 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16383 case AMDGPU::G_FMA:
16384 case AMDGPU::G_FMAD:
16385 case AMDGPU::G_FSQRT:
16386 case AMDGPU::G_FDIV:
16387 case AMDGPU::G_FREM:
16388 case AMDGPU::G_FPOW:
16389 case AMDGPU::G_FPEXT:
16390 case AMDGPU::G_FLOG:
16391 case AMDGPU::G_FLOG2:
16392 case AMDGPU::G_FLOG10:
16393 case AMDGPU::G_FPTRUNC:
16394 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16395 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16396 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16397 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16398 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16399 return true;
16400 case AMDGPU::G_FNEG:
16401 case AMDGPU::G_FABS:
16402 case AMDGPU::G_FCOPYSIGN:
16403 return isCanonicalized(MI->getOperand(1).getReg(), MF, MaxDepth - 1);
16404 case AMDGPU::G_FMINNUM:
16405 case AMDGPU::G_FMAXNUM:
16406 case AMDGPU::G_FMINNUM_IEEE:
16407 case AMDGPU::G_FMAXNUM_IEEE:
16408 case AMDGPU::G_FMINIMUM:
16409 case AMDGPU::G_FMAXIMUM:
16410 case AMDGPU::G_FMINIMUMNUM:
16411 case AMDGPU::G_FMAXIMUMNUM: {
16412 if (Subtarget->supportsMinMaxDenormModes() ||
16413 // FIXME: denormalsEnabledForType is broken for dynamic
16414 denormalsEnabledForType(MRI.getType(Reg), MF))
16415 return true;
16416
16417 [[fallthrough]];
16418 }
16419 case AMDGPU::G_BUILD_VECTOR:
16420 for (const MachineOperand &MO : llvm::drop_begin(MI->operands()))
16421 if (!isCanonicalized(MO.getReg(), MF, MaxDepth - 1))
16422 return false;
16423 return true;
16424 case AMDGPU::G_INTRINSIC:
16425 case AMDGPU::G_INTRINSIC_CONVERGENT:
16426 switch (cast<GIntrinsic>(MI)->getIntrinsicID()) {
16427 case Intrinsic::amdgcn_fmul_legacy:
16428 case Intrinsic::amdgcn_fmad_ftz:
16429 case Intrinsic::amdgcn_sqrt:
16430 case Intrinsic::amdgcn_fmed3:
16431 case Intrinsic::amdgcn_sin:
16432 case Intrinsic::amdgcn_cos:
16433 case Intrinsic::amdgcn_log:
16434 case Intrinsic::amdgcn_exp2:
16435 case Intrinsic::amdgcn_log_clamp:
16436 case Intrinsic::amdgcn_rcp:
16437 case Intrinsic::amdgcn_rcp_legacy:
16438 case Intrinsic::amdgcn_rsq:
16439 case Intrinsic::amdgcn_rsq_clamp:
16440 case Intrinsic::amdgcn_rsq_legacy:
16441 case Intrinsic::amdgcn_div_scale:
16442 case Intrinsic::amdgcn_div_fmas:
16443 case Intrinsic::amdgcn_div_fixup:
16444 case Intrinsic::amdgcn_fract:
16445 case Intrinsic::amdgcn_cvt_pkrtz:
16446 case Intrinsic::amdgcn_cubeid:
16447 case Intrinsic::amdgcn_cubema:
16448 case Intrinsic::amdgcn_cubesc:
16449 case Intrinsic::amdgcn_cubetc:
16450 case Intrinsic::amdgcn_frexp_mant:
16451 case Intrinsic::amdgcn_fdot2:
16452 case Intrinsic::amdgcn_trig_preop:
16453 case Intrinsic::amdgcn_tanh:
16454 return true;
16455 default:
16456 break;
16457 }
16458
16459 [[fallthrough]];
16460 default:
16461 return false;
16462 }
16463
16464 llvm_unreachable("invalid operation");
16465}
16466
16467// Constant fold canonicalize.
16468SDValue SITargetLowering::getCanonicalConstantFP(SelectionDAG &DAG,
16469 const SDLoc &SL, EVT VT,
16470 const APFloat &C) const {
16471 // Flush denormals to 0 if not enabled.
16472 if (C.isDenormal()) {
16473 DenormalMode Mode =
16474 DAG.getMachineFunction().getDenormalMode(C.getSemantics());
16475 if (Mode == DenormalMode::getPreserveSign()) {
16476 return DAG.getConstantFP(
16477 APFloat::getZero(C.getSemantics(), C.isNegative()), SL, VT);
16478 }
16479
16480 if (Mode != DenormalMode::getIEEE())
16481 return SDValue();
16482 }
16483
16484 if (C.isNaN()) {
16485 if (C.isSignaling()) {
16486 // Quiet a signaling NaN.
16487 return DAG.getConstantFP(C.makeQuiet(), SL, VT);
16488 }
16489 }
16490
16491 // Already canonical.
16492 return DAG.getConstantFP(C, SL, VT);
16493}
16494
16496 return Op.isUndef() || isa<ConstantFPSDNode>(Op);
16497}
16498
16499SDValue
16500SITargetLowering::performFCanonicalizeCombine(SDNode *N,
16501 DAGCombinerInfo &DCI) const {
16502 SelectionDAG &DAG = DCI.DAG;
16503 SDValue N0 = N->getOperand(0);
16504 EVT VT = N->getValueType(0);
16505
16506 // fcanonicalize undef -> qnan
16507 if (N0.isUndef()) {
16509 return DAG.getConstantFP(QNaN, SDLoc(N), VT);
16510 }
16511
16512 if (ConstantFPSDNode *CFP = isConstOrConstSplatFP(N0))
16513 return getCanonicalConstantFP(DAG, SDLoc(N), VT, CFP->getValueAPF());
16514
16515 // fcanonicalize (build_vector x, k) -> build_vector (fcanonicalize x),
16516 // (fcanonicalize k)
16517 //
16518 // fcanonicalize (build_vector x, undef) -> build_vector (fcanonicalize x), 0
16519
16520 // TODO: This could be better with wider vectors that will be split to v2f16,
16521 // and to consider uses since there aren't that many packed operations.
16522 if (N0.getOpcode() == ISD::BUILD_VECTOR && N0.getNumOperands() == 2 &&
16523 isTypeLegal(VT)) {
16524 SDLoc SL(N);
16525 SDValue NewElts[2];
16526 SDValue Lo = N0.getOperand(0);
16527 SDValue Hi = N0.getOperand(1);
16528 EVT EltVT = Lo.getValueType();
16529
16530 // Only apply this optimization if scalar canonicalize is legal for the
16531 // element type. Otherwise, scalarizing may require widening the scalar back
16532 // to a vector, adding overhead (e.g., bf16 has no scalar instructions).
16534 return SDValue();
16535
16537 for (unsigned I = 0; I != 2; ++I) {
16538 SDValue Op = N0.getOperand(I);
16539 if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16540 NewElts[I] =
16541 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16542 } else if (Op.isUndef()) {
16543 // Handled below based on what the other operand is.
16544 NewElts[I] = Op;
16545 } else {
16546 NewElts[I] = DAG.getNode(ISD::FCANONICALIZE, SL, EltVT, Op);
16547 }
16548 }
16549
16550 // If one half is undef, and one is constant, prefer a splat vector.
16551 // Otherwise, convert the undef to 0.0 since that's cheaper to use and may
16552 // be free with a packed operation.
16553 if (NewElts[0].isUndef()) {
16554 NewElts[0] = isa<ConstantFPSDNode>(NewElts[1])
16555 ? NewElts[1]
16556 : DAG.getConstantFP(0.0f, SL, EltVT);
16557 }
16558
16559 if (NewElts[1].isUndef()) {
16560 NewElts[1] = isa<ConstantFPSDNode>(NewElts[0])
16561 ? NewElts[0]
16562 : DAG.getConstantFP(0.0f, SL, EltVT);
16563 }
16564
16565 return DAG.getBuildVector(VT, SL, NewElts);
16566 }
16567 }
16568
16569 return SDValue();
16570}
16571
16572static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc) {
16573 switch (Opc) {
16574 case ISD::FMAXNUM:
16575 case ISD::FMAXNUM_IEEE:
16576 case ISD::FMAXIMUMNUM:
16577 return AMDGPUISD::FMAX3;
16578 case ISD::FMAXIMUM:
16579 return AMDGPUISD::FMAXIMUM3;
16580 case ISD::SMAX:
16581 return AMDGPUISD::SMAX3;
16582 case ISD::UMAX:
16583 return AMDGPUISD::UMAX3;
16584 case ISD::FMINNUM:
16585 case ISD::FMINNUM_IEEE:
16586 case ISD::FMINIMUMNUM:
16587 return AMDGPUISD::FMIN3;
16588 case ISD::FMINIMUM:
16589 return AMDGPUISD::FMINIMUM3;
16590 case ISD::SMIN:
16591 return AMDGPUISD::SMIN3;
16592 case ISD::UMIN:
16593 return AMDGPUISD::UMIN3;
16594 default:
16595 llvm_unreachable("Not a min/max opcode");
16596 }
16597}
16598
16599SDValue SITargetLowering::performIntMed3ImmCombine(SelectionDAG &DAG,
16600 const SDLoc &SL, SDValue Src,
16601 SDValue MinVal,
16602 SDValue MaxVal,
16603 bool Signed) const {
16604
16605 // med3 comes from
16606 // min(max(x, K0), K1), K0 < K1
16607 // max(min(x, K0), K1), K1 < K0
16608 //
16609 // "MinVal" and "MaxVal" respectively refer to the rhs of the
16610 // min/max op.
16611 ConstantSDNode *MinK = dyn_cast<ConstantSDNode>(MinVal);
16612 ConstantSDNode *MaxK = dyn_cast<ConstantSDNode>(MaxVal);
16613
16614 if (!MinK || !MaxK)
16615 return SDValue();
16616
16617 if (Signed) {
16618 if (MaxK->getAPIntValue().sge(MinK->getAPIntValue()))
16619 return SDValue();
16620 } else {
16621 if (MaxK->getAPIntValue().uge(MinK->getAPIntValue()))
16622 return SDValue();
16623 }
16624
16625 EVT VT = MinK->getValueType(0);
16626 unsigned Med3Opc = Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16627 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16628 return DAG.getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16629
16630 // Note: we could also extend to i32 and use i32 med3 if i16 med3 is
16631 // not available, but this is unlikely to be profitable as constants
16632 // will often need to be materialized & extended, especially on
16633 // pre-GFX10 where VOP3 instructions couldn't take literal operands.
16634 return SDValue();
16635}
16636
16639 return C;
16640
16642 if (ConstantFPSDNode *C = BV->getConstantFPSplatNode())
16643 return C;
16644 }
16645
16646 return nullptr;
16647}
16648
16649SDValue SITargetLowering::performFPMed3ImmCombine(SelectionDAG &DAG,
16650 const SDLoc &SL, SDValue Op0,
16651 SDValue Op1,
16652 bool IsKnownNoNaNs) const {
16653 ConstantFPSDNode *K1 = getSplatConstantFP(Op1);
16654 if (!K1)
16655 return SDValue();
16656
16657 ConstantFPSDNode *K0 = getSplatConstantFP(Op0.getOperand(1));
16658 if (!K0)
16659 return SDValue();
16660
16661 // Ordered >= (although NaN inputs should have folded away by now).
16662 if (K0->getValueAPF() > K1->getValueAPF())
16663 return SDValue();
16664
16665 // med3 with a nan input acts like
16666 // v_min_f32(v_min_f32(S0.f32, S1.f32), S2.f32)
16667 //
16668 // So the result depends on whether the IEEE mode bit is enabled or not with a
16669 // signaling nan input.
16670 // ieee=1
16671 // s0 snan: yields s2
16672 // s1 snan: yields s2
16673 // s2 snan: qnan
16674
16675 // s0 qnan: min(s1, s2)
16676 // s1 qnan: min(s0, s2)
16677 // s2 qnan: min(s0, s1)
16678
16679 // ieee=0
16680 // s0 snan: min(s1, s2)
16681 // s1 snan: min(s0, s2)
16682 // s2 snan: qnan
16683
16684 // s0 qnan: min(s1, s2)
16685 // s1 qnan: min(s0, s2)
16686 // s2 qnan: min(s0, s1)
16687 const MachineFunction &MF = DAG.getMachineFunction();
16688 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
16689
16690 // TODO: Check IEEE bit enabled. We can form fmed3 with IEEE=0 regardless of
16691 // whether the input is a signaling nan if op0 is fmaximum or fmaximumnum. We
16692 // can only form if op0 is fmaxnum_ieee if IEEE=1.
16693 EVT VT = Op0.getValueType();
16694 if (Info->getMode().DX10Clamp) {
16695 // If dx10_clamp is enabled, NaNs clamp to 0.0. This is the same as the
16696 // hardware fmed3 behavior converting to a min.
16697 // FIXME: Should this be allowing -0.0?
16698 if (K1->isOne() && K0->isPosZero())
16699 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Op0.getOperand(0));
16700 }
16701
16702 // med3 for f16 is only available on gfx9+, and not available for v2f16.
16703 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16704 // This isn't safe with signaling NaNs because in IEEE mode, min/max on a
16705 // signaling NaN gives a quiet NaN. The quiet NaN input to the min would
16706 // then give the other result, which is different from med3 with a NaN
16707 // input.
16708 SDValue Var = Op0.getOperand(0);
16709 if (!IsKnownNoNaNs && !DAG.isKnownNeverSNaN(Var))
16710 return SDValue();
16711
16712 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
16713
16714 if ((!K0->hasOneUse() || TII->isInlineConstant(K0->getValueAPF())) &&
16715 (!K1->hasOneUse() || TII->isInlineConstant(K1->getValueAPF()))) {
16716 return DAG.getNode(AMDGPUISD::FMED3, SL, K0->getValueType(0), Var,
16717 SDValue(K0, 0), SDValue(K1, 0));
16718 }
16719 }
16720
16721 return SDValue();
16722}
16723
16724/// \return true if the subtarget supports minimum3 and maximum3 with the given
16725/// base min/max opcode \p Opc for type \p VT.
16726static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc,
16727 EVT VT) {
16728 switch (Opc) {
16729 case ISD::FMINNUM:
16730 case ISD::FMAXNUM:
16731 case ISD::FMINNUM_IEEE:
16732 case ISD::FMAXNUM_IEEE:
16733 case ISD::FMINIMUMNUM:
16734 case ISD::FMAXIMUMNUM:
16735 case AMDGPUISD::FMIN_LEGACY:
16736 case AMDGPUISD::FMAX_LEGACY:
16737 return (VT == MVT::f32) || (VT == MVT::f16 && Subtarget.hasMin3Max3_16()) ||
16738 (VT == MVT::v2f16 && Subtarget.hasMin3Max3PKF16());
16739 case ISD::FMINIMUM:
16740 case ISD::FMAXIMUM:
16741 return (VT == MVT::f32 && Subtarget.hasMinimum3Maximum3F32()) ||
16742 (VT == MVT::f16 && Subtarget.hasMinimum3Maximum3F16()) ||
16743 (VT == MVT::v2f16 && Subtarget.hasMinimum3Maximum3PKF16());
16744 case ISD::SMAX:
16745 case ISD::SMIN:
16746 case ISD::UMAX:
16747 case ISD::UMIN:
16748 return (VT == MVT::i32) || (VT == MVT::i16 && Subtarget.hasMin3Max3_16());
16749 default:
16750 return false;
16751 }
16752
16753 llvm_unreachable("not a min/max opcode");
16754}
16755
16756SDValue SITargetLowering::performMinMaxCombine(SDNode *N,
16757 DAGCombinerInfo &DCI) const {
16758 SelectionDAG &DAG = DCI.DAG;
16759
16760 EVT VT = N->getValueType(0);
16761 unsigned Opc = N->getOpcode();
16762 SDValue Op0 = N->getOperand(0);
16763 SDValue Op1 = N->getOperand(1);
16764
16765 // Only do this if the inner op has one use since this will just increases
16766 // register pressure for no benefit.
16767
16768 if (supportsMin3Max3(*Subtarget, Opc, VT)) {
16769 auto IsTreeWithCombinableChildren = [Opc](SDValue Op) {
16770 return (Op.getOperand(0).getOpcode() == Opc &&
16771 Op.getOperand(0).hasOneUse()) ||
16772 (Op.getOperand(1).getOpcode() == Opc &&
16773 Op.getOperand(1).hasOneUse());
16774 };
16775
16776 bool CanTreeCombineApply = Op0.getOpcode() == Opc && Op0.hasOneUse() &&
16777 Op1.getOpcode() == Opc && Op1.hasOneUse();
16778 bool HasCombinableTreeChild =
16779 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
16780 IsTreeWithCombinableChildren(Op1));
16781
16782 // Tree reduction: when both operands are the same min/max op, restructure
16783 // to keep a 2-op node on top so higher tree levels can still combine.
16784 //
16785 // max(max(a, b), max(c, d)) -> max(max3(a, b, c), d)
16786 // min(min(a, b), min(c, d)) -> min(min3(a, b, c), d)
16787 //
16788 // Defer when either inner op is a tree node with combinable children.
16789 if (CanTreeCombineApply && !HasCombinableTreeChild) {
16790 SDLoc DL(N);
16791 SDValue Inner =
16793 Op0.getOperand(1), Op1.getOperand(0));
16794 return DAG.getNode(Opc, DL, VT, Inner, Op1.getOperand(1));
16795 }
16796
16797 // max(max(a, b), c) -> max3(a, b, c)
16798 // min(min(a, b), c) -> min3(a, b, c)
16799 // Deferred when Op0 is a tree node with combinable children.
16800 if (Op0.getOpcode() == Opc && Op0.hasOneUse() && !HasCombinableTreeChild) {
16801 SDLoc DL(N);
16802 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
16803 Op0.getOperand(0), Op0.getOperand(1), Op1);
16804 }
16805
16806 // Try commuted.
16807 // max(a, max(b, c)) -> max3(a, b, c)
16808 // min(a, min(b, c)) -> min3(a, b, c)
16809 // Deferred when Op1 is a tree node with combinable children.
16810 if (Op1.getOpcode() == Opc && Op1.hasOneUse() && !HasCombinableTreeChild) {
16811 SDLoc DL(N);
16812 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
16813 Op0, Op1.getOperand(0), Op1.getOperand(1));
16814 }
16815 }
16816
16817 // umin(sffbh(x), bitwidth) -> sffbh(x) if x is known to be not 0 or -1.
16818 SDValue FfbhSrc;
16819 uint64_t Clamp = 0;
16820 if (Opc == ISD::UMIN &&
16821 sd_match(Op0,
16823 sd_match(Op1, m_ConstInt(Clamp))) {
16824 unsigned BitWidth = FfbhSrc.getValueType().getScalarSizeInBits();
16825 if (Clamp >= BitWidth) {
16826 KnownBits Known = DAG.computeKnownBits(FfbhSrc);
16827 if (Known.isNonZero() && Known.Zero.getBoolValue())
16828 return Op0;
16829 }
16830 }
16831
16832 // min(max(x, K0), K1), K0 < K1 -> med3(x, K0, K1)
16833 // max(min(x, K0), K1), K1 < K0 -> med3(x, K1, K0)
16834 if (Opc == ISD::SMIN && Op0.getOpcode() == ISD::SMAX && Op0.hasOneUse()) {
16835 if (SDValue Med3 = performIntMed3ImmCombine(
16836 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), true))
16837 return Med3;
16838 }
16839 if (Opc == ISD::SMAX && Op0.getOpcode() == ISD::SMIN && Op0.hasOneUse()) {
16840 if (SDValue Med3 = performIntMed3ImmCombine(
16841 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, true))
16842 return Med3;
16843 }
16844
16845 if (Opc == ISD::UMIN && Op0.getOpcode() == ISD::UMAX && Op0.hasOneUse()) {
16846 if (SDValue Med3 = performIntMed3ImmCombine(
16847 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), false))
16848 return Med3;
16849 }
16850 if (Opc == ISD::UMAX && Op0.getOpcode() == ISD::UMIN && Op0.hasOneUse()) {
16851 if (SDValue Med3 = performIntMed3ImmCombine(
16852 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, false))
16853 return Med3;
16854 }
16855
16856 // if !is_snan(x):
16857 // fminnum(fmaxnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16858 // fminnum_ieee(fmaxnum_ieee(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16859 // fminnumnum(fmaxnumnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16860 // fmin_legacy(fmax_legacy(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16861 if (((Opc == ISD::FMINNUM && Op0.getOpcode() == ISD::FMAXNUM) ||
16864 (Opc == AMDGPUISD::FMIN_LEGACY &&
16865 Op0.getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
16866 (VT == MVT::f32 || VT == MVT::f64 ||
16867 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
16868 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
16869 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
16870 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
16871 Op0.hasOneUse()) {
16872 if (SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(N), Op0, Op1,
16873 N->getFlags().hasNoNaNs()))
16874 return Res;
16875 }
16876
16877 // Prefer fminnum_ieee over fminimum. For gfx950, minimum/maximum are legal
16878 // for some types, but at a higher cost since it's implemented with a 3
16879 // operand form.
16880 const SDNodeFlags Flags = N->getFlags();
16881 if ((Opc == ISD::FMINIMUM || Opc == ISD::FMAXIMUM) && Flags.hasNoNaNs() &&
16882 !Subtarget->hasIEEEMinimumMaximumInsts() &&
16884 unsigned NewOpc =
16886 return DAG.getNode(NewOpc, SDLoc(N), VT, Op0, Op1, Flags);
16887 }
16888
16889 return SDValue();
16890}
16891
16895 // FIXME: Should this be allowing -0.0?
16896 return (CA->isPosZero() && CB->isOne()) ||
16897 (CA->isOne() && CB->isPosZero());
16898 }
16899 }
16900
16901 return false;
16902}
16903
16904// FIXME: Should only worry about snans for version with chain.
16905SDValue SITargetLowering::performFMed3Combine(SDNode *N,
16906 DAGCombinerInfo &DCI) const {
16907 EVT VT = N->getValueType(0);
16908 // v_med3_f32 and v_max_f32 behave identically wrt denorms, exceptions and
16909 // NaNs. With a NaN input, the order of the operands may change the result.
16910
16911 SelectionDAG &DAG = DCI.DAG;
16912 SDLoc SL(N);
16913
16914 SDValue Src0 = N->getOperand(0);
16915 SDValue Src1 = N->getOperand(1);
16916 SDValue Src2 = N->getOperand(2);
16917
16918 if (isClampZeroToOne(Src0, Src1)) {
16919 // const_a, const_b, x -> clamp is safe in all cases including signaling
16920 // nans.
16921 // FIXME: Should this be allowing -0.0?
16922 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
16923 }
16924
16925 const MachineFunction &MF = DAG.getMachineFunction();
16926 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
16927
16928 // FIXME: dx10_clamp behavior assumed in instcombine. Should we really bother
16929 // handling no dx10-clamp?
16930 if (Info->getMode().DX10Clamp) {
16931 // If NaNs is clamped to 0, we are free to reorder the inputs.
16932
16933 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
16934 std::swap(Src0, Src1);
16935
16936 if (isa<ConstantFPSDNode>(Src1) && !isa<ConstantFPSDNode>(Src2))
16937 std::swap(Src1, Src2);
16938
16939 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
16940 std::swap(Src0, Src1);
16941
16942 if (isClampZeroToOne(Src1, Src2))
16943 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
16944 }
16945
16946 return SDValue();
16947}
16948
16949SDValue SITargetLowering::performCvtPkRTZCombine(SDNode *N,
16950 DAGCombinerInfo &DCI) const {
16951 SDValue Src0 = N->getOperand(0);
16952 SDValue Src1 = N->getOperand(1);
16953 if (Src0.isUndef() && Src1.isUndef())
16954 return DCI.DAG.getUNDEF(N->getValueType(0));
16955 return SDValue();
16956}
16957
16958// Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be
16959// expanded into a set of cmp/select instructions.
16961 unsigned NumElem,
16962 bool IsDivergentIdx,
16963 const GCNSubtarget *Subtarget) {
16965 return false;
16966
16967 unsigned VecSize = EltSize * NumElem;
16968
16969 // Sub-dword vectors of size 2 dword or less have better implementation.
16970 if (VecSize <= 64 && EltSize < 32)
16971 return false;
16972
16973 // Always expand the rest of sub-dword instructions, otherwise it will be
16974 // lowered via memory.
16975 if (EltSize < 32)
16976 return true;
16977
16978 // Always do this if var-idx is divergent, otherwise it will become a loop.
16979 if (IsDivergentIdx)
16980 return true;
16981
16982 // Large vectors would yield too many compares and v_cndmask_b32 instructions.
16983 unsigned NumInsts = NumElem /* Number of compares */ +
16984 ((EltSize + 31) / 32) * NumElem /* Number of cndmasks */;
16985
16986 // On some architectures (GFX9) movrel is not available and it's better
16987 // to expand.
16988 if (Subtarget->useVGPRIndexMode())
16989 return NumInsts <= 16;
16990
16991 // If movrel is available, use it instead of expanding for vector of 8
16992 // elements.
16993 if (Subtarget->hasMovrel())
16994 return NumInsts <= 15;
16995
16996 return true;
16997}
16998
17000 SDValue Idx = N->getOperand(N->getNumOperands() - 1);
17001 if (isa<ConstantSDNode>(Idx))
17002 return false;
17003
17004 SDValue Vec = N->getOperand(0);
17005 EVT VecVT = Vec.getValueType();
17006 EVT EltVT = VecVT.getVectorElementType();
17007 unsigned EltSize = EltVT.getSizeInBits();
17008 unsigned NumElem = VecVT.getVectorNumElements();
17009
17011 EltSize, NumElem, Idx->isDivergent(), getSubtarget());
17012}
17013
17014SDValue
17015SITargetLowering::performExtractVectorEltCombine(SDNode *N,
17016 DAGCombinerInfo &DCI) const {
17017 SDValue Vec = N->getOperand(0);
17018 SelectionDAG &DAG = DCI.DAG;
17019
17020 EVT VecVT = Vec.getValueType();
17021 EVT VecEltVT = VecVT.getVectorElementType();
17022 EVT ResVT = N->getValueType(0);
17023
17024 unsigned VecSize = VecVT.getSizeInBits();
17025 unsigned VecEltSize = VecEltVT.getSizeInBits();
17026
17027 if ((Vec.getOpcode() == ISD::FNEG || Vec.getOpcode() == ISD::FABS) &&
17029 SDLoc SL(N);
17030 SDValue Idx = N->getOperand(1);
17031 SDValue Elt =
17032 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec.getOperand(0), Idx);
17033 return DAG.getNode(Vec.getOpcode(), SL, ResVT, Elt);
17034 }
17035
17036 // (extract_vector_element (and {y0, y1}, (build_vector 0x1f, 0x1f)), index)
17037 // -> (and (extract_vector_element {y0, y1}, index), 0x1f)
17038 // There are optimisations to transform 64-bit shifts into 32-bit shifts
17039 // depending on the shift operand. See e.g. performSraCombine().
17040 // This combine ensures that the optimisation is compatible with v2i32
17041 // legalised AND.
17042 if (VecVT == MVT::v2i32 && Vec->getOpcode() == ISD::AND &&
17043 Vec->getOperand(1)->getOpcode() == ISD::BUILD_VECTOR) {
17044
17046 if (!C || C->getZExtValue() != 0x1f)
17047 return SDValue();
17048
17049 SDLoc SL(N);
17050 SDValue AndMask = DAG.getConstant(0x1f, SL, MVT::i32);
17051 SDValue EVE = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32,
17052 Vec->getOperand(0), N->getOperand(1));
17053 SDValue A = DAG.getNode(ISD::AND, SL, MVT::i32, EVE, AndMask);
17054 DAG.ReplaceAllUsesWith(N, A.getNode());
17055 }
17056
17057 // ScalarRes = EXTRACT_VECTOR_ELT ((vector-BINOP Vec1, Vec2), Idx)
17058 // =>
17059 // Vec1Elt = EXTRACT_VECTOR_ELT(Vec1, Idx)
17060 // Vec2Elt = EXTRACT_VECTOR_ELT(Vec2, Idx)
17061 // ScalarRes = scalar-BINOP Vec1Elt, Vec2Elt
17062 if (Vec.hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17063 SDLoc SL(N);
17064 SDValue Idx = N->getOperand(1);
17065 unsigned Opc = Vec.getOpcode();
17066
17067 switch (Opc) {
17068 default:
17069 break;
17070 // TODO: Support other binary operations.
17071 case ISD::FADD:
17072 case ISD::FSUB:
17073 case ISD::FMUL:
17074 case ISD::ADD:
17075 case ISD::UMIN:
17076 case ISD::UMAX:
17077 case ISD::SMIN:
17078 case ISD::SMAX:
17079 case ISD::FMAXNUM:
17080 case ISD::FMINNUM:
17081 case ISD::FMAXNUM_IEEE:
17082 case ISD::FMINNUM_IEEE:
17083 case ISD::FMAXIMUM:
17084 case ISD::FMINIMUM: {
17085 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17086 Vec.getOperand(0), Idx);
17087 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17088 Vec.getOperand(1), Idx);
17089
17090 DCI.AddToWorklist(Elt0.getNode());
17091 DCI.AddToWorklist(Elt1.getNode());
17092 return DAG.getNode(Opc, SL, ResVT, Elt0, Elt1, Vec->getFlags());
17093 }
17094 }
17095 }
17096
17097 // EXTRACT_VECTOR_ELT (<n x e>, var-idx) => n x select (e, const-idx)
17099 SDLoc SL(N);
17100 SDValue Idx = N->getOperand(1);
17101 SDValue V;
17102 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17103 SDValue IC = DAG.getVectorIdxConstant(I, SL);
17104 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec, IC);
17105 if (I == 0)
17106 V = Elt;
17107 else
17108 V = DAG.getSelectCC(SL, Idx, IC, Elt, V, ISD::SETEQ);
17109 }
17110 return V;
17111 }
17112
17113 // EXTRACT_VECTOR_ELT (v2i32 bitcast (i64/f64:k), Idx)
17114 // =>
17115 // i32:Lo(k) if Idx == 0, or
17116 // i32:Hi(k) if Idx == 1
17117 auto *Idx = dyn_cast<ConstantSDNode>(N->getOperand(1));
17118 if (Vec.getOpcode() == ISD::BITCAST && VecVT == MVT::v2i32 && Idx) {
17119 SDLoc SL(N);
17120 SDValue PeekThrough = Vec.getOperand(0);
17121 auto *KImm = dyn_cast<ConstantSDNode>(PeekThrough);
17122 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17123 uint64_t KImmValue = KImm->getZExtValue();
17124 return DAG.getConstant(
17125 (KImmValue >> (32 * Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17126 }
17127 auto *KFPImm = dyn_cast<ConstantFPSDNode>(PeekThrough);
17128 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17129 uint64_t KFPImmValue =
17130 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17131 return DAG.getConstant((KFPImmValue >> (32 * Idx->getZExtValue())) &
17132 0xffffffff,
17133 SL, MVT::i32);
17134 }
17135 }
17136
17137 if (!DCI.isBeforeLegalize())
17138 return SDValue();
17139
17140 // Try to turn sub-dword accesses of vectors into accesses of the same 32-bit
17141 // elements. This exposes more load reduction opportunities by replacing
17142 // multiple small extract_vector_elements with a single 32-bit extract.
17143 if (isa<MemSDNode>(Vec) && VecEltSize <= 16 && VecEltVT.isByteSized() &&
17144 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17145 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VecVT);
17146
17147 unsigned BitIndex = Idx->getZExtValue() * VecEltSize;
17148 unsigned EltIdx = BitIndex / 32;
17149 unsigned LeftoverBitIdx = BitIndex % 32;
17150 SDLoc SL(N);
17151
17152 SDValue Cast = DAG.getNode(ISD::BITCAST, SL, NewVT, Vec);
17153 DCI.AddToWorklist(Cast.getNode());
17154
17155 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Cast,
17156 DAG.getConstant(EltIdx, SL, MVT::i32));
17157 DCI.AddToWorklist(Elt.getNode());
17158 SDValue Srl = DAG.getNode(ISD::SRL, SL, MVT::i32, Elt,
17159 DAG.getConstant(LeftoverBitIdx, SL, MVT::i32));
17160 DCI.AddToWorklist(Srl.getNode());
17161
17162 EVT VecEltAsIntVT = VecEltVT.changeTypeToInteger();
17163 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SL, VecEltAsIntVT, Srl);
17164 DCI.AddToWorklist(Trunc.getNode());
17165
17166 if (VecEltVT == ResVT) {
17167 return DAG.getNode(ISD::BITCAST, SL, VecEltVT, Trunc);
17168 }
17169
17170 assert(ResVT.isScalarInteger());
17171 return DAG.getAnyExtOrTrunc(Trunc, SL, ResVT);
17172 }
17173
17174 return SDValue();
17175}
17176
17177SDValue
17178SITargetLowering::performInsertVectorEltCombine(SDNode *N,
17179 DAGCombinerInfo &DCI) const {
17180 SDValue Vec = N->getOperand(0);
17181 SDValue Idx = N->getOperand(2);
17182 EVT VecVT = Vec.getValueType();
17183 EVT EltVT = VecVT.getVectorElementType();
17184
17185 // INSERT_VECTOR_ELT (<n x e>, var-idx)
17186 // => BUILD_VECTOR n x select (e, const-idx)
17188 return SDValue();
17189
17190 SelectionDAG &DAG = DCI.DAG;
17191 SDLoc SL(N);
17192 SDValue Ins = N->getOperand(1);
17193 EVT IdxVT = Idx.getValueType();
17194
17196 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17197 SDValue IC = DAG.getConstant(I, SL, IdxVT);
17198 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec, IC);
17199 SDValue V = DAG.getSelectCC(SL, Idx, IC, Ins, Elt, ISD::SETEQ);
17200 Ops.push_back(V);
17201 }
17202
17203 return DAG.getBuildVector(VecVT, SL, Ops);
17204}
17205
17206/// Return the source of an fp_extend from f16 to f32, or a converted FP
17207/// constant.
17209 if (Src.getOpcode() == ISD::FP_EXTEND &&
17210 Src.getOperand(0).getValueType() == MVT::f16) {
17211 return Src.getOperand(0);
17212 }
17213
17214 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Src)) {
17215 APFloat Val = CFP->getValueAPF();
17216 bool LosesInfo = true;
17218 if (!LosesInfo)
17219 return DAG.getConstantFP(Val, SDLoc(Src), MVT::f16);
17220 }
17221
17222 return SDValue();
17223}
17224
17225SDValue SITargetLowering::performFPRoundCombine(SDNode *N,
17226 DAGCombinerInfo &DCI) const {
17227 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17228 "combine only useful on gfx8");
17229
17230 SDValue TruncSrc = N->getOperand(0);
17231 EVT VT = N->getValueType(0);
17232 if (VT != MVT::f16)
17233 return SDValue();
17234
17235 if (TruncSrc.getOpcode() != AMDGPUISD::FMED3 ||
17236 TruncSrc.getValueType() != MVT::f32 || !TruncSrc.hasOneUse())
17237 return SDValue();
17238
17239 SelectionDAG &DAG = DCI.DAG;
17240 SDLoc SL(N);
17241
17242 // Optimize f16 fmed3 pattern performed on f32. On gfx8 there is no f16 fmed3,
17243 // and expanding it with min/max saves 1 instruction vs. casting to f32 and
17244 // casting back.
17245
17246 // fptrunc (f32 (fmed3 (fpext f16:a, fpext f16:b, fpext f16:c))) =>
17247 // fmin(fmax(a, b), fmax(fmin(a, b), c))
17248 SDValue A = strictFPExtFromF16(DAG, TruncSrc.getOperand(0));
17249 if (!A)
17250 return SDValue();
17251
17252 SDValue B = strictFPExtFromF16(DAG, TruncSrc.getOperand(1));
17253 if (!B)
17254 return SDValue();
17255
17256 SDValue C = strictFPExtFromF16(DAG, TruncSrc.getOperand(2));
17257 if (!C)
17258 return SDValue();
17259
17260 // This changes signaling nan behavior. If an input is a signaling nan, it
17261 // would have been quieted by the fpext originally. We don't care because
17262 // these are unconstrained ops. If we needed to insert quieting canonicalizes
17263 // we would be worse off than just doing the promotion.
17264 SDValue A1 = DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, A, B);
17265 SDValue B1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A, B);
17266 SDValue C1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A1, C);
17267 return DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, B1, C1);
17268}
17269
17270unsigned SITargetLowering::getFusedOpcode(const SelectionDAG &DAG,
17271 const SDNode *N0,
17272 const SDNode *N1) const {
17273 EVT VT = N0->getValueType(0);
17274
17275 // Only do this if we are not trying to support denormals. v_mad_f32 does not
17276 // support denormals ever.
17277 if (((VT == MVT::f32 &&
17279 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17282 return ISD::FMAD;
17283
17284 if (N0->getFlags().hasAllowContract() && N1->getFlags().hasAllowContract() &&
17286 return ISD::FMA;
17287 }
17288
17289 return 0;
17290}
17291
17292// For a reassociatable opcode perform:
17293// op x, (op y, z) -> op (op x, z), y, if x and z are uniform
17294SDValue SITargetLowering::reassociateScalarOps(SDNode *N,
17295 SelectionDAG &DAG) const {
17296 EVT VT = N->getValueType(0);
17297 if (VT != MVT::i32 && VT != MVT::i64)
17298 return SDValue();
17299
17300 if (DAG.isBaseWithConstantOffset(SDValue(N, 0)))
17301 return SDValue();
17302
17303 unsigned Opc = N->getOpcode();
17304 SDValue Op0 = N->getOperand(0);
17305 SDValue Op1 = N->getOperand(1);
17306
17307 if (!(Op0->isDivergent() ^ Op1->isDivergent()))
17308 return SDValue();
17309
17310 if (Op0->isDivergent())
17311 std::swap(Op0, Op1);
17312
17313 if (Op1.getOpcode() != Opc || !Op1.hasOneUse())
17314 return SDValue();
17315
17316 SDValue Op2 = Op1.getOperand(1);
17317 Op1 = Op1.getOperand(0);
17318 if (!(Op1->isDivergent() ^ Op2->isDivergent()))
17319 return SDValue();
17320
17321 if (Op1->isDivergent())
17322 std::swap(Op1, Op2);
17323
17324 SDLoc SL(N);
17325 SDValue Add1 = DAG.getNode(Opc, SL, VT, Op0, Op1);
17326 return DAG.getNode(Opc, SL, VT, Add1, Op2);
17327}
17328
17329static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT,
17330 SDValue N0, SDValue N1, SDValue N2, bool Signed) {
17332 SDVTList VTs = DAG.getVTList(MVT::i64, MVT::i1);
17333 SDValue Mad = DAG.getNode(MadOpc, SL, VTs, N0, N1, N2);
17334 return DAG.getNode(ISD::TRUNCATE, SL, VT, Mad);
17335}
17336
17337// Fold
17338// y = lshr i64 x, 32
17339// res = add (mul i64 y, Const), x where "Const" is a 64-bit constant
17340// with Const.hi == -1
17341// To
17342// res = mad_u64_u32 y.lo ,Const.lo, x.lo
17344 SDValue MulLHS, SDValue MulRHS,
17345 SDValue AddRHS) {
17346 if (MulRHS.getOpcode() == ISD::SRL)
17347 std::swap(MulLHS, MulRHS);
17348
17349 if (MulLHS.getValueType() != MVT::i64 || MulLHS.getOpcode() != ISD::SRL)
17350 return SDValue();
17351
17352 ConstantSDNode *ShiftVal = dyn_cast<ConstantSDNode>(MulLHS.getOperand(1));
17353 if (!ShiftVal || ShiftVal->getAsZExtVal() != 32 ||
17354 MulLHS.getOperand(0) != AddRHS)
17355 return SDValue();
17356
17358 if (!Const || Hi_32(Const->getZExtValue()) != uint32_t(-1))
17359 return SDValue();
17360
17361 SDValue ConstMul =
17362 DAG.getConstant(Lo_32(Const->getZExtValue()), SL, MVT::i32);
17363 return getMad64_32(DAG, SL, MVT::i64,
17364 DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS), ConstMul,
17365 DAG.getZeroExtendInReg(AddRHS, SL, MVT::i32), false);
17366}
17367
17368// Fold (add (mul x, y), z) --> (mad_[iu]64_[iu]32 x, y, z) plus high
17369// multiplies, if any.
17370//
17371// Full 64-bit multiplies that feed into an addition are lowered here instead
17372// of using the generic expansion. The generic expansion ends up with
17373// a tree of ADD nodes that prevents us from using the "add" part of the
17374// MAD instruction. The expansion produced here results in a chain of ADDs
17375// instead of a tree.
17376SDValue SITargetLowering::tryFoldToMad64_32(SDNode *N,
17377 DAGCombinerInfo &DCI) const {
17378 assert(N->isAnyAdd());
17379
17380 SelectionDAG &DAG = DCI.DAG;
17381 EVT VT = N->getValueType(0);
17382 SDLoc SL(N);
17383 SDValue LHS = N->getOperand(0);
17384 SDValue RHS = N->getOperand(1);
17385
17386 if (VT.isVector())
17387 return SDValue();
17388
17389 // S_MUL_HI_[IU]32 was added in gfx9, which allows us to keep the overall
17390 // result in scalar registers for uniform values.
17391 if (!N->isDivergent() && Subtarget->hasSMulHi())
17392 return SDValue();
17393
17394 unsigned NumBits = VT.getScalarSizeInBits();
17395 if (NumBits <= 32 || NumBits > 64)
17396 return SDValue();
17397
17398 if (LHS.getOpcode() != ISD::MUL) {
17399 assert(RHS.getOpcode() == ISD::MUL);
17400 std::swap(LHS, RHS);
17401 }
17402
17403 // Avoid the fold if it would unduly increase the number of multiplies due to
17404 // multiple uses, except on hardware with full-rate multiply-add (which is
17405 // part of full-rate 64-bit ops).
17406 if (!Subtarget->hasFullRate64Ops()) {
17407 unsigned NumUsers = 0;
17408 for (SDNode *User : LHS->users()) {
17409 // There is a use that does not feed into addition, so the multiply can't
17410 // be removed. We prefer MUL + ADD + ADDC over MAD + MUL.
17411 if (!User->isAnyAdd())
17412 return SDValue();
17413
17414 // We prefer 2xMAD over MUL + 2xADD + 2xADDC (code density), and prefer
17415 // MUL + 3xADD + 3xADDC over 3xMAD.
17416 ++NumUsers;
17417 if (NumUsers >= 3)
17418 return SDValue();
17419 }
17420 }
17421
17422 SDValue MulLHS = LHS.getOperand(0);
17423 SDValue MulRHS = LHS.getOperand(1);
17424 SDValue AddRHS = RHS;
17425
17426 if (SDValue FoldedMAD = tryFoldMADwithSRL(DAG, SL, MulLHS, MulRHS, AddRHS))
17427 return FoldedMAD;
17428
17429 // Always check whether operands are small unsigned values, since that
17430 // knowledge is useful in more cases. Check for small signed values only if
17431 // doing so can unlock a shorter code sequence.
17432 bool MulLHSUnsigned32 = numBitsUnsigned(MulLHS, DAG) <= 32;
17433 bool MulRHSUnsigned32 = numBitsUnsigned(MulRHS, DAG) <= 32;
17434
17435 bool MulSignedLo = false;
17436 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17437 MulSignedLo =
17438 numBitsSigned(MulLHS, DAG) <= 32 && numBitsSigned(MulRHS, DAG) <= 32;
17439 }
17440
17441 // The operands and final result all have the same number of bits. If
17442 // operands need to be extended, they can be extended with garbage. The
17443 // resulting garbage in the high bits of the mad_[iu]64_[iu]32 result is
17444 // truncated away in the end.
17445 if (VT != MVT::i64) {
17446 MulLHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulLHS);
17447 MulRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulRHS);
17448 AddRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, AddRHS);
17449 }
17450
17451 // The basic code generated is conceptually straightforward. Pseudo code:
17452 //
17453 // accum = mad_64_32 lhs.lo, rhs.lo, accum
17454 // accum.hi = add (mul lhs.hi, rhs.lo), accum.hi
17455 // accum.hi = add (mul lhs.lo, rhs.hi), accum.hi
17456 //
17457 // The second and third lines are optional, depending on whether the factors
17458 // are {sign,zero}-extended or not.
17459 //
17460 // The actual DAG is noisier than the pseudo code, but only due to
17461 // instructions that disassemble values into low and high parts, and
17462 // assemble the final result.
17463 SDValue One = DAG.getConstant(1, SL, MVT::i32);
17464
17465 auto MulLHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS);
17466 auto MulRHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulRHS);
17467 SDValue Accum =
17468 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17469
17470 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17471 auto [AccumLo, AccumHi] = DAG.SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17472
17473 if (!MulLHSUnsigned32) {
17474 auto MulLHSHi =
17475 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulLHS, One);
17476 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSHi, MulRHSLo);
17477 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17478 }
17479
17480 if (!MulRHSUnsigned32) {
17481 auto MulRHSHi =
17482 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulRHS, One);
17483 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSLo, MulRHSHi);
17484 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17485 }
17486
17487 Accum = DAG.getBuildVector(MVT::v2i32, SL, {AccumLo, AccumHi});
17488 Accum = DAG.getBitcast(MVT::i64, Accum);
17489 }
17490
17491 if (VT != MVT::i64)
17492 Accum = DAG.getNode(ISD::TRUNCATE, SL, VT, Accum);
17493 return Accum;
17494}
17495
17496SDValue
17497SITargetLowering::foldAddSub64WithZeroLowBitsTo32(SDNode *N,
17498 DAGCombinerInfo &DCI) const {
17499 SDValue RHS = N->getOperand(1);
17500 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
17501 if (!CRHS)
17502 return SDValue();
17503
17504 // TODO: Worth using computeKnownBits? Maybe expensive since it's so
17505 // common.
17506 uint64_t Val = CRHS->getZExtValue();
17507 if (countr_zero(Val) >= 32) {
17508 SelectionDAG &DAG = DCI.DAG;
17509 SDLoc SL(N);
17510 SDValue LHS = N->getOperand(0);
17511
17512 // Avoid carry machinery if we know the low half of the add does not
17513 // contribute to the final result.
17514 //
17515 // add i64:x, K if computeTrailingZeros(K) >= 32
17516 // => build_pair (add x.hi, K.hi), x.lo
17517
17518 // Breaking the 64-bit add here with this strange constant is unlikely
17519 // to interfere with addressing mode patterns.
17520
17521 SDValue Hi = getHiHalf64(LHS, DAG);
17522 SDValue ConstHi32 = DAG.getConstant(Hi_32(Val), SL, MVT::i32);
17523 unsigned Opcode = N->getOpcode();
17524 if (Opcode == ISD::PTRADD)
17525 Opcode = ISD::ADD;
17526 SDValue AddHi =
17527 DAG.getNode(Opcode, SL, MVT::i32, Hi, ConstHi32, N->getFlags());
17528
17529 SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
17530 return DAG.getNode(ISD::BUILD_PAIR, SL, MVT::i64, Lo, AddHi);
17531 }
17532
17533 return SDValue();
17534}
17535
17536// Collect the ultimate src of each of the mul node's operands, and confirm
17537// each operand is 8 bytes.
17538static std::optional<ByteProvider<SDValue>>
17539handleMulOperand(const SDValue &MulOperand) {
17540 auto Byte0 = calculateByteProvider(MulOperand, 0, 0);
17541 if (!Byte0 || Byte0->isConstantZero()) {
17542 return std::nullopt;
17543 }
17544 auto Byte1 = calculateByteProvider(MulOperand, 1, 0);
17545 if (Byte1 && !Byte1->isConstantZero()) {
17546 return std::nullopt;
17547 }
17548 return Byte0;
17549}
17550
17551static unsigned addPermMasks(unsigned First, unsigned Second) {
17552 unsigned FirstCs = First & 0x0c0c0c0c;
17553 unsigned SecondCs = Second & 0x0c0c0c0c;
17554 unsigned FirstNoCs = First & ~0x0c0c0c0c;
17555 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17556
17557 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17558 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17559 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17560 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17561
17562 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17563}
17564
17565struct DotSrc {
17567 int64_t PermMask;
17569};
17570
17574 SmallVectorImpl<DotSrc> &Src1s, int Step) {
17575
17576 assert(Src0.Src.has_value() && Src1.Src.has_value());
17577 // Src0s and Src1s are empty, just place arbitrarily.
17578 if (Step == 0) {
17579 Src0s.push_back({*Src0.Src, ((Src0.SrcOffset % 4) << 24) + 0x0c0c0c,
17580 Src0.SrcOffset / 4});
17581 Src1s.push_back({*Src1.Src, ((Src1.SrcOffset % 4) << 24) + 0x0c0c0c,
17582 Src1.SrcOffset / 4});
17583 return;
17584 }
17585
17586 for (int BPI = 0; BPI < 2; BPI++) {
17587 std::pair<ByteProvider<SDValue>, ByteProvider<SDValue>> BPP = {Src0, Src1};
17588 if (BPI == 1) {
17589 BPP = {Src1, Src0};
17590 }
17591 unsigned ZeroMask = 0x0c0c0c0c;
17592 unsigned FMask = 0xFF << (8 * (3 - Step));
17593
17594 unsigned FirstMask =
17595 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17596 unsigned SecondMask =
17597 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17598 // Attempt to find Src vector which contains our SDValue, if so, add our
17599 // perm mask to the existing one. If we are unable to find a match for the
17600 // first SDValue, attempt to find match for the second.
17601 int FirstGroup = -1;
17602 for (int I = 0; I < 2; I++) {
17603 SmallVectorImpl<DotSrc> &Srcs = I == 0 ? Src0s : Src1s;
17604 auto MatchesFirst = [&BPP](DotSrc &IterElt) {
17605 return IterElt.SrcOp == *BPP.first.Src &&
17606 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17607 };
17608
17609 auto *Match = llvm::find_if(Srcs, MatchesFirst);
17610 if (Match != Srcs.end()) {
17611 Match->PermMask = addPermMasks(FirstMask, Match->PermMask);
17612 FirstGroup = I;
17613 break;
17614 }
17615 }
17616 if (FirstGroup != -1) {
17617 SmallVectorImpl<DotSrc> &Srcs = FirstGroup == 1 ? Src0s : Src1s;
17618 auto MatchesSecond = [&BPP](DotSrc &IterElt) {
17619 return IterElt.SrcOp == *BPP.second.Src &&
17620 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17621 };
17622 auto *Match = llvm::find_if(Srcs, MatchesSecond);
17623 if (Match != Srcs.end()) {
17624 Match->PermMask = addPermMasks(SecondMask, Match->PermMask);
17625 } else
17626 Srcs.push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17627 return;
17628 }
17629 }
17630
17631 // If we have made it here, then we could not find a match in Src0s or Src1s
17632 // for either Src0 or Src1, so just place them arbitrarily.
17633
17634 unsigned ZeroMask = 0x0c0c0c0c;
17635 unsigned FMask = 0xFF << (8 * (3 - Step));
17636
17637 Src0s.push_back(
17638 {*Src0.Src,
17639 ((Src0.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17640 Src0.SrcOffset / 4});
17641 Src1s.push_back(
17642 {*Src1.Src,
17643 ((Src1.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17644 Src1.SrcOffset / 4});
17645}
17646
17648 SmallVectorImpl<DotSrc> &Srcs, bool IsSigned,
17649 bool IsAny) {
17650
17651 // If we just have one source, just permute it accordingly.
17652 if (Srcs.size() == 1) {
17653 auto *Elt = Srcs.begin();
17654 auto EltOp = getDWordFromOffset(DAG, SL, Elt->SrcOp, Elt->DWordOffset);
17655
17656 // v_perm will produce the original value
17657 if (Elt->PermMask == 0x3020100)
17658 return EltOp;
17659
17660 return DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17661 DAG.getConstant(Elt->PermMask, SL, MVT::i32));
17662 }
17663
17664 auto *FirstElt = Srcs.begin();
17665 auto *SecondElt = std::next(FirstElt);
17666
17668
17669 // If we have multiple sources in the chain, combine them via perms (using
17670 // calculated perm mask) and Ors.
17671 while (true) {
17672 auto FirstMask = FirstElt->PermMask;
17673 auto SecondMask = SecondElt->PermMask;
17674
17675 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17676 unsigned FirstPlusFour = FirstMask | 0x04040404;
17677 // 0x0c + 0x04 = 0x10, so anding with 0x0F will produced 0x00 for any
17678 // original 0x0C.
17679 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17680
17681 auto PermMask = addPermMasks(FirstMask, SecondMask);
17682 auto FirstVal =
17683 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17684 auto SecondVal =
17685 getDWordFromOffset(DAG, SL, SecondElt->SrcOp, SecondElt->DWordOffset);
17686
17687 Perms.push_back(DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, FirstVal,
17688 SecondVal,
17689 DAG.getConstant(PermMask, SL, MVT::i32)));
17690
17691 FirstElt = std::next(SecondElt);
17692 if (FirstElt == Srcs.end())
17693 break;
17694
17695 SecondElt = std::next(FirstElt);
17696 // If we only have a FirstElt, then just combine that into the cumulative
17697 // source node.
17698 if (SecondElt == Srcs.end()) {
17699 auto EltOp =
17700 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17701
17702 Perms.push_back(
17703 DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17704 DAG.getConstant(FirstElt->PermMask, SL, MVT::i32)));
17705 break;
17706 }
17707 }
17708
17709 assert(Perms.size() == 1 || Perms.size() == 2);
17710 return Perms.size() == 2
17711 ? DAG.getNode(ISD::OR, SL, MVT::i32, Perms[0], Perms[1])
17712 : Perms[0];
17713}
17714
17715static void fixMasks(SmallVectorImpl<DotSrc> &Srcs, unsigned ChainLength) {
17716 for (auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17717 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17718 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17719 EntryMask += ZeroMask;
17720 }
17721}
17722
17723static bool isMul(const SDValue Op) {
17724 auto Opcode = Op.getOpcode();
17725
17726 return (Opcode == ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17727 Opcode == AMDGPUISD::MUL_I24);
17728}
17729
17730static std::optional<bool>
17732 ByteProvider<SDValue> &Src1, const SDValue &S0Op,
17733 const SDValue &S1Op, const SelectionDAG &DAG) {
17734 // If we both ops are i8s (pre legalize-dag), then the signedness semantics
17735 // of the dot4 is irrelevant.
17736 if (S0Op.getValueSizeInBits() == 8 && S1Op.getValueSizeInBits() == 8)
17737 return false;
17738
17739 auto Known0 = DAG.computeKnownBits(S0Op, 0);
17740 bool S0IsUnsigned = Known0.countMinLeadingZeros() > 0;
17741 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17742 auto Known1 = DAG.computeKnownBits(S1Op, 0);
17743 bool S1IsUnsigned = Known1.countMinLeadingZeros() > 0;
17744 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
17745
17746 assert(!(S0IsUnsigned && S0IsSigned));
17747 assert(!(S1IsUnsigned && S1IsSigned));
17748
17749 // There are 9 possible permutations of
17750 // {S0IsUnsigned, S0IsSigned, S1IsUnsigned, S1IsSigned}
17751
17752 // In two permutations, the sign bits are known to be the same for both Ops,
17753 // so simply return Signed / Unsigned corresponding to the MSB
17754
17755 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
17756 return S0IsSigned;
17757
17758 // In another two permutations, the sign bits are known to be opposite. In
17759 // this case return std::nullopt to indicate a bad match.
17760
17761 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
17762 return std::nullopt;
17763
17764 // In the remaining five permutations, we don't know the value of the sign
17765 // bit for at least one Op. Since we have a valid ByteProvider, we know that
17766 // the upper bits must be extension bits. Thus, the only ways for the sign
17767 // bit to be unknown is if it was sign extended from unknown value, or if it
17768 // was any extended. In either case, it is correct to use the signed
17769 // version of the signedness semantics of dot4
17770
17771 // In two of such permutations, we known the sign bit is set for
17772 // one op, and the other is unknown. It is okay to used signed version of
17773 // dot4.
17774 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
17775 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
17776 return true;
17777
17778 // In one such permutation, we don't know either of the sign bits. It is okay
17779 // to used the signed version of dot4.
17780 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
17781 return true;
17782
17783 // In two of such permutations, we known the sign bit is unset for
17784 // one op, and the other is unknown. Return std::nullopt to indicate a
17785 // bad match.
17786 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
17787 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
17788 return std::nullopt;
17789
17790 llvm_unreachable("Fully covered condition");
17791}
17792
17793SDValue SITargetLowering::performAddCombine(SDNode *N,
17794 DAGCombinerInfo &DCI) const {
17795 SelectionDAG &DAG = DCI.DAG;
17796 EVT VT = N->getValueType(0);
17797 SDLoc SL(N);
17798 SDValue LHS = N->getOperand(0);
17799 SDValue RHS = N->getOperand(1);
17800
17801 if (LHS.getOpcode() == ISD::MUL || RHS.getOpcode() == ISD::MUL) {
17802 if (Subtarget->hasMad64_32()) {
17803 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
17804 return Folded;
17805 }
17806 }
17807
17808 if (SDValue V = reassociateScalarOps(N, DAG)) {
17809 return V;
17810 }
17811
17812 if (VT == MVT::i64) {
17813 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
17814 return Folded;
17815 }
17816
17817 // dot4 produces a 32-bit result, so a wider VT can't be folded.
17818 if (!VT.isVector() && VT.getSizeInBits() <= 32 &&
17819 (isMul(LHS) || isMul(RHS)) && Subtarget->hasDot7Insts() &&
17820 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
17821 SDValue TempNode(N, 0);
17822 std::optional<bool> IsSigned;
17826
17827 // Match the v_dot4 tree, while collecting src nodes.
17828 int ChainLength = 0;
17829 for (int I = 0; I < 4; I++) {
17830 auto MulIdx = isMul(LHS) ? 0 : isMul(RHS) ? 1 : -1;
17831 if (MulIdx == -1)
17832 break;
17833 auto Src0 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(0));
17834 if (!Src0)
17835 break;
17836 auto Src1 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(1));
17837 if (!Src1)
17838 break;
17839
17840 auto IterIsSigned = checkDot4MulSignedness(
17841 TempNode->getOperand(MulIdx), *Src0, *Src1,
17842 TempNode->getOperand(MulIdx)->getOperand(0),
17843 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
17844 if (!IterIsSigned)
17845 break;
17846 if (!IsSigned)
17847 IsSigned = *IterIsSigned;
17848 if (*IterIsSigned != *IsSigned)
17849 break;
17850 placeSources(*Src0, *Src1, Src0s, Src1s, I);
17851 auto AddIdx = 1 - MulIdx;
17852 // Allow the special case where add (add (mul24, 0), mul24) became ->
17853 // add (mul24, mul24).
17854 if (I == 2 && isMul(TempNode->getOperand(AddIdx))) {
17855 Src2s.push_back(TempNode->getOperand(AddIdx));
17856 auto Src0 =
17857 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(0));
17858 if (!Src0)
17859 break;
17860 auto Src1 =
17861 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(1));
17862 if (!Src1)
17863 break;
17864 auto IterIsSigned = checkDot4MulSignedness(
17865 TempNode->getOperand(AddIdx), *Src0, *Src1,
17866 TempNode->getOperand(AddIdx)->getOperand(0),
17867 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
17868 if (!IterIsSigned)
17869 break;
17870 assert(IsSigned);
17871 if (*IterIsSigned != *IsSigned)
17872 break;
17873 placeSources(*Src0, *Src1, Src0s, Src1s, I + 1);
17874 Src2s.push_back(DAG.getConstant(0, SL, MVT::i32));
17875 ChainLength = I + 2;
17876 break;
17877 }
17878
17879 TempNode = TempNode->getOperand(AddIdx);
17880 Src2s.push_back(TempNode);
17881 ChainLength = I + 1;
17882 // The loop body treats TempNode's operands as addends.
17883 if (TempNode.getOpcode() != ISD::ADD)
17884 break;
17885 LHS = TempNode->getOperand(0);
17886 RHS = TempNode->getOperand(1);
17887 }
17888
17889 if (ChainLength < 2)
17890 return SDValue();
17891
17892 // Masks were constructed with assumption that we would find a chain of
17893 // length 4. If not, then we need to 0 out the MSB bits (via perm mask of
17894 // 0x0c) so they do not affect dot calculation.
17895 if (ChainLength < 4) {
17896 fixMasks(Src0s, ChainLength);
17897 fixMasks(Src1s, ChainLength);
17898 }
17899
17900 SDValue Src0, Src1;
17901
17902 // If we are just using a single source for both, and have permuted the
17903 // bytes consistently, we can just use the sources without permuting
17904 // (commutation).
17905 bool UseOriginalSrc = false;
17906 if (ChainLength == 4 && Src0s.size() == 1 && Src1s.size() == 1 &&
17907 Src0s.begin()->PermMask == Src1s.begin()->PermMask &&
17908 Src0s.begin()->SrcOp.getValueSizeInBits() >= 32 &&
17909 Src1s.begin()->SrcOp.getValueSizeInBits() >= 32) {
17910 SmallVector<unsigned, 4> SrcBytes;
17911 auto Src0Mask = Src0s.begin()->PermMask;
17912 SrcBytes.push_back(Src0Mask & 0xFF000000);
17913 bool UniqueEntries = true;
17914 for (auto I = 1; I < 4; I++) {
17915 auto NextByte = Src0Mask & (0xFF << ((3 - I) * 8));
17916
17917 if (is_contained(SrcBytes, NextByte)) {
17918 UniqueEntries = false;
17919 break;
17920 }
17921 SrcBytes.push_back(NextByte);
17922 }
17923
17924 if (UniqueEntries) {
17925 UseOriginalSrc = true;
17926
17927 auto *FirstElt = Src0s.begin();
17928 auto FirstEltOp =
17929 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17930
17931 auto *SecondElt = Src1s.begin();
17932 auto SecondEltOp = getDWordFromOffset(DAG, SL, SecondElt->SrcOp,
17933 SecondElt->DWordOffset);
17934
17935 Src0 = DAG.getBitcastedAnyExtOrTrunc(FirstEltOp, SL,
17936 MVT::getIntegerVT(32));
17937 Src1 = DAG.getBitcastedAnyExtOrTrunc(SecondEltOp, SL,
17938 MVT::getIntegerVT(32));
17939 }
17940 }
17941
17942 if (!UseOriginalSrc) {
17943 Src0 = resolveSources(DAG, SL, Src0s, false, true);
17944 Src1 = resolveSources(DAG, SL, Src1s, false, true);
17945 }
17946
17947 assert(IsSigned);
17948 SDValue Src2 =
17949 DAG.getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
17950
17951 SDValue IID = DAG.getTargetConstant(*IsSigned ? Intrinsic::amdgcn_sdot4
17952 : Intrinsic::amdgcn_udot4,
17953 SL, MVT::i64);
17954
17955 assert(!VT.isVector());
17956 auto Dot = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32, IID, Src0,
17957 Src1, Src2, DAG.getTargetConstant(0, SL, MVT::i1));
17958
17959 return DAG.getExtOrTrunc(*IsSigned, Dot, SL, VT);
17960 }
17961
17962 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
17963 return SDValue();
17964
17965 // add x, zext (setcc) => uaddo_carry x, 0, setcc
17966 // add x, sext (setcc) => usubo_carry x, 0, setcc
17967 unsigned Opc = LHS.getOpcode();
17970 std::swap(RHS, LHS);
17971
17972 Opc = RHS.getOpcode();
17973 switch (Opc) {
17974 default:
17975 break;
17976 case ISD::ZERO_EXTEND:
17977 case ISD::SIGN_EXTEND:
17978 case ISD::ANY_EXTEND: {
17979 auto Cond = RHS.getOperand(0);
17980 // If this won't be a real VOPC output, we would still need to insert an
17981 // extra instruction anyway.
17982 if (!isBoolSGPR(Cond))
17983 break;
17984 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
17985 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
17987 return DAG.getNode(Opc, SL, VTList, Args);
17988 }
17989 case ISD::UADDO_CARRY: {
17990 // add x, (uaddo_carry y, 0, cc) => uaddo_carry x, y, cc
17991 if (!isNullConstant(RHS.getOperand(1)))
17992 break;
17993 SDValue Args[] = {LHS, RHS.getOperand(0), RHS.getOperand(2)};
17994 return DAG.getNode(ISD::UADDO_CARRY, SDLoc(N), RHS->getVTList(), Args);
17995 }
17996 }
17997 return SDValue();
17998}
17999
18000SDValue SITargetLowering::performPtrAddCombine(SDNode *N,
18001 DAGCombinerInfo &DCI) const {
18002 SelectionDAG &DAG = DCI.DAG;
18003 SDLoc DL(N);
18004 EVT VT = N->getValueType(0);
18005 SDValue N0 = N->getOperand(0);
18006 SDValue N1 = N->getOperand(1);
18007
18008 // The following folds transform PTRADDs into regular arithmetic in cases
18009 // where the PTRADD wouldn't be folded as an immediate offset into memory
18010 // instructions anyway. They are target-specific in that other targets might
18011 // prefer to not lose information about the pointer arithmetic.
18012
18013 // Fold (ptradd x, shl(0 - v, k)) -> sub(x, shl(v, k)).
18014 // Adapted from DAGCombiner::visitADDLikeCommutative.
18015 SDValue V, K;
18016 if (sd_match(N1, m_Shl(m_Neg(m_Value(V)), m_Value(K)))) {
18017 SDNodeFlags ShlFlags = N1->getFlags();
18018 // If the original shl is NUW and NSW, the first k+1 bits of 0-v are all 0,
18019 // so v is either 0 or the first k+1 bits of v are all 1 -> NSW can be
18020 // preserved.
18021 SDNodeFlags NewShlFlags =
18022 ShlFlags.hasNoUnsignedWrap() && ShlFlags.hasNoSignedWrap()
18024 : SDNodeFlags();
18025 SDValue Inner = DAG.getNode(ISD::SHL, DL, VT, V, K, NewShlFlags);
18026 DCI.AddToWorklist(Inner.getNode());
18027 return DAG.getNode(ISD::SUB, DL, VT, N0, Inner);
18028 }
18029
18030 // Fold into Mad64 if the right-hand side is a MUL. Analogous to a fold in
18031 // performAddCombine.
18032 if (N1.getOpcode() == ISD::MUL) {
18033 if (Subtarget->hasMad64_32()) {
18034 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
18035 return Folded;
18036 }
18037 }
18038
18039 // If the 32 low bits of the constant are all zero, there is nothing to fold
18040 // into an immediate offset, so it's better to eliminate the unnecessary
18041 // addition for the lower 32 bits than to preserve the PTRADD.
18042 // Analogous to a fold in performAddCombine.
18043 if (VT == MVT::i64) {
18044 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18045 return Folded;
18046 }
18047
18048 if (N1.getOpcode() != ISD::ADD || !N1.hasOneUse())
18049 return SDValue();
18050
18051 SDValue X = N0;
18052 SDValue Y = N1.getOperand(0);
18053 SDValue Z = N1.getOperand(1);
18054 bool YIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Y);
18055 bool ZIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Z);
18056
18057 if (!YIsConstant && !ZIsConstant && !X->isDivergent() &&
18058 Y->isDivergent() != Z->isDivergent()) {
18059 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, y), z) if x and
18060 // y are uniform and z isn't.
18061 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, z), y) if x and
18062 // z are uniform and y isn't.
18063 // The goal is to push uniform operands up in the computation, so that they
18064 // can be handled with scalar operations. We can't use reassociateScalarOps
18065 // for this since it requires two identical commutative operations to
18066 // reassociate.
18067 if (Y->isDivergent())
18068 std::swap(Y, Z);
18069 // If both additions in the original were NUW, reassociation preserves that.
18070 SDNodeFlags ReassocFlags =
18071 (N->getFlags() & N1->getFlags()) & SDNodeFlags::NoUnsignedWrap;
18072 SDValue UniformInner = DAG.getMemBasePlusOffset(X, Y, DL, ReassocFlags);
18073 DCI.AddToWorklist(UniformInner.getNode());
18074 return DAG.getMemBasePlusOffset(UniformInner, Z, DL, ReassocFlags);
18075 }
18076
18077 return SDValue();
18078}
18079
18080static bool isCtlzOpc(unsigned Opc) {
18081 return Opc == ISD::CTLZ || Opc == ISD::CTLZ_ZERO_POISON;
18082}
18083
18084SDValue SITargetLowering::performSubCombine(SDNode *N,
18085 DAGCombinerInfo &DCI) const {
18086 SelectionDAG &DAG = DCI.DAG;
18087 EVT VT = N->getValueType(0);
18088
18089 if (VT == MVT::i64) {
18090 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18091 return Folded;
18092 }
18093
18094 if (VT != MVT::i32)
18095 return SDValue();
18096
18097 SDLoc SL(N);
18098 SDValue LHS = N->getOperand(0);
18099 SDValue RHS = N->getOperand(1);
18100
18101 // sub x, zext (setcc) => usubo_carry x, 0, setcc
18102 // sub x, sext (setcc) => uaddo_carry x, 0, setcc
18103 unsigned Opc = RHS.getOpcode();
18104 switch (Opc) {
18105 default:
18106 break;
18107 case ISD::ZERO_EXTEND:
18108 case ISD::SIGN_EXTEND:
18109 case ISD::ANY_EXTEND: {
18110 auto Cond = RHS.getOperand(0);
18111 // If this won't be a real VOPC output, we would still need to insert an
18112 // extra instruction anyway.
18113 if (!isBoolSGPR(Cond))
18114 break;
18115 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
18116 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
18118 return DAG.getNode(Opc, SL, VTList, Args);
18119 }
18120 }
18121
18122 if (LHS.getOpcode() == ISD::USUBO_CARRY) {
18123 // sub (usubo_carry x, 0, cc), y => usubo_carry x, y, cc
18124 if (!isNullConstant(LHS.getOperand(1)))
18125 return SDValue();
18126 SDValue Args[] = {LHS.getOperand(0), RHS, LHS.getOperand(2)};
18127 return DAG.getNode(ISD::USUBO_CARRY, SDLoc(N), LHS->getVTList(), Args);
18128 }
18129
18130 // sub (ctlz (xor x, (sra x, 31))), 1 -> ctls x.
18131 if (isOneConstant(RHS) && isCtlzOpc(LHS.getOpcode())) {
18132 SDValue CtlzSrc = LHS.getOperand(0);
18133 // Check for xor x, (sra x, 31) pattern.
18134 if (CtlzSrc.getOpcode() == ISD::XOR) {
18135 SDValue X = CtlzSrc.getOperand(0);
18136 SDValue SignExt = CtlzSrc.getOperand(1);
18137 // Try both ordering of XOR operands.
18138 if (SignExt.getOpcode() != ISD::SRA)
18139 std::swap(X, SignExt);
18140 if (SignExt.getOpcode() == ISD::SRA && SignExt.getOperand(0) == X) {
18141 ConstantSDNode *ShiftAmt =
18143 unsigned BitWidth = X.getValueType().getScalarSizeInBits();
18144 if (ShiftAmt && ShiftAmt->getZExtValue() == BitWidth - 1)
18145 return DAG.getNode(ISD::CTLS, SL, VT, X);
18146 }
18147 }
18148 }
18149
18150 return SDValue();
18151}
18152
18153SDValue SITargetLowering::performFAddCombine(SDNode *N,
18154 DAGCombinerInfo &DCI) const {
18155 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18156 return SDValue();
18157
18158 SelectionDAG &DAG = DCI.DAG;
18159 EVT VT = N->getValueType(0);
18160
18161 SDLoc SL(N);
18162 SDValue LHS = N->getOperand(0);
18163 SDValue RHS = N->getOperand(1);
18164
18165 // These should really be instruction patterns, but writing patterns with
18166 // source modifiers is a pain.
18167
18168 // fadd (fadd (a, a), b) -> mad 2.0, a, b
18169 if (LHS.getOpcode() == ISD::FADD) {
18170 SDValue A = LHS.getOperand(0);
18171 if (A == LHS.getOperand(1)) {
18172 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18173 if (FusedOp != 0) {
18174 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18175 return DAG.getNode(FusedOp, SL, VT, A, Two, RHS);
18176 }
18177 }
18178 }
18179
18180 // fadd (b, fadd (a, a)) -> mad 2.0, a, b
18181 if (RHS.getOpcode() == ISD::FADD) {
18182 SDValue A = RHS.getOperand(0);
18183 if (A == RHS.getOperand(1)) {
18184 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18185 if (FusedOp != 0) {
18186 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18187 return DAG.getNode(FusedOp, SL, VT, A, Two, LHS);
18188 }
18189 }
18190 }
18191
18192 return SDValue();
18193}
18194
18195SDValue SITargetLowering::performFSubCombine(SDNode *N,
18196 DAGCombinerInfo &DCI) const {
18197 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18198 return SDValue();
18199
18200 SelectionDAG &DAG = DCI.DAG;
18201 SDLoc SL(N);
18202 EVT VT = N->getValueType(0);
18203 assert(!VT.isVector());
18204
18205 // Try to get the fneg to fold into the source modifier. This undoes generic
18206 // DAG combines and folds them into the mad.
18207 //
18208 // Only do this if we are not trying to support denormals. v_mad_f32 does
18209 // not support denormals ever.
18210 SDValue LHS = N->getOperand(0);
18211 SDValue RHS = N->getOperand(1);
18212 if (LHS.getOpcode() == ISD::FADD) {
18213 // (fsub (fadd a, a), c) -> mad 2.0, a, (fneg c)
18214 SDValue A = LHS.getOperand(0);
18215 if (A == LHS.getOperand(1)) {
18216 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18217 if (FusedOp != 0) {
18218 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18219 SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
18220
18221 return DAG.getNode(FusedOp, SL, VT, A, Two, NegRHS);
18222 }
18223 }
18224 }
18225
18226 if (RHS.getOpcode() == ISD::FADD) {
18227 // (fsub c, (fadd a, a)) -> mad -2.0, a, c
18228
18229 SDValue A = RHS.getOperand(0);
18230 if (A == RHS.getOperand(1)) {
18231 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18232 if (FusedOp != 0) {
18233 const SDValue NegTwo = DAG.getConstantFP(-2.0, SL, VT);
18234 return DAG.getNode(FusedOp, SL, VT, A, NegTwo, LHS);
18235 }
18236 }
18237 }
18238
18239 return SDValue();
18240}
18241
18242SDValue SITargetLowering::performFDivCombine(SDNode *N,
18243 DAGCombinerInfo &DCI) const {
18244 SelectionDAG &DAG = DCI.DAG;
18245 SDLoc SL(N);
18246 EVT VT = N->getValueType(0);
18247
18248 if (VT != MVT::f16 && VT != MVT::bf16)
18249 return SDValue();
18250
18251 SDValue LHS = N->getOperand(0);
18252 SDValue RHS = N->getOperand(1);
18253
18254 SDNodeFlags Flags = N->getFlags();
18255 SDNodeFlags RHSFlags = RHS->getFlags();
18256 if (!Flags.hasAllowContract() || !RHSFlags.hasAllowContract() ||
18257 !RHS->hasOneUse())
18258 return SDValue();
18259
18260 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
18261 bool IsNegative = false;
18262 if (CLHS->isOne() || (IsNegative = CLHS->isMinusOne())) {
18263 // fdiv contract 1.0, (sqrt contract x) -> rsq
18264 // fdiv contract -1.0, (sqrt contract x) -> fneg(rsq)
18265 if (RHS.getOpcode() == ISD::FSQRT) {
18266 // TODO: Or in RHS flags, somehow missing from SDNodeFlags
18267 SDValue SqrtOp = RHS.getOperand(0);
18268 SDValue Rsq;
18269 if (isOperationLegal(ISD::FSQRT, VT)) {
18270 // fsqrt legality correlates to rsq availability of the same type.
18271 Rsq = DAG.getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18272 } else if (VT == MVT::f16) {
18273 // Targets without 16-bit instructions (gfx6/gfx7) have no f16 rsq,
18274 // but v_rsq_f32 is more than accurate enough for f16. Unlike bf16,
18275 // every f16 value (including denormals) extends to a normal f32, and
18276 // an f16 rsq result is never denormal, so the f32 reciprocal square
18277 // root needs no denormal handling. Compute it in f32 and round back.
18278 SDValue Ext =
18279 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, SqrtOp, Flags);
18280 SDValue F32Rsq =
18281 DAG.getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18282 Rsq = DAG.getNode(ISD::FP_ROUND, SL, VT, F32Rsq,
18283 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
18284 } else {
18285 // bf16 shares f32's exponent range, so bf16 denormals would extend to
18286 // f32 denormals that v_rsq_f32 does not handle. Leave it expanded.
18287 return SDValue();
18288 }
18289 return IsNegative ? DAG.getNode(ISD::FNEG, SL, VT, Rsq, Flags) : Rsq;
18290 }
18291 }
18292 }
18293
18294 return SDValue();
18295}
18296
18297SDValue SITargetLowering::performFMulCombine(SDNode *N,
18298 DAGCombinerInfo &DCI) const {
18299 SelectionDAG &DAG = DCI.DAG;
18300 EVT VT = N->getValueType(0);
18301 EVT ScalarVT = VT.getScalarType();
18302 EVT IntVT = VT.changeElementType(*DAG.getContext(), MVT::i32);
18303
18304 if (!N->isDivergent() && getSubtarget()->hasSALUFloatInsts() &&
18305 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18306 // Prefer to use s_mul_f16/f32 instead of v_ldexp_f16/f32.
18307 return SDValue();
18308 }
18309
18310 SDValue LHS = N->getOperand(0);
18311 SDValue RHS = N->getOperand(1);
18312
18313 // It is cheaper to realize i32 inline constants as compared against
18314 // materializing f16 or f64 (or even non-inline f32) values,
18315 // possible via ldexp usage, as shown below :
18316 //
18317 // Given : A = 2^a & B = 2^b ; where a and b are integers.
18318 // fmul x, (select y, A, B) -> ldexp( x, (select i32 y, a, b) )
18319 // fmul x, (select y, -A, -B) -> ldexp( (fneg x), (select i32 y, a, b) )
18320 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18321 (RHS.hasOneUse() && RHS.getOpcode() == ISD::SELECT)) {
18322 const ConstantFPSDNode *TrueNode = isConstOrConstSplatFP(RHS.getOperand(1));
18323 if (!TrueNode)
18324 return SDValue();
18325 const ConstantFPSDNode *FalseNode =
18326 isConstOrConstSplatFP(RHS.getOperand(2));
18327 if (!FalseNode)
18328 return SDValue();
18329
18330 if (TrueNode->isNegative() != FalseNode->isNegative())
18331 return SDValue();
18332
18333 // For f32, only non-inline constants should be transformed.
18334 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
18335 if (ScalarVT == MVT::f32 &&
18336 TII->isInlineConstant(TrueNode->getValueAPF()) &&
18337 TII->isInlineConstant(FalseNode->getValueAPF()))
18338 return SDValue();
18339
18340 int TrueNodeExpVal = TrueNode->getValueAPF().getExactLog2Abs();
18341 if (TrueNodeExpVal == INT_MIN)
18342 return SDValue();
18343 int FalseNodeExpVal = FalseNode->getValueAPF().getExactLog2Abs();
18344 if (FalseNodeExpVal == INT_MIN)
18345 return SDValue();
18346
18347 SDLoc SL(N);
18348 SDValue SelectNode =
18349 DAG.getNode(ISD::SELECT, SL, IntVT, RHS.getOperand(0),
18350 DAG.getSignedConstant(TrueNodeExpVal, SL, IntVT),
18351 DAG.getSignedConstant(FalseNodeExpVal, SL, IntVT));
18352
18353 LHS = TrueNode->isNegative()
18354 ? DAG.getNode(ISD::FNEG, SL, VT, LHS, LHS->getFlags())
18355 : LHS;
18356
18357 return DAG.getNode(ISD::FLDEXP, SL, VT, LHS, SelectNode, N->getFlags());
18358 }
18359
18360 return SDValue();
18361}
18362
18363SDValue SITargetLowering::performFMACombine(SDNode *N,
18364 DAGCombinerInfo &DCI) const {
18365 SelectionDAG &DAG = DCI.DAG;
18366 EVT VT = N->getValueType(0);
18367 SDLoc SL(N);
18368
18369 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18370 return SDValue();
18371
18372 // FMA((F32)S0.x, (F32)S1. x, FMA((F32)S0.y, (F32)S1.y, (F32)z)) ->
18373 // FDOT2((V2F16)S0, (V2F16)S1, (F32)z))
18374 SDValue Op1 = N->getOperand(0);
18375 SDValue Op2 = N->getOperand(1);
18376 SDValue FMA = N->getOperand(2);
18377
18378 if (FMA.getOpcode() != ISD::FMA || Op1.getOpcode() != ISD::FP_EXTEND ||
18379 Op2.getOpcode() != ISD::FP_EXTEND)
18380 return SDValue();
18381
18382 // The fdot2 fold (fma_mix -> dot2) is only safe when both instructions agree
18383 // on how f16 subnormal inputs are handled. However, if both FMAs carry afn
18384 // the caller accepts approximate results, so any subnormal flushing
18385 // introduced by dot2 is acceptable regardless of mode.
18386 //
18387 // gfx90a (CDNA2) is the sole exception (dot2UnconditionalFlush): v_dot2c
18388 // unconditionally flushes f16 subnormal inputs to zero regardless of MODE,
18389 // while v_fma_mix_f32 preserves them when ieee=1 (the default compute kernel
18390 // mode). The fold is safe only when f32 denorm = PreserveSign, which implies
18391 // ieee=0 so both flush.
18392 //
18393 // All other GPUs: v_dot2 does NOT flush f16 subnormal inputs. v_fma_mix_f32
18394 // flushes them only when f32 denorm = PreserveSign. The fold is safe only
18395 // when f32 denorm is IEEE (both preserve the subnormal). Dynamic mode is
18396 // also rejected since the runtime value is unknown.
18397 bool AllowInaccuracy = N->getFlags().hasApproximateFuncs() &&
18398 FMA->getFlags().hasApproximateFuncs();
18399 if (!AllowInaccuracy) {
18400 const MachineFunction &MF = DAG.getMachineFunction();
18401 DenormalMode Mode = MF.getDenormalMode(APFloat::IEEEsingle());
18402 if (Subtarget->dot2UnconditionalFlush()) {
18403 // gfx90a: fold safe only when f32 denorm flushes.
18405 return SDValue();
18406 } else {
18407 // All other GPUs: fold safe only when f32 denorm is IEEE.
18408 if (Mode != DenormalMode::getIEEE())
18409 return SDValue();
18410 }
18411 }
18412
18413 // fp-contract allows reassociating the fma tree into a dot product.
18414 if (N->getFlags().hasAllowContract() && FMA->getFlags().hasAllowContract()) {
18415 Op1 = Op1.getOperand(0);
18416 Op2 = Op2.getOperand(0);
18417 if (Op1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18419 return SDValue();
18420
18421 SDValue Vec1 = Op1.getOperand(0);
18422 SDValue Idx1 = Op1.getOperand(1);
18423 SDValue Vec2 = Op2.getOperand(0);
18424
18425 SDValue FMAOp1 = FMA.getOperand(0);
18426 SDValue FMAOp2 = FMA.getOperand(1);
18427 SDValue FMAAcc = FMA.getOperand(2);
18428
18429 if (FMAOp1.getOpcode() != ISD::FP_EXTEND ||
18430 FMAOp2.getOpcode() != ISD::FP_EXTEND)
18431 return SDValue();
18432
18433 FMAOp1 = FMAOp1.getOperand(0);
18434 FMAOp2 = FMAOp2.getOperand(0);
18435 if (FMAOp1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18437 return SDValue();
18438
18439 SDValue Vec3 = FMAOp1.getOperand(0);
18440 SDValue Vec4 = FMAOp2.getOperand(0);
18441 SDValue Idx2 = FMAOp1.getOperand(1);
18442
18443 if (Idx1 != Op2.getOperand(1) || Idx2 != FMAOp2.getOperand(1))
18444 return SDValue();
18445
18446 if (!isa<ConstantSDNode>(Idx1) || !isa<ConstantSDNode>(Idx2) ||
18447 Idx1 == Idx2)
18448 return SDValue();
18449
18450 if (Vec1 == Vec2 || Vec3 == Vec4)
18451 return SDValue();
18452
18453 if (Vec1.getValueType() != MVT::v2f16 || Vec2.getValueType() != MVT::v2f16)
18454 return SDValue();
18455
18456 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18457 return DAG.getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18458 DAG.getTargetConstant(0, SL, MVT::i1));
18459 }
18460 }
18461 return SDValue();
18462}
18463
18464// Given a double-precision ordered or unordered comparison, return the
18465// condition code for an equivalent integral comparison of the operands' upper
18466// 32 bits, or `SETCC_INVALID` if not possible.
18467// For simplicity, no simplification occurs if the operands are not both known
18468// to have sign bit zero.
18469//
18470// EQ/NE:
18471// If LHS.lo32 == RHS.lo32:
18472// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18473// If LHS.lo32 != RHS.lo32:
18474// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18475// The reduction is not possible if operands may be +0 and -0.
18476// For ordered eq / unordered ne, at most one operand may be NaN.
18477// For unordered eq / ordered ne, neither operand can be NaN.
18478//
18479// LT/GE:
18480// If LHS.lo32 >= RHS.lo32 (unsigned):
18481// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18482// If LHS.lo32 < RHS.lo32 (unsigned):
18483// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18484// The reduction is only supported if both operands are nonnegative.
18485// For ordered lt / unordered ge, the RHS cannot be NaN.
18486// For unordered lt / ordered ge, neither operand can be NaN.
18487//
18488// LE/GT:
18489// If LHS.lo32 > RHS.lo32 (unsigned):
18490// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18491// If LHS.lo32 <= RHS.lo32 (unsigned):
18492// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18493// The reduction is only supported if both operands are nonnegative.
18494// For unordered le / ordered gt, the LHS cannot be NaN.
18495// For ordered le / unordered gt, neither operand can be NaN.
18497 const SDValue LHS,
18498 const SDValue RHS,
18499 const SelectionDAG &DAG) {
18500 EVT VT = LHS.getValueType();
18501 assert(VT == MVT::f64 && "Incorrect operand type!");
18502
18503 const KnownBits RHSBits = DAG.computeKnownBits(RHS);
18504 // Bail if RHS sign bit is not known to be zero.
18505 if (!RHSBits.Zero.isSignBitSet())
18506 return ISD::SETCC_INVALID;
18507
18508 const KnownBits RHSKnownLo32 = RHSBits.trunc(32);
18509 const KnownFPClass RHSFPClass =
18511 const bool RHSMaybeNaN = !RHSFPClass.isKnownNeverNaN();
18512
18513 const KnownBits LHSBits = DAG.computeKnownBits(LHS);
18514 const KnownBits LHSKnownLo32 = LHSBits.trunc(32);
18515 const KnownFPClass LHSFPClass =
18517 const bool LHSMaybeNaN = !LHSFPClass.isKnownNeverNaN();
18518
18519 // Bail if LHS sign bit is not known to be zero.
18520 if (!LHSBits.Zero.isSignBitSet())
18521 return ISD::SETCC_INVALID;
18522
18523 switch (CC) {
18524 default:
18525 break;
18526 case ISD::SETEQ:
18527 case ISD::SETOEQ:
18528 case ISD::SETUEQ:
18529 case ISD::SETONE:
18530 case ISD::SETUNE: {
18531 // OEQ should be false if either operand is NaN, so it suffices that at
18532 // least one operand is not NaN.
18533 if (CC == ISD::SETOEQ && LHSMaybeNaN && RHSMaybeNaN)
18534 break;
18535 // UEQ should be true if either operand is NaN, but this cannot be checked
18536 // on underlying bits.
18537 if (CC == ISD::SETUEQ && (LHSMaybeNaN || RHSMaybeNaN))
18538 break;
18539 // ONE should be false if either operand is NaN, but this cannot be
18540 // checked on underlying bits.
18541 if (CC == ISD::SETONE && (LHSMaybeNaN || RHSMaybeNaN))
18542 break;
18543 // UNE should be true if either operand is NaN, so it suffices that they
18544 // are not both NaN.
18545 if (CC == ISD::SETUNE && LHSMaybeNaN && RHSMaybeNaN)
18546 break;
18547
18548 const std::optional<bool> KnownEq =
18549 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18550
18551 if (!KnownEq)
18552 break;
18553
18554 if (*KnownEq)
18555 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18556 ? ISD::SETEQ
18557 : ISD::SETNE;
18558
18559 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18561 : ISD::SETTRUE;
18562 }
18563 case ISD::SETLT:
18564 case ISD::SETOLT:
18565 case ISD::SETULT:
18566 case ISD::SETGE:
18567 case ISD::SETOGE:
18568 case ISD::SETUGE: {
18569 // OLT should be false if either operand is NaN.
18570 // Since NaNs have maximum exponent and nonzero mantissa, false positives
18571 // are only possible if the RHS is NaN. (No issue with RHS == +inf since
18572 // the inequality is strict)
18573 if (CC == ISD::SETOLT && RHSMaybeNaN)
18574 break;
18575 // ULT should be true if either operand is NaN, but this cannot be ensured
18576 // with a truncated comparison.
18577 if (CC == ISD::SETULT && (LHSMaybeNaN || RHSMaybeNaN))
18578 break;
18579 // OGE should be false if either operand is NaN, but this cannot be
18580 // ensured with a truncated comparison.
18581 if (CC == ISD::SETOGE && (LHSMaybeNaN || RHSMaybeNaN))
18582 break;
18583 // UGE should be true if either operand is NaN.
18584 // False negatives are only possible if the RHS is NaN.
18585 // (No issue with RHS == +inf since the inequality is inclusive)
18586 if (CC == ISD::SETUGE && RHSMaybeNaN)
18587 break;
18588
18589 const std::optional<bool> KnownUge =
18590 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
18591
18592 if (!KnownUge)
18593 break;
18594
18595 if (*KnownUge) {
18596 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
18597 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18598 ? ISD::SETLT
18599 : ISD::SETGE;
18600 }
18601 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
18602 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18603 ? ISD::SETLE
18604 : ISD::SETGT;
18605 }
18606 case ISD::SETLE:
18607 case ISD::SETOLE:
18608 case ISD::SETULE:
18609 case ISD::SETGT:
18610 case ISD::SETOGT:
18611 case ISD::SETUGT: {
18612 // OLE should be false if either operand is NaN, but this cannot be
18613 // ensured with a truncated comparison.
18614 if (CC == ISD::SETOLE && (LHSMaybeNaN || RHSMaybeNaN))
18615 break;
18616 // ULE should be true if either operand is NaN.
18617 // False negatives are only possible if the LHS is NaN.
18618 // (No issue with LHS == +inf since the inequality is inclusive)
18619 if (CC == ISD::SETULE && LHSMaybeNaN)
18620 break;
18621 // OGT should be false if either operand is NaN.
18622 // False positives are only possible if the LHS is NaN.
18623 // (No issue with LHS == +inf since the inequality is strict)
18624 if (CC == ISD::SETOGT && LHSMaybeNaN)
18625 break;
18626 // UGT should be true if either operand is NaN, but this cannot be ensured
18627 // with a truncated comparison.
18628 if (CC == ISD::SETUGT && (LHSMaybeNaN || RHSMaybeNaN))
18629 break;
18630
18631 const std::optional<bool> KnownUle =
18632 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
18633
18634 if (!KnownUle)
18635 break;
18636
18637 if (*KnownUle) {
18638 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
18639 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18640 ? ISD::SETLE
18641 : ISD::SETGT;
18642 }
18643 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
18644 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18645 ? ISD::SETLT
18646 : ISD::SETGE;
18647 }
18648 }
18649
18650 return ISD::SETCC_INVALID;
18651}
18652
18653SDValue SITargetLowering::performSetCCCombine(SDNode *N,
18654 DAGCombinerInfo &DCI) const {
18655 SelectionDAG &DAG = DCI.DAG;
18656 SDLoc SL(N);
18657
18658 SDValue LHS = N->getOperand(0);
18659 SDValue RHS = N->getOperand(1);
18660 EVT VT = LHS.getValueType();
18661 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
18662
18663 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
18664 if (!CRHS) {
18666 if (CRHS) {
18667 std::swap(LHS, RHS);
18668 CC = getSetCCSwappedOperands(CC);
18669 }
18670 }
18671
18672 if (CRHS) {
18673 if (VT == MVT::i32 && LHS.getOpcode() == ISD::SIGN_EXTEND &&
18674 isBoolSGPR(LHS.getOperand(0))) {
18675 // setcc (sext from i1 cc), -1, ne|sgt|ult) => not cc => xor cc, -1
18676 // setcc (sext from i1 cc), -1, eq|sle|uge) => cc
18677 // setcc (sext from i1 cc), 0, eq|sge|ule) => not cc => xor cc, -1
18678 // setcc (sext from i1 cc), 0, ne|ugt|slt) => cc
18679 if ((CRHS->isAllOnes() &&
18680 (CC == ISD::SETNE || CC == ISD::SETGT || CC == ISD::SETULT)) ||
18681 (CRHS->isZero() &&
18682 (CC == ISD::SETEQ || CC == ISD::SETGE || CC == ISD::SETULE)))
18683 return DAG.getNode(ISD::XOR, SL, MVT::i1, LHS.getOperand(0),
18684 DAG.getAllOnesConstant(SL, MVT::i1));
18685 if ((CRHS->isAllOnes() &&
18686 (CC == ISD::SETEQ || CC == ISD::SETLE || CC == ISD::SETUGE)) ||
18687 (CRHS->isZero() &&
18688 (CC == ISD::SETNE || CC == ISD::SETUGT || CC == ISD::SETLT)))
18689 return LHS.getOperand(0);
18690 }
18691
18692 const APInt &CRHSVal = CRHS->getAPIntValue();
18693 if ((CC == ISD::SETEQ || CC == ISD::SETNE) &&
18694 LHS.getOpcode() == ISD::SELECT &&
18695 isa<ConstantSDNode>(LHS.getOperand(1)) &&
18696 isa<ConstantSDNode>(LHS.getOperand(2)) &&
18697 isBoolSGPR(LHS.getOperand(0))) {
18698 // Given CT != FT:
18699 // setcc (select cc, CT, CF), CF, eq => xor cc, -1
18700 // setcc (select cc, CT, CF), CF, ne => cc
18701 // setcc (select cc, CT, CF), CT, ne => xor cc, -1
18702 // setcc (select cc, CT, CF), CT, eq => cc
18703 const APInt &CT = LHS.getConstantOperandAPInt(1);
18704 const APInt &CF = LHS.getConstantOperandAPInt(2);
18705
18706 if (CT != CF) {
18707 if ((CF == CRHSVal && CC == ISD::SETEQ) ||
18708 (CT == CRHSVal && CC == ISD::SETNE))
18709 return DAG.getNOT(SL, LHS.getOperand(0), MVT::i1);
18710 if ((CF == CRHSVal && CC == ISD::SETNE) ||
18711 (CT == CRHSVal && CC == ISD::SETEQ))
18712 return LHS.getOperand(0);
18713 }
18714 }
18715 }
18716
18717 // Truncate 64-bit setcc to test only upper 32-bits of its operands in the
18718 // following cases where information about the lower 32-bits of its operands
18719 // is known:
18720 //
18721 // If LHS.lo32 == RHS.lo32:
18722 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18723 // If LHS.lo32 != RHS.lo32:
18724 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18725 // If LHS.lo32 >= RHS.lo32 (unsigned):
18726 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18727 // If LHS.lo32 > RHS.lo32 (unsigned):
18728 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18729 // If LHS.lo32 <= RHS.lo32 (unsigned):
18730 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18731 // If LHS.lo32 < RHS.lo32 (unsigned):
18732 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18733 if (VT == MVT::i64) {
18734 const KnownBits LHSKnownLo32 = DAG.computeKnownBits(LHS).trunc(32);
18735 const KnownBits RHSKnownLo32 = DAG.computeKnownBits(RHS).trunc(32);
18736
18737 // NewCC is valid iff we can truncate the setcc to only test the upper 32
18738 // bits
18740
18741 switch (CC) {
18742 default:
18743 break;
18744 case ISD::SETEQ: {
18745 const std::optional<bool> KnownEq =
18746 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18747 if (KnownEq)
18748 NewCC = *KnownEq ? ISD::SETEQ : ISD::SETFALSE;
18749
18750 break;
18751 }
18752 case ISD::SETNE: {
18753 const std::optional<bool> KnownEq =
18754 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18755 if (KnownEq)
18756 NewCC = *KnownEq ? ISD::SETNE : ISD::SETTRUE;
18757
18758 break;
18759 }
18760 case ISD::SETULT:
18761 case ISD::SETUGE:
18762 case ISD::SETLT:
18763 case ISD::SETGE: {
18764 const std::optional<bool> KnownUge =
18765 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
18766 if (KnownUge) {
18767 if (*KnownUge) {
18768 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
18769 NewCC = CC;
18770 } else {
18771 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
18772 NewCC = CC == ISD::SETULT ? ISD::SETULE
18773 : CC == ISD::SETUGE ? ISD::SETUGT
18774 : CC == ISD::SETLT ? ISD::SETLE
18775 : ISD::SETGT;
18776 }
18777 }
18778 break;
18779 }
18780 case ISD::SETULE:
18781 case ISD::SETUGT:
18782 case ISD::SETLE:
18783 case ISD::SETGT: {
18784 const std::optional<bool> KnownUle =
18785 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
18786 if (KnownUle) {
18787 if (*KnownUle) {
18788 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
18789 NewCC = CC;
18790 } else {
18791 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
18792 NewCC = CC == ISD::SETULE ? ISD::SETULT
18793 : CC == ISD::SETUGT ? ISD::SETUGE
18794 : CC == ISD::SETLE ? ISD::SETLT
18795 : ISD::SETGE;
18796 }
18797 }
18798 break;
18799 }
18800 }
18801
18802 if (NewCC != ISD::SETCC_INVALID)
18803 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
18804 getHiHalf64(RHS, DAG), NewCC);
18805 }
18806
18807 // Eliminate setcc by using carryout from add/sub instruction
18808
18809 // LHS = ADD i64 RHS, Z LHSlo = UADDO i32 RHSlo, Zlo
18810 // setcc LHS ult RHS -> LHSHi = UADDO_CARRY i32 RHShi, Zhi
18811 // similarly for subtraction
18812
18813 // LHS = ADD i64 Y, 1 LHSlo = UADDO i32 Ylo, 1
18814 // setcc LHS eq 0 -> LHSHi = UADDO_CARRY i32 Yhi, 0
18815
18816 if (VT == MVT::i64 && ((CC == ISD::SETULT &&
18818 (CC == ISD::SETUGT &&
18820 (CC == ISD::SETEQ && CRHS && CRHS->isZero() &&
18821 sd_match(LHS, m_Add(m_Value(), m_One()))))) {
18822 bool IsAdd = LHS.getOpcode() == ISD::ADD;
18823
18824 SDValue Op0 = LHS.getOperand(0);
18825 SDValue Op1 = LHS.getOperand(1);
18826
18827 SDValue Op0Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op0);
18828 SDValue Op1Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op1);
18829
18830 SDValue Op0Hi = getHiHalf64(Op0, DAG);
18831 SDValue Op1Hi = getHiHalf64(Op1, DAG);
18832
18833 SDValue NodeLo =
18834 DAG.getNode(IsAdd ? ISD::UADDO : ISD::USUBO, SL,
18835 DAG.getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
18836
18837 SDValue CarryInHi = NodeLo.getValue(1);
18838 SDValue NodeHi = DAG.getNode(IsAdd ? ISD::UADDO_CARRY : ISD::USUBO_CARRY,
18839 SL, DAG.getVTList(MVT::i32, MVT::i1),
18840 {Op0Hi, Op1Hi, CarryInHi});
18841
18842 SDValue ResultLo = NodeLo.getValue(0);
18843 SDValue ResultHi = NodeHi.getValue(0);
18844
18845 SDValue JoinedResult =
18846 DAG.getBuildVector(MVT::v2i32, SL, {ResultLo, ResultHi});
18847
18848 SDValue Result = DAG.getNode(ISD::BITCAST, SL, VT, JoinedResult);
18849 SDValue Overflow = NodeHi.getValue(1);
18850 DCI.CombineTo(LHS.getNode(), Result);
18851 return Overflow;
18852 }
18853
18854 if (VT != MVT::f32 && VT != MVT::f64 &&
18855 (!Subtarget->has16BitInsts() || VT != MVT::f16))
18856 return SDValue();
18857
18858 // Match isinf/isfinite pattern
18859 // (fcmp oeq (fabs x), inf) -> (fp_class x, (p_infinity | n_infinity))
18860 // (fcmp one (fabs x), inf) -> (fp_class x,
18861 // (p_normal | n_normal | p_subnormal | n_subnormal | p_zero | n_zero)
18862 if ((CC == ISD::SETOEQ || CC == ISD::SETONE) &&
18863 LHS.getOpcode() == ISD::FABS) {
18864 const ConstantFPSDNode *CRHS = dyn_cast<ConstantFPSDNode>(RHS);
18865 if (!CRHS)
18866 return SDValue();
18867
18868 const APFloat &APF = CRHS->getValueAPF();
18869 if (APF.isInfinity() && !APF.isNegative()) {
18870 const unsigned IsInfMask =
18872 const unsigned IsFiniteMask =
18876 unsigned Mask = CC == ISD::SETOEQ ? IsInfMask : IsFiniteMask;
18877 return DAG.getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1, LHS.getOperand(0),
18878 DAG.getConstant(Mask, SL, MVT::i32));
18879 }
18880 }
18881
18882 if (VT == MVT::f64) {
18883 ISD::CondCode HiHalfCC = tryReduceF64CompareToHiHalf(CC, LHS, RHS, DAG);
18884 if (HiHalfCC != ISD::SETCC_INVALID)
18885 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
18886 getHiHalf64(RHS, DAG), HiHalfCC);
18887 }
18888
18889 return SDValue();
18890}
18891
18892SDValue
18893SITargetLowering::performCvtF32UByteNCombine(SDNode *N,
18894 DAGCombinerInfo &DCI) const {
18895 SelectionDAG &DAG = DCI.DAG;
18896 SDLoc SL(N);
18897 unsigned Offset = N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
18898
18899 SDValue Src = N->getOperand(0);
18900 SDValue Shift = N->getOperand(0);
18901
18902 // TODO: Extend type shouldn't matter (assuming legal types).
18903 if (Shift.getOpcode() == ISD::ZERO_EXTEND)
18904 Shift = Shift.getOperand(0);
18905
18906 if (Shift.getOpcode() == ISD::SRL || Shift.getOpcode() == ISD::SHL) {
18907 // cvt_f32_ubyte1 (shl x, 8) -> cvt_f32_ubyte0 x
18908 // cvt_f32_ubyte3 (shl x, 16) -> cvt_f32_ubyte1 x
18909 // cvt_f32_ubyte0 (srl x, 16) -> cvt_f32_ubyte2 x
18910 // cvt_f32_ubyte1 (srl x, 16) -> cvt_f32_ubyte3 x
18911 // cvt_f32_ubyte0 (srl x, 8) -> cvt_f32_ubyte1 x
18912 if (auto *C = dyn_cast<ConstantSDNode>(Shift.getOperand(1))) {
18913 SDValue Shifted = DAG.getZExtOrTrunc(
18914 Shift.getOperand(0), SDLoc(Shift.getOperand(0)), MVT::i32);
18915
18916 unsigned ShiftOffset = 8 * Offset;
18917 if (Shift.getOpcode() == ISD::SHL)
18918 ShiftOffset -= C->getZExtValue();
18919 else
18920 ShiftOffset += C->getZExtValue();
18921
18922 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
18923 return DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
18924 MVT::f32, Shifted);
18925 }
18926 }
18927 }
18928
18929 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
18930 APInt DemandedBits = APInt::getBitsSet(32, 8 * Offset, 8 * Offset + 8);
18931 if (TLI.SimplifyDemandedBits(Src, DemandedBits, DCI)) {
18932 // We simplified Src. If this node is not dead, visit it again so it is
18933 // folded properly.
18934 if (N->getOpcode() != ISD::DELETED_NODE)
18935 DCI.AddToWorklist(N);
18936 return SDValue(N, 0);
18937 }
18938
18939 // Handle (or x, (srl y, 8)) pattern when known bits are zero.
18940 if (SDValue DemandedSrc =
18941 TLI.SimplifyMultipleUseDemandedBits(Src, DemandedBits, DAG))
18942 return DAG.getNode(N->getOpcode(), SL, MVT::f32, DemandedSrc);
18943
18944 return SDValue();
18945}
18946
18947SDValue SITargetLowering::performClampCombine(SDNode *N,
18948 DAGCombinerInfo &DCI) const {
18949 ConstantFPSDNode *CSrc = dyn_cast<ConstantFPSDNode>(N->getOperand(0));
18950 if (!CSrc)
18951 return SDValue();
18952
18953 const MachineFunction &MF = DCI.DAG.getMachineFunction();
18954 const APFloat &F = CSrc->getValueAPF();
18955 APFloat Zero = APFloat::getZero(F.getSemantics());
18956 if (F < Zero ||
18957 (F.isNaN() && MF.getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
18958 return DCI.DAG.getConstantFP(Zero, SDLoc(N), N->getValueType(0));
18959 }
18960
18961 APFloat One = APFloat::getOne(F.getSemantics());
18962 if (F > One)
18963 return DCI.DAG.getConstantFP(One, SDLoc(N), N->getValueType(0));
18964
18965 return getCanonicalConstantFP(DCI.DAG, SDLoc(N), N->getValueType(0), F);
18966}
18967
18968// Check if V is the exponent result of a frexp operation. Returns the frexp
18969// input via FrexpInput if matched. We only match the exponent (not mantissa)
18970// because V_FREXP_MANT returns its input for Inf/NaN, not zero.
18971static bool isFrexpExp(SDValue V, SDValue &FrexpInput) {
18972 // ISD::FFREXP returns {mant, exp} - only match if using the exp result
18973 // (result number 1).
18974 if (V.getOpcode() == ISD::FFREXP && V.getResNo() == 1) {
18975 FrexpInput = V.getOperand(0);
18976 return true;
18977 }
18979 m_Value(FrexpInput))))
18980 return true;
18981 return false;
18982}
18983
18984SDValue
18985SITargetLowering::performFrexpSelectCombine(SDNode *N,
18986 DAGCombinerInfo &DCI) const {
18987 // This optimization only applies when the hardware handles inf/nan correctly.
18988 if (Subtarget->hasFractBug())
18989 return SDValue();
18990
18991 SDValue Cond = N->getOperand(0);
18992 SDValue TrueVal = N->getOperand(1);
18993 SDValue FalseVal = N->getOperand(2);
18994
18995 // Identify which operand is the frexp result and which is the zero constant.
18996 // Pattern 1: select cond, 0, frexp_result (cond true -> return 0)
18997 // Pattern 2: select cond, frexp_result, 0 (cond false -> return 0)
18998 SDValue FrexpVal;
18999 SDValue ZeroVal;
19000 bool CondSelectsZero; // If true, condition=true selects zero
19001
19002 // Check if FrexpVal comes from ISD::FFREXP (exponent result only) or
19003 // amdgcn_frexp_exp intrinsic.
19004 SDValue FrexpInput;
19005 if (isFrexpExp(FalseVal, FrexpInput)) {
19006 FrexpVal = FalseVal;
19007 ZeroVal = TrueVal;
19008 CondSelectsZero = true;
19009 } else if (isFrexpExp(TrueVal, FrexpInput)) {
19010 FrexpVal = TrueVal;
19011 ZeroVal = FalseVal;
19012 CondSelectsZero = false;
19013 } else {
19014 return SDValue();
19015 }
19016
19017 // frexp_exp returns integer, so check for integer zero.
19018 if (!isNullConstant(ZeroVal))
19019 return SDValue();
19020
19021 // The frexp intrinsics ignore sign, so we can strip sign ops when comparing.
19022 SDValue FrexpInputStripped = peekFPSignOps(FrexpInput);
19023
19024 bool IsNonFiniteTest = false;
19025
19026 // Handle SETCC conditions for inf/nan tests.
19027 // The canonical form of these checks is fcmp + fabs.
19028 if (Cond.getOpcode() == ISD::SETCC) {
19029 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
19030 SDValue CondLHS = Cond.getOperand(0);
19031 SDValue CondRHS = Cond.getOperand(1);
19032
19033 // Check if LHS is fabs(FrexpInput) - required for infinity comparisons.
19034 SDValue FAbsInput;
19035 bool LHSIsFabs = sd_match(CondLHS, m_FAbs(m_Value(FAbsInput)));
19036 bool LHSMatchesFrexp =
19037 (CondLHS == FrexpInput) ||
19038 (LHSIsFabs && peekFPSignOps(FAbsInput) == FrexpInputStripped) ||
19039 (peekFPSignOps(CondLHS) == FrexpInputStripped);
19040 bool RHSMatchesFrexp = (CondRHS == FrexpInput) ||
19041 (peekFPSignOps(CondRHS) == FrexpInputStripped);
19042
19043 if (CC == ISD::SETUO) {
19044 // fcmp uno x, y - true if either x or y is NaN
19045 // We can only fold if the non-frexp operand is known to never be NaN,
19046 // otherwise the comparison could be true due to the other operand.
19047 // Special case: fcmp uno x, x (same operand) is a valid NaN test.
19048 SelectionDAG &DAG = DCI.DAG;
19049 if (LHSMatchesFrexp &&
19050 (CondLHS == CondRHS || DAG.isKnownNeverNaN(CondRHS)))
19051 IsNonFiniteTest = CondSelectsZero;
19052 else if (RHSMatchesFrexp && DAG.isKnownNeverNaN(CondLHS))
19053 IsNonFiniteTest = CondSelectsZero;
19054 } else if ((CC == ISD::SETOEQ || CC == ISD::SETUEQ) && LHSMatchesFrexp &&
19055 LHSIsFabs &&
19056 sd_match(CondRHS,
19058 CondRHS.getValueType().getFltSemantics())))) {
19059 // fcmp oeq/ueq fabs(x), +inf - true if x is inf (or inf/nan for ueq)
19060 IsNonFiniteTest = CondSelectsZero;
19061 } else if ((CC == ISD::SETONE || CC == ISD::SETUNE) && LHSMatchesFrexp &&
19062 LHSIsFabs &&
19063 sd_match(CondRHS,
19065 CondRHS.getValueType().getFltSemantics())))) {
19066 // fcmp one/une fabs(x), +inf - true if x is NOT inf
19067 IsNonFiniteTest = !CondSelectsZero;
19068 } else if (CC == ISD::SETO) {
19069 // fcmp ord x, y - true if both are NOT NaN
19070 // We can only fold if the non-frexp operand is known to never be NaN,
19071 // otherwise the comparison could be false due to the other operand.
19072 // Special case: fcmp ord x, x (same operand) is a valid not-NaN test.
19073 SelectionDAG &DAG = DCI.DAG;
19074 if (LHSMatchesFrexp &&
19075 (CondLHS == CondRHS || DAG.isKnownNeverNaN(CondRHS)))
19076 IsNonFiniteTest = !CondSelectsZero;
19077 else if (RHSMatchesFrexp && DAG.isKnownNeverNaN(CondLHS))
19078 IsNonFiniteTest = !CondSelectsZero;
19079 }
19080 }
19081
19082 if (!IsNonFiniteTest)
19083 return SDValue();
19084
19085 // The select can be eliminated - just return the frexp result directly.
19086 return FrexpVal;
19087}
19088
19089SDValue SITargetLowering::performSelectCombine(SDNode *N,
19090 DAGCombinerInfo &DCI) const {
19091
19092 // Try to fold CMP + SELECT patterns with shared constants (both FP and
19093 // integer).
19094 // Detect when CMP and SELECT use the same constant and fold them to avoid
19095 // loading the constant twice. Specifically handles patterns like:
19096 // %cmp = icmp eq i32 %val, 4242
19097 // %sel = select i1 %cmp, i32 4242, i32 %other
19098 // It can be optimized to reuse %val instead of 4242 in select.
19099 SDValue Cond = N->getOperand(0);
19100 SDValue TrueVal = N->getOperand(1);
19101 SDValue FalseVal = N->getOperand(2);
19102
19103 // Check if condition is a comparison.
19104 if (Cond.getOpcode() != ISD::SETCC)
19105 return SDValue();
19106
19107 SDValue LHS = Cond.getOperand(0);
19108 SDValue RHS = Cond.getOperand(1);
19109 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
19110
19111 bool isFloatingPoint = LHS.getValueType().isFloatingPoint();
19112 bool isInteger = LHS.getValueType().isInteger();
19113
19114 // Handle simple floating-point and integer types only.
19115 if (!isFloatingPoint && !isInteger)
19116 return SDValue();
19117
19118 // Bare SETEQ/SETNE is the builder's NaN-impossible downgrade.
19119 bool isEquality = CC == ISD::SETEQ || (isFloatingPoint && CC == ISD::SETOEQ);
19120 bool isNonEquality =
19121 CC == ISD::SETNE || (isFloatingPoint && CC == ISD::SETONE);
19122 if (!isEquality && !isNonEquality)
19123 return SDValue();
19124
19125 SDValue ArgVal, ConstVal;
19126 if ((isFloatingPoint && isa<ConstantFPSDNode>(RHS)) ||
19127 (isInteger && isa<ConstantSDNode>(RHS))) {
19128 ConstVal = RHS;
19129 ArgVal = LHS;
19130 } else if ((isFloatingPoint && isa<ConstantFPSDNode>(LHS)) ||
19131 (isInteger && isa<ConstantSDNode>(LHS))) {
19132 ConstVal = LHS;
19133 ArgVal = RHS;
19134 } else {
19135 return SDValue();
19136 }
19137
19138 // Skip optimization for inlinable immediates.
19139 if (isFloatingPoint) {
19140 const APFloat &Val = cast<ConstantFPSDNode>(ConstVal)->getValueAPF();
19141 if (!Val.isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
19142 return SDValue();
19143 } else {
19144 const std::optional<int64_t> Val =
19145 cast<ConstantSDNode>(ConstVal)->getAPIntValue().trySExtValue();
19146 if (Val && AMDGPU::isInlinableIntLiteral(*Val))
19147 return SDValue();
19148 }
19149
19150 // For equality and non-equality comparisons, patterns:
19151 // select (setcc x, const), const, y -> select (setcc x, const), x, y
19152 // select (setccinv x, const), y, const -> select (setccinv x, const), y, x
19153 if (!(isEquality && TrueVal == ConstVal) &&
19154 !(isNonEquality && FalseVal == ConstVal))
19155 return SDValue();
19156
19157 // SETONE's false arm is also taken for NaN ArgVal, so require NaN excluded.
19158 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
19159 !Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
19160 return SDValue();
19161
19162 SDValue SelectLHS = (isEquality && TrueVal == ConstVal) ? ArgVal : TrueVal;
19163 SDValue SelectRHS =
19164 (isNonEquality && FalseVal == ConstVal) ? ArgVal : FalseVal;
19165 return DCI.DAG.getNode(ISD::SELECT, SDLoc(N), N->getValueType(0), Cond,
19166 SelectLHS, SelectRHS);
19167}
19168
19170 DAGCombinerInfo &DCI) const {
19171 switch (N->getOpcode()) {
19172 case ISD::ABS:
19173 if (SDValue Res = promoteUniformUnaryOpToI32(SDValue(N, 0), DCI))
19174 return Res;
19175 break;
19176 case ISD::ADD:
19177 case ISD::SUB:
19178 case ISD::SHL:
19179 case ISD::SRL:
19180 case ISD::SRA:
19181 case ISD::AND:
19182 case ISD::OR:
19183 case ISD::XOR:
19184 case ISD::MUL:
19185 case ISD::SETCC:
19186 case ISD::SELECT:
19187 case ISD::SMIN:
19188 case ISD::SMAX:
19189 case ISD::UMIN:
19190 case ISD::UMAX:
19191 case ISD::USUBSAT:
19192 case ISD::UADDSAT:
19193 if (auto Res = promoteUniformOpToI32(SDValue(N, 0), DCI))
19194 return Res;
19195 break;
19196 default:
19197 break;
19198 }
19199
19200 if (getTargetMachine().getOptLevel() == CodeGenOptLevel::None)
19201 return SDValue();
19202
19203 switch (N->getOpcode()) {
19204 case ISD::ADD:
19205 return performAddCombine(N, DCI);
19206 case ISD::PTRADD:
19207 return performPtrAddCombine(N, DCI);
19208 case ISD::SUB:
19209 return performSubCombine(N, DCI);
19210 case ISD::FADD:
19211 return performFAddCombine(N, DCI);
19212 case ISD::FSUB:
19213 return performFSubCombine(N, DCI);
19214 case ISD::FDIV:
19215 return performFDivCombine(N, DCI);
19216 case ISD::FMUL:
19217 return performFMulCombine(N, DCI);
19218 case ISD::SETCC:
19219 return performSetCCCombine(N, DCI);
19220 case ISD::SELECT:
19221 if (auto Res = performFrexpSelectCombine(N, DCI))
19222 return Res;
19223 if (auto Res = performSelectCombine(N, DCI))
19224 return Res;
19225 break;
19226 case ISD::FMAXNUM:
19227 case ISD::FMINNUM:
19228 case ISD::FMAXNUM_IEEE:
19229 case ISD::FMINNUM_IEEE:
19230 case ISD::FMAXIMUM:
19231 case ISD::FMINIMUM:
19232 case ISD::FMAXIMUMNUM:
19233 case ISD::FMINIMUMNUM:
19234 case ISD::SMAX:
19235 case ISD::SMIN:
19236 case ISD::UMAX:
19237 case ISD::UMIN:
19238 case AMDGPUISD::FMIN_LEGACY:
19239 case AMDGPUISD::FMAX_LEGACY:
19240 return performMinMaxCombine(N, DCI);
19241 case ISD::FMA:
19242 return performFMACombine(N, DCI);
19243 case ISD::AND:
19244 return performAndCombine(N, DCI);
19245 case ISD::OR:
19246 return performOrCombine(N, DCI);
19247 case ISD::FSHR: {
19249 if (N->getValueType(0) == MVT::i32 && N->isDivergent() &&
19250 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19251 return matchPERM(N, DCI);
19252 }
19253 break;
19254 }
19255 case ISD::XOR:
19256 return performXorCombine(N, DCI);
19257 case ISD::ANY_EXTEND:
19258 case ISD::ZERO_EXTEND:
19259 return performZeroOrAnyExtendCombine(N, DCI);
19261 return performSignExtendInRegCombine(N, DCI);
19262 case AMDGPUISD::FP_CLASS:
19263 return performClassCombine(N, DCI);
19264 case ISD::FCANONICALIZE:
19265 return performFCanonicalizeCombine(N, DCI);
19266 case AMDGPUISD::RCP:
19267 return performRcpCombine(N, DCI);
19268 case ISD::FLDEXP:
19269 case AMDGPUISD::FRACT:
19270 case AMDGPUISD::RSQ:
19271 case AMDGPUISD::RCP_LEGACY:
19272 case AMDGPUISD::RCP_IFLAG:
19273 case AMDGPUISD::RSQ_CLAMP: {
19274 // FIXME: This is probably wrong. If src is an sNaN, it won't be quieted
19275 SDValue Src = N->getOperand(0);
19276 if (Src.isUndef())
19277 return Src;
19278 break;
19279 }
19280 case ISD::SINT_TO_FP:
19281 case ISD::UINT_TO_FP:
19282 return performUCharToFloatCombine(N, DCI);
19283 case ISD::FCOPYSIGN:
19284 return performFCopySignCombine(N, DCI);
19285 case AMDGPUISD::CVT_F32_UBYTE0:
19286 case AMDGPUISD::CVT_F32_UBYTE1:
19287 case AMDGPUISD::CVT_F32_UBYTE2:
19288 case AMDGPUISD::CVT_F32_UBYTE3:
19289 return performCvtF32UByteNCombine(N, DCI);
19290 case AMDGPUISD::FMED3:
19291 return performFMed3Combine(N, DCI);
19292 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19293 return performCvtPkRTZCombine(N, DCI);
19294 case AMDGPUISD::CLAMP:
19295 return performClampCombine(N, DCI);
19296 case ISD::SCALAR_TO_VECTOR: {
19297 SelectionDAG &DAG = DCI.DAG;
19298 EVT VT = N->getValueType(0);
19299
19300 // v2i16 (scalar_to_vector i16:x) -> v2i16 (bitcast (any_extend i16:x))
19301 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19302 SDLoc SL(N);
19303 SDValue Src = N->getOperand(0);
19304 EVT EltVT = Src.getValueType();
19305 if (EltVT != MVT::i16)
19306 Src = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
19307
19308 SDValue Ext = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Src);
19309 return DAG.getNode(ISD::BITCAST, SL, VT, Ext);
19310 }
19311
19312 break;
19313 }
19315 return performExtractVectorEltCombine(N, DCI);
19317 return performInsertVectorEltCombine(N, DCI);
19318 case ISD::FP_ROUND:
19319 return performFPRoundCombine(N, DCI);
19320 case ISD::LOAD: {
19321 if (SDValue Widened = widenLoad(cast<LoadSDNode>(N), DCI))
19322 return Widened;
19323 [[fallthrough]];
19324 }
19325 default: {
19326 if (!DCI.isBeforeLegalize()) {
19327 if (MemSDNode *MemNode = dyn_cast<MemSDNode>(N))
19328 return performMemSDNodeCombine(MemNode, DCI);
19329 }
19330
19331 break;
19332 }
19333 }
19334
19336}
19337
19338/// Helper function for adjustWritemask
19339static unsigned SubIdx2Lane(unsigned Idx) {
19340 switch (Idx) {
19341 default:
19342 return ~0u;
19343 case AMDGPU::sub0:
19344 return 0;
19345 case AMDGPU::sub1:
19346 return 1;
19347 case AMDGPU::sub2:
19348 return 2;
19349 case AMDGPU::sub3:
19350 return 3;
19351 case AMDGPU::sub4:
19352 return 4; // Possible with TFE/LWE
19353 }
19354}
19355
19356/// Adjust the writemask of MIMG, VIMAGE or VSAMPLE instructions
19357SDNode *SITargetLowering::adjustWritemask(MachineSDNode *&Node,
19358 SelectionDAG &DAG) const {
19359 unsigned Opcode = Node->getMachineOpcode();
19360
19361 // Subtract 1 because the vdata output is not a MachineSDNode operand.
19362 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19363 if (D16Idx >= 0 && Node->getConstantOperandVal(D16Idx))
19364 return Node; // not implemented for D16
19365
19366 SDNode *Users[5] = {nullptr};
19367 unsigned Lane = 0;
19368 unsigned DmaskIdx =
19369 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19370 unsigned OldDmask = Node->getConstantOperandVal(DmaskIdx);
19371 unsigned NewDmask = 0;
19372 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19373 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19374 bool UsesTFC = (int(TFEIdx) >= 0 && Node->getConstantOperandVal(TFEIdx)) ||
19375 (int(LWEIdx) >= 0 && Node->getConstantOperandVal(LWEIdx));
19376 unsigned TFCLane = 0;
19377 bool HasChain = Node->getNumValues() > 1;
19378
19379 if (OldDmask == 0) {
19380 // These are folded out, but on the chance it happens don't assert.
19381 return Node;
19382 }
19383
19384 unsigned OldBitsSet = llvm::popcount(OldDmask);
19385 // Work out which is the TFE/LWE lane if that is enabled.
19386 if (UsesTFC) {
19387 TFCLane = OldBitsSet;
19388 }
19389
19390 // Try to figure out the used register components
19391 for (SDUse &Use : Node->uses()) {
19392
19393 // Don't look at users of the chain.
19394 if (Use.getResNo() != 0)
19395 continue;
19396
19397 SDNode *User = Use.getUser();
19398
19399 // Abort if we can't understand the usage
19400 if (!User->isMachineOpcode() ||
19401 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19402 return Node;
19403
19404 // Lane means which subreg of %vgpra_vgprb_vgprc_vgprd is used.
19405 // Note that subregs are packed, i.e. Lane==0 is the first bit set
19406 // in OldDmask, so it can be any of X,Y,Z,W; Lane==1 is the second bit
19407 // set, etc.
19408 Lane = SubIdx2Lane(User->getConstantOperandVal(1));
19409 if (Lane == ~0u)
19410 return Node;
19411
19412 // Check if the use is for the TFE/LWE generated result at VGPRn+1.
19413 if (UsesTFC && Lane == TFCLane) {
19414 Users[Lane] = User;
19415 } else {
19416 // Set which texture component corresponds to the lane.
19417 unsigned Comp;
19418 for (unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19419 Comp = llvm::countr_zero(Dmask);
19420 Dmask &= ~(1 << Comp);
19421 }
19422
19423 // Abort if we have more than one user per component.
19424 if (Users[Lane])
19425 return Node;
19426
19427 Users[Lane] = User;
19428 NewDmask |= 1 << Comp;
19429 }
19430 }
19431
19432 // Don't allow 0 dmask, as hardware assumes one channel enabled.
19433 bool NoChannels = !NewDmask;
19434 if (NoChannels) {
19435 if (!UsesTFC) {
19436 // No uses of the result and not using TFC. Then do nothing.
19437 return Node;
19438 }
19439 // If the original dmask has one channel - then nothing to do
19440 if (OldBitsSet == 1)
19441 return Node;
19442 // Use an arbitrary dmask - required for the instruction to work
19443 NewDmask = 1;
19444 }
19445 // Abort if there's no change
19446 if (NewDmask == OldDmask)
19447 return Node;
19448
19449 unsigned BitsSet = llvm::popcount(NewDmask);
19450
19451 // Check for TFE or LWE - increase the number of channels by one to account
19452 // for the extra return value
19453 // This will need adjustment for D16 if this is also included in
19454 // adjustWriteMask (this function) but at present D16 are excluded.
19455 unsigned NewChannels = BitsSet + UsesTFC;
19456
19457 int NewOpcode =
19458 AMDGPU::getMaskedMIMGOp(Node->getMachineOpcode(), NewChannels);
19459 assert(NewOpcode != -1 &&
19460 NewOpcode != static_cast<int>(Node->getMachineOpcode()) &&
19461 "failed to find equivalent MIMG op");
19462
19463 // Adjust the writemask in the node
19465 llvm::append_range(Ops, Node->ops().take_front(DmaskIdx));
19466 Ops.push_back(DAG.getTargetConstant(NewDmask, SDLoc(Node), MVT::i32));
19467 llvm::append_range(Ops, Node->ops().drop_front(DmaskIdx + 1));
19468
19469 MVT SVT = Node->getValueType(0).getVectorElementType().getSimpleVT();
19470
19471 MVT ResultVT = NewChannels == 1
19472 ? SVT
19473 : MVT::getVectorVT(SVT, NewChannels == 3 ? 4
19474 : NewChannels == 5 ? 8
19475 : NewChannels);
19476 SDVTList NewVTList =
19477 HasChain ? DAG.getVTList(ResultVT, MVT::Other) : DAG.getVTList(ResultVT);
19478
19479 MachineSDNode *NewNode =
19480 DAG.getMachineNode(NewOpcode, SDLoc(Node), NewVTList, Ops);
19481
19482 if (HasChain) {
19483 // Update chain.
19484 DAG.setNodeMemRefs(NewNode, Node->memoperands());
19485 DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), SDValue(NewNode, 1));
19486 }
19487
19488 if (NewChannels == 1) {
19489 assert(Node->hasNUsesOfValue(1, 0));
19490 SDNode *Copy =
19491 DAG.getMachineNode(TargetOpcode::COPY, SDLoc(Node),
19492 Users[Lane]->getValueType(0), SDValue(NewNode, 0));
19493 DAG.ReplaceAllUsesWith(Users[Lane], Copy);
19494 return nullptr;
19495 }
19496
19497 // Update the users of the node with the new indices
19498 for (unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19499 SDNode *User = Users[i];
19500 if (!User) {
19501 // Handle the special case of NoChannels. We set NewDmask to 1 above, but
19502 // Users[0] is still nullptr because channel 0 doesn't really have a use.
19503 if (i || !NoChannels)
19504 continue;
19505 } else {
19506 SDValue Op = DAG.getTargetConstant(Idx, SDLoc(User), MVT::i32);
19507 SDNode *NewUser = DAG.UpdateNodeOperands(User, SDValue(NewNode, 0), Op);
19508 if (NewUser != User) {
19509 DAG.ReplaceAllUsesWith(SDValue(User, 0), SDValue(NewUser, 0));
19510 DAG.RemoveDeadNode(User);
19511 }
19512 }
19513
19514 switch (Idx) {
19515 default:
19516 break;
19517 case AMDGPU::sub0:
19518 Idx = AMDGPU::sub1;
19519 break;
19520 case AMDGPU::sub1:
19521 Idx = AMDGPU::sub2;
19522 break;
19523 case AMDGPU::sub2:
19524 Idx = AMDGPU::sub3;
19525 break;
19526 case AMDGPU::sub3:
19527 Idx = AMDGPU::sub4;
19528 break;
19529 }
19530 }
19531
19532 DAG.RemoveDeadNode(Node);
19533 return nullptr;
19534}
19535
19537 if (Op.getOpcode() == ISD::AssertZext)
19538 Op = Op.getOperand(0);
19539
19540 return isa<FrameIndexSDNode>(Op);
19541}
19542
19543/// Legalize target independent instructions (e.g. INSERT_SUBREG)
19544/// with frame index operands.
19545/// LLVM assumes that inputs are to these instructions are registers.
19546SDNode *
19548 SelectionDAG &DAG) const {
19549 if (Node->getOpcode() == ISD::CopyToReg) {
19550 RegisterSDNode *DestReg = cast<RegisterSDNode>(Node->getOperand(1));
19551 SDValue SrcVal = Node->getOperand(2);
19552
19553 // Insert a copy to a VReg_1 virtual register so LowerI1Copies doesn't have
19554 // to try understanding copies to physical registers.
19555 if (SrcVal.getValueType() == MVT::i1 && DestReg->getReg().isPhysical()) {
19556 SDLoc SL(Node);
19558 SDValue VReg = DAG.getRegister(
19559 MRI.createVirtualRegister(&AMDGPU::VReg_1RegClass), MVT::i1);
19560
19561 SDNode *Glued = Node->getGluedNode();
19562 SDValue ToVReg = DAG.getCopyToReg(
19563 Node->getOperand(0), SL, VReg, SrcVal,
19564 SDValue(Glued, Glued ? Glued->getNumValues() - 1 : 0));
19565 SDValue ToResultReg = DAG.getCopyToReg(ToVReg, SL, SDValue(DestReg, 0),
19566 VReg, ToVReg.getValue(1));
19567 DAG.ReplaceAllUsesWith(Node, ToResultReg.getNode());
19568 DAG.RemoveDeadNode(Node);
19569 return ToResultReg.getNode();
19570 }
19571 }
19572
19574 for (unsigned i = 0; i < Node->getNumOperands(); ++i) {
19575 if (!isFrameIndexOp(Node->getOperand(i))) {
19576 Ops.push_back(Node->getOperand(i));
19577 continue;
19578 }
19579
19580 SDLoc DL(Node);
19581 Ops.push_back(SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL,
19582 Node->getOperand(i).getValueType(),
19583 Node->getOperand(i)),
19584 0));
19585 }
19586
19587 return DAG.UpdateNodeOperands(Node, Ops);
19588}
19589
19590/// Fold the instructions after selecting them.
19591/// Returns null if users were already updated.
19593 SelectionDAG &DAG) const {
19595 unsigned Opcode = Node->getMachineOpcode();
19596
19597 if (TII->isImage(Opcode) && !TII->get(Opcode).mayStore() &&
19598 !TII->isGather4(Opcode) &&
19599 AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::dmask)) {
19600 return adjustWritemask(Node, DAG);
19601 }
19602
19603 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19605 return Node;
19606 }
19607
19608 switch (Opcode) {
19609 case AMDGPU::V_DIV_SCALE_F32_e64:
19610 case AMDGPU::V_DIV_SCALE_F64_e64: {
19611 // Satisfy the operand register constraint when one of the inputs is
19612 // undefined. Ordinarily each undef value will have its own implicit_def of
19613 // a vreg, so force these to use a single register.
19614 SDValue Src0 = Node->getOperand(1);
19615 SDValue Src1 = Node->getOperand(3);
19616 SDValue Src2 = Node->getOperand(5);
19617
19618 if ((Src0.isMachineOpcode() &&
19619 Src0.getMachineOpcode() != AMDGPU::IMPLICIT_DEF) &&
19620 (Src0 == Src1 || Src0 == Src2))
19621 break;
19622
19623 MVT VT = Src0.getValueType().getSimpleVT();
19624 const TargetRegisterClass *RC =
19625 getRegClassFor(VT, Src0.getNode()->isDivergent());
19626
19628 SDValue UndefReg = DAG.getRegister(MRI.createVirtualRegister(RC), VT);
19629
19630 SDValue ImpDef = DAG.getCopyToReg(DAG.getEntryNode(), SDLoc(Node), UndefReg,
19631 Src0, SDValue());
19632
19633 // src0 must be the same register as src1 or src2, even if the value is
19634 // undefined, so make sure we don't violate this constraint.
19635 if (Src0.isMachineOpcode() &&
19636 Src0.getMachineOpcode() == AMDGPU::IMPLICIT_DEF) {
19637 if (Src1.isMachineOpcode() &&
19638 Src1.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19639 Src0 = Src1;
19640 else if (Src2.isMachineOpcode() &&
19641 Src2.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19642 Src0 = Src2;
19643 else {
19644 assert(Src1.getMachineOpcode() == AMDGPU::IMPLICIT_DEF);
19645 Src0 = UndefReg;
19646 Src1 = UndefReg;
19647 }
19648 } else
19649 break;
19650
19652 Ops[1] = Src0;
19653 Ops[3] = Src1;
19654 Ops[5] = Src2;
19655 Ops.push_back(ImpDef.getValue(1));
19656 return DAG.getMachineNode(Opcode, SDLoc(Node), Node->getVTList(), Ops);
19657 }
19658 default:
19659 break;
19660 }
19661
19662 return Node;
19663}
19664
19665// Any MIMG instructions that use tfe or lwe require an initialization of the
19666// result register that will be written in the case of a memory access failure.
19667// The required code is also added to tie this init code to the result of the
19668// img instruction.
19671 const SIRegisterInfo &TRI = TII->getRegisterInfo();
19672 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
19673 MachineBasicBlock &MBB = *MI.getParent();
19674
19675 int DstIdx =
19676 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
19677 unsigned InitIdx = 0;
19678
19679 if (TII->isImage(MI)) {
19680 MachineOperand *TFE = TII->getNamedOperand(MI, AMDGPU::OpName::tfe);
19681 MachineOperand *LWE = TII->getNamedOperand(MI, AMDGPU::OpName::lwe);
19682 MachineOperand *D16 = TII->getNamedOperand(MI, AMDGPU::OpName::d16);
19683
19684 if (!TFE && !LWE) // intersect_ray
19685 return;
19686
19687 unsigned TFEVal = TFE ? TFE->getImm() : 0;
19688 unsigned LWEVal = LWE ? LWE->getImm() : 0;
19689 unsigned D16Val = D16 ? D16->getImm() : 0;
19690
19691 if (!TFEVal && !LWEVal)
19692 return;
19693
19694 // At least one of TFE or LWE are non-zero
19695 // We have to insert a suitable initialization of the result value and
19696 // tie this to the dest of the image instruction.
19697
19698 // Calculate which dword we have to initialize to 0.
19699 MachineOperand *MO_Dmask = TII->getNamedOperand(MI, AMDGPU::OpName::dmask);
19700
19701 // check that dmask operand is found.
19702 assert(MO_Dmask && "Expected dmask operand in instruction");
19703
19704 unsigned dmask = MO_Dmask->getImm();
19705 // Determine the number of active lanes taking into account the
19706 // Gather4 special case
19707 unsigned ActiveLanes = TII->isGather4(MI) ? 4 : llvm::popcount(dmask);
19708
19709 bool Packed = !Subtarget->hasUnpackedD16VMem();
19710
19711 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19712
19713 // Abandon attempt if the dst size isn't large enough
19714 // - this is in fact an error but this is picked up elsewhere and
19715 // reported correctly.
19716 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
19717
19718 uint32_t DstSize = TRI.getRegSizeInBits(*DstRC) / 32;
19719 if (DstSize < InitIdx)
19720 return;
19721 } else if (TII->isMUBUF(MI) && AMDGPU::getMUBUFTfe(MI.getOpcode())) {
19722 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
19723 InitIdx = TRI.getRegSizeInBits(*DstRC) / 32;
19724 } else {
19725 return;
19726 }
19727
19728 const DebugLoc &DL = MI.getDebugLoc();
19729
19730 // Create a register for the initialization value.
19731 Register PrevDst = MRI.cloneVirtualRegister(MI.getOperand(DstIdx).getReg());
19732 unsigned NewDst = 0; // Final initialized value will be in here
19733
19734 // If PRTStrictNull feature is enabled (the default) then initialize
19735 // all the result registers to 0, otherwise just the error indication
19736 // register (VGPRn+1)
19737 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
19738 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
19739
19740 BuildMI(MBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), PrevDst);
19741 for (; SizeLeft; SizeLeft--, CurrIdx++) {
19742 NewDst = MRI.createVirtualRegister(TII->getOpRegClass(MI, DstIdx));
19743 // Initialize dword
19744 Register SubReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
19745 // clang-format off
19746 BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), SubReg)
19747 .addImm(0);
19748 // clang-format on
19749 // Insert into the super-reg
19750 BuildMI(MBB, MI, DL, TII->get(TargetOpcode::INSERT_SUBREG), NewDst)
19751 .addReg(PrevDst)
19752 .addReg(SubReg)
19754
19755 PrevDst = NewDst;
19756 }
19757
19758 // Add as an implicit operand
19759 MI.addOperand(MachineOperand::CreateReg(NewDst, false, true));
19760
19761 // Tie the just added implicit operand to the dst
19762 MI.tieOperands(DstIdx, MI.getNumOperands() - 1);
19763}
19764
19765/// Assign the register class depending on the number of
19766/// bits set in the writemask
19768 SDNode *Node) const {
19770
19771 MachineFunction *MF = MI.getMF();
19772 MachineRegisterInfo &MRI = MF->getRegInfo();
19773
19774 if (TII->isVOP3(MI.getOpcode())) {
19775 // Make sure constant bus requirements are respected.
19776 TII->legalizeOperandsVOP3(MRI, MI);
19777
19778 if (TII->isMAI(MI)) {
19779 // The ordinary src0, src1, src2 were legalized above.
19780 //
19781 // We have to also legalize the appended v_mfma_ld_scale_b32 operands,
19782 // as a separate instruction.
19783 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
19784 AMDGPU::OpName::scale_src0);
19785 if (Src0Idx != -1) {
19786 int Src1Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
19787 AMDGPU::OpName::scale_src1);
19788 if (TII->usesConstantBus(MRI, MI, Src0Idx) &&
19789 TII->usesConstantBus(MRI, MI, Src1Idx))
19790 TII->legalizeOpWithMove(MI, Src1Idx);
19791 }
19792 }
19793
19794 return;
19795 }
19796
19797 if (TII->isImage(MI))
19798 TII->enforceOperandRCAlignment(MI, AMDGPU::OpName::vaddr);
19799}
19800
19802 uint64_t Val) {
19803 SDValue K = DAG.getTargetConstant(Val, DL, MVT::i32);
19804 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, K), 0);
19805}
19806
19808 const SDLoc &DL,
19809 SDValue Ptr) const {
19811
19812 // Build the half of the subregister with the constants before building the
19813 // full 128-bit register. If we are building multiple resource descriptors,
19814 // this will allow CSEing of the 2-component register.
19815 const SDValue Ops0[] = {
19816 DAG.getTargetConstant(AMDGPU::SGPR_64RegClassID, DL, MVT::i32),
19817 buildSMovImm32(DAG, DL, 0),
19818 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
19819 buildSMovImm32(DAG, DL, TII->getDefaultRsrcDataFormat() >> 32),
19820 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32)};
19821
19822 SDValue SubRegHi = SDValue(
19823 DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v2i32, Ops0), 0);
19824
19825 // Combine the constants and the pointer.
19826 const SDValue Ops1[] = {
19827 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32), Ptr,
19828 DAG.getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32), SubRegHi,
19829 DAG.getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32)};
19830
19831 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops1);
19832}
19833
19834/// Return a resource descriptor with the 'Add TID' bit enabled
19835/// The TID (Thread ID) is multiplied by the stride value (bits [61:48]
19836/// of the resource descriptor) to create an offset, which is added to
19837/// the resource pointer.
19839 SDValue Ptr, uint32_t RsrcDword1,
19840 uint64_t RsrcDword2And3) const {
19841 SDValue PtrLo = DAG.getTargetExtractSubreg(AMDGPU::sub0, DL, MVT::i32, Ptr);
19842 SDValue PtrHi = DAG.getTargetExtractSubreg(AMDGPU::sub1, DL, MVT::i32, Ptr);
19843 if (RsrcDword1) {
19844 PtrHi = DAG.getNode(ISD::OR, DL, MVT::i32, PtrHi,
19845 DAG.getConstant(RsrcDword1, DL, MVT::i32));
19846 }
19847
19848 SDValue DataLo =
19849 buildSMovImm32(DAG, DL, RsrcDword2And3 & UINT64_C(0xFFFFFFFF));
19850 SDValue DataHi = buildSMovImm32(DAG, DL, RsrcDword2And3 >> 32);
19851
19852 const SDValue Ops[] = {
19853 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32),
19854 PtrLo,
19855 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
19856 PtrHi,
19857 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32),
19858 DataLo,
19859 DAG.getTargetConstant(AMDGPU::sub2, DL, MVT::i32),
19860 DataHi,
19861 DAG.getTargetConstant(AMDGPU::sub3, DL, MVT::i32)};
19862
19863 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops);
19864}
19865
19866//===----------------------------------------------------------------------===//
19867// SI Inline Assembly Support
19868//===----------------------------------------------------------------------===//
19869
19870std::pair<unsigned, const TargetRegisterClass *>
19872 StringRef Constraint,
19873 MVT VT) const {
19874 const SIRegisterInfo *TRI = static_cast<const SIRegisterInfo *>(TRI_);
19875
19876 const TargetRegisterClass *RC = nullptr;
19877 if (Constraint.size() == 1) {
19878 // Check if we cannot determine the bit size of the given value type. This
19879 // can happen, for example, in this situation where we have an empty struct
19880 // (size 0): `call void asm "", "v"({} poison)`-
19881 if (VT == MVT::Other)
19882 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
19883 const unsigned BitWidth = VT.getSizeInBits();
19884 switch (Constraint[0]) {
19885 default:
19886 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
19887 case 's':
19888 case 'r':
19889 switch (BitWidth) {
19890 case 16:
19891 RC = &AMDGPU::SReg_32RegClass;
19892 break;
19893 case 64:
19894 RC = &AMDGPU::SGPR_64RegClass;
19895 break;
19896 default:
19898 if (!RC)
19899 return std::pair(0U, nullptr);
19900 break;
19901 }
19902 break;
19903 case 'v':
19904 switch (BitWidth) {
19905 case 1:
19906 return std::pair(0U, nullptr);
19907 case 16:
19908 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
19909 : &AMDGPU::VGPR_32_Lo256RegClass;
19910 break;
19911 default:
19912 RC = Subtarget->has1024AddressableVGPRs()
19913 ? TRI->getAlignedLo256VGPRClassForBitWidth(BitWidth)
19914 : TRI->getVGPRClassForBitWidth(BitWidth);
19915 if (!RC)
19916 return std::pair(0U, nullptr);
19917 break;
19918 }
19919 break;
19920 case 'a':
19921 if (!Subtarget->hasMAIInsts())
19922 break;
19923 switch (BitWidth) {
19924 case 1:
19925 return std::pair(0U, nullptr);
19926 case 16:
19927 RC = &AMDGPU::AGPR_32RegClass;
19928 break;
19929 default:
19930 RC = TRI->getAGPRClassForBitWidth(BitWidth);
19931 if (!RC)
19932 return std::pair(0U, nullptr);
19933 break;
19934 }
19935 break;
19936 }
19937 } else if (Constraint == "VA" && Subtarget->hasGFX90AInsts()) {
19938 const unsigned BitWidth = VT.getSizeInBits();
19939 switch (BitWidth) {
19940 case 16:
19941 RC = &AMDGPU::AV_32RegClass;
19942 break;
19943 default:
19944 RC = TRI->getVectorSuperClassForBitWidth(BitWidth);
19945 if (!RC)
19946 return std::pair(0U, nullptr);
19947 break;
19948 }
19949 }
19950
19951 // We actually support i128, i16 and f16 as inline parameters
19952 // even if they are not reported as legal
19953 if (RC && (isTypeLegal(VT) || VT.SimpleTy == MVT::i128 ||
19954 VT.SimpleTy == MVT::i16 || VT.SimpleTy == MVT::f16))
19955 return std::pair(0U, RC);
19956
19957 auto [Kind, Idx, NumRegs] = AMDGPU::parseAsmConstraintPhysReg(Constraint);
19958 if (Kind != '\0') {
19959 if (Kind == 'v') {
19960 RC = &AMDGPU::VGPR_32_Lo256RegClass;
19961 } else if (Kind == 's') {
19962 RC = &AMDGPU::SGPR_32RegClass;
19963 } else if (Kind == 'a') {
19964 RC = &AMDGPU::AGPR_32RegClass;
19965 }
19966
19967 if (RC) {
19968 if (NumRegs > 1) {
19969 if (Idx >= RC->getNumRegs() || Idx + NumRegs - 1 >= RC->getNumRegs())
19970 return std::pair(0U, nullptr);
19971
19972 uint32_t Width = NumRegs * 32;
19973 // Prohibit constraints for register ranges with a width that does not
19974 // match the required type.
19975 if (VT.SimpleTy != MVT::Other && Width != VT.getSizeInBits())
19976 return std::pair(0U, nullptr);
19977
19978 MCRegister Reg = RC->getRegister(Idx);
19980 RC = TRI->getVGPRClassForBitWidth(Width);
19981 else if (SIRegisterInfo::isSGPRClass(RC))
19982 RC = TRI->getSGPRClassForBitWidth(Width);
19983 else if (SIRegisterInfo::isAGPRClass(RC))
19984 RC = TRI->getAGPRClassForBitWidth(Width);
19985 if (RC) {
19986 Reg = TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
19987 if (!Reg) {
19988 // The register class does not contain the requested register,
19989 // e.g., because it is an SGPR pair that would violate alignment
19990 // requirements.
19991 return std::pair(0U, nullptr);
19992 }
19993 return std::pair(Reg, RC);
19994 }
19995 }
19996
19997 // Reject types that do not fit a single 32-bit register: any scalar wider
19998 // than 32 bits, or a vector that is not exactly 32 bits.
19999 if (VT.SimpleTy != MVT::Other &&
20000 (VT.getSizeInBits() > 32 ||
20001 (VT.isVector() && VT.getSizeInBits() != 32)))
20002 return std::pair(0U, nullptr);
20003 if (RC && Idx < RC->getNumRegs())
20004 return std::pair(RC->getRegister(Idx), RC);
20005 return std::pair(0U, nullptr);
20006 }
20007 }
20008
20009 auto Ret = TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20010 if (Ret.first)
20011 Ret.second = TRI->getPhysRegBaseClass(Ret.first);
20012
20013 return Ret;
20014}
20015
20016static bool isImmConstraint(StringRef Constraint) {
20017 if (Constraint.size() == 1) {
20018 switch (Constraint[0]) {
20019 default:
20020 break;
20021 case 'I':
20022 case 'J':
20023 case 'A':
20024 case 'B':
20025 case 'C':
20026 return true;
20027 }
20028 } else if (Constraint == "DA" || Constraint == "DB") {
20029 return true;
20030 }
20031 return false;
20032}
20033
20036 if (Constraint.size() == 1) {
20037 switch (Constraint[0]) {
20038 default:
20039 break;
20040 case 's':
20041 case 'v':
20042 case 'a':
20043 return C_RegisterClass;
20044 }
20045 } else if (Constraint.size() == 2) {
20046 if (Constraint == "VA")
20047 return C_RegisterClass;
20048 }
20049 if (isImmConstraint(Constraint)) {
20050 return C_Other;
20051 }
20052 return TargetLowering::getConstraintType(Constraint);
20053}
20054
20055static uint64_t clearUnusedBits(uint64_t Val, unsigned Size) {
20057 Val = Val & maskTrailingOnes<uint64_t>(Size);
20058 }
20059 return Val;
20060}
20061
20063 StringRef Constraint,
20064 std::vector<SDValue> &Ops,
20065 SelectionDAG &DAG) const {
20066 if (isImmConstraint(Constraint)) {
20067 uint64_t Val;
20068 if (getAsmOperandConstVal(Op, Val) &&
20069 checkAsmConstraintVal(Op, Constraint, Val)) {
20070 Val = clearUnusedBits(Val, Op.getScalarValueSizeInBits());
20071 Ops.push_back(DAG.getTargetConstant(Val, SDLoc(Op), MVT::i64));
20072 }
20073 } else {
20075 }
20076}
20077
20079 unsigned Size = Op.getScalarValueSizeInBits();
20080 if (Size > 64)
20081 return false;
20082
20083 if (Size == 16 && !Subtarget->has16BitInsts())
20084 return false;
20085
20087 Val = C->getSExtValue();
20088 return true;
20089 }
20091 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
20092 return true;
20093 }
20095 if (Size != 16 || Op.getNumOperands() != 2)
20096 return false;
20097 if (Op.getOperand(0).isUndef() || Op.getOperand(1).isUndef())
20098 return false;
20099 if (ConstantSDNode *C = V->getConstantSplatNode()) {
20100 Val = C->getSExtValue();
20101 return true;
20102 }
20103 if (ConstantFPSDNode *C = V->getConstantFPSplatNode()) {
20104 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
20105 return true;
20106 }
20107 }
20108
20109 return false;
20110}
20111
20113 uint64_t Val) const {
20114 if (Constraint.size() == 1) {
20115 switch (Constraint[0]) {
20116 case 'I':
20118 case 'J':
20119 return isInt<16>(Val);
20120 case 'A':
20121 return checkAsmConstraintValA(Op, Val);
20122 case 'B':
20123 return isInt<32>(Val);
20124 case 'C':
20125 return isUInt<32>(clearUnusedBits(Val, Op.getScalarValueSizeInBits())) ||
20127 default:
20128 break;
20129 }
20130 } else if (Constraint.size() == 2) {
20131 if (Constraint == "DA") {
20132 int64_t HiBits = static_cast<int32_t>(Val >> 32);
20133 int64_t LoBits = static_cast<int32_t>(Val);
20134 return checkAsmConstraintValA(Op, HiBits, 32) &&
20135 checkAsmConstraintValA(Op, LoBits, 32);
20136 }
20137 if (Constraint == "DB") {
20138 return true;
20139 }
20140 }
20141 llvm_unreachable("Invalid asm constraint");
20142}
20143
20145 unsigned MaxSize) const {
20146 unsigned Size = std::min<unsigned>(Op.getScalarValueSizeInBits(), MaxSize);
20147 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
20148 if (Size == 16) {
20149 MVT VT = Op.getSimpleValueType();
20150 switch (VT.SimpleTy) {
20151 default:
20152 return false;
20153 case MVT::i16:
20154 return AMDGPU::isInlinableLiteralI16(Val, HasInv2Pi);
20155 case MVT::f16:
20156 return AMDGPU::isInlinableLiteralFP16(Val, HasInv2Pi);
20157 case MVT::bf16:
20158 return AMDGPU::isInlinableLiteralBF16(Val, HasInv2Pi);
20159 case MVT::v2i16:
20160 return AMDGPU::getInlineEncodingV2I16(Val).has_value();
20161 case MVT::v2f16:
20162 return AMDGPU::getInlineEncodingV2F16(Val).has_value();
20163 case MVT::v2bf16:
20164 return AMDGPU::getInlineEncodingV2BF16(Val).has_value();
20165 }
20166 }
20167 if ((Size == 32 && AMDGPU::isInlinableLiteral32(Val, HasInv2Pi)) ||
20168 (Size == 64 && AMDGPU::isInlinableLiteral64(Val, HasInv2Pi)))
20169 return true;
20170 return false;
20171}
20172
20173static int getAlignedAGPRClassID(unsigned UnalignedClassID) {
20174 switch (UnalignedClassID) {
20175 case AMDGPU::VReg_64RegClassID:
20176 return AMDGPU::VReg_64_Align2RegClassID;
20177 case AMDGPU::VReg_96RegClassID:
20178 return AMDGPU::VReg_96_Align2RegClassID;
20179 case AMDGPU::VReg_128RegClassID:
20180 return AMDGPU::VReg_128_Align2RegClassID;
20181 case AMDGPU::VReg_160RegClassID:
20182 return AMDGPU::VReg_160_Align2RegClassID;
20183 case AMDGPU::VReg_192RegClassID:
20184 return AMDGPU::VReg_192_Align2RegClassID;
20185 case AMDGPU::VReg_224RegClassID:
20186 return AMDGPU::VReg_224_Align2RegClassID;
20187 case AMDGPU::VReg_256RegClassID:
20188 return AMDGPU::VReg_256_Align2RegClassID;
20189 case AMDGPU::VReg_288RegClassID:
20190 return AMDGPU::VReg_288_Align2RegClassID;
20191 case AMDGPU::VReg_320RegClassID:
20192 return AMDGPU::VReg_320_Align2RegClassID;
20193 case AMDGPU::VReg_352RegClassID:
20194 return AMDGPU::VReg_352_Align2RegClassID;
20195 case AMDGPU::VReg_384RegClassID:
20196 return AMDGPU::VReg_384_Align2RegClassID;
20197 case AMDGPU::VReg_512RegClassID:
20198 return AMDGPU::VReg_512_Align2RegClassID;
20199 case AMDGPU::VReg_1024RegClassID:
20200 return AMDGPU::VReg_1024_Align2RegClassID;
20201 case AMDGPU::AReg_64RegClassID:
20202 return AMDGPU::AReg_64_Align2RegClassID;
20203 case AMDGPU::AReg_96RegClassID:
20204 return AMDGPU::AReg_96_Align2RegClassID;
20205 case AMDGPU::AReg_128RegClassID:
20206 return AMDGPU::AReg_128_Align2RegClassID;
20207 case AMDGPU::AReg_160RegClassID:
20208 return AMDGPU::AReg_160_Align2RegClassID;
20209 case AMDGPU::AReg_192RegClassID:
20210 return AMDGPU::AReg_192_Align2RegClassID;
20211 case AMDGPU::AReg_256RegClassID:
20212 return AMDGPU::AReg_256_Align2RegClassID;
20213 case AMDGPU::AReg_512RegClassID:
20214 return AMDGPU::AReg_512_Align2RegClassID;
20215 case AMDGPU::AReg_1024RegClassID:
20216 return AMDGPU::AReg_1024_Align2RegClassID;
20217 default:
20218 return -1;
20219 }
20220}
20221
20222// Figure out which registers should be reserved for stack access. Only after
20223// the function is legalized do we know all of the non-spill stack objects or if
20224// calls are present.
20226 MachineRegisterInfo &MRI = MF.getRegInfo();
20228 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
20229 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20230 const SIInstrInfo *TII = ST.getInstrInfo();
20231
20232 if (Info->isEntryFunction()) {
20233 // Callable functions have fixed registers used for stack access.
20235 }
20236
20237 // TODO: Move this logic to getReservedRegs()
20238 // Reserve the SGPR(s) to save/restore EXEC for WWM spill/copy handling.
20239 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20240 Register SReg = ST.isWave32()
20241 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20242 : TRI->getAlignedHighSGPRForRC(MF, /*Align=*/2,
20243 &AMDGPU::SGPR_64RegClass);
20244 Info->setSGPRForEXECCopy(SReg);
20245
20246 assert(!TRI->isSubRegister(Info->getScratchRSrcReg(),
20247 Info->getStackPtrOffsetReg()));
20248 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20249 MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20250
20251 // We need to worry about replacing the default register with itself in case
20252 // of MIR testcases missing the MFI.
20253 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20254 MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20255
20256 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20257 MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());
20258
20259 Info->limitOccupancy(MF);
20260
20261 if (ST.isWave32() && !MF.empty()) {
20262 for (auto &MBB : MF) {
20263 for (auto &MI : MBB) {
20264 TII->fixImplicitOperands(MI);
20265 }
20266 }
20267 }
20268
20269 // FIXME: This is a hack to fixup AGPR classes to use the properly aligned
20270 // classes if required. Ideally the register class constraints would differ
20271 // per-subtarget, but there's no easy way to achieve that right now. This is
20272 // not a problem for VGPRs because the correctly aligned VGPR class is implied
20273 // from using them as the register class for legal types.
20274 if (ST.needsAlignedVGPRs()) {
20275 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
20276 const Register Reg = Register::index2VirtReg(I);
20277 const TargetRegisterClass *RC = MRI.getRegClassOrNull(Reg);
20278 if (!RC)
20279 continue;
20280 int NewClassID = getAlignedAGPRClassID(RC->getID());
20281 if (NewClassID != -1)
20282 MRI.setRegClass(Reg, TRI->getRegClass(NewClassID));
20283 }
20284 }
20285
20287}
20288
20291 const APInt &DemandedElts,
20292 const SelectionDAG &DAG,
20293 unsigned Depth) const {
20294 Known.resetAll();
20295 unsigned Opc = Op.getOpcode();
20296 switch (Opc) {
20298 unsigned IID = Op.getConstantOperandVal(0);
20299 switch (IID) {
20300 case Intrinsic::amdgcn_mbcnt_lo:
20301 case Intrinsic::amdgcn_mbcnt_hi: {
20302 const GCNSubtarget &ST =
20304 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20305 // most 31 + src1.
20306 Known.Zero.setBitsFrom(
20307 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20308 KnownBits Known2 = DAG.computeKnownBits(Op.getOperand(2), Depth + 1);
20309 Known = KnownBits::add(Known, Known2);
20310 return;
20311 }
20312 }
20313 break;
20314 }
20315 }
20317 Op, Known, DemandedElts, DAG, Depth);
20318}
20319
20321 KnownBits &Known, const MachineFunction &MF, Align Alignment) const {
20323
20324 // Set the high bits to zero based on the maximum allowed scratch size per
20325 // wave. We can't use vaddr in MUBUF instructions if we don't know the address
20326 // calculation won't overflow, so assume the sign bit is never set.
20327 Known.Zero.setHighBits(getSubtarget()->getKnownHighZeroBitsForFrameIndex());
20328}
20329
20332 unsigned Dim) {
20333 unsigned MaxValue =
20334 ST.getMaxWorkitemID(VT.getMachineFunction().getFunction(), Dim);
20335 Known.Zero.setHighBits(llvm::countl_zero(MaxValue));
20336}
20337
20339 KnownBits &Known, const APInt &DemandedElts,
20340 unsigned BFEWidth, bool SExt, unsigned Depth) {
20342 const MachineOperand &Src1 = MI.getOperand(2);
20343
20344 unsigned Src1Cst = 0;
20345 if (Src1.isImm()) {
20346 Src1Cst = Src1.getImm();
20347 } else if (Src1.isReg()) {
20348 auto Cst = getIConstantVRegValWithLookThrough(Src1.getReg(), MRI);
20349 if (!Cst)
20350 return;
20351 Src1Cst = Cst->Value.getZExtValue();
20352 } else {
20353 return;
20354 }
20355
20356 // Offset is at bits [4:0] for 32 bit, [5:0] for 64 bit.
20357 // Width is always [22:16].
20358 const unsigned Offset =
20359 Src1Cst & maskTrailingOnes<unsigned>((BFEWidth == 32) ? 5 : 6);
20360 const unsigned Width = (Src1Cst >> 16) & maskTrailingOnes<unsigned>(6);
20361
20362 if (Width >= BFEWidth) // Ill-formed.
20363 return;
20364
20365 VT.computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
20366 Depth + 1);
20367
20368 Known = Known.extractBits(Width, Offset);
20369
20370 if (SExt)
20371 Known = Known.sext(BFEWidth);
20372 else
20373 Known = Known.zext(BFEWidth);
20374}
20375
20378 const APInt &DemandedElts, const MachineRegisterInfo &MRI,
20379 unsigned Depth) const {
20380 Known.resetAll();
20381 const MachineInstr *MI = MRI.getVRegDef(R);
20382 switch (MI->getOpcode()) {
20383 case AMDGPU::S_BFE_I32:
20384 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20385 /*SExt=*/true, Depth);
20386 case AMDGPU::S_BFE_U32:
20387 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20388 /*SExt=*/false, Depth);
20389 case AMDGPU::S_BFE_I64:
20390 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20391 /*SExt=*/true, Depth);
20392 case AMDGPU::S_BFE_U64:
20393 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20394 /*SExt=*/false, Depth);
20395 case AMDGPU::G_INTRINSIC:
20396 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20397 Intrinsic::ID IID = cast<GIntrinsic>(MI)->getIntrinsicID();
20398 switch (IID) {
20399 case Intrinsic::amdgcn_workitem_id_x:
20401 break;
20402 case Intrinsic::amdgcn_workitem_id_y:
20404 break;
20405 case Intrinsic::amdgcn_workitem_id_z:
20407 break;
20408 case Intrinsic::amdgcn_mbcnt_lo:
20409 case Intrinsic::amdgcn_mbcnt_hi: {
20410 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20411 // most 31 + src1.
20412 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20413 ? getSubtarget()->getWavefrontSizeLog2()
20414 : 5);
20415 KnownBits Known2;
20416 VT.computeKnownBitsImpl(MI->getOperand(3).getReg(), Known2, DemandedElts,
20417 Depth + 1);
20418 Known = KnownBits::add(Known, Known2);
20419 break;
20420 }
20421 case Intrinsic::amdgcn_groupstaticsize: {
20422 // We can report everything over the maximum size as 0. We can't report
20423 // based on the actual size because we don't know if it's accurate or not
20424 // at any given point.
20425 Known.Zero.setHighBits(
20426 llvm::countl_zero(getSubtarget()->getAddressableLocalMemorySize()));
20427 break;
20428 }
20429 }
20430 break;
20431 }
20432 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20433 Known.Zero.setHighBits(24);
20434 break;
20435 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20436 Known.Zero.setHighBits(16);
20437 break;
20438 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20439 // G_AMDGPU_COPY_SCC_VCC converts a uniform boolean in VCC to SGPR s32,
20440 // producing exactly 0 or 1.
20441 Known.Zero.setHighBits(Known.getBitWidth() - 1);
20442 break;
20443 case AMDGPU::G_AMDGPU_SMED3:
20444 case AMDGPU::G_AMDGPU_UMED3: {
20445 auto [Dst, Src0, Src1, Src2] = MI->getFirst4Regs();
20446
20447 KnownBits Known2;
20448 VT.computeKnownBitsImpl(Src2, Known2, DemandedElts, Depth + 1);
20449 if (Known2.isUnknown())
20450 break;
20451
20452 KnownBits Known1;
20453 VT.computeKnownBitsImpl(Src1, Known1, DemandedElts, Depth + 1);
20454 if (Known1.isUnknown())
20455 break;
20456
20457 KnownBits Known0;
20458 VT.computeKnownBitsImpl(Src0, Known0, DemandedElts, Depth + 1);
20459 if (Known0.isUnknown())
20460 break;
20461
20462 // TODO: Handle LeadZero/LeadOne from UMIN/UMAX handling.
20463 Known.Zero = Known0.Zero & Known1.Zero & Known2.Zero;
20464 Known.One = Known0.One & Known1.One & Known2.One;
20465 break;
20466 }
20467 }
20468}
20469
20472 unsigned Depth) const {
20473 const MachineInstr *MI = MRI.getVRegDef(R);
20474 if (auto *GI = dyn_cast<GIntrinsic>(MI)) {
20475 // FIXME: Can this move to generic code? What about the case where the call
20476 // site specifies a lower alignment?
20477 Intrinsic::ID IID = GI->getIntrinsicID();
20479 AttributeList Attrs =
20480 Intrinsic::getAttributes(Ctx, IID, Intrinsic::getType(Ctx, IID));
20481 if (MaybeAlign RetAlign = Attrs.getRetAlignment())
20482 return *RetAlign;
20483 }
20484 return Align(1);
20485}
20486
20489 const Align CacheLineAlign = Align(64);
20490
20491 // GFX950: Prevent an 8-byte instruction at loop header from being split by
20492 // the 32-byte instruction fetch window boundary. This avoids a significant
20493 // fetch delay after backward branch. We use 32-byte alignment with max
20494 // padding of 4 bytes (one s_nop), see getMaxPermittedBytesForAlignment().
20495 if (ML && !DisableLoopAlignment &&
20496 getSubtarget()->hasLoopHeadInstSplitSensitivity()) {
20497 const MachineBasicBlock *Header = ML->getHeader();
20498 // Respect user-specified or previously set alignment.
20499 if (Header->getAlignment() != PrefAlign)
20500 return Header->getAlignment();
20501 if (needsFetchWindowAlignment(*Header))
20502 return Align(32);
20503 }
20504
20505 // Pre-GFX10 target did not benefit from loop alignment
20506 if (!ML || DisableLoopAlignment || !getSubtarget()->hasInstPrefetch() ||
20507 getSubtarget()->hasInstFwdPrefetchBug())
20508 return PrefAlign;
20509
20510 // On GFX10 I$ is 4 x 64 bytes cache lines.
20511 // By default prefetcher keeps one cache line behind and reads two ahead.
20512 // We can modify it with S_INST_PREFETCH for larger loops to have two lines
20513 // behind and one ahead.
20514 // Therefor we can benefit from aligning loop headers if loop fits 192 bytes.
20515 // If loop fits 64 bytes it always spans no more than two cache lines and
20516 // does not need an alignment.
20517 // Else if loop is less or equal 128 bytes we do not need to modify prefetch,
20518 // Else if loop is less or equal 192 bytes we need two lines behind.
20519
20521 const MachineBasicBlock *Header = ML->getHeader();
20522 if (Header->getAlignment() != PrefAlign)
20523 return Header->getAlignment(); // Already processed.
20524
20525 unsigned LoopSize = 0;
20526 for (const MachineBasicBlock *MBB : ML->blocks()) {
20527 // If inner loop block is aligned assume in average half of the alignment
20528 // size to be added as nops.
20529 if (MBB != Header)
20530 LoopSize += MBB->getAlignment().value() / 2;
20531
20532 for (const MachineInstr &MI : *MBB) {
20533 LoopSize += TII->getInstSizeInBytes(MI);
20534 if (LoopSize > 192)
20535 return PrefAlign;
20536 }
20537 }
20538
20539 if (LoopSize <= 64)
20540 return PrefAlign;
20541
20542 if (LoopSize <= 128)
20543 return CacheLineAlign;
20544
20545 // If any of parent loops is surrounded by prefetch instructions do not
20546 // insert new for inner loop, which would reset parent's settings.
20547 for (MachineLoop *P = ML->getParentLoop(); P; P = P->getParentLoop()) {
20548 if (MachineBasicBlock *Exit = P->getExitBlock()) {
20549 auto I = Exit->getFirstNonDebugInstr();
20550 if (I != Exit->end() && I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20551 return CacheLineAlign;
20552 }
20553 }
20554
20555 MachineBasicBlock *Pre = ML->getLoopPreheader();
20556 MachineBasicBlock *Exit = ML->getExitBlock();
20557
20558 if (Pre && Exit) {
20559 auto PreTerm = Pre->getFirstTerminator();
20560 if (PreTerm == Pre->begin() ||
20561 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20562 BuildMI(*Pre, PreTerm, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20563 .addImm(1); // prefetch 2 lines behind PC
20564
20565 auto ExitHead = Exit->getFirstNonDebugInstr();
20566 if (ExitHead == Exit->end() ||
20567 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20568 BuildMI(*Exit, ExitHead, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20569 .addImm(2); // prefetch 1 line behind PC
20570 }
20571
20572 return CacheLineAlign;
20573}
20574
20576 MachineBasicBlock *MBB) const {
20577 // GFX950: Limit padding to 4 bytes (one s_nop) for blocks where an 8-byte
20578 // instruction could be split by the 32-byte fetch window boundary.
20579 // See getPrefLoopAlignment() for context.
20580 if (needsFetchWindowAlignment(*MBB))
20581 return 4;
20583}
20584
20585bool SITargetLowering::needsFetchWindowAlignment(
20586 const MachineBasicBlock &MBB) const {
20587 if (!getSubtarget()->hasLoopHeadInstSplitSensitivity())
20588 return false;
20590 for (const MachineInstr &MI : MBB) {
20591 if (MI.isMetaInstruction())
20592 continue;
20593 // Instructions larger than 4 bytes can be split by a 32-byte boundary.
20594 return TII->getInstSizeInBytes(MI) > 4;
20595 }
20596 return false;
20597}
20598
20599[[maybe_unused]]
20600static bool isCopyFromRegOfInlineAsm(const SDNode *N) {
20601 assert(N->getOpcode() == ISD::CopyFromReg);
20602 do {
20603 // Follow the chain until we find an INLINEASM node.
20604 N = N->getOperand(0).getNode();
20605 if (N->getOpcode() == ISD::INLINEASM || N->getOpcode() == ISD::INLINEASM_BR)
20606 return true;
20607 } while (N->getOpcode() == ISD::CopyFromReg);
20608 return false;
20609}
20610
20613 UniformityInfo *UA) const {
20614 switch (N->getOpcode()) {
20615 case ISD::CopyFromReg: {
20616 const RegisterSDNode *R = cast<RegisterSDNode>(N->getOperand(1));
20617 const MachineRegisterInfo &MRI = FLI->MF->getRegInfo();
20618 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20619 Register Reg = R->getReg();
20620
20621 // FIXME: Why does this need to consider isLiveIn?
20622 if (Reg.isPhysical() || MRI.isLiveIn(Reg))
20623 return !TRI->isSGPRReg(MRI, Reg);
20624
20625 if (const Value *V = FLI->getValueFromVirtualReg(R->getReg()))
20626 return UA->isDivergentAtDef(V);
20627
20629 return !TRI->isSGPRReg(MRI, Reg);
20630 }
20631 case ISD::LOAD: {
20632 const LoadSDNode *L = cast<LoadSDNode>(N);
20633 unsigned AS = L->getAddressSpace();
20634 // A flat load may access private memory.
20636 }
20637 case ISD::CALLSEQ_END:
20638 return true;
20640 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(0));
20642 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(1));
20643 case AMDGPUISD::ATOMIC_CMP_SWAP:
20644 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20645 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20646 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20647 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20648 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20649 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20650 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20651 case AMDGPUISD::BUFFER_ATOMIC_AND:
20652 case AMDGPUISD::BUFFER_ATOMIC_OR:
20653 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20654 case AMDGPUISD::BUFFER_ATOMIC_INC:
20655 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20656 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20657 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20658 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20659 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20660 // Target-specific read-modify-write atomics are sources of divergence.
20661 return true;
20662 default:
20663 if (auto *A = dyn_cast<AtomicSDNode>(N)) {
20664 // Generic read-modify-write atomics are sources of divergence.
20665 return A->readMem() && A->writeMem();
20666 }
20667 return false;
20668 }
20669}
20670
20672 EVT VT) const {
20673 switch (VT.getScalarType().getSimpleVT().SimpleTy) {
20674 case MVT::f32:
20676 case MVT::f64:
20677 case MVT::f16:
20679 default:
20680 return false;
20681 }
20682}
20683
20685 LLT Ty, const MachineFunction &MF) const {
20686 switch (Ty.getScalarSizeInBits()) {
20687 case 32:
20688 return !denormalModeIsFlushAllF32(MF);
20689 case 64:
20690 case 16:
20691 return !denormalModeIsFlushAllF64F16(MF);
20692 default:
20693 return false;
20694 }
20695}
20696
20698 const APInt &DemandedElts,
20699 const SelectionDAG &DAG,
20700 bool SNaN,
20701 unsigned Depth) const {
20702 if (Op.getOpcode() == AMDGPUISD::CLAMP) {
20703 const MachineFunction &MF = DAG.getMachineFunction();
20705
20706 if (Info->getMode().DX10Clamp)
20707 return true; // Clamped to 0.
20708 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);
20709 }
20710
20712 DAG, SNaN, Depth);
20713}
20714
20715// On older subtargets, global FP atomic instructions have a hardcoded FP mode
20716// and do not support FP32 denormals, and only support v2f16/f64 denormals.
20718 if (RMW->hasMetadata("amdgpu.ignore.denormal.mode"))
20719 return true;
20720
20721 const fltSemantics &Flt = RMW->getType()->getScalarType()->getFltSemantics();
20722 auto DenormMode = RMW->getFunction()->getDenormalMode(Flt);
20723 if (DenormMode == DenormalMode::getPreserveSign())
20724 return true;
20725
20726 // TODO: Remove this.
20727 return RMW->getFunction()
20728 ->getFnAttribute("amdgpu-unsafe-fp-atomics")
20729 .getValueAsBool();
20730}
20731
20733 LLVMContext &Ctx = RMW->getContext();
20734 StringRef MemScope =
20735 Ctx.getSyncScopeName(RMW->getSyncScopeID()).value_or("system");
20736
20737 return OptimizationRemark(DEBUG_TYPE, "Passed", RMW)
20738 << "Hardware instruction generated for atomic "
20739 << RMW->getOperationName(RMW->getOperation())
20740 << " operation at memory scope " << MemScope;
20741}
20742
20743static bool isV2F16OrV2BF16(Type *Ty) {
20744 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
20745 Type *EltTy = VT->getElementType();
20746 return VT->getNumElements() == 2 &&
20747 (EltTy->isHalfTy() || EltTy->isBFloatTy());
20748 }
20749
20750 return false;
20751}
20752
20753static bool isV2F16(Type *Ty) {
20755 return VT && VT->getNumElements() == 2 && VT->getElementType()->isHalfTy();
20756}
20757
20758static bool isV2BF16(Type *Ty) {
20760 return VT && VT->getNumElements() == 2 && VT->getElementType()->isBFloatTy();
20761}
20762
20763/// \return true if atomicrmw integer ops work for the type.
20764static bool isAtomicRMWLegalIntTy(Type *Ty) {
20765 if (auto *IT = dyn_cast<IntegerType>(Ty)) {
20766 unsigned BW = IT->getBitWidth();
20767 return BW == 32 || BW == 64;
20768 }
20769
20770 return false;
20771}
20772
20773/// \return true if this atomicrmw xchg type can be selected.
20774static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW) {
20775 Type *Ty = RMW->getType();
20776 if (isAtomicRMWLegalIntTy(Ty))
20777 return true;
20778
20779 if (PointerType *PT = dyn_cast<PointerType>(Ty)) {
20780 const DataLayout &DL = RMW->getFunction()->getParent()->getDataLayout();
20781 unsigned BW = DL.getPointerSizeInBits(PT->getAddressSpace());
20782 return BW == 32 || BW == 64;
20783 }
20784
20785 if (Ty->isFloatTy() || Ty->isDoubleTy())
20786 return true;
20787
20789 return VT->getNumElements() == 2 &&
20790 VT->getElementType()->getPrimitiveSizeInBits() == 16;
20791 }
20792
20793 return false;
20794}
20795
20796/// \returns true if it's valid to emit a native instruction for \p RMW, based
20797/// on the properties of the target memory.
20798static bool globalMemoryFPAtomicIsLegal(const GCNSubtarget &Subtarget,
20799 const AtomicRMWInst *RMW,
20800 bool HasSystemScope) {
20801 // The remote/fine-grained access logic is different from the integer
20802 // atomics. Without AgentScopeFineGrainedRemoteMemoryAtomics support,
20803 // fine-grained access does not work, even for a device local allocation.
20804 //
20805 // With AgentScopeFineGrainedRemoteMemoryAtomics, system scoped device local
20806 // allocations work.
20807 if (HasSystemScope) {
20808 if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
20809 RMW->hasMetadata("amdgpu.no.remote.memory"))
20810 return true;
20811 if (Subtarget.hasEmulatedSystemScopeAtomics())
20812 return true;
20813 } else if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
20814 return true;
20815
20816 return RMW->hasMetadata("amdgpu.no.fine.grained.memory");
20817}
20818
20819/// \return Action to perform on AtomicRMWInsts for integer operations.
20826
20827/// Return if a flat address space atomicrmw can access private memory.
20829 const MDNode *MD = I->getMetadata(LLVMContext::MD_noalias_addrspace);
20830 return !MD ||
20832}
20833
20836 // For GAS, lower to flat atomic.
20837 return STI.hasGloballyAddressableScratch()
20840}
20841
20844 unsigned AS = RMW->getPointerAddressSpace();
20845 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
20847
20848 // 64-bit flat atomics that dynamically reside in private memory will silently
20849 // be dropped.
20850 //
20851 // Note that we will emit a new copy of the original atomic in the expansion,
20852 // which will be incrementally relegalized.
20853 const DataLayout &DL = RMW->getFunction()->getDataLayout();
20854 if (AS == AMDGPUAS::FLAT_ADDRESS &&
20855 DL.getTypeSizeInBits(RMW->getType()) == 64 &&
20858
20859 auto ReportUnsafeHWInst = [=](TargetLowering::AtomicExpansionKind Kind) {
20861 ORE.emit([=]() {
20862 return emitAtomicRMWLegalRemark(RMW) << " due to an unsafe request.";
20863 });
20864 return Kind;
20865 };
20866
20867 auto SSID = RMW->getSyncScopeID();
20868 bool HasSystemScope =
20869 SSID == SyncScope::System ||
20871 getTargetMachine().getTargetTriple(), AtomicScope::System,
20872 /*OneAddressSpace=*/true));
20873
20874 auto Op = RMW->getOperation();
20875 switch (Op) {
20877 // PCIe supports add and xchg for system atomics.
20878 return isAtomicRMWLegalXChgTy(RMW)
20881 case AtomicRMWInst::Add:
20882 // PCIe supports add and xchg for system atomics.
20884 case AtomicRMWInst::Sub:
20885 case AtomicRMWInst::And:
20886 case AtomicRMWInst::Or:
20887 case AtomicRMWInst::Xor:
20888 case AtomicRMWInst::Max:
20889 case AtomicRMWInst::Min:
20896 if (Op == AtomicRMWInst::USubCond && !Subtarget->hasCondSubInsts())
20898 if (Op == AtomicRMWInst::USubSat && !Subtarget->hasSubClampInsts())
20901 auto *IT = dyn_cast<IntegerType>(RMW->getType());
20902 if (!IT || IT->getBitWidth() != 32)
20904 }
20905
20908 if (Subtarget->hasEmulatedSystemScopeAtomics())
20910
20911 // On most subtargets, for atomicrmw operations other than add/xchg,
20912 // whether or not the instructions will behave correctly depends on where
20913 // the address physically resides and what interconnect is used in the
20914 // system configuration. On some some targets the instruction will nop,
20915 // and in others synchronization will only occur at degraded device scope.
20916 //
20917 // If the allocation is known local to the device, the instructions should
20918 // work correctly.
20919 if (RMW->hasMetadata("amdgpu.no.remote.memory"))
20921
20922 // If fine-grained remote memory works at device scope, we don't need to
20923 // do anything.
20924 if (!HasSystemScope &&
20925 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
20927
20928 // If we are targeting a remote allocated address, it depends what kind of
20929 // allocation the address belongs to.
20930 //
20931 // If the allocation is fine-grained (in host memory, or in PCIe peer
20932 // device memory), the operation will fail depending on the target.
20933 //
20934 // Note fine-grained host memory access does work on APUs or if XGMI is
20935 // used, but we do not know if we are targeting an APU or the system
20936 // configuration from the ISA version/target-cpu.
20937 if (RMW->hasMetadata("amdgpu.no.fine.grained.memory"))
20939
20942 // Atomic sub/or/xor do not work over PCI express, but atomic add
20943 // does. InstCombine transforms these with 0 to or, so undo that.
20944 // Sub-word types are not selectable and take the cmpxchg expansion.
20945 if (const Constant *ConstVal = dyn_cast<Constant>(RMW->getValOperand());
20946 ConstVal && ConstVal->isNullValue() &&
20949 }
20950
20951 // If the allocation could be in remote, fine-grained memory, the rmw
20952 // instructions may fail. cmpxchg should work, so emit that. On some
20953 // system configurations, PCIe atomics aren't supported so cmpxchg won't
20954 // even work, so you're out of luck anyway.
20955
20956 // In summary:
20957 //
20958 // Cases that may fail:
20959 // - fine-grained pinned host memory
20960 // - fine-grained migratable host memory
20961 // - fine-grained PCIe peer device
20962 //
20963 // Cases that should work, but may be treated overly conservatively.
20964 // - fine-grained host memory on an APU
20965 // - fine-grained XGMI peer device
20967 }
20968
20970 }
20971 case AtomicRMWInst::FAdd: {
20972 Type *Ty = RMW->getType();
20973
20974 // TODO: Handle REGION_ADDRESS
20975 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
20976 // DS F32 FP atomics do respect the denormal mode, but the rounding mode
20977 // is fixed to round-to-nearest-even.
20978 //
20979 // F64 / PK_F16 / PK_BF16 never flush and are also fixed to
20980 // round-to-nearest-even.
20981 //
20982 // We ignore the rounding mode problem, even in strictfp. The C++ standard
20983 // suggests it is OK if the floating-point mode may not match the calling
20984 // thread.
20985 if (Ty->isFloatTy()) {
20986 return Subtarget->hasLDSFPAtomicAddF32() ? AtomicExpansionKind::None
20988 }
20989
20990 if (Ty->isDoubleTy()) {
20991 // Ignores denormal mode, but we don't consider flushing mandatory.
20992 return Subtarget->hasLDSFPAtomicAddF64() ? AtomicExpansionKind::None
20994 }
20995
20996 if (Subtarget->hasAtomicDsPkAdd16Insts() && isV2F16OrV2BF16(Ty))
20998
21000 }
21001
21002 // LDS atomics respect the denormal mode from the mode register.
21003 //
21004 // Traditionally f32 global/buffer memory atomics would unconditionally
21005 // flush denormals, but newer targets do not flush. f64/f16/bf16 cases never
21006 // flush.
21007 //
21008 // On targets with flat atomic fadd, denormals would flush depending on
21009 // whether the target address resides in LDS or global memory. We consider
21010 // this flat-maybe-flush as will-flush.
21011 if (Ty->isFloatTy() &&
21012 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport() &&
21015
21016 // FIXME: These ReportUnsafeHWInsts are imprecise. Some of these cases are
21017 // safe. The message phrasing also should be better.
21018 if (globalMemoryFPAtomicIsLegal(*Subtarget, RMW, HasSystemScope)) {
21019 if (AS == AMDGPUAS::FLAT_ADDRESS) {
21020 // gfx942, gfx12
21021 if (Subtarget->hasAtomicFlatPkAdd16Insts() && isV2F16OrV2BF16(Ty))
21022 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21023 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS)) {
21024 // gfx90a, gfx942, gfx12
21025 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
21026 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21027
21028 // gfx942, gfx12
21029 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() && isV2BF16(Ty))
21030 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21031 } else if (AS == AMDGPUAS::BUFFER_FAT_POINTER) {
21032 // gfx90a, gfx942, gfx12
21033 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
21034 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21035
21036 // While gfx90a/gfx942 supports v2bf16 for global/flat, it does not for
21037 // buffer. gfx12 does have the buffer version.
21038 if (Subtarget->hasAtomicBufferPkAddBF16Inst() && isV2BF16(Ty))
21039 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21040 }
21041
21042 // global and flat atomic fadd f64: gfx90a, gfx942.
21043 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
21044 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21045
21046 if (AS != AMDGPUAS::FLAT_ADDRESS) {
21047 if (Ty->isFloatTy()) {
21048 // global/buffer atomic fadd f32 no-rtn: gfx908, gfx90a, gfx942,
21049 // gfx11+.
21050 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21051 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21052 // global/buffer atomic fadd f32 rtn: gfx90a, gfx942, gfx11+.
21053 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21054 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21055 } else {
21056 // gfx908
21057 if (RMW->use_empty() &&
21058 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
21059 isV2F16(Ty))
21060 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21061 }
21062 }
21063
21064 // flat atomic fadd f32: gfx942, gfx11+.
21065 if (AS == AMDGPUAS::FLAT_ADDRESS && Ty->isFloatTy()) {
21066 if (Subtarget->hasFlatAtomicFaddF32Inst())
21067 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21068
21069 // If it is in flat address space, and the type is float, we will try to
21070 // expand it, if the target supports global and lds atomic fadd. The
21071 // reason we need that is, in the expansion, we emit the check of
21072 // address space. If it is in global address space, we emit the global
21073 // atomic fadd; if it is in shared address space, we emit the LDS atomic
21074 // fadd.
21075 if (Subtarget->hasLDSFPAtomicAddF32()) {
21076 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21078 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21080 }
21081 }
21082 }
21083
21085 }
21087 case AtomicRMWInst::FMax: {
21088 Type *Ty = RMW->getType();
21089
21090 // LDS float and double fmin/fmax were always supported.
21091 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
21092 return Ty->isFloatTy() || Ty->isDoubleTy() ? AtomicExpansionKind::None
21094 }
21095
21096 if (globalMemoryFPAtomicIsLegal(*Subtarget, RMW, HasSystemScope)) {
21097 // For flat and global cases:
21098 // float, double in gfx7. Manual claims denormal support.
21099 // Removed in gfx8.
21100 // float, double restored in gfx10.
21101 // double removed again in gfx11, so only f32 for gfx11/gfx12.
21102 //
21103 // For gfx9, gfx90a and gfx942 support f64 for global (same as fadd), but
21104 // no f32.
21105 if (AS == AMDGPUAS::FLAT_ADDRESS) {
21106 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
21107 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21108 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
21109 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21110 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS) ||
21112 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
21113 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21114 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
21115 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21116 }
21117 }
21118
21120 }
21123 default:
21125 }
21126
21127 llvm_unreachable("covered atomicrmw op switch");
21128}
21129
21136
21143
21146 const AtomicCmpXchgInst *CmpX) const {
21147 unsigned AddrSpace = CmpX->getPointerAddressSpace();
21148 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS)
21150
21151 if (AddrSpace != AMDGPUAS::FLAT_ADDRESS || !flatInstrMayAccessPrivate(CmpX))
21153
21154 const DataLayout &DL = CmpX->getDataLayout();
21155
21156 Type *ValTy = CmpX->getNewValOperand()->getType();
21157
21158 // If a 64-bit flat atomic may alias private, we need to avoid using the
21159 // atomic in the private case.
21160 return DL.getTypeSizeInBits(ValTy) == 64 ? AtomicExpansionKind::CustomExpand
21162}
21163
21164const TargetRegisterClass *
21165SITargetLowering::getRegClassFor(MVT VT, bool isDivergent) const {
21167 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
21168 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
21169 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
21170 : &AMDGPU::SReg_32RegClass;
21171 if (!TRI->isSGPRClass(RC) && !isDivergent)
21172 return TRI->getEquivalentSGPRClass(RC);
21173 if (TRI->isSGPRClass(RC) && isDivergent) {
21174 if (Subtarget->hasGFX90AInsts())
21175 return TRI->getEquivalentAVClass(RC);
21176 return TRI->getEquivalentVGPRClass(RC);
21177 }
21178
21179 return RC;
21180}
21181
21182// FIXME: This is a workaround for DivergenceAnalysis not understanding always
21183// uniform values (as produced by the mask results of control flow intrinsics)
21184// used outside of divergent blocks. The phi users need to also be treated as
21185// always uniform.
21186//
21187// FIXME: DA is no longer in-use. Does this still apply to UniformityAnalysis?
21188static bool hasCFUser(const Value *V, SmallPtrSet<const Value *, 16> &Visited,
21189 unsigned WaveSize) {
21190 // FIXME: We assume we never cast the mask results of a control flow
21191 // intrinsic.
21192 // Early exit if the type won't be consistent as a compile time hack.
21193 IntegerType *IT = dyn_cast<IntegerType>(V->getType());
21194 if (!IT || IT->getBitWidth() != WaveSize)
21195 return false;
21196
21197 if (!isa<Instruction>(V))
21198 return false;
21199 if (!Visited.insert(V).second)
21200 return false;
21201 bool Result = false;
21202 for (const auto *U : V->users()) {
21204 if (V == U->getOperand(1)) {
21205 switch (Intrinsic->getIntrinsicID()) {
21206 default:
21207 Result = false;
21208 break;
21209 case Intrinsic::amdgcn_if_break:
21210 case Intrinsic::amdgcn_if:
21211 case Intrinsic::amdgcn_else:
21212 Result = true;
21213 break;
21214 }
21215 }
21216 if (V == U->getOperand(0)) {
21217 switch (Intrinsic->getIntrinsicID()) {
21218 default:
21219 Result = false;
21220 break;
21221 case Intrinsic::amdgcn_end_cf:
21222 case Intrinsic::amdgcn_loop:
21223 Result = true;
21224 break;
21225 }
21226 }
21227 } else {
21228 Result = hasCFUser(U, Visited, WaveSize);
21229 }
21230 if (Result)
21231 break;
21232 }
21233 return Result;
21234}
21235
21237 const Value *V) const {
21238 if (const CallInst *CI = dyn_cast<CallInst>(V)) {
21239 if (CI->isInlineAsm()) {
21240 // FIXME: This cannot give a correct answer. This should only trigger in
21241 // the case where inline asm returns mixed SGPR and VGPR results, used
21242 // outside the defining block. We don't have a specific result to
21243 // consider, so this assumes if any value is SGPR, the overall register
21244 // also needs to be SGPR.
21245 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
21247 MF.getDataLayout(), Subtarget->getRegisterInfo(), *CI);
21248 for (auto &TC : TargetConstraints) {
21249 if (TC.Type == InlineAsm::isOutput) {
21251 const TargetRegisterClass *RC =
21252 getRegForInlineAsmConstraint(SIRI, TC.ConstraintCode,
21253 TC.ConstraintVT)
21254 .second;
21255 if (RC && SIRI->isSGPRClass(RC))
21256 return true;
21257 }
21258 }
21259 }
21260 }
21262 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21263}
21264
21266 for (SDUse &Use : N->uses()) {
21268 if (getBasePtrIndex(M) == Use.getOperandNo())
21269 return true;
21270 }
21271 }
21272 return false;
21273}
21274
21276 SDValue N1) const {
21277 if (!N0.hasOneUse())
21278 return false;
21279 // Take care of the opportunity to keep N0 uniform
21280 if (N0->isDivergent() || !N1->isDivergent())
21281 return true;
21282 // Check if we have a good chance to form the memory access pattern with the
21283 // base and offset
21284 return (DAG.isBaseWithConstantOffset(N0) &&
21286}
21287
21289 Register N0, Register N1) const {
21290 return MRI.hasOneNonDBGUse(N0); // FIXME: handle regbanks
21291}
21292
21295 // Propagate metadata set by AMDGPUAnnotateUniformValues to the MMO of a load.
21297 if (I.getMetadata("amdgpu.noclobber"))
21298 Flags |= MONoClobber;
21299 if (I.getMetadata("amdgpu.last.use"))
21300 Flags |= MOLastUse;
21301 return Flags;
21302}
21303
21305 Instruction *AI) const {
21306 // Given: atomicrmw fadd ptr %addr, float %val ordering
21307 //
21308 // With this expansion we produce the following code:
21309 // [...]
21310 // %is.shared = call i1 @llvm.amdgcn.is.shared(ptr %addr)
21311 // br i1 %is.shared, label %atomicrmw.shared, label %atomicrmw.check.private
21312 //
21313 // atomicrmw.shared:
21314 // %cast.shared = addrspacecast ptr %addr to ptr addrspace(3)
21315 // %loaded.shared = atomicrmw fadd ptr addrspace(3) %cast.shared,
21316 // float %val ordering
21317 // br label %atomicrmw.phi
21318 //
21319 // atomicrmw.check.private:
21320 // %is.private = call i1 @llvm.amdgcn.is.private(ptr %int8ptr)
21321 // br i1 %is.private, label %atomicrmw.private, label %atomicrmw.global
21322 //
21323 // atomicrmw.private:
21324 // %cast.private = addrspacecast ptr %addr to ptr addrspace(5)
21325 // %loaded.private = load float, ptr addrspace(5) %cast.private
21326 // %val.new = fadd float %loaded.private, %val
21327 // store float %val.new, ptr addrspace(5) %cast.private
21328 // br label %atomicrmw.phi
21329 //
21330 // atomicrmw.global:
21331 // %cast.global = addrspacecast ptr %addr to ptr addrspace(1)
21332 // %loaded.global = atomicrmw fadd ptr addrspace(1) %cast.global,
21333 // float %val ordering
21334 // br label %atomicrmw.phi
21335 //
21336 // atomicrmw.phi:
21337 // %loaded.phi = phi float [ %loaded.shared, %atomicrmw.shared ],
21338 // [ %loaded.private, %atomicrmw.private ],
21339 // [ %loaded.global, %atomicrmw.global ]
21340 // br label %atomicrmw.end
21341 //
21342 // atomicrmw.end:
21343 // [...]
21344 //
21345 //
21346 // For 64-bit atomics which may reside in private memory, we perform a simpler
21347 // version that only inserts the private check, and uses the flat operation.
21348
21349 IRBuilder<> Builder(AI);
21350 LLVMContext &Ctx = Builder.getContext();
21351
21352 auto *RMW = dyn_cast<AtomicRMWInst>(AI);
21353 const unsigned PtrOpIdx = RMW ? AtomicRMWInst::getPointerOperandIndex()
21355 Value *Addr = AI->getOperand(PtrOpIdx);
21356
21357 /// TODO: Only need to check private, then emit flat-known-not private (no
21358 /// need for shared block, or cast to global).
21360
21361 Align Alignment;
21362 if (RMW)
21363 Alignment = RMW->getAlign();
21364 else if (CX)
21365 Alignment = CX->getAlign();
21366 else
21367 llvm_unreachable("unhandled atomic operation");
21368
21369 // FullFlatEmulation is true if we need to issue the private, shared, and
21370 // global cases.
21371 //
21372 // If this is false, we are only dealing with the flat-targeting-private case,
21373 // where we only insert a check for private and still use the flat instruction
21374 // for global and shared.
21375
21376 bool FullFlatEmulation =
21377 RMW && RMW->getOperation() == AtomicRMWInst::FAdd &&
21378 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21379 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21380 RMW->getType()->isDoubleTy()));
21381
21382 // If the return value isn't used, do not introduce a false use in the phi.
21383 bool ReturnValueIsUsed = !AI->use_empty();
21384
21385 BasicBlock *BB = Builder.GetInsertBlock();
21386 Function *F = BB->getParent();
21387 BasicBlock *ExitBB =
21388 BB->splitBasicBlock(Builder.GetInsertPoint(), "atomicrmw.end");
21389 BasicBlock *SharedBB = nullptr;
21390
21391 BasicBlock *CheckPrivateBB = BB;
21392 if (FullFlatEmulation) {
21393 SharedBB = BasicBlock::Create(Ctx, "atomicrmw.shared", F, ExitBB);
21394 CheckPrivateBB =
21395 BasicBlock::Create(Ctx, "atomicrmw.check.private", F, ExitBB);
21396 }
21397
21398 BasicBlock *PrivateBB =
21399 BasicBlock::Create(Ctx, "atomicrmw.private", F, ExitBB);
21400 BasicBlock *GlobalBB = BasicBlock::Create(Ctx, "atomicrmw.global", F, ExitBB);
21401 BasicBlock *PhiBB = BasicBlock::Create(Ctx, "atomicrmw.phi", F, ExitBB);
21402
21403 std::prev(BB->end())->eraseFromParent();
21404 Builder.SetInsertPoint(BB);
21405
21406 Value *LoadedShared = nullptr;
21407 if (FullFlatEmulation) {
21408 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21409 {Addr}, nullptr, "is.shared");
21410 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21411 Builder.SetInsertPoint(SharedBB);
21412 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21414
21415 Instruction *Clone = AI->clone();
21416 Clone->insertInto(SharedBB, SharedBB->end());
21417 Clone->getOperandUse(PtrOpIdx).set(CastToLocal);
21418 LoadedShared = Clone;
21419
21420 Builder.CreateBr(PhiBB);
21421 Builder.SetInsertPoint(CheckPrivateBB);
21422 }
21423
21424 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21425 {Addr}, nullptr, "is.private");
21426 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21427
21428 Builder.SetInsertPoint(PrivateBB);
21429
21430 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21432
21433 Value *LoadedPrivate;
21434 if (RMW) {
21435 LoadedPrivate = Builder.CreateAlignedLoad(
21436 RMW->getType(), CastToPrivate, RMW->getAlign(), "loaded.private");
21437
21438 Value *NewVal = buildAtomicRMWValue(RMW->getOperation(), Builder,
21439 LoadedPrivate, RMW->getValOperand());
21440
21441 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign());
21442 } else {
21443 auto [ResultLoad, Equal] =
21444 buildCmpXchgValue(Builder, CastToPrivate, CX->getCompareOperand(),
21445 CX->getNewValOperand(), CX->getAlign());
21446
21447 Value *Insert = Builder.CreateInsertValue(PoisonValue::get(CX->getType()),
21448 ResultLoad, 0);
21449 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21450 }
21451
21452 Builder.CreateBr(PhiBB);
21453
21454 Builder.SetInsertPoint(GlobalBB);
21455
21456 // Continue using a flat instruction if we only emitted the check for private.
21457 Instruction *LoadedGlobal = AI;
21458 if (FullFlatEmulation) {
21459 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21461 AI->getOperandUse(PtrOpIdx).set(CastToGlobal);
21462 }
21463
21464 AI->removeFromParent();
21465 AI->insertInto(GlobalBB, GlobalBB->end());
21466
21467 // The new atomicrmw may go through another round of legalization later.
21468 if (!FullFlatEmulation) {
21469 // We inserted the runtime check already, make sure we do not try to
21470 // re-expand this.
21471 // TODO: Should union with any existing metadata.
21472 MDBuilder MDB(F->getContext());
21473 MDNode *RangeNotPrivate =
21476 LoadedGlobal->setMetadata(LLVMContext::MD_noalias_addrspace,
21477 RangeNotPrivate);
21478 }
21479
21480 Builder.CreateBr(PhiBB);
21481
21482 Builder.SetInsertPoint(PhiBB);
21483
21484 if (ReturnValueIsUsed) {
21485 PHINode *Loaded = Builder.CreatePHI(AI->getType(), 3);
21486 AI->replaceAllUsesWith(Loaded);
21487 if (FullFlatEmulation)
21488 Loaded->addIncoming(LoadedShared, SharedBB);
21489 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21490 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21491 Loaded->takeName(AI);
21492 }
21493
21494 Builder.CreateBr(ExitBB);
21495}
21496
21498 unsigned PtrOpIdx) {
21499 Value *PtrOp = I->getOperand(PtrOpIdx);
21502
21503 Type *FlatPtr = PointerType::get(I->getContext(), AMDGPUAS::FLAT_ADDRESS);
21504 Value *ASCast = CastInst::CreatePointerCast(PtrOp, FlatPtr, "scratch.ascast",
21505 I->getIterator());
21506 I->setOperand(PtrOpIdx, ASCast);
21507}
21508
21511
21514
21517 if (const auto *ConstVal = dyn_cast<Constant>(AI->getValOperand());
21518 ConstVal && ConstVal->isNullValue() &&
21520 // atomicrmw or %ptr, 0 -> atomicrmw add %ptr, 0
21522
21523 // We may still need the private-alias-flat handling below.
21524
21525 // TODO: Skip this for cases where we cannot access remote memory.
21526 }
21527 }
21528
21529 // The non-flat expansions should only perform the de-canonicalization of
21530 // identity values.
21532 return;
21533
21535}
21536
21543
21547
21549 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21550}
21551
21553 if (SI->getPointerAddressSpace() == AMDGPUAS::PRIVATE_ADDRESS)
21554 return convertScratchAtomicToFlatAtomic(SI, SI->getPointerOperandIndex());
21555
21557 "Expand Atomic Store only handles SCRATCH -> FLAT conversion");
21558}
static bool isMul(MachineInstr *MI)
return SDValue()
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
static constexpr std::pair< ImplicitArgumentMask, StringLiteral > ImplicitAttrs[]
static bool allUsesHaveSourceMods(MachineInstr &MI, MachineRegisterInfo &MRI, unsigned CostThreshold=4)
unsigned Imm
unsigned uint64_t
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.
constexpr LLT S32
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
Function Alias Analysis Results
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
@ DEFAULT
Default weight is used in cases when there is no dedicated execution weight set.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< SDByteProvider > calculateByteProvider(SDValue Op, unsigned Index, unsigned Depth, std::optional< uint64_t > VectorIndex, unsigned StartingIndex=0, MutableArrayRef< uint8_t > ByteMask={})
dxil translate DXIL Translate Metadata
static bool isSigned(unsigned Opcode)
Utilities for dealing with flags related to floating point properties and mode controls.
AMD GCN specific subclass of TargetSubtarget.
Provides analysis for querying information about KnownBits during GISel passes.
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
iv Induction Variable Users
Definition IVUsers.cpp:48
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RegName(no)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Contains matchers for matching SSA Machine Instructions.
static bool isUndef(const MachineInstr &MI)
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
uint64_t IntrinsicInst * II
#define P(N)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
Contains matchers for matching SelectionDAG nodes and values.
static void r0(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:39
static void r3(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:57
static void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:51
static void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:45
#define FP_DENORM_FLUSH_NONE
Definition SIDefines.h:1513
#define FP_DENORM_FLUSH_IN_FLUSH_OUT
Definition SIDefines.h:1510
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 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 bool globalMemoryFPAtomicIsLegal(const GCNSubtarget &Subtarget, const AtomicRMWInst *RMW, bool HasSystemScope)
static std::tuple< unsigned, unsigned > getDPPOpcForWaveReduction(unsigned Opc, const GCNSubtarget &ST)
static void fixMasks(SmallVectorImpl< DotSrc > &Srcs, unsigned ChainLength)
static bool is32bitWaveReduceOperation(unsigned Opc)
static TargetLowering::AtomicExpansionKind atomicSupportedIfLegalIntType(const AtomicRMWInst *RMW)
static SDValue strictFPExtFromF16(SelectionDAG &DAG, SDValue Src)
Return the source of an fp_extend from f16 to f32, or a converted FP constant.
static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW)
static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val)
static void convertScratchAtomicToFlatAtomic(Instruction *I, unsigned PtrOpIdx)
static bool isCopyFromRegOfInlineAsm(const SDNode *N)
static bool elementPairIsOddToEven(ArrayRef< int > Mask, int Elt)
static SDValue lowerBFEIntrinsic(SDValue Op, SelectionDAG &DAG, Intrinsic::ID IntrinsicID)
static cl::opt< bool > DisableLoopAlignment("amdgpu-disable-loop-alignment", cl::desc("Do not align and prefetch loops"), cl::init(false))
static SDValue getDWordFromOffset(SelectionDAG &DAG, SDLoc SL, SDValue Src, unsigned DWordOffset)
static MachineBasicBlock::iterator loadM0FromVGPR(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineInstr &MI, unsigned InitResultReg, unsigned PhiReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static bool isFloatingPointWaveReduceOperation(unsigned Opc)
static bool isImmConstraint(StringRef Constraint)
static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT, SDValue Src, int ExtraElts)
static bool hasCFUser(const Value *V, SmallPtrSet< const Value *, 16 > &Visited, unsigned WaveSize)
static std::pair< Register, Register > ExtractSubRegs(MachineInstr &MI, MachineOperand &Op, const TargetRegisterClass *SrcRC, const GCNSubtarget &ST, MachineRegisterInfo &MRI)
static OptimizationRemark emitAtomicRMWLegalRemark(const AtomicRMWInst *RMW)
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 ArgDescriptor allocateVGPR32Input(CCState &CCInfo, unsigned Mask=~0u, ArgDescriptor Arg=ArgDescriptor())
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::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 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 bool atomicIgnoresDenormalModeOrFPModeIsFTZ(const AtomicRMWInst *RMW)
static SDValue emitRemovedIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue GlueChain, SDNodeFlags Flags)
static SDValue buildPCRelGlobalAddress(SelectionDAG &DAG, const GlobalValue *GV, const SDLoc &DL, int64_t Offset, EVT PtrVT, unsigned GAFlags=SIInstrInfo::MO_NONE)
static cl::opt< bool > UseDivergentRegisterIndexing("amdgpu-use-divergent-register-indexing", cl::Hidden, cl::desc("Use indirect register addressing for divergent indexes"), cl::init(false))
static const std::optional< ByteProvider< SDValue > > calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex=0, unsigned Depth=0)
static bool isV2F16(Type *Ty)
static void initializeM0ToZeroForClusterLoad(SDValue Op, SelectionDAG &DAG, SDLoc DL)
static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg)
static uint64_t getIdentityValueForWaveReduction(unsigned Opc)
SI DAG Lowering interface definition.
Interface definition for SIRegisterInfo.
const char * Msg
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
static unsigned getScalarSizeInBits(Type *Ty)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
LLVM IR instance of the generic uniformity analysis.
static constexpr int Concat[]
Value * RHS
Value * LHS
The Input class is used to parse a yaml document into in-memory structs and vectors.
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
static std::optional< uint32_t > get32BitAbsoluteAddress(const GlobalValue &GV, unsigned AS)
static unsigned numBitsSigned(SDValue Op, SelectionDAG &DAG)
SDValue SplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Split a vector load into 2 loads of half the vector.
void analyzeFormalArgumentsCompute(CCState &State, const SmallVectorImpl< ISD::InputArg > &Ins) const
The SelectionDAGBuilder will automatically promote function arguments with illegal types.
SDValue LowerF64ToF16Safe(SDValue Src, const SDLoc &DL, SelectionDAG &DAG) const
SDValue storeStackInputValue(SelectionDAG &DAG, const SDLoc &SL, SDValue Chain, SDValue ArgVal, int64_t Offset) const
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue splitBinaryBitConstantOpImpl(DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS, uint32_t ValLo, uint32_t ValHi) const
Split the 64-bit value LHS into two 32-bit components, and perform the binary operation Opc to it wit...
SDValue lowerUnhandledCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals, StringRef Reason) const
virtual SDValue LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI, SDValue Op, SelectionDAG &DAG) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
SDValue addTokenForArgument(SDValue Chain, SelectionDAG &DAG, MachineFrameInfo &MFI, int ClobberedFI) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
static bool needsDenormHandlingF32(const SelectionDAG &DAG, SDValue Src, SDNodeFlags Flags)
uint32_t getImplicitParameterOffset(const MachineFunction &MF, const ImplicitParameter Param) const
Helper function that returns the byte offset of the given type of implicit parameter.
SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const
SDValue loadInputValue(SelectionDAG &DAG, const TargetRegisterClass *RC, EVT VT, const SDLoc &SL, const ArgDescriptor &Arg) const
AMDGPUTargetLowering(const TargetMachine &TM, const TargetSubtargetInfo &STI, const AMDGPUSubtarget &AMDGPUSTI)
static EVT getEquivalentMemType(LLVMContext &Context, EVT VT)
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
SDValue CreateLiveInRegister(SelectionDAG &DAG, const TargetRegisterClass *RC, Register Reg, EVT VT, const SDLoc &SL, bool RawReg=false) const
Helper function that adds Reg to the LiveIn list of the DAG's MachineFunction.
SDValue SplitVectorStore(SDValue Op, SelectionDAG &DAG) const
Split a vector store into 2 stores of half the vector.
std::pair< SDValue, SDValue > split64BitValue(SDValue Op, SelectionDAG &DAG) const
Return 64-bit value Op as two 32-bit integers.
static CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg)
static CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg)
Selects the correct CCAssignFn for a given CallingConvention value.
static unsigned numBitsUnsigned(SDValue Op, SelectionDAG &DAG)
static bool allowApproxFunc(const SelectionDAG &DAG, SDNodeFlags Flags)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
SDValue performRcpCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const
static bool shouldFoldFNegIntoSrc(SDNode *FNeg, SDValue FNegSrc)
bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const override
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue WidenOrSplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Widen a suitably aligned v3 load.
SDValue getHiHalf64(SDValue Op, SelectionDAG &DAG) const
bool isNoopAddrSpaceCast(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