LLVM 24.0.0git
SIISelLowering.cpp
Go to the documentation of this file.
1//===-- SIISelLowering.cpp - SI DAG Lowering Implementation ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// Custom DAG lowering for SI
11//
12//===----------------------------------------------------------------------===//
13
14#include "SIISelLowering.h"
15#include "AMDGPU.h"
16#include "AMDGPUIGroupLP.h"
17#include "AMDGPUInstrInfo.h"
18#include "AMDGPULaneMaskUtils.h"
19#include "AMDGPUMemoryUtils.h"
21#include "AMDGPUTargetMachine.h"
22#include "GCNSubtarget.h"
25#include "SIRegisterInfo.h"
26#include "llvm/ADT/APFloat.h"
27#include "llvm/ADT/APInt.h"
29#include "llvm/ADT/Statistic.h"
44#include "llvm/IR/IRBuilder.h"
46#include "llvm/IR/IntrinsicsAMDGPU.h"
47#include "llvm/IR/IntrinsicsR600.h"
48#include "llvm/IR/MDBuilder.h"
52#include "llvm/Support/ModRef.h"
55#include <optional>
56
57using namespace llvm;
58using namespace llvm::SDPatternMatch;
59
60#define DEBUG_TYPE "si-lower"
61
62STATISTIC(NumTailCalls, "Number of tail calls");
63
64static cl::opt<bool>
65 DisableLoopAlignment("amdgpu-disable-loop-alignment",
66 cl::desc("Do not align and prefetch loops"),
67 cl::init(false));
68
70 "amdgpu-use-divergent-register-indexing", cl::Hidden,
71 cl::desc("Use indirect register addressing for divergent indexes"),
72 cl::init(false));
73
75 return MF.getInfo<SIMachineFunctionInfo>()->getMode().getDenormalFPEnv();
76}
77
82
87
88static unsigned findFirstFreeSGPR(CCState &CCInfo) {
89 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
90 for (unsigned Reg = 0; Reg < NumSGPRs; ++Reg) {
91 if (!CCInfo.isAllocated(AMDGPU::SGPR0 + Reg)) {
92 return AMDGPU::SGPR0 + Reg;
93 }
94 }
95 llvm_unreachable("Cannot allocate sgpr");
96}
97
99 const GCNSubtarget &STI)
100 : AMDGPUTargetLowering(TM, STI, STI), Subtarget(&STI) {
101 addRegisterClass(MVT::i1, &AMDGPU::VReg_1RegClass);
102 addRegisterClass(MVT::i64, &AMDGPU::SReg_64RegClass);
103
104 addRegisterClass(MVT::i32, &AMDGPU::SReg_32RegClass);
105
106 const SIRegisterInfo *TRI = STI.getRegisterInfo();
107 const TargetRegisterClass *V32RegClass =
108 TRI->getDefaultVectorSuperClassForBitWidth(32);
109 addRegisterClass(MVT::f32, V32RegClass);
110
111 addRegisterClass(MVT::v2i32, &AMDGPU::SReg_64RegClass);
112
113 const TargetRegisterClass *V64RegClass =
114 TRI->getDefaultVectorSuperClassForBitWidth(64);
115
116 addRegisterClass(MVT::f64, V64RegClass);
117 addRegisterClass(MVT::v2f32, V64RegClass);
118 addRegisterClass(MVT::Untyped, V64RegClass);
119
120 addRegisterClass(MVT::v3i32, &AMDGPU::SGPR_96RegClass);
121 addRegisterClass(MVT::v3f32, TRI->getDefaultVectorSuperClassForBitWidth(96));
122
123 addRegisterClass(MVT::v2i64, &AMDGPU::SGPR_128RegClass);
124 addRegisterClass(MVT::v2f64, &AMDGPU::SGPR_128RegClass);
125
126 addRegisterClass(MVT::v4i32, &AMDGPU::SGPR_128RegClass);
127 addRegisterClass(MVT::v4f32, TRI->getDefaultVectorSuperClassForBitWidth(128));
128
129 addRegisterClass(MVT::v5i32, &AMDGPU::SGPR_160RegClass);
130 addRegisterClass(MVT::v5f32, TRI->getDefaultVectorSuperClassForBitWidth(160));
131
132 addRegisterClass(MVT::v6i32, &AMDGPU::SGPR_192RegClass);
133 addRegisterClass(MVT::v6f32, TRI->getDefaultVectorSuperClassForBitWidth(192));
134
135 addRegisterClass(MVT::v3i64, &AMDGPU::SGPR_192RegClass);
136 addRegisterClass(MVT::v3f64, TRI->getDefaultVectorSuperClassForBitWidth(192));
137
138 addRegisterClass(MVT::v7i32, &AMDGPU::SGPR_224RegClass);
139 addRegisterClass(MVT::v7f32, TRI->getDefaultVectorSuperClassForBitWidth(224));
140
141 addRegisterClass(MVT::v8i32, &AMDGPU::SGPR_256RegClass);
142 addRegisterClass(MVT::v8f32, TRI->getDefaultVectorSuperClassForBitWidth(256));
143
144 addRegisterClass(MVT::v4i64, &AMDGPU::SGPR_256RegClass);
145 addRegisterClass(MVT::v4f64, TRI->getDefaultVectorSuperClassForBitWidth(256));
146
147 addRegisterClass(MVT::v9i32, &AMDGPU::SGPR_288RegClass);
148 addRegisterClass(MVT::v9f32, TRI->getDefaultVectorSuperClassForBitWidth(288));
149
150 addRegisterClass(MVT::v10i32, &AMDGPU::SGPR_320RegClass);
151 addRegisterClass(MVT::v10f32,
152 TRI->getDefaultVectorSuperClassForBitWidth(320));
153
154 addRegisterClass(MVT::v11i32, &AMDGPU::SGPR_352RegClass);
155 addRegisterClass(MVT::v11f32,
156 TRI->getDefaultVectorSuperClassForBitWidth(352));
157
158 addRegisterClass(MVT::v12i32, &AMDGPU::SGPR_384RegClass);
159 addRegisterClass(MVT::v12f32,
160 TRI->getDefaultVectorSuperClassForBitWidth(384));
161
162 addRegisterClass(MVT::v16i32, &AMDGPU::SGPR_512RegClass);
163 addRegisterClass(MVT::v16f32,
164 TRI->getDefaultVectorSuperClassForBitWidth(512));
165
166 addRegisterClass(MVT::v8i64, &AMDGPU::SGPR_512RegClass);
167 addRegisterClass(MVT::v8f64, TRI->getDefaultVectorSuperClassForBitWidth(512));
168
169 addRegisterClass(MVT::v16i64, &AMDGPU::SGPR_1024RegClass);
170 addRegisterClass(MVT::v16f64,
171 TRI->getDefaultVectorSuperClassForBitWidth(1024));
172
173 if (Subtarget->has16BitInsts()) {
174 if (Subtarget->useRealTrue16Insts()) {
175 addRegisterClass(MVT::i16, &AMDGPU::VGPR_16RegClass);
176 addRegisterClass(MVT::f16, &AMDGPU::VGPR_16RegClass);
177 addRegisterClass(MVT::bf16, &AMDGPU::VGPR_16RegClass);
178 } else {
179 addRegisterClass(MVT::i16, &AMDGPU::SReg_32RegClass);
180 addRegisterClass(MVT::f16, &AMDGPU::SReg_32RegClass);
181 addRegisterClass(MVT::bf16, &AMDGPU::SReg_32RegClass);
182 }
183
184 // Unless there are also VOP3P operations, not operations are really legal.
185 addRegisterClass(MVT::v2i16, &AMDGPU::SReg_32RegClass);
186 addRegisterClass(MVT::v2f16, &AMDGPU::SReg_32RegClass);
187 addRegisterClass(MVT::v2bf16, &AMDGPU::SReg_32RegClass);
188 addRegisterClass(MVT::v4i16, &AMDGPU::SReg_64RegClass);
189 addRegisterClass(MVT::v4f16, &AMDGPU::SReg_64RegClass);
190 addRegisterClass(MVT::v4bf16, &AMDGPU::SReg_64RegClass);
191 addRegisterClass(MVT::v8i16, &AMDGPU::SGPR_128RegClass);
192 addRegisterClass(MVT::v8f16, &AMDGPU::SGPR_128RegClass);
193 addRegisterClass(MVT::v8bf16, &AMDGPU::SGPR_128RegClass);
194 addRegisterClass(MVT::v16i16, &AMDGPU::SGPR_256RegClass);
195 addRegisterClass(MVT::v16f16, &AMDGPU::SGPR_256RegClass);
196 addRegisterClass(MVT::v16bf16, &AMDGPU::SGPR_256RegClass);
197 addRegisterClass(MVT::v32i16, &AMDGPU::SGPR_512RegClass);
198 addRegisterClass(MVT::v32f16, &AMDGPU::SGPR_512RegClass);
199 addRegisterClass(MVT::v32bf16, &AMDGPU::SGPR_512RegClass);
200 }
201
202 addRegisterClass(MVT::v32i32, &AMDGPU::VReg_1024RegClass);
203 addRegisterClass(MVT::v32f32,
204 TRI->getDefaultVectorSuperClassForBitWidth(1024));
205
206 computeRegisterProperties(Subtarget->getRegisterInfo());
207
210
211 // The boolean content concept here is too inflexible. Compares only ever
212 // really produce a 1-bit result. Any copy/extend from these will turn into a
213 // select, and zext/1 or sext/-1 are equally cheap. Arbitrarily choose 0/1, as
214 // it's what most targets use.
217
218 // We need to custom lower vector stores from local memory
220 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
221 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
222 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
223 MVT::i1, MVT::v32i32},
224 Custom);
225
227 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
228 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
229 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
230 MVT::i1, MVT::v32i32},
231 Custom);
232
233 if (isTypeLegal(MVT::bf16)) {
234 for (unsigned Opc :
243 ISD::SETCC}) {
244 setOperationAction(Opc, MVT::bf16, Promote);
245 }
246
247 // Only targets with packed bf16 instructions, e.g. gfx13.
248 if (Subtarget->hasBF16PackedInsts()) {
249 // Don't use Expand for fsub - the DAG combiner will undo fadd+fneg back
250 // to fsub, causing a libcall (which doesn't exist for bf16). Instead,
251 // directly expand to widened v2bf16 operations.
253 // Promote scalar operations to a v2bf16 operation with an unused high
254 // lane.
255 for (unsigned Opc : {ISD::FADD, ISD::FMUL, ISD::FMA, ISD::FMAXNUM,
257 AddPromotedToType(Opc, MVT::bf16, MVT::v2bf16);
258 }
259
261
263 AddPromotedToType(ISD::SELECT, MVT::bf16, MVT::i16);
264
268
269 // We only need to custom lower because we can't specify an action for bf16
270 // sources.
273 }
274
275 setTruncStoreAction(MVT::v2i32, MVT::v2i16, Expand);
276 setTruncStoreAction(MVT::v3i32, MVT::v3i16, Expand);
277 setTruncStoreAction(MVT::v4i32, MVT::v4i16, Expand);
278 setTruncStoreAction(MVT::v8i32, MVT::v8i16, Expand);
279 setTruncStoreAction(MVT::v16i32, MVT::v16i16, Expand);
280 setTruncStoreAction(MVT::v32i32, MVT::v32i16, Expand);
281 setTruncStoreAction(MVT::v2i32, MVT::v2i8, Expand);
282 setTruncStoreAction(MVT::v4i32, MVT::v4i8, Expand);
283 setTruncStoreAction(MVT::v8i32, MVT::v8i8, Expand);
284 setTruncStoreAction(MVT::v16i32, MVT::v16i8, Expand);
285 setTruncStoreAction(MVT::v32i32, MVT::v32i8, Expand);
286 setTruncStoreAction(MVT::v2i16, MVT::v2i8, Expand);
287 setTruncStoreAction(MVT::v4i16, MVT::v4i8, Expand);
288 setTruncStoreAction(MVT::v8i16, MVT::v8i8, Expand);
289 setTruncStoreAction(MVT::v16i16, MVT::v16i8, Expand);
290 setTruncStoreAction(MVT::v32i16, MVT::v32i8, Expand);
291
292 setTruncStoreAction(MVT::v3i64, MVT::v3i16, Expand);
293 setTruncStoreAction(MVT::v3i64, MVT::v3i32, Expand);
294 setTruncStoreAction(MVT::v4i64, MVT::v4i8, Expand);
295 setTruncStoreAction(MVT::v8i64, MVT::v8i8, Expand);
296 setTruncStoreAction(MVT::v8i64, MVT::v8i16, Expand);
297 setTruncStoreAction(MVT::v8i64, MVT::v8i32, Expand);
298 setTruncStoreAction(MVT::v16i64, MVT::v16i32, Expand);
299
300 setOperationAction(ISD::GlobalAddress, {MVT::i32, MVT::i64}, Custom);
301 setOperationAction(ISD::BlockAddress, {MVT::i32, MVT::i64}, Custom);
302 setOperationAction(ISD::ExternalSymbol, {MVT::i32, MVT::i64}, Custom);
303
307 AddPromotedToType(ISD::SELECT, MVT::f64, MVT::i64);
308
309 setOperationAction(ISD::FSQRT, {MVT::f32, MVT::f64}, Custom);
310
312 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1}, Expand);
313
315 setOperationAction(ISD::SETCC, {MVT::v2i1, MVT::v4i1}, Expand);
316 AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32);
317
319 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
320 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
321 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
322 Expand);
324 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
325 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
326 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
327 Expand);
328
330 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
331 MVT::v3i16, MVT::v4i16, MVT::Other},
332 Custom);
333
336 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64}, Expand);
337
340
343
345 Expand);
346
348
349 // We only support LOAD/STORE and vector manipulation ops for vectors
350 // with > 4 elements.
351 for (MVT VT :
352 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
353 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
354 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
355 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
356 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
357 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
358 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
359 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
360 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
361 switch (Op) {
362 case ISD::LOAD:
363 case ISD::STORE:
365 case ISD::BITCAST:
366 case ISD::UNDEF:
367 case ISD::POISON:
371 case ISD::IS_FPCLASS:
372 break;
377 break;
378 default:
380 break;
381 }
382 }
383 }
384
386
387 // TODO: For dynamic 64-bit vector inserts/extracts, should emit a pseudo that
388 // is expanded to avoid having two separate loops in case the index is a VGPR.
389
390 // Most operations are naturally 32-bit vector operations. We only support
391 // load and store of i64 vectors, so promote v2i64 vector operations to v4i32.
392 for (MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
394 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v4i32);
395
397 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v4i32);
398
400 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v4i32);
401
403 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v4i32);
404 }
405
406 for (MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
408 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v6i32);
409
411 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v6i32);
412
414 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v6i32);
415
417 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v6i32);
418 }
419
420 for (MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
422 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v8i32);
423
425 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v8i32);
426
428 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v8i32);
429
431 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v8i32);
432 }
433
434 for (MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
436 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v16i32);
437
439 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v16i32);
440
442 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v16i32);
443
445 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v16i32);
446 }
447
448 for (MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
450 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v32i32);
451
453 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v32i32);
454
456 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v32i32);
457
459 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v32i32);
460 }
461
463 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
464 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
465 Custom);
466
467 if (Subtarget->hasPkMovB32()) {
468 // TODO: 16-bit element vectors should be legal with even aligned elements.
469 // TODO: Can be legal with wider source types than the result with
470 // subregister extracts.
471 setOperationAction(ISD::VECTOR_SHUFFLE, {MVT::v2i32, MVT::v2f32}, Legal);
472 }
473
475 // Prevent SELECT v2i32 from being implemented with the above bitwise ops and
476 // instead lower to cndmask in SITargetLowering::LowerSELECT().
478 // Enable MatchRotate to produce ISD::ROTR, which is later transformed to
479 // alignbit.
480 setOperationAction(ISD::ROTR, MVT::v2i32, Custom);
481
482 setOperationAction(ISD::BUILD_VECTOR, {MVT::v4f16, MVT::v4i16, MVT::v4bf16},
483 Custom);
484
485 // Avoid stack access for these.
486 // TODO: Generalize to more vector types.
488 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
489 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
490 Custom);
491
492 // Deal with vec3 vector operations when widened to vec4.
494 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32}, Custom);
495
496 // Deal with vec5/6/7 vector operations when widened to vec8.
498 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
499 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
500 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
501 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
502 Custom);
503
504 // BUFFER/FLAT_ATOMIC_CMP_SWAP on GCN GPUs needs input marshalling,
505 // and output demarshalling
506 setOperationAction(ISD::ATOMIC_CMP_SWAP, {MVT::i32, MVT::i64}, Custom);
507
508 // We can't return success/failure, only the old value,
509 // let LLVM add the comparison
511 Expand);
512
513 setOperationAction(ISD::ADDRSPACECAST, {MVT::i32, MVT::i64}, Custom);
514
515 setOperationAction(ISD::BITREVERSE, {MVT::i32, MVT::i64}, Legal);
516
517 // FIXME: This should be narrowed to i32, but that only happens if i64 is
518 // illegal.
519 // FIXME: Should lower sub-i32 bswaps to bit-ops without v_perm_b32.
520 setOperationAction(ISD::BSWAP, {MVT::i64, MVT::i32}, Legal);
521
522 // On SI this is s_memtime and s_memrealtime on VI.
524
525 if (Subtarget->hasSMemRealTime() ||
526 Subtarget->getGeneration() >= AMDGPUSubtarget::GFX11)
529
530 if (Subtarget->has16BitInsts()) {
533 setOperationAction(ISD::IS_FPCLASS, {MVT::f16, MVT::f32, MVT::f64}, Legal);
536 } else {
538 }
539
540 if (Subtarget->hasMadMacF32Insts())
542
546
547 // We only really have 32-bit BFE instructions (and 16-bit on VI).
548 //
549 // On SI+ there are 64-bit BFEs, but they are scalar only and there isn't any
550 // effort to match them now. We want this to be false for i64 cases when the
551 // extraction isn't restricted to the upper or lower half. Ideally we would
552 // have some pass reduce 64-bit extracts to 32-bit if possible. Extracts that
553 // span the midpoint are probably relatively rare, so don't worry about them
554 // for now.
556
557 // Clamp modifier on add/sub
558 if (Subtarget->hasIntClamp())
560
561 if (Subtarget->hasAddNoCarryInsts())
562 setOperationAction({ISD::SADDSAT, ISD::SSUBSAT}, {MVT::i16, MVT::i32},
563 Legal);
564
565 // Do not have s_{min|max}_*f64 instruction f64 will only be lowered to
566 // v_{min|max}_*f64
567 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
570 {MVT::f64, MVT::f32}, Legal);
571 } else {
574 {MVT::f64, MVT::f32}, Custom);
575 // These are really only legal for ieee_mode functions. We should be
576 // avoiding them for functions that don't have ieee_mode enabled, so just
577 // say they are legal.
579 {MVT::f64, MVT::f32}, Legal);
580 }
581
582 if (Subtarget->haveRoundOpsF64())
584 Legal);
585 else
587 MVT::f64, Custom);
588
590 setOperationAction({ISD::FLDEXP, ISD::STRICT_FLDEXP}, {MVT::f32, MVT::f64},
591 Legal);
592 setOperationAction(ISD::FFREXP, {MVT::f32, MVT::f64}, Custom);
593
596
597 setOperationAction(ISD::BF16_TO_FP, {MVT::i16, MVT::f32, MVT::f64}, Expand);
598 setOperationAction(ISD::FP_TO_BF16, {MVT::i16, MVT::f32, MVT::f64}, Expand);
599
601 Custom);
603 Custom);
605 Custom);
606
607 // Custom lower these because we can't specify a rule based on an illegal
608 // source bf16.
611
612 if (Subtarget->has16BitInsts()) {
615 MVT::i16, Legal);
616
617 AddPromotedToType(ISD::SIGN_EXTEND, MVT::i16, MVT::i32);
618
620 MVT::i16, Expand);
621
625 ISD::CTPOP},
626 MVT::i16, Promote);
627
629
630 setTruncStoreAction(MVT::i64, MVT::i16, Expand);
631
633 AddPromotedToType(ISD::FP16_TO_FP, MVT::i16, MVT::i32);
635 AddPromotedToType(ISD::FP_TO_FP16, MVT::i16, MVT::i32);
636
641
643
644 // F16 - Constant Actions.
647
648 // F16 - Load/Store Actions.
650 AddPromotedToType(ISD::LOAD, MVT::f16, MVT::i16);
652 AddPromotedToType(ISD::STORE, MVT::f16, MVT::i16);
653
654 // BF16 - Load/Store Actions.
656 AddPromotedToType(ISD::LOAD, MVT::bf16, MVT::i16);
658 AddPromotedToType(ISD::STORE, MVT::bf16, MVT::i16);
659
660 // F16 - VOP1 Actions.
663 MVT::f16, Custom);
664
665 // BF16 - VOP1 Actions.
666 if (Subtarget->hasBF16TransInsts())
668
669 // F16 - VOP2 Actions.
670 setOperationAction({ISD::BR_CC, ISD::SELECT_CC}, {MVT::f16, MVT::bf16},
671 Expand);
675
676 // F16 - VOP3 Actions.
678 if (STI.hasMadF16())
680
681 for (MVT VT :
682 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
683 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
684 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
685 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
686 switch (Op) {
687 case ISD::LOAD:
688 case ISD::STORE:
690 case ISD::BITCAST:
691 case ISD::UNDEF:
692 case ISD::POISON:
697 case ISD::IS_FPCLASS:
698 break;
701 case ISD::FSIN:
702 case ISD::FCOS:
704 break;
705 default:
707 break;
708 }
709 }
710 }
711
712 // v_perm_b32 can handle either of these.
713 setOperationAction(ISD::BSWAP, {MVT::i16, MVT::v2i16}, Legal);
715
716 // Legalize vector types for sat conversions to select v_cvt_pk_[iu]16_f32.
717 if (Subtarget->hasVCvtPkIU16F32())
720 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
721 Custom);
722
723 // XXX - Do these do anything? Vector constants turn into build_vector.
724 setOperationAction(ISD::Constant, {MVT::v2i16, MVT::v2f16}, Legal);
725
727 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Legal);
728
730 AddPromotedToType(ISD::STORE, MVT::v2i16, MVT::i32);
732 AddPromotedToType(ISD::STORE, MVT::v2f16, MVT::i32);
733
735 AddPromotedToType(ISD::LOAD, MVT::v2i16, MVT::i32);
737 AddPromotedToType(ISD::LOAD, MVT::v2f16, MVT::i32);
738
740 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v2i16, MVT::i32);
742 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v2f16, MVT::i32);
743
745 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v2i16, MVT::i32);
747 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v2f16, MVT::i32);
748
749 setOperationAction(ISD::AND, MVT::v2i16, Promote);
750 AddPromotedToType(ISD::AND, MVT::v2i16, MVT::i32);
751 setOperationAction(ISD::OR, MVT::v2i16, Promote);
752 AddPromotedToType(ISD::OR, MVT::v2i16, MVT::i32);
753 setOperationAction(ISD::XOR, MVT::v2i16, Promote);
754 AddPromotedToType(ISD::XOR, MVT::v2i16, MVT::i32);
755
757 AddPromotedToType(ISD::LOAD, MVT::v4i16, MVT::v2i32);
759 AddPromotedToType(ISD::LOAD, MVT::v4f16, MVT::v2i32);
760 setOperationAction(ISD::LOAD, MVT::v4bf16, Promote);
761 AddPromotedToType(ISD::LOAD, MVT::v4bf16, MVT::v2i32);
762
764 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v4i16, MVT::i64);
766 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v4f16, MVT::i64);
767
769 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v4i16, MVT::i64);
771 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v4f16, MVT::i64);
772
774 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
776 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
778 AddPromotedToType(ISD::STORE, MVT::v4bf16, MVT::v2i32);
779
781 AddPromotedToType(ISD::LOAD, MVT::v8i16, MVT::v4i32);
783 AddPromotedToType(ISD::LOAD, MVT::v8f16, MVT::v4i32);
784 setOperationAction(ISD::LOAD, MVT::v8bf16, Promote);
785 AddPromotedToType(ISD::LOAD, MVT::v8bf16, MVT::v4i32);
786
788 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
790 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
791
793 AddPromotedToType(ISD::STORE, MVT::v8i16, MVT::v4i32);
795 AddPromotedToType(ISD::STORE, MVT::v8f16, MVT::v4i32);
797 AddPromotedToType(ISD::STORE, MVT::v8bf16, MVT::v4i32);
798
799 setOperationAction(ISD::LOAD, MVT::v16i16, Promote);
800 AddPromotedToType(ISD::LOAD, MVT::v16i16, MVT::v8i32);
801 setOperationAction(ISD::LOAD, MVT::v16f16, Promote);
802 AddPromotedToType(ISD::LOAD, MVT::v16f16, MVT::v8i32);
803 setOperationAction(ISD::LOAD, MVT::v16bf16, Promote);
804 AddPromotedToType(ISD::LOAD, MVT::v16bf16, MVT::v8i32);
805
807 AddPromotedToType(ISD::STORE, MVT::v16i16, MVT::v8i32);
809 AddPromotedToType(ISD::STORE, MVT::v16f16, MVT::v8i32);
810 setOperationAction(ISD::STORE, MVT::v16bf16, Promote);
811 AddPromotedToType(ISD::STORE, MVT::v16bf16, MVT::v8i32);
812
813 setOperationAction(ISD::LOAD, MVT::v32i16, Promote);
814 AddPromotedToType(ISD::LOAD, MVT::v32i16, MVT::v16i32);
815 setOperationAction(ISD::LOAD, MVT::v32f16, Promote);
816 AddPromotedToType(ISD::LOAD, MVT::v32f16, MVT::v16i32);
817 setOperationAction(ISD::LOAD, MVT::v32bf16, Promote);
818 AddPromotedToType(ISD::LOAD, MVT::v32bf16, MVT::v16i32);
819
821 AddPromotedToType(ISD::STORE, MVT::v32i16, MVT::v16i32);
823 AddPromotedToType(ISD::STORE, MVT::v32f16, MVT::v16i32);
824 setOperationAction(ISD::STORE, MVT::v32bf16, Promote);
825 AddPromotedToType(ISD::STORE, MVT::v32bf16, MVT::v16i32);
826
828 MVT::v2i32, Expand);
830
832 MVT::v4i32, Expand);
833
835 MVT::v8i32, Expand);
836
837 setOperationAction(ISD::BUILD_VECTOR, {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
838 Subtarget->hasVOP3PInsts() ? Legal : Custom);
839
840 setOperationAction(ISD::FNEG, {MVT::v2f16, MVT::v2bf16}, Legal);
841 // This isn't really legal, but this avoids the legalizer unrolling it (and
842 // allows matching fneg (fabs x) patterns)
843 setOperationAction(ISD::FABS, {MVT::v2f16, MVT::v2bf16}, Legal);
844
845 // Can do this in one BFI plus a constant materialize.
847 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
848 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
849 MVT::v32f16, MVT::v32bf16},
850 Custom);
851 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
854 MVT::f16, Legal);
855
858 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16}, Custom);
859 } else {
862 MVT::f16, Custom);
863
865 Legal);
866
869 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
870 Custom);
871
873 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
874 Expand);
875 }
876
877 for (MVT Vec16 :
878 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
879 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
882 Vec16, Custom);
884 }
885 }
886
887 if (Subtarget->hasVOP3PInsts()) {
891 MVT::v2i16, Legal);
892
895 MVT::v2f16, Legal);
896
898 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Custom);
899
901 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
902 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
903 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
904 Custom);
905
906 for (MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
907 // Split vector operations.
912 VT, Custom);
913
914 for (MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
915 // Split vector operations.
918 VT, Custom);
919
920 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
923 MVT::v2f16, Legal);
924 } else {
926 Legal);
927
930 {MVT::v2f16, MVT::v4f16}, Custom);
931 }
932 setOperationAction(ISD::FEXP, MVT::v2f16, Custom);
933 setOperationAction(ISD::SELECT, {MVT::v4i16, MVT::v4f16, MVT::v4bf16},
934 Custom);
935
936 if (Subtarget->hasBF16PackedInsts()) {
940 MVT::v2bf16, Legal);
941
942 for (MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
943 // Split vector operations.
947 VT, Custom);
948 }
949
950 if (Subtarget->hasAnyPackedFP32Ops()) {
952 MVT::v2f32, Legal);
954 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
955 Custom);
956 }
957 if (Subtarget->hasAnyPackedFP64Ops()) {
960 MVT::v2f64, Legal);
963 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64}, Custom);
964
965 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
968 MVT::v2f64, Legal);
969
972 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64}, Custom);
973 } else {
975 Legal);
978 MVT::v2f64, Custom);
981 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
982 Custom);
983 }
984 }
985
986 if (Subtarget->hasAnyPackedU64Ops()) {
988 MVT::v2i64, Legal);
990 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
991 Custom);
992 }
993 }
994
996
997 if (Subtarget->has16BitInsts()) {
999 AddPromotedToType(ISD::SELECT, MVT::v2i16, MVT::i32);
1001 AddPromotedToType(ISD::SELECT, MVT::v2f16, MVT::i32);
1002 setOperationAction(ISD::SELECT, MVT::v2bf16, Promote);
1003 AddPromotedToType(ISD::SELECT, MVT::v2bf16, MVT::i32);
1004 } else {
1005 // Legalization hack.
1006 setOperationAction(ISD::SELECT, {MVT::v2i16, MVT::v2f16}, Custom);
1007
1009 }
1010
1012 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
1013 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1014 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
1015 MVT::v32f16, MVT::v32bf16},
1016 Custom);
1017
1019
1020 if (Subtarget->useVMulU64Inst())
1021 setOperationAction(ISD::MUL, MVT::i64, Legal);
1022 else if (Subtarget->hasScalarSMulU64())
1024
1025 if (Subtarget->hasMad64_32())
1027
1028 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
1030
1031 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
1033 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16}, Legal);
1034 } else {
1035 // FIXME: For nnan fmaximum, emit the fmaximum3 instead of fmaxnum
1036 if (Subtarget->hasMinimum3Maximum3F32())
1038
1039 if (Subtarget->hasMinimum3Maximum3PKF16()) {
1041
1042 // If only the vector form is available, we need to widen to a vector.
1043 if (!Subtarget->hasMinimum3Maximum3F16())
1045 MVT::v2f16);
1046 }
1047 }
1048
1049 if (Subtarget->hasVOP3PInsts()) {
1050 // We want to break these into v2f16 pieces, not scalarize.
1052 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1053 Custom);
1054 }
1055
1056 if (Subtarget->useMinMaxI64Insts())
1058 Legal);
1059
1061 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1062 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1063 MVT::i8},
1064 Custom);
1065
1067 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1068 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1069 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1070 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1071 Custom);
1072
1073 // The s_buffer_load intrinsics accept any result type in IR, but only a few
1074 // of them can be selected. Mark the remaining illegal result types Custom so
1075 // ReplaceNodeResults gets a chance to diagnose them instead of letting the
1076 // type legalizer abort. Its INTRINSIC_WO_CHAIN case dispatches on the
1077 // intrinsic ID, but INTRINSIC_W_CHAIN does not, so remember the types added
1078 // here to keep other chained intrinsics on generic legalization.
1079 for (MVT VT : MVT::all_valuetypes()) {
1080 if (VT.isScalableVector() || isTypeLegal(VT))
1081 continue;
1085 SBufferLoadDiagnosticVTs.set(VT.SimpleTy);
1086 }
1087 }
1088
1090 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1091 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1092 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1093 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1094 Custom);
1095
1101
1102 // TODO: Could move this to custom lowering, could benefit from combines on
1103 // extract of relevant bits.
1105
1107
1108 if (Subtarget->hasBF16ConversionInsts()) {
1110 {MVT::bf16, MVT::v2bf16}, Custom);
1112 }
1113
1114 if (Subtarget->hasBF16TransInsts()) {
1116 }
1117
1118 const bool HasE5M3ConversionInsts =
1119 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
1120 if (Subtarget->hasOCPFP8ConversionInsts() || HasE5M3ConversionInsts) {
1121 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f32, MVT::v2f32},
1122 Custom);
1124
1125 // i8 result promotes to i16, wider vectors split down to v2i8, and v2i8 is
1126 // handled in ReplaceNodeResults before the legalizer splits it per lane.
1127 setOperationAction(ISD::CONVERT_TO_ARBITRARY_FP, {MVT::i16, MVT::v2i8},
1128 Custom);
1129 }
1130
1131 if (Subtarget->hasFP8F16ConversionInsts()) {
1132 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f16, MVT::v2f16},
1133 Custom);
1134 }
1135
1136 if (Subtarget->hasCvtPkF16F32Inst()) {
1138 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1139 Custom);
1140 }
1141
1144 ISD::SUB,
1145 ISD::MUL,
1146 ISD::FADD,
1147 ISD::FSUB,
1148 ISD::FDIV,
1149 ISD::FMUL,
1158 ISD::FMA,
1159 ISD::ABS,
1160 ISD::SMIN,
1161 ISD::SMAX,
1162 ISD::UMIN,
1163 ISD::UMAX,
1164 ISD::SETCC,
1166 ISD::SMIN,
1167 ISD::SMAX,
1168 ISD::UMIN,
1169 ISD::UMAX,
1172 ISD::AND,
1173 ISD::OR,
1174 ISD::XOR,
1175 ISD::SHL,
1176 ISD::SRL,
1177 ISD::SRA,
1178 ISD::FSHR,
1189
1190 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1192
1193 // All memory operations. Some folding on the pointer operand is done to help
1194 // matching the constant offsets in the addressing modes.
1196 ISD::STORE,
1221
1222 // FIXME: In other contexts we pretend this is a per-function property.
1224
1226}
1227
1228const GCNSubtarget *SITargetLowering::getSubtarget() const { return Subtarget; }
1229
1231 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1232 return RCRegs;
1233}
1234
1235//===----------------------------------------------------------------------===//
1236// TargetLowering queries
1237//===----------------------------------------------------------------------===//
1238
1239// v_mad_mix* support a conversion from f16 to f32.
1240//
1241// There is only one special case when denormals are enabled we don't currently,
1242// where this is OK to use.
1243bool SITargetLowering::isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode,
1244 EVT DestVT, EVT SrcVT) const {
1245 return DestVT.getScalarType() == MVT::f32 &&
1246 ((((Opcode == ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1247 (Opcode == ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1248 SrcVT.getScalarType() == MVT::f16) ||
1249 (Opcode == ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1250 SrcVT.getScalarType() == MVT::bf16)) &&
1251 // TODO: This probably only requires no input flushing?
1253}
1254
1256 LLT DestTy, LLT SrcTy) const {
1257 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1258 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1259 DestTy.getScalarSizeInBits() == 32 &&
1260 SrcTy.getScalarSizeInBits() == 16 &&
1261 // TODO: This probably only requires no input flushing?
1262 denormalModeIsFlushAllF32(*MI.getMF());
1263}
1264
1266 // SI has some legal vector types, but no legal vector operations. Say no
1267 // shuffles are legal in order to prefer scalarizing some vector operations.
1268 return false;
1269}
1270
1272 CallingConv::ID CC,
1273 EVT VT) const {
1275 return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
1276
1277 if (VT.isVector()) {
1278 EVT ScalarVT = VT.getScalarType();
1279 unsigned Size = ScalarVT.getSizeInBits();
1280 if (Size == 16) {
1281 return Subtarget->has16BitInsts()
1282 ? MVT::getVectorVT(ScalarVT.getSimpleVT(), 2)
1283 : MVT::i32;
1284 }
1285
1286 if (Size < 16)
1287 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1288 return Size == 32 ? ScalarVT.getSimpleVT() : MVT::i32;
1289 }
1290
1291 if (!Subtarget->has16BitInsts() && VT.getSizeInBits() == 16)
1292 return MVT::i32;
1293
1294 if (VT.getSizeInBits() > 32)
1295 return MVT::i32;
1296
1297 return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
1298}
1299
1301 CallingConv::ID CC,
1302 EVT VT) const {
1304 return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
1305
1306 if (VT.isVector()) {
1307 unsigned NumElts = VT.getVectorNumElements();
1308 EVT ScalarVT = VT.getScalarType();
1309 unsigned Size = ScalarVT.getSizeInBits();
1310
1311 // FIXME: Should probably promote 8-bit vectors to i16.
1312 if (Size == 16)
1313 return (NumElts + 1) / 2;
1314
1315 if (Size <= 32)
1316 return NumElts;
1317
1318 if (Size > 32)
1319 return NumElts * ((Size + 31) / 32);
1320 } else if (VT.getSizeInBits() > 32)
1321 return (VT.getSizeInBits() + 31) / 32;
1322
1323 return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
1324}
1325
1327 LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT,
1328 unsigned &NumIntermediates, MVT &RegisterVT) const {
1329 if (CC != CallingConv::AMDGPU_KERNEL && VT.isVector()) {
1330 unsigned NumElts = VT.getVectorNumElements();
1331 EVT ScalarVT = VT.getScalarType();
1332 unsigned Size = ScalarVT.getSizeInBits();
1333 // FIXME: We should fix the ABI to be the same on targets without 16-bit
1334 // support, but unless we can properly handle 3-vectors, it will be still be
1335 // inconsistent.
1336 if (Size == 16) {
1337 MVT SimpleIntermediateVT =
1339 IntermediateVT = SimpleIntermediateVT;
1340 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1341 NumIntermediates = (NumElts + 1) / 2;
1342 return (NumElts + 1) / 2;
1343 }
1344
1345 if (Size == 32) {
1346 RegisterVT = ScalarVT.getSimpleVT();
1347 IntermediateVT = RegisterVT;
1348 NumIntermediates = NumElts;
1349 return NumIntermediates;
1350 }
1351
1352 if (Size < 16 && Subtarget->has16BitInsts()) {
1353 // FIXME: Should probably form v2i16 pieces
1354 RegisterVT = MVT::i16;
1355 IntermediateVT = ScalarVT;
1356 NumIntermediates = NumElts;
1357 return NumIntermediates;
1358 }
1359
1360 if (Size != 16 && Size <= 32) {
1361 RegisterVT = MVT::i32;
1362 IntermediateVT = ScalarVT;
1363 NumIntermediates = NumElts;
1364 return NumIntermediates;
1365 }
1366
1367 if (Size > 32) {
1368 RegisterVT = MVT::i32;
1369 IntermediateVT = RegisterVT;
1370 NumIntermediates = NumElts * ((Size + 31) / 32);
1371 return NumIntermediates;
1372 }
1373 }
1374
1376 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1377}
1378
1380 const DataLayout &DL, Type *Ty,
1381 unsigned MaxNumLanes) {
1382 assert(MaxNumLanes != 0);
1383
1384 LLVMContext &Ctx = Ty->getContext();
1385 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1386 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1387 return EVT::getVectorVT(Ctx, TLI.getValueType(DL, VT->getElementType()),
1388 NumElts);
1389 }
1390
1391 return TLI.getValueType(DL, Ty);
1392}
1393
1394// Peek through TFE struct returns to only use the data size.
1396 const DataLayout &DL, Type *Ty,
1397 unsigned MaxNumLanes) {
1398 auto *ST = dyn_cast<StructType>(Ty);
1399 if (!ST)
1400 return memVTFromLoadIntrData(TLI, DL, Ty, MaxNumLanes);
1401
1402 // TFE intrinsics return an aggregate type.
1403 assert(ST->getNumContainedTypes() == 2 &&
1404 ST->getContainedType(1)->isIntegerTy(32));
1405 return memVTFromLoadIntrData(TLI, DL, ST->getContainedType(0), MaxNumLanes);
1406}
1407
1408/// Map address space 7 to MVT::amdgpuBufferFatPointer because that's its
1409/// in-memory representation. This return value is a custom type because there
1410/// is no MVT::i160 and adding one breaks integer promotion logic. While this
1411/// could cause issues during codegen, these address space 7 pointers will be
1412/// rewritten away by then. Therefore, we can return MVT::amdgpuBufferFatPointer
1413/// in order to allow pre-codegen passes that query TargetTransformInfo, often
1414/// for cost modeling, to work. (This also sets us up decently for doing the
1415/// buffer lowering in GlobalISel if SelectionDAG ever goes away.)
1417 if (AMDGPUAS::BUFFER_FAT_POINTER == AS && DL.getPointerSizeInBits(AS) == 160)
1418 return MVT::amdgpuBufferFatPointer;
1420 DL.getPointerSizeInBits(AS) == 192)
1421 return MVT::amdgpuBufferStridedPointer;
1423}
1424/// Similarly, the in-memory representation of a p7 is {p8, i32}, aka
1425/// v8i32 when padding is added.
1426/// The in-memory representation of a p9 is {p8, i32, i32}, which is
1427/// also v8i32 with padding.
1429 if ((AMDGPUAS::BUFFER_FAT_POINTER == AS &&
1430 DL.getPointerSizeInBits(AS) == 160) ||
1432 DL.getPointerSizeInBits(AS) == 192))
1433 return MVT::v8i32;
1435}
1436
1437static unsigned getIntrMemWidth(unsigned IntrID) {
1438 switch (IntrID) {
1439 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1440 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1441 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1442 return 8;
1443 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1444 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1445 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1446 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1447 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1448 case Intrinsic::amdgcn_flat_load_monitor_b32:
1449 case Intrinsic::amdgcn_global_load_monitor_b32:
1450 return 32;
1451 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1452 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1453 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1454 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1455 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1456 case Intrinsic::amdgcn_flat_load_monitor_b64:
1457 case Intrinsic::amdgcn_global_load_monitor_b64:
1458 return 64;
1459 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1460 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1461 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1462 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1463 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1464 case Intrinsic::amdgcn_flat_load_monitor_b128:
1465 case Intrinsic::amdgcn_global_load_monitor_b128:
1466 return 128;
1467 default:
1468 llvm_unreachable("Unknown width");
1469 }
1470}
1471
1473 unsigned ArgIdx) {
1474 Value *OrderingArg = CI.getArgOperand(ArgIdx);
1475 unsigned Ord = cast<ConstantInt>(OrderingArg)->getZExtValue();
1476 switch (AtomicOrderingCABI(Ord)) {
1479 break;
1482 break;
1485 break;
1486 default:
1488 }
1489}
1490
1491static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx) {
1492 MDNode *ScopeMD = cast<MDNode>(
1493 cast<MetadataAsValue>(CI.getArgOperand(ArgIdx))->getMetadata());
1494 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1495 return CI.getContext().getOrInsertSyncScopeID(Scope);
1496}
1497
1499 const CallBase &CI,
1500 MachineFunction &MF,
1501 unsigned IntrID) const {
1503 if (CI.hasMetadata(LLVMContext::MD_invariant_load))
1505 if (CI.hasMetadata(LLVMContext::MD_nontemporal))
1507 Flags |= getTargetMMOFlags(CI);
1508
1509 if (const AMDGPU::RsrcIntrinsic *RsrcIntr =
1511 AttributeSet Attr =
1513 MemoryEffects ME = Attr.getMemoryEffects();
1514 if (ME.doesNotAccessMemory())
1515 return;
1516
1517 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1518 if (!IsSPrefetch) {
1519 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1520 if (Aux->getZExtValue() & AMDGPU::CPol::VOLATILE)
1522 }
1523
1525
1526 IntrinsicInfo Info;
1527 // TODO: Should images get their own address space?
1529
1530 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = nullptr;
1531 if (RsrcIntr->IsImage) {
1532 const AMDGPU::ImageDimIntrinsicInfo *Intr =
1534 BaseOpcode = AMDGPU::getMIMGBaseOpcodeInfo(Intr->BaseOpcode);
1535 Info.align.reset();
1536 }
1537
1538 Value *RsrcArg = CI.getArgOperand(RsrcIntr->RsrcArg);
1539 if (auto *RsrcPtrTy = dyn_cast<PointerType>(RsrcArg->getType())) {
1540 if (RsrcPtrTy->getAddressSpace() == AMDGPUAS::BUFFER_RESOURCE)
1541 // We conservatively set the memory operand of a buffer intrinsic to the
1542 // base resource pointer, so that we can access alias information about
1543 // those pointers. Cases like "this points at the same value
1544 // but with a different offset" are handled in
1545 // areMemAccessesTriviallyDisjoint.
1546 Info.ptrVal = RsrcArg;
1547 }
1548
1549 if (ME.onlyReadsMemory()) {
1550 if (RsrcIntr->IsImage) {
1551 unsigned MaxNumLanes = 4;
1552
1553 if (!BaseOpcode->Gather4) {
1554 // If this isn't a gather, we may have excess loaded elements in the
1555 // IR type. Check the dmask for the real number of elements loaded.
1556 unsigned DMask =
1557 cast<ConstantInt>(CI.getArgOperand(0))->getZExtValue();
1558 MaxNumLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1559 }
1560
1561 Info.memVT = memVTFromLoadIntrReturn(*this, MF.getDataLayout(),
1562 CI.getType(), MaxNumLanes);
1563 } else {
1564 Info.memVT =
1566 std::numeric_limits<unsigned>::max());
1567 }
1568
1569 // FIXME: What does alignment mean for an image?
1570 Info.opc = ISD::INTRINSIC_W_CHAIN;
1571 Info.flags = Flags | MachineMemOperand::MOLoad;
1572 } else if (ME.onlyWritesMemory()) {
1573 Info.opc = ISD::INTRINSIC_VOID;
1574
1575 Type *DataTy = CI.getArgOperand(0)->getType();
1576 if (RsrcIntr->IsImage) {
1577 unsigned DMask = cast<ConstantInt>(CI.getArgOperand(1))->getZExtValue();
1578 unsigned DMaskLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1579 Info.memVT = memVTFromLoadIntrData(*this, MF.getDataLayout(), DataTy,
1580 DMaskLanes);
1581 } else
1582 Info.memVT = getValueType(MF.getDataLayout(), DataTy);
1583
1584 Info.flags = Flags | MachineMemOperand::MOStore;
1585 } else {
1586 // Atomic, NoReturn Sampler or prefetch
1587 Info.opc = CI.getType()->isVoidTy() ? ISD::INTRINSIC_VOID
1589
1590 switch (IntrID) {
1591 default:
1592 Info.flags = Flags | MachineMemOperand::MOLoad;
1593 if (!IsSPrefetch)
1594 Info.flags |= MachineMemOperand::MOStore;
1595
1596 if ((RsrcIntr->IsImage && BaseOpcode->NoReturn) || IsSPrefetch) {
1597 // Fake memory access type for no return sampler intrinsics
1598 Info.memVT = MVT::i32;
1599 } else {
1600 // XXX - Should this be volatile without known ordering?
1601 Info.flags |= MachineMemOperand::MOVolatile;
1602 Info.memVT = MVT::getVT(CI.getArgOperand(0)->getType());
1603 }
1604 break;
1605 case Intrinsic::amdgcn_raw_buffer_load_lds:
1606 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1607 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1608 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1609 case Intrinsic::amdgcn_struct_buffer_load_lds:
1610 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1611 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1612 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1613 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1614
1615 // Entry 0: Load from buffer.
1616 // Don't set an offset, since the pointer value always represents the
1617 // base of the buffer.
1618 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1619 Info.flags = Flags | MachineMemOperand::MOLoad;
1620 Infos.push_back(Info);
1621
1622 // Entry 1: Store to LDS.
1623 // Instruction offset is applied, and an additional per-lane offset
1624 // which we simulate using a larger memory type.
1625 Info.memVT = EVT::getIntegerVT(
1626 CI.getContext(), Width * 8 * Subtarget->getWavefrontSize());
1627 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1628 Info.offset = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 2))
1629 ->getZExtValue();
1630 Info.fallbackAddressSpace = AMDGPUAS::LOCAL_ADDRESS;
1631 Info.flags = Flags | MachineMemOperand::MOStore;
1632 Infos.push_back(Info);
1633 return;
1634 }
1635 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1636 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1637 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1638 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1639 Info.memVT =
1641 std::numeric_limits<unsigned>::max());
1642 Info.flags = Flags | MachineMemOperand::MOLoad;
1643 Infos.push_back(Info);
1644 return;
1645 }
1646 }
1647 }
1648 Infos.push_back(Info);
1649 return;
1650 }
1651
1652 IntrinsicInfo Info;
1653 switch (IntrID) {
1654 case Intrinsic::amdgcn_ds_ordered_add:
1655 case Intrinsic::amdgcn_ds_ordered_swap: {
1656 Info.opc = ISD::INTRINSIC_W_CHAIN;
1657 Info.memVT = MVT::getVT(CI.getType());
1658 Info.ptrVal = CI.getOperand(0);
1659 Info.align.reset();
1661
1662 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(4));
1663 if (!Vol->isZero())
1664 Info.flags |= MachineMemOperand::MOVolatile;
1665
1666 Infos.push_back(Info);
1667 return;
1668 }
1669 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1670 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1671 Info.opc = ISD::INTRINSIC_W_CHAIN;
1672 Info.memVT = MVT::getVT(CI.getOperand(0)->getType());
1673 Info.ptrVal = nullptr;
1674 Info.fallbackAddressSpace = AMDGPUAS::STREAMOUT_REGISTER;
1676 Infos.push_back(Info);
1677 return;
1678 }
1679 case Intrinsic::amdgcn_ds_append:
1680 case Intrinsic::amdgcn_ds_consume: {
1681 Info.opc = ISD::INTRINSIC_W_CHAIN;
1682 Info.memVT = MVT::getVT(CI.getType());
1683 Info.ptrVal = CI.getOperand(0);
1684 Info.align.reset();
1686
1687 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(1));
1688 if (!Vol->isZero())
1689 Info.flags |= MachineMemOperand::MOVolatile;
1690
1691 Infos.push_back(Info);
1692 return;
1693 }
1694 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1695 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1696 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1699 Info.memVT = MVT::getVT(CI.getType());
1700 Info.ptrVal = CI.getOperand(0);
1701 Info.memVT = MVT::i64;
1702 Info.size = 8;
1703 Info.align.reset();
1705 Info.order = AtomicOrdering::Monotonic;
1706 Infos.push_back(Info);
1707 return;
1708 }
1709 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1710 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1711 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1712 Info.opc = ISD::INTRINSIC_W_CHAIN;
1713 Info.memVT =
1714 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1715 ? CI.getType()
1717 ->getElementType(0)); // XXX: what is correct VT?
1718
1719 Info.fallbackAddressSpace = AMDGPUAS::BUFFER_RESOURCE;
1720 Info.align.reset();
1721 Info.flags = Flags | MachineMemOperand::MOLoad |
1723 Infos.push_back(Info);
1724 return;
1725 }
1726 case Intrinsic::amdgcn_global_atomic_fmin_num:
1727 case Intrinsic::amdgcn_global_atomic_fmax_num:
1728 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1729 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1730 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1731 Info.opc = ISD::INTRINSIC_W_CHAIN;
1732 Info.memVT = MVT::getVT(CI.getType());
1733 Info.ptrVal = CI.getOperand(0);
1734 Info.align.reset();
1735 Info.flags =
1738 Infos.push_back(Info);
1739 return;
1740 }
1741 case Intrinsic::amdgcn_cluster_load_b32:
1742 case Intrinsic::amdgcn_cluster_load_b64:
1743 case Intrinsic::amdgcn_cluster_load_b128:
1744 case Intrinsic::amdgcn_ds_load_tr6_b96:
1745 case Intrinsic::amdgcn_ds_load_tr4_b64:
1746 case Intrinsic::amdgcn_ds_load_tr8_b64:
1747 case Intrinsic::amdgcn_ds_load_tr16_b128:
1748 case Intrinsic::amdgcn_global_load_tr6_b96:
1749 case Intrinsic::amdgcn_global_load_tr4_b64:
1750 case Intrinsic::amdgcn_global_load_tr_b64:
1751 case Intrinsic::amdgcn_global_load_tr_b128:
1752 case Intrinsic::amdgcn_ds_read_tr4_b64:
1753 case Intrinsic::amdgcn_ds_read_tr6_b96:
1754 case Intrinsic::amdgcn_ds_read_tr8_b64:
1755 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1756 Info.opc = ISD::INTRINSIC_W_CHAIN;
1757 Info.memVT = MVT::getVT(CI.getType());
1758 Info.ptrVal = CI.getOperand(0);
1759 Info.align.reset();
1760 Info.flags = Flags | MachineMemOperand::MOLoad;
1761 Infos.push_back(Info);
1762 return;
1763 }
1764 case Intrinsic::amdgcn_flat_load_monitor_b32:
1765 case Intrinsic::amdgcn_flat_load_monitor_b64:
1766 case Intrinsic::amdgcn_flat_load_monitor_b128:
1767 case Intrinsic::amdgcn_global_load_monitor_b32:
1768 case Intrinsic::amdgcn_global_load_monitor_b64:
1769 case Intrinsic::amdgcn_global_load_monitor_b128: {
1770 Info.opc = ISD::INTRINSIC_W_CHAIN;
1771 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1772 Info.ptrVal = CI.getOperand(0);
1773 Info.align.reset();
1774 Info.flags = MachineMemOperand::MOLoad;
1775 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1776 Info.ssid = parseSyncscopeMDArg(CI, 2);
1777 Infos.push_back(Info);
1778 return;
1779 }
1780 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1781 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1782 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1783 Info.opc = ISD::INTRINSIC_W_CHAIN;
1784 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1785 Info.ptrVal = CI.getOperand(0);
1786 Info.align.reset();
1788 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1789 Info.ssid = parseSyncscopeMDArg(CI, 2);
1790 Infos.push_back(Info);
1791 return;
1792 }
1793 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1794 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1795 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1796 Info.opc = ISD::INTRINSIC_VOID;
1797 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1798 Info.ptrVal = CI.getArgOperand(0);
1799 Info.align.reset();
1801 Info.order = parseAtomicOrderingCABIArg(CI, 2);
1802 Info.ssid = parseSyncscopeMDArg(CI, 3);
1803 Infos.push_back(Info);
1804 return;
1805 }
1806 case Intrinsic::amdgcn_ds_gws_init:
1807 case Intrinsic::amdgcn_ds_gws_barrier:
1808 case Intrinsic::amdgcn_ds_gws_sema_v:
1809 case Intrinsic::amdgcn_ds_gws_sema_br:
1810 case Intrinsic::amdgcn_ds_gws_sema_p:
1811 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1812 Info.opc = ISD::INTRINSIC_VOID;
1813
1814 const GCNTargetMachine &TM =
1815 static_cast<const GCNTargetMachine &>(getTargetMachine());
1816
1818 Info.ptrVal = MFI->getGWSPSV(TM);
1819
1820 // This is an abstract access, but we need to specify a type and size.
1821 Info.memVT = MVT::i32;
1822 Info.size = 4;
1823 Info.align = Align(4);
1824
1825 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1826 Info.flags = Flags | MachineMemOperand::MOLoad;
1827 else
1828 Info.flags = Flags | MachineMemOperand::MOStore;
1829 Infos.push_back(Info);
1830 return;
1831 }
1832 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1833 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1834 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1835 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1836 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1837 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1838 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1839 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1840 // Entry 0: Load from source (global/flat).
1841 Info.opc = ISD::INTRINSIC_VOID;
1842 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1843 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1844 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1845 Info.flags = Flags | MachineMemOperand::MOLoad;
1846 Infos.push_back(Info);
1847
1848 // Entry 1: Store to LDS (same offset).
1849 Info.flags = Flags | MachineMemOperand::MOStore;
1850 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1851 Infos.push_back(Info);
1852 return;
1853 }
1854 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1855 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1856 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1857 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1858 // Entry 0: Load from LDS.
1859 Info.opc = ISD::INTRINSIC_VOID;
1860 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1861 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1862 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1863 Info.flags = Flags | MachineMemOperand::MOLoad;
1864 Infos.push_back(Info);
1865
1866 // Entry 1: Store to global (same offset).
1867 Info.flags = Flags | MachineMemOperand::MOStore;
1868 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1869 Infos.push_back(Info);
1870 return;
1871 }
1872 case Intrinsic::amdgcn_av_load_b128:
1873 case Intrinsic::amdgcn_av_store_b128: {
1874 bool IsStore = IntrID == Intrinsic::amdgcn_av_store_b128;
1875 Info.opc = IsStore ? ISD::INTRINSIC_VOID : ISD::INTRINSIC_W_CHAIN;
1876 Info.memVT = MVT::v4i32;
1877 Info.ptrVal = CI.getArgOperand(0);
1878 Info.align = Align(16);
1879 Info.flags |=
1881 // Pretend to be atomic so that SIMemoryLegalizer::expandStore sets cache
1882 // flags appropriately.
1883 Info.order = AtomicOrdering::Monotonic;
1884
1885 LLVMContext &Ctx = CI.getContext();
1886 unsigned ScopeIdx = CI.arg_size() - 1;
1887 MDNode *ScopeMD = cast<MDNode>(
1888 cast<MetadataAsValue>(CI.getArgOperand(ScopeIdx))->getMetadata());
1889 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1890 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1891 Infos.push_back(Info);
1892 return;
1893 }
1894 case Intrinsic::amdgcn_load_to_lds:
1895 case Intrinsic::amdgcn_load_async_to_lds:
1896 case Intrinsic::amdgcn_global_load_lds:
1897 case Intrinsic::amdgcn_global_load_async_lds: {
1898 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1899 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1900 bool IsVolatile = Aux->getZExtValue() & AMDGPU::CPol::VOLATILE;
1901 if (IsVolatile)
1903
1904 // Entry 0: Load from source (global/flat).
1905 Info.opc = ISD::INTRINSIC_VOID;
1906 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1907 Info.ptrVal = CI.getArgOperand(0); // Source pointer
1908 Info.offset = cast<ConstantInt>(CI.getArgOperand(3))->getSExtValue();
1909 Info.flags = Flags | MachineMemOperand::MOLoad;
1910 Infos.push_back(Info);
1911
1912 // Entry 1: Store to LDS.
1913 // Same offset from the instruction, but an additional per-lane offset is
1914 // added. Represent that using a wider memory type.
1915 Info.memVT = EVT::getIntegerVT(CI.getContext(),
1916 Width * 8 * Subtarget->getWavefrontSize());
1917 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1918 Info.flags = Flags | MachineMemOperand::MOStore;
1919 Infos.push_back(Info);
1920 return;
1921 }
1922 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1923 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1924 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1925 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1926 Info.opc = ISD::INTRINSIC_W_CHAIN;
1927
1928 const GCNTargetMachine &TM =
1929 static_cast<const GCNTargetMachine &>(getTargetMachine());
1930
1932 Info.ptrVal = MFI->getGWSPSV(TM);
1933
1934 // This is an abstract access, but we need to specify a type and size.
1935 Info.memVT = MVT::i32;
1936 Info.size = 4;
1937 Info.align = Align(4);
1938
1940 Infos.push_back(Info);
1941 return;
1942 }
1943 case Intrinsic::amdgcn_s_prefetch_data:
1944 case Intrinsic::amdgcn_s_prefetch_inst:
1945 case Intrinsic::amdgcn_flat_prefetch:
1946 case Intrinsic::amdgcn_global_prefetch: {
1947 Info.opc = ISD::INTRINSIC_VOID;
1948 Info.memVT = EVT::getIntegerVT(CI.getContext(), 8);
1949 Info.ptrVal = CI.getArgOperand(0);
1950 Info.flags = Flags | MachineMemOperand::MOLoad;
1951 Infos.push_back(Info);
1952 return;
1953 }
1954 default:
1955 return;
1956 }
1957}
1958
1961 Type *&AccessTy) const {
1962 Value *Ptr = nullptr;
1963 switch (II->getIntrinsicID()) {
1964 case Intrinsic::amdgcn_cluster_load_b128:
1965 case Intrinsic::amdgcn_cluster_load_b64:
1966 case Intrinsic::amdgcn_cluster_load_b32:
1967 case Intrinsic::amdgcn_ds_append:
1968 case Intrinsic::amdgcn_ds_consume:
1969 case Intrinsic::amdgcn_ds_load_tr8_b64:
1970 case Intrinsic::amdgcn_ds_load_tr16_b128:
1971 case Intrinsic::amdgcn_ds_load_tr4_b64:
1972 case Intrinsic::amdgcn_ds_load_tr6_b96:
1973 case Intrinsic::amdgcn_ds_read_tr4_b64:
1974 case Intrinsic::amdgcn_ds_read_tr6_b96:
1975 case Intrinsic::amdgcn_ds_read_tr8_b64:
1976 case Intrinsic::amdgcn_ds_read_tr16_b64:
1977 case Intrinsic::amdgcn_ds_ordered_add:
1978 case Intrinsic::amdgcn_ds_ordered_swap:
1979 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1980 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1981 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1982 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1983 case Intrinsic::amdgcn_global_atomic_fmax_num:
1984 case Intrinsic::amdgcn_global_atomic_fmin_num:
1985 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1986 case Intrinsic::amdgcn_global_load_tr_b64:
1987 case Intrinsic::amdgcn_global_load_tr_b128:
1988 case Intrinsic::amdgcn_global_load_tr4_b64:
1989 case Intrinsic::amdgcn_global_load_tr6_b96:
1990 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1991 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1992 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1993 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1994 case Intrinsic::amdgcn_av_load_b128:
1995 case Intrinsic::amdgcn_av_store_b128:
1996 Ptr = II->getArgOperand(0);
1997 break;
1998 case Intrinsic::amdgcn_load_to_lds:
1999 case Intrinsic::amdgcn_load_async_to_lds:
2000 case Intrinsic::amdgcn_global_load_lds:
2001 case Intrinsic::amdgcn_global_load_async_lds:
2002 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
2003 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
2004 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
2005 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
2006 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
2007 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
2008 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
2009 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
2010 Ptr = II->getArgOperand(1);
2011 break;
2012 default:
2013 return false;
2014 }
2015 AccessTy = II->getType();
2016 Ops.push_back(Ptr);
2017 return true;
2018}
2019
2021 unsigned AddrSpace) const {
2022 if (!Subtarget->hasFlatInstOffsets()) {
2023 // Flat instructions do not have offsets, and only have the register
2024 // address.
2025 return AM.BaseOffs == 0 && AM.Scale == 0;
2026 }
2027
2029 FlatAddrSpace FlatVariant =
2030 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS ? FlatAddrSpace::FlatGlobal
2031 : AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ? FlatAddrSpace::FlatScratch
2032 : FlatAddrSpace::FLAT;
2033
2034 return AM.Scale == 0 &&
2035 (AM.BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
2036 AM.BaseOffs, AddrSpace, FlatVariant));
2037}
2038
2040 if (Subtarget->hasFlatGlobalInsts())
2042
2043 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
2044 // Assume the we will use FLAT for all global memory accesses
2045 // on VI.
2046 // FIXME: This assumption is currently wrong. On VI we still use
2047 // MUBUF instructions for the r + i addressing mode. As currently
2048 // implemented, the MUBUF instructions only work on buffer < 4GB.
2049 // It may be possible to support > 4GB buffers with MUBUF instructions,
2050 // by setting the stride value in the resource descriptor which would
2051 // increase the size limit to (stride * 4GB). However, this is risky,
2052 // because it has never been validated.
2054 }
2055
2056 return isLegalMUBUFAddressingMode(AM);
2057}
2058
2059bool SITargetLowering::isLegalMUBUFAddressingMode(const AddrMode &AM) const {
2060 // MUBUF / MTBUF instructions have a 12-bit unsigned byte offset, and
2061 // additionally can do r + r + i with addr64. 32-bit has more addressing
2062 // mode options. Depending on the resource constant, it can also do
2063 // (i64 r0) + (i32 r1) * (i14 i).
2064 //
2065 // Private arrays end up using a scratch buffer most of the time, so also
2066 // assume those use MUBUF instructions. Scratch loads / stores are currently
2067 // implemented as mubuf instructions with offen bit set, so slightly
2068 // different than the normal addr64.
2069 const SIInstrInfo *TII = Subtarget->getInstrInfo();
2070 if (!TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2071 return false;
2072
2073 // FIXME: Since we can split immediate into soffset and immediate offset,
2074 // would it make sense to allow any immediate?
2075
2076 switch (AM.Scale) {
2077 case 0: // r + i or just i, depending on HasBaseReg.
2078 return true;
2079 case 1:
2080 return true; // We have r + r or r + i.
2081 case 2:
2082 if (AM.HasBaseReg) {
2083 // Reject 2 * r + r.
2084 return false;
2085 }
2086
2087 // Allow 2 * r as r + r
2088 // Or 2 * r + i is allowed as r + r + i.
2089 return true;
2090 default: // Don't allow n * r
2091 return false;
2092 }
2093}
2094
2096 const AddrMode &AM, Type *Ty,
2097 unsigned AS,
2098 Instruction *I) const {
2099 // No global is ever allowed as a base.
2100 if (AM.BaseGV)
2101 return false;
2102
2103 if (AS == AMDGPUAS::GLOBAL_ADDRESS)
2104 return isLegalGlobalAddressingMode(AM);
2105
2106 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
2110 // If the offset isn't a multiple of 4, it probably isn't going to be
2111 // correctly aligned.
2112 // FIXME: Can we get the real alignment here?
2113 if (AM.BaseOffs % 4 != 0)
2114 return isLegalMUBUFAddressingMode(AM);
2115
2116 if (!Subtarget->hasScalarSubwordLoads()) {
2117 // There are no SMRD extloads, so if we have to do a small type access we
2118 // will use a MUBUF load.
2119 // FIXME?: We also need to do this if unaligned, but we don't know the
2120 // alignment here.
2121 if (Ty->isSized() && DL.getTypeStoreSize(Ty) < 4)
2122 return isLegalGlobalAddressingMode(AM);
2123 }
2124
2125 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS) {
2126 // SMRD instructions have an 8-bit, dword offset on SI.
2127 if (!isUInt<8>(AM.BaseOffs / 4))
2128 return false;
2129 } else if (Subtarget->getGeneration() == AMDGPUSubtarget::SEA_ISLANDS) {
2130 // On CI+, this can also be a 32-bit literal constant offset. If it fits
2131 // in 8-bits, it can use a smaller encoding.
2132 if (!isUInt<32>(AM.BaseOffs / 4))
2133 return false;
2134 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX9) {
2135 // On VI, these use the SMEM format and the offset is 20-bit in bytes.
2136 if (!isUInt<20>(AM.BaseOffs))
2137 return false;
2138 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX12) {
2139 // On GFX9 the offset is signed 21-bit in bytes (but must not be negative
2140 // for S_BUFFER_* instructions).
2141 if (!isInt<21>(AM.BaseOffs))
2142 return false;
2143 } else {
2144 // On GFX12, all offsets are signed 24-bit in bytes.
2145 if (!isInt<24>(AM.BaseOffs))
2146 return false;
2147 }
2148
2149 if ((AS == AMDGPUAS::CONSTANT_ADDRESS ||
2151 AM.BaseOffs < 0) {
2152 // Scalar (non-buffer) loads can only use a negative offset if
2153 // soffset+offset is non-negative. Since the compiler can only prove that
2154 // in a few special cases, it is safer to claim that negative offsets are
2155 // not supported.
2156 return false;
2157 }
2158
2159 if (AM.Scale == 0) // r + i or just i, depending on HasBaseReg.
2160 return true;
2161
2162 if (AM.Scale == 1 && AM.HasBaseReg)
2163 return true;
2164
2165 return false;
2166 }
2167
2168 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
2169 return Subtarget->hasFlatScratchEnabled()
2171 : isLegalMUBUFAddressingMode(AM);
2172
2173 if (AS == AMDGPUAS::LOCAL_ADDRESS ||
2174 (AS == AMDGPUAS::REGION_ADDRESS && Subtarget->hasGDS())) {
2175 // Basic, single offset DS instructions allow a 16-bit unsigned immediate
2176 // field.
2177 // XXX - If doing a 4-byte aligned 8-byte type access, we effectively have
2178 // an 8-bit dword offset but we don't know the alignment here.
2179 if (!isUInt<16>(AM.BaseOffs))
2180 return false;
2181
2182 if (AM.Scale == 0) // r + i or just i, depending on HasBaseReg.
2183 return true;
2184
2185 if (AM.Scale == 1 && AM.HasBaseReg)
2186 return true;
2187
2188 return false;
2189 }
2190
2192 // For an unknown address space, this usually means that this is for some
2193 // reason being used for pure arithmetic, and not based on some addressing
2194 // computation. We don't have instructions that compute pointers with any
2195 // addressing modes, so treat them as having no offset like flat
2196 // instructions.
2198 }
2199
2200 // Assume a user alias of global for unknown address spaces.
2201 return isLegalGlobalAddressingMode(AM);
2202}
2203
2205 const MachineFunction &MF) const {
2207 return (MemVT.getSizeInBits() <= 4 * 32);
2208 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
2209 unsigned MaxPrivateBits = 8 * getSubtarget()->getMaxPrivateElementSize();
2210 return (MemVT.getSizeInBits() <= MaxPrivateBits);
2211 }
2213 return (MemVT.getSizeInBits() <= 2 * 32);
2214 return true;
2215}
2216
2218 unsigned Size, unsigned AddrSpace, Align Alignment,
2219 MachineMemOperand::Flags Flags, unsigned *IsFast) const {
2220 if (IsFast)
2221 *IsFast = 0;
2222
2223 if (AddrSpace == AMDGPUAS::LOCAL_ADDRESS ||
2224 AddrSpace == AMDGPUAS::REGION_ADDRESS) {
2225 // Check if alignment requirements for ds_read/write instructions are
2226 // disabled.
2227 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment < Align(4))
2228 return false;
2229
2230 Align RequiredAlignment(
2231 PowerOf2Ceil(divideCeil(Size, 8))); // Natural alignment.
2232 if (Subtarget->hasLDSMisalignedBugInWGPMode() && Size > 32 &&
2233 Alignment < RequiredAlignment)
2234 return false;
2235
2236 // Either, the alignment requirements are "enabled", or there is an
2237 // unaligned LDS access related hardware bug though alignment requirements
2238 // are "disabled". In either case, we need to check for proper alignment
2239 // requirements.
2240 //
2241 switch (Size) {
2242 case 64:
2243 // SI has a hardware bug in the LDS / GDS bounds checking: if the base
2244 // address is negative, then the instruction is incorrectly treated as
2245 // out-of-bounds even if base + offsets is in bounds. Split vectorized
2246 // loads here to avoid emitting ds_read2_b32. We may re-combine the
2247 // load later in the SILoadStoreOptimizer.
2248 if (!Subtarget->hasUsableDSOffset() && Alignment < Align(8))
2249 return false;
2250
2251 // 8 byte accessing via ds_read/write_b64 require 8-byte alignment, but we
2252 // can do a 4 byte aligned, 8 byte access in a single operation using
2253 // ds_read2/write2_b32 with adjacent offsets.
2254 RequiredAlignment = Align(4);
2255
2256 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2257 // We will either select ds_read_b64/ds_write_b64 or ds_read2_b32/
2258 // ds_write2_b32 depending on the alignment. In either case with either
2259 // alignment there is no faster way of doing this.
2260
2261 // The numbers returned here and below are not additive, it is a 'speed
2262 // rank'. They are just meant to be compared to decide if a certain way
2263 // of lowering an operation is faster than another. For that purpose
2264 // naturally aligned operation gets it bitsize to indicate that "it
2265 // operates with a speed comparable to N-bit wide load". With the full
2266 // alignment ds128 is slower than ds96 for example. If underaligned it
2267 // is comparable to a speed of a single dword access, which would then
2268 // mean 32 < 128 and it is faster to issue a wide load regardless.
2269 // 1 is simply "slow, don't do it". I.e. comparing an aligned load to a
2270 // wider load which will not be aligned anymore the latter is slower.
2271 if (IsFast)
2272 *IsFast = (Alignment >= RequiredAlignment) ? 64
2273 : (Alignment < Align(4)) ? 32
2274 : 1;
2275 return true;
2276 }
2277
2278 break;
2279 case 96:
2280 if (!Subtarget->hasDS96AndDS128())
2281 return false;
2282
2283 // 12 byte accessing via ds_read/write_b96 require 16-byte alignment on
2284 // gfx8 and older.
2285
2286 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2287 // Naturally aligned access is fastest. However, also report it is Fast
2288 // if memory is aligned less than DWORD. A narrow load or store will be
2289 // be equally slow as a single ds_read_b96/ds_write_b96, but there will
2290 // be more of them, so overall we will pay less penalty issuing a single
2291 // instruction.
2292
2293 // See comment on the values above.
2294 if (IsFast)
2295 *IsFast = (Alignment >= RequiredAlignment) ? 96
2296 : (Alignment < Align(4)) ? 32
2297 : 1;
2298 return true;
2299 }
2300
2301 break;
2302 case 128:
2303 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2304 return false;
2305
2306 // 16 byte accessing via ds_read/write_b128 require 16-byte alignment on
2307 // gfx8 and older, but we can do a 8 byte aligned, 16 byte access in a
2308 // single operation using ds_read2/write2_b64.
2309 RequiredAlignment = Align(8);
2310
2311 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2312 // Naturally aligned access is fastest. However, also report it is Fast
2313 // if memory is aligned less than DWORD. A narrow load or store will be
2314 // be equally slow as a single ds_read_b128/ds_write_b128, but there
2315 // will be more of them, so overall we will pay less penalty issuing a
2316 // single instruction.
2317
2318 // See comment on the values above.
2319 if (IsFast)
2320 *IsFast = (Alignment >= RequiredAlignment) ? 128
2321 : (Alignment < Align(4)) ? 32
2322 : 1;
2323 return true;
2324 }
2325
2326 break;
2327 default:
2328 if (Size > 32)
2329 return false;
2330
2331 break;
2332 }
2333
2334 // See comment on the values above.
2335 // Note that we have a single-dword or sub-dword here, so if underaligned
2336 // it is a slowest possible access, hence returned value is 0.
2337 if (IsFast)
2338 *IsFast = (Alignment >= RequiredAlignment) ? Size : 0;
2339
2340 return Alignment >= RequiredAlignment ||
2341 Subtarget->hasUnalignedDSAccessEnabled();
2342 }
2343
2344 // FIXME: We have to be conservative here and assume that flat operations
2345 // will access scratch. If we had access to the IR function, then we
2346 // could determine if any private memory was used in the function.
2347 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ||
2348 AddrSpace == AMDGPUAS::FLAT_ADDRESS) {
2349 bool AlignedBy4 = Alignment >= Align(4);
2350 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2351 if (IsFast)
2352 *IsFast = AlignedBy4 ? Size : 1;
2353 return true;
2354 }
2355
2356 if (IsFast)
2357 *IsFast = AlignedBy4;
2358
2359 return AlignedBy4;
2360 }
2361
2362 // So long as they are correct, wide global memory operations perform better
2363 // than multiple smaller memory ops -- even when misaligned
2364 if (AMDGPU::isExtendedGlobalAddrSpace(AddrSpace)) {
2365 if (IsFast)
2366 *IsFast = Size;
2367
2368 return Alignment >= Align(4) ||
2369 Subtarget->hasUnalignedBufferAccessEnabled();
2370 }
2371
2372 // Ensure robust out-of-bounds guarantees for buffer accesses are met when the
2373 // "amdgpu.buffer.oob.mode" module flag has not enabled relaxed untyped-buffer
2374 // OOB semantics. Normally hardware will ensure proper
2375 // out-of-bounds behavior, but in the edge case where an access starts
2376 // out-of-bounds and then enters in-bounds, the entire access would be treated
2377 // as out-of-bounds. Prevent misaligned memory accesses by requiring the
2378 // natural alignment of buffer accesses.
2379 if (AddrSpace == AMDGPUAS::BUFFER_FAT_POINTER ||
2380 AddrSpace == AMDGPUAS::BUFFER_RESOURCE ||
2381 AddrSpace == AMDGPUAS::BUFFER_STRIDED_POINTER) {
2382 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2383 Alignment < Align(PowerOf2Ceil(divideCeil(Size, 8))))
2384 return false;
2385 }
2386
2387 // Smaller than dword value must be aligned.
2388 if (Size < 32)
2389 return false;
2390
2391 // 8.1.6 - For Dword or larger reads or writes, the two LSBs of the
2392 // byte-address are ignored, thus forcing Dword alignment.
2393 // This applies to private, global, and constant memory.
2394 if (IsFast)
2395 *IsFast = 1;
2396
2397 return Size >= 32 && Alignment >= Align(4);
2398}
2399
2401 EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
2402 unsigned *IsFast) const {
2404 Alignment, Flags, IsFast);
2405}
2406
2408 LLVMContext &Context, const MemOp &Op,
2409 const AttributeList &FuncAttributes) const {
2410 // FIXME: Should account for address space here.
2411
2412 // The default fallback uses the private pointer size as a guess for a type to
2413 // use. Make sure we switch these to 64-bit accesses.
2414
2415 if (Op.size() >= 16 &&
2416 Op.isDstAligned(Align(4))) // XXX: Should only do for global
2417 return MVT::v4i32;
2418
2419 if (Op.size() >= 8 && Op.isDstAligned(Align(4)))
2420 return MVT::v2i32;
2421
2422 // Use the default.
2423 return MVT::Other;
2424}
2425
2427 const MemSDNode *MemNode = cast<MemSDNode>(N);
2428 return MemNode->getMemOperand()->getFlags() & MONoClobber;
2429}
2430
2435
2437 unsigned DestAS) const {
2438 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
2439 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
2440 Subtarget->hasGloballyAddressableScratch()) {
2441 // Flat -> private requires subtracting src_flat_scratch_base_lo.
2442 return false;
2443 }
2444
2445 // Flat -> private/local is a simple truncate.
2446 // Flat -> global is no-op
2447 return true;
2448 }
2449
2450 const GCNTargetMachine &TM =
2451 static_cast<const GCNTargetMachine &>(getTargetMachine());
2452 return TM.isNoopAddrSpaceCast(SrcAS, DestAS);
2453}
2454
2462
2464 Type *Ty) const {
2465 // FIXME: Could be smarter if called for vector constants.
2466 return true;
2467}
2468
2471 unsigned Index) const {
2474
2475 // TODO: Add more cases that are cheap.
2476 if (Index == 0)
2479}
2480
2481bool SITargetLowering::isExtractVecEltCheap(EVT VT, unsigned Index) const {
2482 // TODO: This should be more aggressive, particular for 16-bit element
2483 // vectors. However there are some mixed improvements and regressions.
2484 EVT EltTy = VT.getVectorElementType();
2485 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2486 return EltTy.getSizeInBits() % MinAlign == 0;
2487}
2488
2490 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2491 switch (Op) {
2492 case ISD::LOAD:
2493 case ISD::STORE:
2494 return true;
2495 default:
2496 return false;
2497 }
2498 }
2499
2500 // SimplifySetCC uses this function to determine whether or not it should
2501 // create setcc with i1 operands. We don't have instructions for i1 setcc.
2502 if (VT == MVT::i1 && Op == ISD::SETCC)
2503 return false;
2504
2506}
2507
2510 // This isn't really a constant pool but close enough.
2513 return PtrInfo;
2514}
2515
2516SDValue SITargetLowering::lowerKernArgParameterPtr(SelectionDAG &DAG,
2517 const SDLoc &SL,
2518 SDValue Chain,
2519 uint64_t Offset) const {
2520 const DataLayout &DL = DAG.getDataLayout();
2524
2525 auto [InputPtrReg, RC, ArgTy] =
2526 Info->getPreloadedValue(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
2527
2528 // We may not have the kernarg segment argument if we have no kernel
2529 // arguments.
2530 if (!InputPtrReg)
2531 return DAG.getConstant(Offset, SL, PtrVT);
2532
2534 SDValue BasePtr = DAG.getCopyFromReg(
2535 Chain, SL, MRI.getLiveInVirtReg(InputPtrReg->getRegister()), PtrVT);
2536
2537 return DAG.getObjectPtrOffset(SL, BasePtr, TypeSize::getFixed(Offset));
2538}
2539
2540SDValue SITargetLowering::getImplicitArgPtr(SelectionDAG &DAG,
2541 const SDLoc &SL) const {
2544 return lowerKernArgParameterPtr(DAG, SL, DAG.getEntryNode(), Offset);
2545}
2546
2547SDValue SITargetLowering::getLDSKernelId(SelectionDAG &DAG,
2548 const SDLoc &SL) const {
2549
2551 std::optional<uint32_t> KnownSize =
2553 if (KnownSize.has_value())
2554 return DAG.getConstant(*KnownSize, SL, MVT::i32);
2555 return SDValue();
2556}
2557
2558SDValue SITargetLowering::convertArgType(SelectionDAG &DAG, EVT VT, EVT MemVT,
2559 const SDLoc &SL, SDValue Val,
2560 bool Signed,
2561 const ISD::InputArg *Arg) const {
2562 // First, if it is a widened vector, narrow it.
2563 if (VT.isVector() &&
2565 EVT NarrowedVT =
2568 Val = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, NarrowedVT, Val,
2569 DAG.getConstant(0, SL, MVT::i32));
2570 }
2571
2572 // Then convert the vector elements or scalar value.
2573 if (Arg && (Arg->Flags.isSExt() || Arg->Flags.isZExt()) && VT.bitsLT(MemVT)) {
2574 unsigned Opc = Arg->Flags.isZExt() ? ISD::AssertZext : ISD::AssertSext;
2575 Val = DAG.getNode(Opc, SL, MemVT, Val, DAG.getValueType(VT));
2576 }
2577
2578 if (MemVT.isFloatingPoint()) {
2579 if (VT.isFloatingPoint()) {
2580 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2581 } else {
2582 assert(!MemVT.isVector());
2583 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
2584 SDValue Cast = DAG.getBitcast(IntVT, Val);
2585 Val = DAG.getAnyExtOrTrunc(Cast, SL, VT);
2586 }
2587 } else if (Signed)
2588 Val = DAG.getSExtOrTrunc(Val, SL, VT);
2589 else
2590 Val = DAG.getZExtOrTrunc(Val, SL, VT);
2591
2592 return Val;
2593}
2594
2595SDValue SITargetLowering::lowerKernargMemParameter(
2596 SelectionDAG &DAG, EVT VT, EVT MemVT, const SDLoc &SL, SDValue Chain,
2597 uint64_t Offset, Align Alignment, bool Signed,
2598 const ISD::InputArg *Arg) const {
2599
2600 MachinePointerInfo PtrInfo =
2602
2603 // Try to avoid using an extload by loading earlier than the argument address,
2604 // and extracting the relevant bits. The load should hopefully be merged with
2605 // the previous argument.
2606 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
2607 // TODO: Handle align < 4 and size >= 4 (can happen with packed structs).
2608 int64_t AlignDownOffset = alignDown(Offset, 4);
2609 int64_t OffsetDiff = Offset - AlignDownOffset;
2610
2611 EVT IntVT = MemVT.changeTypeToInteger();
2612
2613 // TODO: If we passed in the base kernel offset we could have a better
2614 // alignment than 4, but we don't really need it.
2615 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2616 SDValue Load = DAG.getLoad(MVT::i32, SL, Chain, Ptr,
2617 PtrInfo.getWithOffset(AlignDownOffset), Align(4),
2620
2621 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, SL, MVT::i32);
2622 SDValue Extract = DAG.getNode(ISD::SRL, SL, MVT::i32, Load, ShiftAmt);
2623
2624 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, SL, IntVT, Extract);
2625 ArgVal = DAG.getNode(ISD::BITCAST, SL, MemVT, ArgVal);
2626 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal, Signed, Arg);
2627
2628 return DAG.getMergeValues({ArgVal, Load.getValue(1)}, SL);
2629 }
2630
2631 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, Offset);
2632 SDValue Load = DAG.getLoad(
2633 MemVT, SL, Chain, Ptr, PtrInfo.getWithOffset(Offset), Alignment,
2635
2636 SDValue Val = convertArgType(DAG, VT, MemVT, SL, Load, Signed, Arg);
2637 return DAG.getMergeValues({Val, Load.getValue(1)}, SL);
2638}
2639
2640/// Coerce an argument which was passed in a different ABI type to the original
2641/// expected value type.
2642SDValue SITargetLowering::convertABITypeToValueType(SelectionDAG &DAG,
2643 SDValue Val,
2644 CCValAssign &VA,
2645 const SDLoc &SL) const {
2646 EVT ValVT = VA.getValVT();
2647
2648 // If this is an 8 or 16-bit value, it is really passed promoted
2649 // to 32 bits. Insert an assert[sz]ext to capture this, then
2650 // truncate to the right size.
2651 switch (VA.getLocInfo()) {
2652 case CCValAssign::Full:
2653 return Val;
2654 case CCValAssign::BCvt:
2655 return DAG.getNode(ISD::BITCAST, SL, ValVT, Val);
2656 case CCValAssign::SExt:
2657 Val = DAG.getNode(ISD::AssertSext, SL, VA.getLocVT(), Val,
2658 DAG.getValueType(ValVT));
2659 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2660 case CCValAssign::ZExt:
2661 Val = DAG.getNode(ISD::AssertZext, SL, VA.getLocVT(), Val,
2662 DAG.getValueType(ValVT));
2663 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2664 case CCValAssign::AExt:
2665 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2666 default:
2667 llvm_unreachable("Unknown loc info!");
2668 }
2669}
2670
2671SDValue SITargetLowering::lowerStackParameter(SelectionDAG &DAG,
2672 CCValAssign &VA, const SDLoc &SL,
2673 SDValue Chain,
2674 const ISD::InputArg &Arg) const {
2676 MachineFrameInfo &MFI = MF.getFrameInfo();
2677
2678 if (Arg.Flags.isByVal()) {
2679 unsigned Size = Arg.Flags.getByValSize();
2680 int FrameIdx = MFI.CreateFixedObject(Size, VA.getLocMemOffset(), false);
2681 return DAG.getFrameIndex(FrameIdx, MVT::i32);
2682 }
2683
2684 unsigned ArgOffset = VA.getLocMemOffset();
2685 unsigned ArgSize = VA.getValVT().getStoreSize();
2686
2687 int FI = MFI.CreateFixedObject(ArgSize, ArgOffset, true);
2688
2689 // Create load nodes to retrieve arguments from the stack.
2690 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
2691
2692 // For NON_EXTLOAD, generic code in getLoad assert(ValVT == MemVT)
2694 MVT MemVT = VA.getValVT();
2695
2696 switch (VA.getLocInfo()) {
2697 default:
2698 break;
2699 case CCValAssign::BCvt:
2700 MemVT = VA.getLocVT();
2701 break;
2702 case CCValAssign::SExt:
2703 ExtType = ISD::SEXTLOAD;
2704 break;
2705 case CCValAssign::ZExt:
2706 ExtType = ISD::ZEXTLOAD;
2707 break;
2708 case CCValAssign::AExt:
2709 ExtType = ISD::EXTLOAD;
2710 break;
2711 }
2712
2713 SDValue ArgValue = DAG.getExtLoad(
2714 ExtType, SL, VA.getLocVT(), Chain, FIN,
2716
2717 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2718 if (ConvertedVal == ArgValue)
2719 return ConvertedVal;
2720
2721 return DAG.getMergeValues({ConvertedVal, ArgValue.getValue(1)}, SL);
2722}
2723
2724SDValue SITargetLowering::lowerWorkGroupId(
2725 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2728 AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const {
2729 if (!Subtarget->hasClusters())
2730 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2731
2732 // Clusters are supported. Return the global position in the grid. If clusters
2733 // are enabled, WorkGroupIdPV returns the cluster ID not the workgroup ID.
2734
2735 // WorkGroupIdXYZ = ClusterId == 0 ?
2736 // ClusterIdXYZ :
2737 // ClusterIdXYZ * (ClusterMaxIdXYZ + 1) + ClusterWorkGroupIdXYZ
2738 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2739 SDLoc SL(ClusterIdXYZ);
2740 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2741 SDValue One = DAG.getConstant(1, SL, VT);
2742 SDValue ClusterSizeXYZ = DAG.getNode(ISD::ADD, SL, VT, ClusterMaxIdXYZ, One);
2743 SDValue ClusterWorkGroupIdXYZ =
2744 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2745 SDValue GlobalIdXYZ =
2746 DAG.getNode(ISD::ADD, SL, VT, ClusterWorkGroupIdXYZ,
2747 DAG.getNode(ISD::MUL, SL, VT, ClusterIdXYZ, ClusterSizeXYZ));
2748
2749 switch (MFI.getClusterDims().getKind()) {
2752 return GlobalIdXYZ;
2754 return ClusterIdXYZ;
2756 using namespace AMDGPU::Hwreg;
2757 SDValue ClusterIdField =
2758 DAG.getTargetConstant(HwregEncoding::encode(ID_IB_STS2, 6, 4), SL, VT);
2759 SDNode *GetReg =
2760 DAG.getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2761 SDValue ClusterId(GetReg, 0);
2762 SDValue Zero = DAG.getConstant(0, SL, VT);
2763 return DAG.getNode(ISD::SELECT_CC, SL, VT, ClusterId, Zero, ClusterIdXYZ,
2764 GlobalIdXYZ, DAG.getCondCode(ISD::SETEQ));
2765 }
2766 }
2767
2768 llvm_unreachable("nothing should reach here");
2769}
2770
2771SDValue SITargetLowering::getPreloadedValue(
2772 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2774 const ArgDescriptor *Reg = nullptr;
2775 const TargetRegisterClass *RC = nullptr;
2776 LLT Ty;
2777
2779 const ArgDescriptor WorkGroupIDX =
2780 ArgDescriptor::createRegister(AMDGPU::TTMP9);
2781 // If GridZ is not programmed in an entry function then the hardware will set
2782 // it to all zeros, so there is no need to mask the GridY value in the low
2783 // order bits.
2784 const ArgDescriptor WorkGroupIDY = ArgDescriptor::createRegister(
2785 AMDGPU::TTMP7,
2786 AMDGPU::isEntryFunctionCC(CC) && !MFI.hasWorkGroupIDZ() ? ~0u : 0xFFFFu);
2787 const ArgDescriptor WorkGroupIDZ =
2788 ArgDescriptor::createRegister(AMDGPU::TTMP7, 0xFFFF0000u);
2789 const ArgDescriptor ClusterWorkGroupIDX =
2790 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000000Fu);
2791 const ArgDescriptor ClusterWorkGroupIDY =
2792 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000000F0u);
2793 const ArgDescriptor ClusterWorkGroupIDZ =
2794 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00000F00u);
2795 const ArgDescriptor ClusterWorkGroupMaxIDX =
2796 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000F000u);
2797 const ArgDescriptor ClusterWorkGroupMaxIDY =
2798 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000F0000u);
2799 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2800 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00F00000u);
2801 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2802 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0F000000u);
2803
2804 auto LoadConstant = [&](unsigned N) {
2805 return DAG.getConstant(N, SDLoc(), VT);
2806 };
2807
2808 if (Subtarget->hasArchitectedSGPRs() &&
2810 AMDGPU::ClusterDimsAttr ClusterDims = MFI.getClusterDims();
2811 bool HasFixedDims = ClusterDims.isFixedDims();
2812
2813 switch (PVID) {
2815 Reg = &WorkGroupIDX;
2816 RC = &AMDGPU::SReg_32RegClass;
2817 Ty = LLT::scalar(32);
2818 break;
2820 Reg = &WorkGroupIDY;
2821 RC = &AMDGPU::SReg_32RegClass;
2822 Ty = LLT::scalar(32);
2823 break;
2825 Reg = &WorkGroupIDZ;
2826 RC = &AMDGPU::SReg_32RegClass;
2827 Ty = LLT::scalar(32);
2828 break;
2830 if (HasFixedDims && ClusterDims.getDims()[0] == 1)
2831 return LoadConstant(0);
2832 Reg = &ClusterWorkGroupIDX;
2833 RC = &AMDGPU::SReg_32RegClass;
2834 Ty = LLT::scalar(32);
2835 break;
2837 if (HasFixedDims && ClusterDims.getDims()[1] == 1)
2838 return LoadConstant(0);
2839 Reg = &ClusterWorkGroupIDY;
2840 RC = &AMDGPU::SReg_32RegClass;
2841 Ty = LLT::scalar(32);
2842 break;
2844 if (HasFixedDims && ClusterDims.getDims()[2] == 1)
2845 return LoadConstant(0);
2846 Reg = &ClusterWorkGroupIDZ;
2847 RC = &AMDGPU::SReg_32RegClass;
2848 Ty = LLT::scalar(32);
2849 break;
2851 if (HasFixedDims)
2852 return LoadConstant(ClusterDims.getDims()[0] - 1);
2853 Reg = &ClusterWorkGroupMaxIDX;
2854 RC = &AMDGPU::SReg_32RegClass;
2855 Ty = LLT::scalar(32);
2856 break;
2858 if (HasFixedDims)
2859 return LoadConstant(ClusterDims.getDims()[1] - 1);
2860 Reg = &ClusterWorkGroupMaxIDY;
2861 RC = &AMDGPU::SReg_32RegClass;
2862 Ty = LLT::scalar(32);
2863 break;
2865 if (HasFixedDims)
2866 return LoadConstant(ClusterDims.getDims()[2] - 1);
2867 Reg = &ClusterWorkGroupMaxIDZ;
2868 RC = &AMDGPU::SReg_32RegClass;
2869 Ty = LLT::scalar(32);
2870 break;
2872 Reg = &ClusterWorkGroupMaxFlatID;
2873 RC = &AMDGPU::SReg_32RegClass;
2874 Ty = LLT::scalar(32);
2875 break;
2876 default:
2877 break;
2878 }
2879 }
2880
2881 if (!Reg)
2882 std::tie(Reg, RC, Ty) = MFI.getPreloadedValue(PVID);
2883 if (!Reg) {
2885 // It's possible for a kernarg intrinsic call to appear in a kernel with
2886 // no allocated segment, in which case we do not add the user sgpr
2887 // argument, so just return null.
2888 return DAG.getConstant(0, SDLoc(), VT);
2889 }
2890
2891 // It's undefined behavior if a function marked with the amdgpu-no-*
2892 // attributes uses the corresponding intrinsic.
2893 return DAG.getPOISON(VT);
2894 }
2895
2896 return loadInputValue(DAG, RC, VT, SDLoc(DAG.getEntryNode()), *Reg);
2897}
2898
2900 CallingConv::ID CallConv,
2901 ArrayRef<ISD::InputArg> Ins, BitVector &Skipped,
2902 FunctionType *FType,
2903 SIMachineFunctionInfo *Info) {
2904 for (unsigned I = 0, E = Ins.size(), PSInputNum = 0; I != E; ++I) {
2905 const ISD::InputArg *Arg = &Ins[I];
2906
2907 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2908 "vector type argument should have been split");
2909
2910 // First check if it's a PS input addr.
2911 if (CallConv == CallingConv::AMDGPU_PS && !Arg->Flags.isInReg() &&
2912 PSInputNum <= 15) {
2913 bool SkipArg = !Arg->Used && !Info->isPSInputAllocated(PSInputNum);
2914
2915 // Inconveniently only the first part of the split is marked as isSplit,
2916 // so skip to the end. We only want to increment PSInputNum once for the
2917 // entire split argument.
2918 if (Arg->Flags.isSplit()) {
2919 while (!Arg->Flags.isSplitEnd()) {
2920 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2921 "unexpected vector split in ps argument type");
2922 if (!SkipArg)
2923 Splits.push_back(*Arg);
2924 Arg = &Ins[++I];
2925 }
2926 }
2927
2928 if (SkipArg) {
2929 // We can safely skip PS inputs.
2930 Skipped.set(Arg->getOrigArgIndex());
2931 ++PSInputNum;
2932 continue;
2933 }
2934
2935 Info->markPSInputAllocated(PSInputNum);
2936 if (Arg->Used)
2937 Info->markPSInputEnabled(PSInputNum);
2938
2939 ++PSInputNum;
2940 }
2941
2942 Splits.push_back(*Arg);
2943 }
2944}
2945
2946// Allocate special inputs passed in VGPRs.
2948 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
2949 SIMachineFunctionInfo &Info) const {
2950 const LLT I32 = LLT::integer(32);
2951 MachineRegisterInfo &MRI = MF.getRegInfo();
2952
2953 if (Info.hasWorkItemIDX()) {
2954 Register Reg = AMDGPU::VGPR0;
2955 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
2956
2957 CCInfo.AllocateReg(Reg);
2958 unsigned Mask =
2959 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
2960 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
2961 }
2962
2963 if (Info.hasWorkItemIDY()) {
2964 assert(Info.hasWorkItemIDX());
2965 if (Subtarget->hasPackedTID()) {
2966 Info.setWorkItemIDY(
2967 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 10));
2968 } else {
2969 unsigned Reg = AMDGPU::VGPR1;
2970 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
2971
2972 CCInfo.AllocateReg(Reg);
2973 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg));
2974 }
2975 }
2976
2977 if (Info.hasWorkItemIDZ()) {
2978 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
2979 if (Subtarget->hasPackedTID()) {
2980 Info.setWorkItemIDZ(
2981 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 20));
2982 } else {
2983 unsigned Reg = AMDGPU::VGPR2;
2984 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
2985
2986 CCInfo.AllocateReg(Reg);
2987 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg));
2988 }
2989 }
2990}
2991
2992// Try to allocate a VGPR at the end of the argument list, or if no argument
2993// VGPRs are left allocating a stack slot.
2994// If \p Mask is given it indicates bitfield position in the register.
2995// If \p Arg is given use it with new ]p Mask instead of allocating new.
2996static ArgDescriptor allocateVGPR32Input(CCState &CCInfo, unsigned Mask = ~0u,
2997 ArgDescriptor Arg = ArgDescriptor()) {
2998 if (Arg.isSet())
2999 return ArgDescriptor::createArg(Arg, Mask);
3000
3001 ArrayRef<MCPhysReg> ArgVGPRs = ArrayRef(AMDGPU::VGPR_32RegClass.begin(), 32);
3002 unsigned RegIdx = CCInfo.getFirstUnallocated(ArgVGPRs);
3003 if (RegIdx == ArgVGPRs.size()) {
3004 // Spill to stack required.
3005 int64_t Offset = CCInfo.AllocateStack(4, Align(4));
3006
3007 return ArgDescriptor::createStack(Offset, Mask);
3008 }
3009
3010 unsigned Reg = ArgVGPRs[RegIdx];
3011 Reg = CCInfo.AllocateReg(Reg);
3012 assert(Reg != AMDGPU::NoRegister);
3013
3014 MachineFunction &MF = CCInfo.getMachineFunction();
3015 Register LiveInVReg = MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass);
3016 MF.getRegInfo().setType(LiveInVReg, LLT::scalar(32));
3017 return ArgDescriptor::createRegister(Reg, Mask);
3018}
3019
3021 const TargetRegisterClass *RC,
3022 unsigned NumArgRegs) {
3023 ArrayRef<MCPhysReg> ArgSGPRs = ArrayRef(RC->begin(), 32);
3024 unsigned RegIdx = CCInfo.getFirstUnallocated(ArgSGPRs);
3025 if (RegIdx == ArgSGPRs.size())
3026 report_fatal_error("ran out of SGPRs for arguments");
3027
3028 unsigned Reg = ArgSGPRs[RegIdx];
3029 Reg = CCInfo.AllocateReg(Reg);
3030 assert(Reg != AMDGPU::NoRegister);
3031
3032 MachineFunction &MF = CCInfo.getMachineFunction();
3033 MF.addLiveIn(Reg, RC);
3035}
3036
3037// If this has a fixed position, we still should allocate the register in the
3038// CCInfo state. Technically we could get away with this for values passed
3039// outside of the normal argument range.
3041 const TargetRegisterClass *RC,
3042 MCRegister Reg) {
3043 Reg = CCInfo.AllocateReg(Reg);
3044 assert(Reg != AMDGPU::NoRegister);
3045 MachineFunction &MF = CCInfo.getMachineFunction();
3046 MF.addLiveIn(Reg, RC);
3047}
3048
3049static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg) {
3050 if (Arg) {
3051 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_32RegClass,
3052 Arg.getRegister());
3053 } else
3054 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_32RegClass, 32);
3055}
3056
3057static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg) {
3058 if (Arg) {
3059 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_64RegClass,
3060 Arg.getRegister());
3061 } else
3062 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_64RegClass, 16);
3063}
3064
3065/// Allocate implicit function VGPR arguments at the end of allocated user
3066/// arguments.
3068 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3069 SIMachineFunctionInfo &Info) const {
3070 const unsigned Mask = 0x3ff;
3071 ArgDescriptor Arg;
3072
3073 if (Info.hasWorkItemIDX()) {
3074 Arg = allocateVGPR32Input(CCInfo, Mask);
3075 Info.setWorkItemIDX(Arg);
3076 }
3077
3078 if (Info.hasWorkItemIDY()) {
3079 Arg = allocateVGPR32Input(CCInfo, Mask << 10, Arg);
3080 Info.setWorkItemIDY(Arg);
3081 }
3082
3083 if (Info.hasWorkItemIDZ())
3084 Info.setWorkItemIDZ(allocateVGPR32Input(CCInfo, Mask << 20, Arg));
3085}
3086
3087/// Allocate implicit function VGPR arguments in fixed registers.
3089 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3090 SIMachineFunctionInfo &Info) const {
3091 Register Reg = CCInfo.AllocateReg(AMDGPU::VGPR31);
3092 if (!Reg)
3093 report_fatal_error("failed to allocate VGPR for implicit arguments");
3094
3095 const unsigned Mask = 0x3ff;
3096 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
3097 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg, Mask << 10));
3098 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg, Mask << 20));
3099}
3100
3102 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3103 SIMachineFunctionInfo &Info) const {
3104 auto &ArgInfo = Info.getArgInfo();
3105 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3106
3107 // TODO: Unify handling with private memory pointers.
3108 if (UserSGPRInfo.hasDispatchPtr())
3109 allocateSGPR64Input(CCInfo, ArgInfo.DispatchPtr);
3110
3111 if (UserSGPRInfo.hasQueuePtr())
3112 allocateSGPR64Input(CCInfo, ArgInfo.QueuePtr);
3113
3114 // Implicit arg ptr takes the place of the kernarg segment pointer. This is a
3115 // constant offset from the kernarg segment.
3116 if (Info.hasImplicitArgPtr())
3117 allocateSGPR64Input(CCInfo, ArgInfo.ImplicitArgPtr);
3118
3119 if (UserSGPRInfo.hasDispatchID())
3120 allocateSGPR64Input(CCInfo, ArgInfo.DispatchID);
3121
3122 // flat_scratch_init is not applicable for non-kernel functions.
3123
3124 if (Info.hasWorkGroupIDX())
3125 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDX);
3126
3127 if (Info.hasWorkGroupIDY())
3128 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDY);
3129
3130 if (Info.hasWorkGroupIDZ())
3131 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDZ);
3132
3133 if (Info.hasLDSKernelId())
3134 allocateSGPR32Input(CCInfo, ArgInfo.LDSKernelId);
3135}
3136
3137// Allocate special inputs passed in user SGPRs.
3139 MachineFunction &MF,
3140 const SIRegisterInfo &TRI,
3141 SIMachineFunctionInfo &Info) const {
3142 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3143 if (UserSGPRInfo.hasImplicitBufferPtr()) {
3144 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(TRI);
3145 MF.addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3146 CCInfo.AllocateReg(ImplicitBufferPtrReg);
3147 }
3148
3149 // FIXME: How should these inputs interact with inreg / custom SGPR inputs?
3150 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
3151 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(TRI);
3152 MF.addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3153 CCInfo.AllocateReg(PrivateSegmentBufferReg);
3154 }
3155
3156 if (UserSGPRInfo.hasDispatchPtr()) {
3157 Register DispatchPtrReg = Info.addDispatchPtr(TRI);
3158 MF.addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3159 CCInfo.AllocateReg(DispatchPtrReg);
3160 }
3161
3162 if (UserSGPRInfo.hasQueuePtr()) {
3163 Register QueuePtrReg = Info.addQueuePtr(TRI);
3164 MF.addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3165 CCInfo.AllocateReg(QueuePtrReg);
3166 }
3167
3168 if (UserSGPRInfo.hasKernargSegmentPtr()) {
3169 MachineRegisterInfo &MRI = MF.getRegInfo();
3170 Register InputPtrReg = Info.addKernargSegmentPtr(TRI);
3171 CCInfo.AllocateReg(InputPtrReg);
3172
3173 Register VReg = MF.addLiveIn(InputPtrReg, &AMDGPU::SGPR_64RegClass);
3175 }
3176
3177 if (UserSGPRInfo.hasDispatchID()) {
3178 Register DispatchIDReg = Info.addDispatchID(TRI);
3179 MF.addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3180 CCInfo.AllocateReg(DispatchIDReg);
3181 }
3182
3183 if (UserSGPRInfo.hasFlatScratchInit() && !getSubtarget()->isAmdPalOS()) {
3184 Register FlatScratchInitReg = Info.addFlatScratchInit(TRI);
3185 MF.addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3186 CCInfo.AllocateReg(FlatScratchInitReg);
3187 }
3188
3189 if (UserSGPRInfo.hasPrivateSegmentSize()) {
3190 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(TRI);
3191 MF.addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3192 CCInfo.AllocateReg(PrivateSegmentSizeReg);
3193 }
3194
3195 // TODO: Add GridWorkGroupCount user SGPRs when used. For now with HSA we read
3196 // these from the dispatch pointer.
3197}
3198
3199// Allocate pre-loaded kernel arguemtns. Arguments to be preloading must be
3200// sequential starting from the first argument.
3202 CCState &CCInfo, SmallVectorImpl<CCValAssign> &ArgLocs,
3204 const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const {
3205 Function &F = MF.getFunction();
3206 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3207 GCNUserSGPRUsageInfo &SGPRInfo = Info.getUserSGPRInfo();
3208 bool InPreloadSequence = true;
3209 unsigned InIdx = 0;
3210 bool AlignedForImplictArgs = false;
3211 unsigned ImplicitArgOffset = 0;
3212 for (auto &Arg : F.args()) {
3213 if (!InPreloadSequence || !Arg.hasInRegAttr())
3214 break;
3215
3216 unsigned ArgIdx = Arg.getArgNo();
3217 // Don't preload non-original args or parts not in the current preload
3218 // sequence.
3219 if (InIdx < Ins.size() &&
3220 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3221 break;
3222
3223 for (; InIdx < Ins.size() && Ins[InIdx].isOrigArg() &&
3224 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3225 InIdx++) {
3226 assert(ArgLocs[ArgIdx].isMemLoc());
3227 auto &ArgLoc = ArgLocs[InIdx];
3228 const Align KernelArgBaseAlign = Align(16);
3229 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3230 Align Alignment = commonAlignment(KernelArgBaseAlign, ArgOffset);
3231 unsigned NumAllocSGPRs =
3232 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3233
3234 // Fix alignment for hidden arguments.
3235 if (Arg.hasAttribute("amdgpu-hidden-argument")) {
3236 if (!AlignedForImplictArgs) {
3237 ImplicitArgOffset =
3238 alignTo(LastExplicitArgOffset,
3239 Subtarget->getAlignmentForImplicitArgPtr()) -
3240 LastExplicitArgOffset;
3241 AlignedForImplictArgs = true;
3242 }
3243 ArgOffset += ImplicitArgOffset;
3244 }
3245
3246 // Arg is preloaded into the previous SGPR.
3247 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3248 assert(InIdx >= 1 && "No previous SGPR");
3249 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3250 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3251 continue;
3252 }
3253
3254 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3255 unsigned PaddingSGPRs = alignTo(Padding, 4) / 4;
3256 // Check for free user SGPRs for preloading.
3257 if (PaddingSGPRs + NumAllocSGPRs > SGPRInfo.getNumFreeUserSGPRs()) {
3258 InPreloadSequence = false;
3259 break;
3260 }
3261
3262 // Preload this argument.
3263 const TargetRegisterClass *RC =
3264 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3265 SmallVectorImpl<MCRegister> *PreloadRegs =
3266 Info.addPreloadedKernArg(TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3267
3268 if (PreloadRegs->size() > 1)
3269 RC = &AMDGPU::SGPR_32RegClass;
3270 for (auto &Reg : *PreloadRegs) {
3271 assert(Reg);
3272 MF.addLiveIn(Reg, RC);
3273 CCInfo.AllocateReg(Reg);
3274 }
3275
3276 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3277 }
3278 }
3279}
3280
3282 const SIRegisterInfo &TRI,
3283 SIMachineFunctionInfo &Info) const {
3284 // Always allocate this last since it is a synthetic preload.
3285 if (Info.hasLDSKernelId()) {
3286 Register Reg = Info.addLDSKernelId();
3287 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3288 CCInfo.AllocateReg(Reg);
3289 }
3290}
3291
3292// Allocate special input registers that are initialized per-wave.
3295 CallingConv::ID CallConv,
3296 bool IsShader) const {
3297 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3298 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3299 // Note: user SGPRs are handled by the front-end for graphics shaders
3300 // Pad up the used user SGPRs with dead inputs.
3301
3302 // TODO: NumRequiredSystemSGPRs computation should be adjusted appropriately
3303 // before enabling architected SGPRs for workgroup IDs.
3304 assert(!HasArchitectedSGPRs && "Unhandled feature for the subtarget");
3305
3306 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3307 // Note we do not count the PrivateSegmentWaveByteOffset. We do not want to
3308 // rely on it to reach 16 since if we end up having no stack usage, it will
3309 // not really be added.
3310 unsigned NumRequiredSystemSGPRs =
3311 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3312 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3313 for (unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3314 Register Reg = Info.addReservedUserSGPR();
3315 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3316 CCInfo.AllocateReg(Reg);
3317 }
3318 }
3319
3320 if (!HasArchitectedSGPRs) {
3321 if (Info.hasWorkGroupIDX()) {
3322 Register Reg = Info.addWorkGroupIDX();
3323 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3324 CCInfo.AllocateReg(Reg);
3325 }
3326
3327 if (Info.hasWorkGroupIDY()) {
3328 Register Reg = Info.addWorkGroupIDY();
3329 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3330 CCInfo.AllocateReg(Reg);
3331 }
3332
3333 if (Info.hasWorkGroupIDZ()) {
3334 Register Reg = Info.addWorkGroupIDZ();
3335 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3336 CCInfo.AllocateReg(Reg);
3337 }
3338 }
3339
3340 if (Info.hasWorkGroupInfo()) {
3341 Register Reg = Info.addWorkGroupInfo();
3342 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3343 CCInfo.AllocateReg(Reg);
3344 }
3345
3346 if (Info.hasPrivateSegmentWaveByteOffset()) {
3347 // Scratch wave offset passed in system SGPR.
3348 unsigned PrivateSegmentWaveByteOffsetReg;
3349
3350 if (IsShader) {
3351 PrivateSegmentWaveByteOffsetReg =
3352 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3353
3354 // This is true if the scratch wave byte offset doesn't have a fixed
3355 // location.
3356 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3357 PrivateSegmentWaveByteOffsetReg = findFirstFreeSGPR(CCInfo);
3358 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3359 }
3360 } else
3361 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3362
3363 MF.addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3364 CCInfo.AllocateReg(PrivateSegmentWaveByteOffsetReg);
3365 }
3366
3367 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3368 Info.getNumPreloadedSGPRs() >= 16);
3369}
3370
3372 MachineFunction &MF,
3373 const SIRegisterInfo &TRI,
3374 SIMachineFunctionInfo &Info) {
3375 // Now that we've figured out where the scratch register inputs are, see if
3376 // should reserve the arguments and use them directly.
3377 MachineFrameInfo &MFI = MF.getFrameInfo();
3378 bool HasStackObjects = MFI.hasStackObjects();
3379 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3380
3381 // Record that we know we have non-spill stack objects so we don't need to
3382 // check all stack objects later.
3383 if (HasStackObjects)
3384 Info.setHasNonSpillStackObjects(true);
3385
3386 // Everything live out of a block is spilled with fast regalloc, so it's
3387 // almost certain that spilling will be required.
3389 HasStackObjects = true;
3390
3391 // For now assume stack access is needed in any callee functions, so we need
3392 // the scratch registers to pass in.
3393 bool RequiresStackAccess = HasStackObjects || MFI.hasCalls();
3394
3395 if (!ST.hasFlatScratchEnabled()) {
3396 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.getFunction())) {
3397 // If we have stack objects, we unquestionably need the private buffer
3398 // resource. For the Code Object V2 ABI, this will be the first 4 user
3399 // SGPR inputs. We can reserve those and use them directly.
3400
3401 Register PrivateSegmentBufferReg =
3403 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3404 } else {
3405 unsigned ReservedBufferReg = TRI.reservedPrivateSegmentBufferReg(MF);
3406 // We tentatively reserve the last registers (skipping the last registers
3407 // which may contain VCC, FLAT_SCR, and XNACK). After register allocation,
3408 // we'll replace these with the ones immediately after those which were
3409 // really allocated. In the prologue copies will be inserted from the
3410 // argument to these reserved registers.
3411
3412 // Without HSA, relocations are used for the scratch pointer and the
3413 // buffer resource setup is always inserted in the prologue. Scratch wave
3414 // offset is still in an input SGPR.
3415 Info.setScratchRSrcReg(ReservedBufferReg);
3416 }
3417 }
3418
3419 MachineRegisterInfo &MRI = MF.getRegInfo();
3420
3421 // For entry functions we have to set up the stack pointer if we use it,
3422 // whereas non-entry functions get this "for free". This means there is no
3423 // intrinsic advantage to using S32 over S34 in cases where we do not have
3424 // calls but do need a frame pointer (i.e. if we are requested to have one
3425 // because frame pointer elimination is disabled). To keep things simple we
3426 // only ever use S32 as the call ABI stack pointer, and so using it does not
3427 // imply we need a separate frame pointer.
3428 //
3429 // Try to use s32 as the SP, but move it if it would interfere with input
3430 // arguments. This won't work with calls though.
3431 //
3432 // FIXME: Move SP to avoid any possible inputs, or find a way to spill input
3433 // registers.
3434 if (!MRI.isLiveIn(AMDGPU::SGPR32)) {
3435 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3436 } else {
3438
3439 if (MFI.hasCalls())
3440 report_fatal_error("call in graphics shader with too many input SGPRs");
3441
3442 for (unsigned Reg : AMDGPU::SGPR_32RegClass) {
3443 if (!MRI.isLiveIn(Reg)) {
3444 Info.setStackPtrOffsetReg(Reg);
3445 break;
3446 }
3447 }
3448
3449 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3450 report_fatal_error("failed to find register for SP");
3451 }
3452
3453 // hasFP should be accurate for entry functions even before the frame is
3454 // finalized, because it does not rely on the known stack size, only
3455 // properties like whether variable sized objects are present.
3456 if (ST.getFrameLowering()->hasFP(MF)) {
3457 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3458 }
3459}
3460
3463 return !Info->isEntryFunction();
3464}
3465
3467
3469 MachineBasicBlock *Entry,
3470 const SmallVectorImpl<MachineBasicBlock *> &Exits) const {
3472
3473 const MCPhysReg *IStart = TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3474 if (!IStart)
3475 return;
3476
3477 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3478 MachineRegisterInfo *MRI = &Entry->getParent()->getRegInfo();
3479 MachineBasicBlock::iterator MBBI = Entry->begin();
3480 for (const MCPhysReg *I = IStart; *I; ++I) {
3481 const TargetRegisterClass *RC = nullptr;
3482 if (AMDGPU::SReg_64RegClass.contains(*I))
3483 RC = &AMDGPU::SGPR_64RegClass;
3484 else if (AMDGPU::SReg_32RegClass.contains(*I))
3485 RC = &AMDGPU::SGPR_32RegClass;
3486 else
3487 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3488
3489 Register NewVR = MRI->createVirtualRegister(RC);
3490 // Create copy from CSR to a virtual register.
3491 Entry->addLiveIn(*I);
3492 BuildMI(*Entry, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY), NewVR)
3493 .addReg(*I);
3494
3495 // Insert the copy-back instructions right before the terminator.
3496 for (auto *Exit : Exits)
3497 BuildMI(*Exit, Exit->getFirstTerminator(), DebugLoc(),
3498 TII->get(TargetOpcode::COPY), *I)
3499 .addReg(NewVR);
3500 }
3501}
3502
3504 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
3505 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3506 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
3508
3510 const Function &Fn = MF.getFunction();
3513 bool IsError = false;
3514
3515 if (Subtarget->isAmdHsaOS() && AMDGPU::isGraphics(CallConv)) {
3517 Fn, "unsupported non-compute shaders with HSA", DL.getDebugLoc()));
3518 IsError = true;
3519 }
3520
3523 BitVector Skipped(Fn.arg_size());
3524 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
3525 *DAG.getContext());
3526
3527 bool IsGraphics = AMDGPU::isGraphics(CallConv);
3528 bool IsKernel = AMDGPU::isKernel(CallConv);
3529 bool IsEntryFunc = AMDGPU::isEntryFunctionCC(CallConv);
3530
3531 if (IsGraphics) {
3532 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info->getUserSGPRInfo();
3533 assert(!UserSGPRInfo.hasDispatchPtr() &&
3534 !UserSGPRInfo.hasKernargSegmentPtr() && !Info->hasWorkGroupInfo() &&
3535 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3536 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3537 (void)UserSGPRInfo;
3538 if (!Subtarget->hasFlatScratchEnabled())
3539 assert(!UserSGPRInfo.hasFlatScratchInit());
3540 if ((CallConv != CallingConv::AMDGPU_CS &&
3541 CallConv != CallingConv::AMDGPU_Gfx &&
3542 CallConv != CallingConv::AMDGPU_Gfx_WholeWave) ||
3543 !Subtarget->hasArchitectedSGPRs())
3544 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3545 !Info->hasWorkGroupIDZ());
3546 }
3547
3548 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3549
3550 if (CallConv == CallingConv::AMDGPU_PS) {
3551 processPSInputArgs(Splits, CallConv, Ins, Skipped, FType, Info);
3552
3553 // At least one interpolation mode must be enabled or else the GPU will
3554 // hang.
3555 //
3556 // Check PSInputAddr instead of PSInputEnable. The idea is that if the user
3557 // set PSInputAddr, the user wants to enable some bits after the compilation
3558 // based on run-time states. Since we can't know what the final PSInputEna
3559 // will look like, so we shouldn't do anything here and the user should take
3560 // responsibility for the correct programming.
3561 //
3562 // Otherwise, the following restrictions apply:
3563 // - At least one of PERSP_* (0xF) or LINEAR_* (0x70) must be enabled.
3564 // - If POS_W_FLOAT (11) is enabled, at least one of PERSP_* must be
3565 // enabled too.
3566 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3567 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3568 CCInfo.AllocateReg(AMDGPU::VGPR0);
3569 CCInfo.AllocateReg(AMDGPU::VGPR1);
3570 Info->markPSInputAllocated(0);
3571 Info->markPSInputEnabled(0);
3572 }
3573 if (Subtarget->isAmdPalOS()) {
3574 // For isAmdPalOS, the user does not enable some bits after compilation
3575 // based on run-time states; the register values being generated here are
3576 // the final ones set in hardware. Therefore we need to apply the
3577 // workaround to PSInputAddr and PSInputEnable together. (The case where
3578 // a bit is set in PSInputAddr but not PSInputEnable is where the
3579 // frontend set up an input arg for a particular interpolation mode, but
3580 // nothing uses that input arg. Really we should have an earlier pass
3581 // that removes such an arg.)
3582 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3583 if ((PsInputBits & 0x7F) == 0 ||
3584 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3585 Info->markPSInputEnabled(llvm::countr_zero(Info->getPSInputAddr()));
3586 }
3587 } else if (IsKernel) {
3588 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3589 } else {
3590 Splits.append(IsWholeWaveFunc ? std::next(Ins.begin()) : Ins.begin(),
3591 Ins.end());
3592 }
3593
3594 if (IsKernel)
3595 analyzeFormalArgumentsCompute(CCInfo, Ins);
3596
3597 if (IsEntryFunc) {
3598 allocateSpecialEntryInputVGPRs(CCInfo, MF, *TRI, *Info);
3599 allocateHSAUserSGPRs(CCInfo, MF, *TRI, *Info);
3600 if (IsKernel && Subtarget->hasKernargPreload())
3601 allocatePreloadKernArgSGPRs(CCInfo, ArgLocs, Ins, MF, *TRI, *Info);
3602
3603 allocateLDSKernelId(CCInfo, MF, *TRI, *Info);
3604 } else if (!IsGraphics) {
3605 // For the fixed ABI, pass workitem IDs in the last argument register.
3606 allocateSpecialInputVGPRsFixed(CCInfo, MF, *TRI, *Info);
3607
3608 // FIXME: Sink this into allocateSpecialInputSGPRs
3609 if (!Subtarget->hasFlatScratchEnabled())
3610 CCInfo.AllocateReg(Info->getScratchRSrcReg());
3611
3612 allocateSpecialInputSGPRs(CCInfo, MF, *TRI, *Info);
3613 }
3614
3615 if (!IsKernel) {
3616 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, isVarArg);
3617 CCInfo.AnalyzeFormalArguments(Splits, AssignFn);
3618
3619 // This assumes the registers are allocated by CCInfo in ascending order
3620 // with no gaps.
3621 Info->setNumWaveDispatchSGPRs(
3622 CCInfo.getFirstUnallocated(AMDGPU::SGPR_32RegClass.getRegisters()));
3623 Info->setNumWaveDispatchVGPRs(
3624 CCInfo.getFirstUnallocated(AMDGPU::VGPR_32RegClass.getRegisters()));
3625 } else if (Info->getNumKernargPreloadedSGPRs()) {
3626 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3627 }
3628
3630
3631 if (IsWholeWaveFunc) {
3632 SDValue Setup = DAG.getNode(AMDGPUISD::WHOLE_WAVE_SETUP, DL,
3633 {MVT::i1, MVT::Other}, Chain);
3634 InVals.push_back(Setup.getValue(0));
3635 Chains.push_back(Setup.getValue(1));
3636 }
3637
3638 // FIXME: This is the minimum kernel argument alignment. We should improve
3639 // this to the maximum alignment of the arguments.
3640 //
3641 // FIXME: Alignment of explicit arguments totally broken with non-0 explicit
3642 // kern arg offset.
3643 const Align KernelArgBaseAlign = Align(16);
3644
3645 for (unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.size(), ArgIdx = 0; i != e;
3646 ++i) {
3647 const ISD::InputArg &Arg = Ins[i];
3648 if ((Arg.isOrigArg() && Skipped[Arg.getOrigArgIndex()]) || IsError) {
3649 InVals.push_back(DAG.getPOISON(Arg.VT));
3650 continue;
3651 }
3652
3653 CCValAssign &VA = ArgLocs[ArgIdx++];
3654 MVT VT = VA.getLocVT();
3655
3656 if (IsEntryFunc && VA.isMemLoc()) {
3657 VT = Ins[i].VT;
3658 EVT MemVT = VA.getLocVT();
3659
3660 const uint64_t Offset = VA.getLocMemOffset();
3661 Align Alignment = commonAlignment(KernelArgBaseAlign, Offset);
3662
3663 if (Arg.Flags.isByRef()) {
3664 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, Chain, Offset);
3665
3666 const GCNTargetMachine &TM =
3667 static_cast<const GCNTargetMachine &>(getTargetMachine());
3668 if (!TM.isNoopAddrSpaceCast(AMDGPUAS::CONSTANT_ADDRESS,
3669 Arg.Flags.getPointerAddrSpace())) {
3672 }
3673
3674 InVals.push_back(Ptr);
3675 continue;
3676 }
3677
3678 SDValue NewArg;
3679 if (Arg.isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3680 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
3681 // In this case the argument is packed into the previous preload SGPR.
3682 int64_t AlignDownOffset = alignDown(Offset, 4);
3683 int64_t OffsetDiff = Offset - AlignDownOffset;
3684 EVT IntVT = MemVT.changeTypeToInteger();
3685
3686 const SIMachineFunctionInfo *Info =
3689 Register Reg =
3690 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3691
3692 assert(Reg);
3693 Register VReg = MRI.getLiveInVirtReg(Reg);
3694 SDValue Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3695
3696 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, DL, MVT::i32);
3697 SDValue Extract = DAG.getNode(ISD::SRL, DL, MVT::i32, Copy, ShiftAmt);
3698
3699 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Extract);
3700 ArgVal = DAG.getNode(ISD::BITCAST, DL, MemVT, ArgVal);
3701 NewArg = convertArgType(DAG, VT, MemVT, DL, ArgVal,
3702 Ins[i].Flags.isSExt(), &Ins[i]);
3703
3704 NewArg = DAG.getMergeValues({NewArg, Copy.getValue(1)}, DL);
3705 } else {
3706 const SIMachineFunctionInfo *Info =
3709 const SmallVectorImpl<MCRegister> &PreloadRegs =
3710 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3711
3712 SDValue Copy;
3713 if (PreloadRegs.size() == 1) {
3714 Register VReg = MRI.getLiveInVirtReg(PreloadRegs[0]);
3715 const TargetRegisterClass *RC = MRI.getRegClass(VReg);
3716 NewArg = DAG.getCopyFromReg(
3717 Chain, DL, VReg,
3719 TRI->getRegSizeInBits(*RC)));
3720
3721 } else {
3722 // If the kernarg alignment does not match the alignment of the SGPR
3723 // tuple RC that can accommodate this argument, it will be built up
3724 // via copies from from the individual SGPRs that the argument was
3725 // preloaded to.
3727 for (auto Reg : PreloadRegs) {
3728 Register VReg = MRI.getLiveInVirtReg(Reg);
3729 Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3730 Elts.push_back(Copy);
3731 }
3732 NewArg =
3733 DAG.getBuildVector(EVT::getVectorVT(*DAG.getContext(), MVT::i32,
3734 PreloadRegs.size()),
3735 DL, Elts);
3736 }
3737
3738 // If the argument was preloaded to multiple consecutive 32-bit
3739 // registers because of misalignment between addressable SGPR tuples
3740 // and the argument size, we can still assume that because of kernarg
3741 // segment alignment restrictions that NewArg's size is the same as
3742 // MemVT and just do a bitcast. If MemVT is less than 32-bits we add a
3743 // truncate since we cannot preload to less than a single SGPR and the
3744 // MemVT may be smaller.
3745 EVT MemVTInt =
3747 if (MemVT.bitsLT(NewArg.getSimpleValueType()))
3748 NewArg = DAG.getNode(ISD::TRUNCATE, DL, MemVTInt, NewArg);
3749
3750 NewArg = DAG.getBitcast(MemVT, NewArg);
3751 NewArg = convertArgType(DAG, VT, MemVT, DL, NewArg,
3752 Ins[i].Flags.isSExt(), &Ins[i]);
3753 NewArg = DAG.getMergeValues({NewArg, Chain}, DL);
3754 }
3755 } else {
3756 // Hidden arguments that are in the kernel signature must be preloaded
3757 // to user SGPRs. Print a diagnostic error if a hidden argument is in
3758 // the argument list and is not preloaded.
3759 if (Arg.isOrigArg()) {
3760 Argument *OrigArg = Fn.getArg(Arg.getOrigArgIndex());
3761 if (OrigArg->hasAttribute("amdgpu-hidden-argument")) {
3763 *OrigArg->getParent(),
3764 "hidden argument in kernel signature was not preloaded",
3765 DL.getDebugLoc()));
3766 }
3767 }
3768
3769 NewArg =
3770 lowerKernargMemParameter(DAG, VT, MemVT, DL, Chain, Offset,
3771 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3772 }
3773 Chains.push_back(NewArg.getValue(1));
3774
3775 auto *ParamTy =
3776 dyn_cast<PointerType>(FType->getParamType(Ins[i].getOrigArgIndex()));
3777 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS &&
3778 ParamTy &&
3779 (ParamTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
3780 ParamTy->getAddressSpace() == AMDGPUAS::REGION_ADDRESS)) {
3781 // On SI local pointers are just offsets into LDS, so they are always
3782 // less than 16-bits. On CI and newer they could potentially be
3783 // real pointers, so we can't guarantee their size.
3784 NewArg = DAG.getNode(ISD::AssertZext, DL, NewArg.getValueType(), NewArg,
3785 DAG.getValueType(MVT::i16));
3786 }
3787
3788 InVals.push_back(NewArg);
3789 continue;
3790 }
3791 if (!IsEntryFunc && VA.isMemLoc()) {
3792 SDValue Val = lowerStackParameter(DAG, VA, DL, Chain, Arg);
3793 InVals.push_back(Val);
3794 if (!Arg.Flags.isByVal())
3795 Chains.push_back(Val.getValue(1));
3796 continue;
3797 }
3798
3799 assert(VA.isRegLoc() && "Parameter must be in a register!");
3800
3801 Register Reg = VA.getLocReg();
3802 const TargetRegisterClass *RC = nullptr;
3803 if (AMDGPU::VGPR_32RegClass.contains(Reg))
3804 RC = &AMDGPU::VGPR_32RegClass;
3805 else if (AMDGPU::SGPR_32RegClass.contains(Reg))
3806 RC = &AMDGPU::SGPR_32RegClass;
3807 else
3808 llvm_unreachable("Unexpected register class in LowerFormalArguments!");
3809
3810 Reg = MF.addLiveIn(Reg, RC);
3811 SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, VT);
3812 if (Arg.Flags.isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3813 // FIXME: Need to forward the chains created by `CopyFromReg`s, make sure
3814 // they will read physical regs before any side effect instructions.
3815 SDValue ReadFirstLane =
3816 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3818 ReadFirstLane, Val);
3819 }
3820
3821 if (Arg.Flags.isSRet()) {
3822 // The return object should be reasonably addressable.
3823 Val = annotateStackObjectPointer(Val, DAG, DL,
3825 }
3826
3827 Val = convertABITypeToValueType(DAG, Val, VA, DL);
3828 InVals.push_back(Val);
3829 }
3830
3831 // Start adding system SGPRs.
3832 if (IsEntryFunc)
3833 allocateSystemSGPRs(CCInfo, MF, *Info, CallConv, IsGraphics);
3834
3835 unsigned StackArgSize = CCInfo.getStackSize();
3836 Info->setBytesInStackArgArea(StackArgSize);
3837
3838 return Chains.empty() ? Chain
3839 : DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
3840}
3841
3842// TODO: If return values can't fit in registers, we should return as many as
3843// possible in registers before passing on stack.
3845 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
3846 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
3847 const Type *RetTy) const {
3848 // Replacing returns with sret/stack usage doesn't make sense for shaders.
3849 // FIXME: Also sort of a workaround for custom vector splitting in LowerReturn
3850 // for shaders. Vector types should be explicitly handled by CC.
3851 if (AMDGPU::isEntryFunctionCC(CallConv))
3852 return true;
3853
3855 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3856 if (!CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)))
3857 return false;
3858
3859 // We must use the stack if return would require unavailable registers.
3860 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3861 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3862 for (unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3863 if (CCInfo.isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3864 return false;
3865
3866 return true;
3867}
3868
3869SDValue
3871 bool isVarArg,
3873 const SmallVectorImpl<SDValue> &OutVals,
3874 const SDLoc &DL, SelectionDAG &DAG) const {
3878
3879 if (AMDGPU::isKernel(CallConv)) {
3880 return AMDGPUTargetLowering::LowerReturn(Chain, CallConv, isVarArg, Outs,
3881 OutVals, DL, DAG);
3882 }
3883
3884 bool IsShader = AMDGPU::isShader(CallConv);
3885
3886 Info->setIfReturnsVoid(Outs.empty());
3887 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3888
3889 // CCValAssign - represent the assignment of the return value to a location.
3891
3892 // CCState - Info about the registers and stack slots.
3893 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
3894 *DAG.getContext());
3895
3896 // Analyze outgoing return values.
3897 CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, isVarArg));
3898
3899 SDValue Glue;
3901 RetOps.push_back(Chain); // Operand #0 = Chain (updated below)
3902
3903 SDValue ReadFirstLane =
3904 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3905 // Copy the result values into the output registers.
3906 for (unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.size(); I != E;
3907 ++I, ++RealRVLocIdx) {
3908 CCValAssign &VA = RVLocs[I];
3909 assert(VA.isRegLoc() && "Can only return in registers!");
3910 // TODO: Partially return in registers if return values don't fit.
3911 SDValue Arg = OutVals[RealRVLocIdx];
3912
3913 // Copied from other backends.
3914 switch (VA.getLocInfo()) {
3915 case CCValAssign::Full:
3916 break;
3917 case CCValAssign::BCvt:
3918 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
3919 break;
3920 case CCValAssign::SExt:
3921 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
3922 break;
3923 case CCValAssign::ZExt:
3924 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
3925 break;
3926 case CCValAssign::AExt:
3927 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
3928 break;
3929 default:
3930 llvm_unreachable("Unknown loc info!");
3931 }
3932 if (TRI->isSGPRPhysReg(VA.getLocReg()))
3934 ReadFirstLane, Arg);
3935 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Glue);
3936 Glue = Chain.getValue(1);
3937 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
3938 }
3939
3940 // FIXME: Does sret work properly?
3941 if (!Info->isEntryFunction()) {
3942 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
3943 const MCPhysReg *I =
3944 TRI->getCalleeSavedRegsViaCopy(&DAG.getMachineFunction());
3945 if (I) {
3946 for (; *I; ++I) {
3947 if (AMDGPU::SReg_64RegClass.contains(*I))
3948 RetOps.push_back(DAG.getRegister(*I, MVT::i64));
3949 else if (AMDGPU::SReg_32RegClass.contains(*I))
3950 RetOps.push_back(DAG.getRegister(*I, MVT::i32));
3951 else
3952 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3953 }
3954 }
3955 }
3956
3957 // Update chain and glue.
3958 RetOps[0] = Chain;
3959 if (Glue.getNode())
3960 RetOps.push_back(Glue);
3961
3962 unsigned Opc = AMDGPUISD::ENDPGM;
3963 if (!IsWaveEnd)
3964 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3965 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3966 : AMDGPUISD::RET_GLUE;
3967 return DAG.getNode(Opc, DL, MVT::Other, RetOps);
3968}
3969
3971 SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
3972 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3973 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, bool IsThisReturn,
3974 SDValue ThisVal) const {
3975 CCAssignFn *RetCC = CCAssignFnForReturn(CallConv, IsVarArg);
3976
3977 // Assign locations to each value returned by this call.
3979 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
3980 *DAG.getContext());
3981 CCInfo.AnalyzeCallResult(Ins, RetCC);
3982
3983 // Copy all of the result registers out of their specified physreg.
3984 for (CCValAssign VA : RVLocs) {
3985 SDValue Val;
3986
3987 if (VA.isRegLoc()) {
3988 Val =
3989 DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), InGlue);
3990 Chain = Val.getValue(1);
3991 InGlue = Val.getValue(2);
3992 } else if (VA.isMemLoc()) {
3993 report_fatal_error("TODO: return values in memory");
3994 } else
3995 llvm_unreachable("unknown argument location type");
3996
3997 switch (VA.getLocInfo()) {
3998 case CCValAssign::Full:
3999 break;
4000 case CCValAssign::BCvt:
4001 Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
4002 break;
4003 case CCValAssign::ZExt:
4004 Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val,
4005 DAG.getValueType(VA.getValVT()));
4006 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4007 break;
4008 case CCValAssign::SExt:
4009 Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val,
4010 DAG.getValueType(VA.getValVT()));
4011 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4012 break;
4013 case CCValAssign::AExt:
4014 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4015 break;
4016 default:
4017 llvm_unreachable("Unknown loc info!");
4018 }
4019
4020 InVals.push_back(Val);
4021 }
4022
4023 return Chain;
4024}
4025
4026// Add code to pass special inputs required depending on used features separate
4027// from the explicit user arguments present in the IR.
4029 CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info,
4030 SmallVectorImpl<std::pair<unsigned, SDValue>> &RegsToPass,
4031 SmallVectorImpl<SDValue> &MemOpChains, SDValue Chain) const {
4032 // If we don't have a call site, this was a call inserted by
4033 // legalization. These can never use special inputs.
4034 if (!CLI.CB)
4035 return;
4036
4037 SelectionDAG &DAG = CLI.DAG;
4038 const SDLoc &DL = CLI.DL;
4039 const Function &F = DAG.getMachineFunction().getFunction();
4040
4041 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
4042 const AMDGPUFunctionArgInfo &CallerArgInfo = Info.getArgInfo();
4043
4044 const AMDGPUFunctionArgInfo &CalleeArgInfo =
4046
4047 // TODO: Unify with private memory register handling. This is complicated by
4048 // the fact that at least in kernels, the input argument is not necessarily
4049 // in the same location as the input.
4050 // clang-format off
4051 static constexpr std::pair<AMDGPUFunctionArgInfo::PreloadedValue,
4052 std::array<StringLiteral, 2>> ImplicitAttrs[] = {
4053 {AMDGPUFunctionArgInfo::DISPATCH_PTR, {"amdgpu-no-dispatch-ptr", ""}},
4054 {AMDGPUFunctionArgInfo::QUEUE_PTR, {"amdgpu-no-queue-ptr", ""}},
4055 {AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR, {"amdgpu-no-implicitarg-ptr", ""}},
4056 {AMDGPUFunctionArgInfo::DISPATCH_ID, {"amdgpu-no-dispatch-id", ""}},
4057 {AMDGPUFunctionArgInfo::WORKGROUP_ID_X, {"amdgpu-no-workgroup-id-x", "amdgpu-no-cluster-id-x"}},
4058 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Y, {"amdgpu-no-workgroup-id-y", "amdgpu-no-cluster-id-y"}},
4059 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Z, {"amdgpu-no-workgroup-id-z", "amdgpu-no-cluster-id-z"}},
4060 {AMDGPUFunctionArgInfo::LDS_KERNEL_ID, {"amdgpu-no-lds-kernel-id", ""}},
4061 };
4062 // clang-format on
4063
4064 for (auto [InputID, Attrs] : ImplicitAttrs) {
4065 // If the callee does not use the attribute value, skip copying the value.
4066 if (all_of(Attrs, [&](StringRef Attr) {
4067 return Attr.empty() || CLI.CB->hasFnAttr(Attr);
4068 }))
4069 continue;
4070
4071 const auto [OutgoingArg, ArgRC, ArgTy] =
4072 CalleeArgInfo.getPreloadedValue(InputID);
4073 if (!OutgoingArg)
4074 continue;
4075
4076 const auto [IncomingArg, IncomingArgRC, Ty] =
4077 CallerArgInfo.getPreloadedValue(InputID);
4078 assert(IncomingArgRC == ArgRC);
4079
4080 // All special arguments are ints for now.
4081 EVT ArgVT = TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4082 SDValue InputReg;
4083
4084 if (IncomingArg) {
4085 InputReg = loadInputValue(DAG, ArgRC, ArgVT, DL, *IncomingArg);
4086 } else if (InputID == AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR) {
4087 // The implicit arg ptr is special because it doesn't have a corresponding
4088 // input for kernels, and is computed from the kernarg segment pointer.
4089 InputReg = getImplicitArgPtr(DAG, DL);
4090 } else if (InputID == AMDGPUFunctionArgInfo::LDS_KERNEL_ID) {
4091 std::optional<uint32_t> Id =
4093 if (Id.has_value()) {
4094 InputReg = DAG.getConstant(*Id, DL, ArgVT);
4095 } else {
4096 InputReg = DAG.getPOISON(ArgVT);
4097 }
4098 } else {
4099 // We may have proven the input wasn't needed, although the ABI is
4100 // requiring it. We just need to allocate the register appropriately.
4101 InputReg = DAG.getPOISON(ArgVT);
4102 }
4103
4104 if (OutgoingArg->isRegister()) {
4105 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4106 if (!CCInfo.AllocateReg(OutgoingArg->getRegister()))
4107 report_fatal_error("failed to allocate implicit input argument");
4108 } else {
4109 unsigned SpecialArgOffset =
4110 CCInfo.AllocateStack(ArgVT.getStoreSize(), Align(4));
4111 SDValue ArgStore =
4112 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4113 MemOpChains.push_back(ArgStore);
4114 }
4115 }
4116
4117 // Pack workitem IDs into a single register or pass it as is if already
4118 // packed.
4119
4120 auto [OutgoingArg, ArgRC, Ty] =
4122 if (!OutgoingArg)
4123 std::tie(OutgoingArg, ArgRC, Ty) =
4125 if (!OutgoingArg)
4126 std::tie(OutgoingArg, ArgRC, Ty) =
4128 if (!OutgoingArg)
4129 return;
4130
4131 const ArgDescriptor *IncomingArgX = std::get<0>(
4133 const ArgDescriptor *IncomingArgY = std::get<0>(
4135 const ArgDescriptor *IncomingArgZ = std::get<0>(
4137
4138 SDValue InputReg;
4139 SDLoc SL;
4140
4141 const bool NeedWorkItemIDX = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-x");
4142 const bool NeedWorkItemIDY = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-y");
4143 const bool NeedWorkItemIDZ = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-z");
4144
4145 // If incoming ids are not packed we need to pack them.
4146 if (IncomingArgX && !IncomingArgX->isMasked() && CalleeArgInfo.WorkItemIDX &&
4147 NeedWorkItemIDX) {
4148 if (Subtarget->getMaxWorkitemID(F, 0) != 0) {
4149 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgX);
4150 } else {
4151 InputReg = DAG.getConstant(0, DL, MVT::i32);
4152 }
4153 }
4154
4155 if (IncomingArgY && !IncomingArgY->isMasked() && CalleeArgInfo.WorkItemIDY &&
4156 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(F, 1) != 0) {
4157 SDValue Y = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgY);
4158 Y = DAG.getNode(ISD::SHL, SL, MVT::i32, Y,
4159 DAG.getShiftAmountConstant(10, MVT::i32, SL));
4160 InputReg = InputReg.getNode()
4161 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Y)
4162 : Y;
4163 }
4164
4165 if (IncomingArgZ && !IncomingArgZ->isMasked() && CalleeArgInfo.WorkItemIDZ &&
4166 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(F, 2) != 0) {
4167 SDValue Z = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgZ);
4168 Z = DAG.getNode(ISD::SHL, SL, MVT::i32, Z,
4169 DAG.getShiftAmountConstant(20, MVT::i32, SL));
4170 InputReg = InputReg.getNode()
4171 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Z)
4172 : Z;
4173 }
4174
4175 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4176 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4177 // We're in a situation where the outgoing function requires the workitem
4178 // ID, but the calling function does not have it (e.g a graphics function
4179 // calling a C calling convention function). This is illegal, but we need
4180 // to produce something.
4181 InputReg = DAG.getPOISON(MVT::i32);
4182 } else {
4183 // Workitem ids are already packed, any of present incoming arguments
4184 // will carry all required fields.
4185 ArgDescriptor IncomingArg =
4186 ArgDescriptor::createArg(IncomingArgX ? *IncomingArgX
4187 : IncomingArgY ? *IncomingArgY
4188 : *IncomingArgZ,
4189 ~0u);
4190 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, IncomingArg);
4191 }
4192 }
4193
4194 if (OutgoingArg->isRegister()) {
4195 if (InputReg)
4196 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4197
4198 CCInfo.AllocateReg(OutgoingArg->getRegister());
4199 } else {
4200 unsigned SpecialArgOffset = CCInfo.AllocateStack(4, Align(4));
4201 if (InputReg) {
4202 SDValue ArgStore =
4203 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4204 MemOpChains.push_back(ArgStore);
4205 }
4206 }
4207}
4208
4210 SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg,
4212 const SmallVectorImpl<SDValue> &OutVals,
4213 const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const {
4214 if (AMDGPU::isChainCC(CalleeCC))
4215 return true;
4216
4217 if (!AMDGPU::mayTailCallThisCC(CalleeCC))
4218 return false;
4219
4220 // For a divergent call target, we need to do a waterfall loop over the
4221 // possible callees which precludes us from using a simple jump.
4222 if (Callee->isDivergent())
4223 return false;
4224
4226 const Function &CallerF = MF.getFunction();
4227 CallingConv::ID CallerCC = CallerF.getCallingConv();
4229 const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC);
4230
4231 // Kernels aren't callable, and don't have a live in return address so it
4232 // doesn't make sense to do a tail call with entry functions.
4233 if (!CallerPreserved)
4234 return false;
4235
4236 bool CCMatch = CallerCC == CalleeCC;
4237
4239 if (AMDGPU::canGuaranteeTCO(CalleeCC) && CCMatch)
4240 return true;
4241 return false;
4242 }
4243
4244 // TODO: Can we handle var args?
4245 if (IsVarArg)
4246 return false;
4247
4248 for (const Argument &Arg : CallerF.args()) {
4249 if (Arg.hasByValAttr())
4250 return false;
4251 }
4252
4253 LLVMContext &Ctx = *DAG.getContext();
4254
4255 // Check that the call results are passed in the same way.
4256 if (!CCState::resultsCompatible(CalleeCC, CallerCC, MF, Ctx, Ins,
4257 CCAssignFnForCall(CalleeCC, IsVarArg),
4258 CCAssignFnForCall(CallerCC, IsVarArg)))
4259 return false;
4260
4261 // The callee has to preserve all registers the caller needs to preserve.
4262 if (!CCMatch) {
4263 const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC);
4264 if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4265 return false;
4266 }
4267
4268 // Nothing more to check if the callee is taking no arguments.
4269 if (Outs.empty())
4270 return true;
4271
4273 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4274
4275 // FIXME: We are not allocating special input registers, so we will be
4276 // deciding based on incorrect register assignments.
4277 CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CalleeCC, IsVarArg));
4278
4279 const SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
4280 // If the stack arguments for this call do not fit into our own save area then
4281 // the call cannot be made tail.
4282 // TODO: Is this really necessary?
4283 if (CCInfo.getStackSize() > FuncInfo->getBytesInStackArgArea())
4284 return false;
4285
4286 for (const auto &[CCVA, ArgVal] : zip_equal(ArgLocs, OutVals)) {
4287 // FIXME: What about inreg arguments that end up passed in memory?
4288 if (!CCVA.isRegLoc())
4289 continue;
4290
4291 // If we are passing an argument in an SGPR, and the value is divergent,
4292 // this call requires a waterfall loop.
4293 if (ArgVal->isDivergent() && TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4294 LLVM_DEBUG(
4295 dbgs() << "Cannot tail call due to divergent outgoing argument in "
4296 << printReg(CCVA.getLocReg(), TRI) << '\n');
4297 return false;
4298 }
4299 }
4300
4301 const MachineRegisterInfo &MRI = MF.getRegInfo();
4302 return parametersInCSRMatch(MRI, CallerPreserved, ArgLocs, OutVals);
4303}
4304
4306 if (!CI->isTailCall())
4307 return false;
4308
4309 const Function *ParentFn = CI->getFunction();
4311 return false;
4312 return true;
4313}
4314
4315namespace {
4316// Chain calls have special arguments that we need to handle. These are
4317// tagging along at the end of the arguments list(s), after the SGPR and VGPR
4318// arguments (index 0 and 1 respectively).
4319enum ChainCallArgIdx {
4320 Exec = 2,
4321 Flags,
4322 NumVGPRs,
4323 FallbackExec,
4324 FallbackCallee
4325};
4326} // anonymous namespace
4327
4328// The wave scratch offset register is used as the global base pointer.
4330 SmallVectorImpl<SDValue> &InVals) const {
4331 CallingConv::ID CallConv = CLI.CallConv;
4332 bool IsChainCallConv = AMDGPU::isChainCC(CallConv);
4333
4334 SelectionDAG &DAG = CLI.DAG;
4335
4336 const SDLoc &DL = CLI.DL;
4337 SDValue Chain = CLI.Chain;
4338 SDValue Callee = CLI.Callee;
4339
4340 llvm::SmallVector<SDValue, 6> ChainCallSpecialArgs;
4341 bool UsesDynamicVGPRs = false;
4342 if (IsChainCallConv) {
4343 // The last arguments should be the value that we need to put in EXEC,
4344 // followed by the flags and any other arguments with special meanings.
4345 // Pop them out of CLI.Outs and CLI.OutVals before we do any processing so
4346 // we don't treat them like the "real" arguments.
4347 auto RequestedExecIt =
4348 llvm::find_if(CLI.Outs, [](const ISD::OutputArg &Arg) {
4349 return Arg.OrigArgIndex == 2;
4350 });
4351 assert(RequestedExecIt != CLI.Outs.end() && "No node for EXEC");
4352
4353 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.Outs.begin();
4354 CLI.OutVals.erase(CLI.OutVals.begin() + SpecialArgsBeginIdx,
4355 CLI.OutVals.end());
4356 CLI.Outs.erase(RequestedExecIt, CLI.Outs.end());
4357
4358 assert(CLI.Outs.back().OrigArgIndex < 2 &&
4359 "Haven't popped all the special args");
4360
4361 TargetLowering::ArgListEntry RequestedExecArg =
4362 CLI.Args[ChainCallArgIdx::Exec];
4363 if (!RequestedExecArg.Ty->isIntegerTy(Subtarget->getWavefrontSize()))
4364 return lowerUnhandledCall(CLI, InVals, "Invalid value for EXEC");
4365
4366 // Convert constants into TargetConstants, so they become immediate operands
4367 // instead of being selected into S_MOV.
4368 auto PushNodeOrTargetConstant = [&](TargetLowering::ArgListEntry Arg) {
4369 if (const auto *ArgNode = dyn_cast<ConstantSDNode>(Arg.Node)) {
4370 ChainCallSpecialArgs.push_back(DAG.getTargetConstant(
4371 ArgNode->getAPIntValue(), DL, ArgNode->getValueType(0)));
4372 } else
4373 ChainCallSpecialArgs.push_back(Arg.Node);
4374 };
4375
4376 PushNodeOrTargetConstant(RequestedExecArg);
4377
4378 // Process any other special arguments depending on the value of the flags.
4379 TargetLowering::ArgListEntry Flags = CLI.Args[ChainCallArgIdx::Flags];
4380
4381 const APInt &FlagsValue = cast<ConstantSDNode>(Flags.Node)->getAPIntValue();
4382 if (FlagsValue.isZero()) {
4383 if (CLI.Args.size() > ChainCallArgIdx::Flags + 1)
4384 return lowerUnhandledCall(CLI, InVals,
4385 "no additional args allowed if flags == 0");
4386 } else if (FlagsValue.isOneBitSet(0)) {
4387 if (CLI.Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4388 return lowerUnhandledCall(CLI, InVals, "expected 3 additional args");
4389 }
4390
4391 if (!Subtarget->isWave32()) {
4392 return lowerUnhandledCall(
4393 CLI, InVals, "dynamic VGPR mode is only supported for wave32");
4394 }
4395
4396 UsesDynamicVGPRs = true;
4397 std::for_each(CLI.Args.begin() + ChainCallArgIdx::NumVGPRs,
4398 CLI.Args.end(), PushNodeOrTargetConstant);
4399 }
4400 }
4401
4403 SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
4405 bool &IsTailCall = CLI.IsTailCall;
4406 bool IsVarArg = CLI.IsVarArg;
4407 bool IsSibCall = false;
4409
4410 if (Callee.isUndef() || isNullConstant(Callee)) {
4411 if (!CLI.IsTailCall) {
4412 for (ISD::InputArg &Arg : CLI.Ins)
4413 InVals.push_back(DAG.getPOISON(Arg.VT));
4414 }
4415
4416 return Chain;
4417 }
4418
4419 if (IsVarArg) {
4420 return lowerUnhandledCall(CLI, InVals,
4421 "unsupported call to variadic function ");
4422 }
4423
4424 if (!CLI.CB)
4425 return lowerUnhandledCall(CLI, InVals, "unsupported libcall legalization");
4426
4427 if (IsTailCall && MF.getTarget().Options.GuaranteedTailCallOpt) {
4428 return lowerUnhandledCall(CLI, InVals,
4429 "unsupported required tail call to function ");
4430 }
4431
4432 if (IsTailCall) {
4433 IsTailCall = isEligibleForTailCallOptimization(Callee, CallConv, IsVarArg,
4434 Outs, OutVals, Ins, DAG);
4435 if (!IsTailCall &&
4436 ((CLI.CB && CLI.CB->isMustTailCall()) || IsChainCallConv)) {
4437 report_fatal_error("failed to perform tail call elimination on a call "
4438 "site marked musttail or on llvm.amdgcn.cs.chain");
4439 }
4440
4441 bool TailCallOpt = MF.getTarget().Options.GuaranteedTailCallOpt;
4442
4443 // A sibling call is one where we're under the usual C ABI and not planning
4444 // to change that but can still do a tail call:
4445 if (!TailCallOpt && IsTailCall)
4446 IsSibCall = true;
4447
4448 if (IsTailCall)
4449 ++NumTailCalls;
4450 }
4451
4454 SmallVector<SDValue, 8> MemOpChains;
4455
4456 // Analyze operands of the call, assigning locations to each operand.
4458 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
4459 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, IsVarArg);
4460
4461 if (CallConv != CallingConv::AMDGPU_Gfx && !AMDGPU::isChainCC(CallConv) &&
4463 // With a fixed ABI, allocate fixed registers before user arguments.
4464 passSpecialInputs(CLI, CCInfo, *Info, RegsToPass, MemOpChains, Chain);
4465 }
4466
4467 // Mark the scratch resource descriptor as allocated so the CC analysis
4468 // does not assign user arguments to these registers, matching the callee.
4469 if (!Subtarget->hasFlatScratchEnabled())
4470 CCInfo.AllocateReg(Info->getScratchRSrcReg());
4471
4472 CCInfo.AnalyzeCallOperands(Outs, AssignFn);
4473
4474 // Get a count of how many bytes are to be pushed on the stack.
4475 unsigned NumBytes = CCInfo.getStackSize();
4476
4477 if (IsSibCall) {
4478 // Since we're not changing the ABI to make this a tail call, the memory
4479 // operands are already available in the caller's incoming argument space.
4480 NumBytes = 0;
4481 }
4482
4483 // FPDiff is the byte offset of the call's argument area from the callee's.
4484 // Stores to callee stack arguments will be placed in FixedStackSlots offset
4485 // by this amount for a tail call. In a sibling call it must be 0 because the
4486 // caller will deallocate the entire stack and the callee still expects its
4487 // arguments to begin at SP+0. Completely unused for non-tail calls.
4488 int32_t FPDiff = 0;
4489 MachineFrameInfo &MFI = MF.getFrameInfo();
4490 auto *TRI = Subtarget->getRegisterInfo();
4491
4492 // Adjust the stack pointer for the new arguments...
4493 // These operations are automatically eliminated by the prolog/epilog pass
4494 if (!IsSibCall)
4495 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL);
4496
4497 if (!IsSibCall || IsChainCallConv) {
4498 if (!Subtarget->hasFlatScratchEnabled()) {
4499 SmallVector<SDValue, 4> CopyFromChains;
4500
4501 // In the HSA case, this should be an identity copy.
4502 SDValue ScratchRSrcReg =
4503 DAG.getCopyFromReg(Chain, DL, Info->getScratchRSrcReg(), MVT::v4i32);
4504 RegsToPass.emplace_back(IsChainCallConv
4505 ? AMDGPU::SGPR48_SGPR49_SGPR50_SGPR51
4506 : AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3,
4507 ScratchRSrcReg);
4508 CopyFromChains.push_back(ScratchRSrcReg.getValue(1));
4509 Chain = DAG.getTokenFactor(DL, CopyFromChains);
4510 }
4511 }
4512
4513 const unsigned NumSpecialInputs = RegsToPass.size();
4514
4515 MVT PtrVT = MVT::i32;
4516
4517 // Walk the register/memloc assignments, inserting copies/loads.
4518 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4519 CCValAssign &VA = ArgLocs[i];
4520 SDValue Arg = OutVals[i];
4521
4522 // Promote the value if needed.
4523 switch (VA.getLocInfo()) {
4524 case CCValAssign::Full:
4525 break;
4526 case CCValAssign::BCvt:
4527 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
4528 break;
4529 case CCValAssign::ZExt:
4530 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
4531 break;
4532 case CCValAssign::SExt:
4533 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
4534 break;
4535 case CCValAssign::AExt:
4536 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
4537 break;
4538 case CCValAssign::FPExt:
4539 Arg = DAG.getNode(ISD::FP_EXTEND, DL, VA.getLocVT(), Arg);
4540 break;
4541 default:
4542 llvm_unreachable("Unknown loc info!");
4543 }
4544
4545 if (VA.isRegLoc()) {
4546 RegsToPass.push_back(std::pair(VA.getLocReg(), Arg));
4547 } else {
4548 assert(VA.isMemLoc());
4549
4550 SDValue DstAddr;
4551 MachinePointerInfo DstInfo;
4552
4553 unsigned LocMemOffset = VA.getLocMemOffset();
4554 int32_t Offset = LocMemOffset;
4555
4556 SDValue PtrOff = DAG.getConstant(Offset, DL, PtrVT);
4557 MaybeAlign Alignment;
4558
4559 if (IsTailCall) {
4560 ISD::ArgFlagsTy Flags = Outs[i].Flags;
4561 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4562 : VA.getValVT().getStoreSize();
4563
4564 // FIXME: We can have better than the minimum byval required alignment.
4565 Alignment =
4566 Flags.isByVal()
4567 ? Flags.getNonZeroByValAlign()
4568 : commonAlignment(Subtarget->getStackAlignment(), Offset);
4569
4570 Offset = Offset + FPDiff;
4571 int FI = MFI.CreateFixedObject(OpSize, Offset, true);
4572
4573 DstAddr = DAG.getFrameIndex(FI, PtrVT);
4574 DstInfo = MachinePointerInfo::getFixedStack(MF, FI);
4575
4576 // Make sure any stack arguments overlapping with where we're storing
4577 // are loaded before this eventual operation. Otherwise they'll be
4578 // clobbered.
4579
4580 // FIXME: Why is this really necessary? This seems to just result in a
4581 // lot of code to copy the stack and write them back to the same
4582 // locations, which are supposed to be immutable?
4583 Chain = addTokenForArgument(Chain, DAG, MFI, FI);
4584 } else {
4585 // Stores to the argument stack area are relative to the stack pointer.
4586 SDValue SP = DAG.getCopyFromReg(Chain, DL, Info->getStackPtrOffsetReg(),
4587 MVT::i32);
4588 DstAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, SP, PtrOff);
4589 DstInfo = MachinePointerInfo::getStack(MF, LocMemOffset);
4590 Alignment =
4591 commonAlignment(Subtarget->getStackAlignment(), LocMemOffset);
4592 }
4593
4594 if (Outs[i].Flags.isByVal()) {
4595 SDValue SizeNode =
4596 DAG.getConstant(Outs[i].Flags.getByValSize(), DL, MVT::i32);
4597 SDValue Cpy =
4598 DAG.getMemcpy(Chain, DL, DstAddr, Arg, SizeNode,
4599 Outs[i].Flags.getNonZeroByValAlign(),
4600 Outs[i].Flags.getNonZeroByValAlign(),
4601 /*isVol = */ false, /*AlwaysInline = */ true,
4602 /*CI=*/nullptr, std::nullopt, DstInfo,
4604
4605 MemOpChains.push_back(Cpy);
4606 } else {
4607 SDValue Store =
4608 DAG.getStore(Chain, DL, Arg, DstAddr, DstInfo, Alignment);
4609 MemOpChains.push_back(Store);
4610 }
4611 }
4612 }
4613
4614 if (!MemOpChains.empty())
4615 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
4616
4617 SDValue ReadFirstLaneID =
4618 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4619
4620 SDValue TokenGlue;
4621 if (CLI.ConvergenceControlToken) {
4622 TokenGlue = DAG.getNode(ISD::CONVERGENCECTRL_GLUE, DL, MVT::Glue,
4624 }
4625
4626 // Build a sequence of copy-to-reg nodes chained together with token chain
4627 // and flag operands which copy the outgoing args into the appropriate regs.
4628 SDValue InGlue;
4629
4630 unsigned ArgIdx = 0;
4631 for (auto [Reg, Val] : RegsToPass) {
4632 if (ArgIdx++ >= NumSpecialInputs &&
4633 (IsChainCallConv || !Val->isDivergent()) && TRI->isSGPRPhysReg(Reg)) {
4634 // For chain calls, the inreg arguments are required to be
4635 // uniform. Speculatively Insert a readfirstlane in case we cannot prove
4636 // they are uniform.
4637 //
4638 // For other calls, if an inreg arguments is known to be uniform,
4639 // speculatively insert a readfirstlane in case it is in a VGPR.
4640 //
4641 // FIXME: We need to execute this in a waterfall loop if it is a divergent
4642 // value, so let that continue to produce invalid code.
4643
4644 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Val});
4645 if (TokenGlue)
4646 ReadfirstlaneArgs.push_back(TokenGlue);
4648 ReadfirstlaneArgs);
4649 }
4650
4651 Chain = DAG.getCopyToReg(Chain, DL, Reg, Val, InGlue);
4652 InGlue = Chain.getValue(1);
4653 }
4654
4655 // We don't usually want to end the call-sequence here because we would tidy
4656 // the frame up *after* the call, however in the ABI-changing tail-call case
4657 // we've carefully laid out the parameters so that when sp is reset they'll be
4658 // in the correct location.
4659 if (IsTailCall && !IsSibCall) {
4660 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
4661 InGlue = Chain.getValue(1);
4662 }
4663
4664 std::vector<SDValue> Ops({Chain});
4665
4666 // Add a redundant copy of the callee global which will not be legalized, as
4667 // we need direct access to the callee later.
4669 const GlobalValue *GV = GSD->getGlobal();
4670 Ops.push_back(Callee);
4671 Ops.push_back(DAG.getTargetGlobalAddress(GV, DL, MVT::i64));
4672 } else {
4673 if (IsTailCall) {
4674 // isEligibleForTailCallOptimization considered whether the call target is
4675 // divergent, but we may still end up with a uniform value in a VGPR.
4676 // Insert a readfirstlane just in case.
4677 SDValue ReadFirstLaneID =
4678 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4679
4680 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Callee});
4681 if (TokenGlue)
4682 ReadfirstlaneArgs.push_back(TokenGlue); // Wire up convergence token.
4683 Callee = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Callee.getValueType(),
4684 ReadfirstlaneArgs);
4685 }
4686
4687 Ops.push_back(Callee);
4688 Ops.push_back(DAG.getTargetConstant(0, DL, MVT::i64));
4689 }
4690
4691 if (IsTailCall) {
4692 // Each tail call may have to adjust the stack by a different amount, so
4693 // this information must travel along with the operation for eventual
4694 // consumption by emitEpilogue.
4695 Ops.push_back(DAG.getTargetConstant(FPDiff, DL, MVT::i32));
4696 }
4697
4698 if (IsChainCallConv)
4699 llvm::append_range(Ops, ChainCallSpecialArgs);
4700
4701 // Add argument registers to the end of the list so that they are known live
4702 // into the call.
4703 for (auto &[Reg, Val] : RegsToPass)
4704 Ops.push_back(DAG.getRegister(Reg, Val.getValueType()));
4705
4706 // Add a register mask operand representing the call-preserved registers.
4707 const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
4708 assert(Mask && "Missing call preserved mask for calling convention");
4709 Ops.push_back(DAG.getRegisterMask(Mask));
4710
4711 if (SDValue Token = CLI.ConvergenceControlToken) {
4713 GlueOps.push_back(Token);
4714 if (InGlue)
4715 GlueOps.push_back(InGlue);
4716
4717 InGlue = SDValue(DAG.getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, DL,
4718 MVT::Glue, GlueOps),
4719 0);
4720 }
4721
4722 if (InGlue)
4723 Ops.push_back(InGlue);
4724
4725 // If we're doing a tall call, use a TC_RETURN here rather than an
4726 // actual call instruction.
4727 if (IsTailCall) {
4728 MFI.setHasTailCall();
4729 unsigned OPC = AMDGPUISD::TC_RETURN;
4730 switch (CallConv) {
4732 OPC = AMDGPUISD::TC_RETURN_GFX;
4733 break;
4736 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4737 : AMDGPUISD::TC_RETURN_CHAIN;
4738 break;
4739 }
4740
4741 // If the caller is a whole wave function, we need to use a special opcode
4742 // so we can patch up EXEC.
4743 if (Info->isWholeWaveFunction())
4744 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4745
4746 return DAG.getNode(OPC, DL, MVT::Other, Ops);
4747 }
4748
4749 // Returns a chain and a flag for retval copy to use.
4750 SDValue Call = DAG.getNode(AMDGPUISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops);
4751 Chain = Call.getValue(0);
4752 InGlue = Call.getValue(1);
4753
4754 uint64_t CalleePopBytes = NumBytes;
4755 Chain = DAG.getCALLSEQ_END(Chain, 0, CalleePopBytes, InGlue, DL);
4756 if (!Ins.empty())
4757 InGlue = Chain.getValue(1);
4758
4759 // Handle result values, copying them out of physregs into vregs that we
4760 // return.
4761 return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG,
4762 InVals, /*IsThisReturn=*/false, SDValue());
4763}
4764
4765// This is similar to the default implementation in ExpandDYNAMIC_STACKALLOC,
4766// except for:
4767// 1. Stack growth direction(default: downwards, AMDGPU: upwards), and
4768// 2. Scale size where, scale = wave-reduction(alloca-size) * wave-size
4770 SelectionDAG &DAG) const {
4771 const MachineFunction &MF = DAG.getMachineFunction();
4773
4774 SDLoc dl(Op);
4775 EVT VT = Op.getValueType();
4776 SDValue Chain = Op.getOperand(0);
4777 Register SPReg = Info->getStackPtrOffsetReg();
4778
4779 // Chain the dynamic stack allocation so that it doesn't modify the stack
4780 // pointer when other instructions are using the stack.
4781 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, dl);
4782
4783 SDValue Size = Op.getOperand(1);
4784 SDValue BaseAddr = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
4785 Align Alignment = cast<ConstantSDNode>(Op.getOperand(2))->getAlignValue();
4786
4787 const TargetFrameLowering *TFL = Subtarget->getFrameLowering();
4789 "Stack grows upwards for AMDGPU");
4790
4791 Chain = BaseAddr.getValue(1);
4792 // When using flat-scratch, the stack offset is unscaled.
4793 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4794 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4795
4796 Align StackAlign = TFL->getStackAlign();
4797 if (Alignment > StackAlign) {
4798 uint64_t ScaledAlignment = Alignment.value()
4799 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4800 uint64_t StackAlignMask = ScaledAlignment - 1;
4801 SDValue TmpAddr = DAG.getNode(ISD::ADD, dl, VT, BaseAddr,
4802 DAG.getConstant(StackAlignMask, dl, VT));
4803 BaseAddr = DAG.getNode(ISD::AND, dl, VT, TmpAddr,
4804 DAG.getSignedConstant(-ScaledAlignment, dl, VT));
4805 }
4806
4807 assert(Size.getValueType() == MVT::i32 && "Size must be 32-bit");
4808 SDValue NewSP;
4810 // Increase the stack pointer by the size of the alloca.
4811 // If not using flat-scratch, we have to scale the size by the wave-size.
4812 SDValue ScaledSize =
4813 HasFlatScratch
4814 ? Size
4815 : DAG.getNode(ISD::SHL, dl, VT, Size,
4816 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4817 NewSP = DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value
4818 } else {
4819 // For dynamic sized alloca, perform wave-wide reduction to get max of
4820 // alloca size(divergent), and then scale it (when not using flat-scratch)
4821 // by wave-size.
4822 SDValue WaveReduction =
4823 DAG.getTargetConstant(Intrinsic::amdgcn_wave_reduce_umax, dl, MVT::i32);
4824 Size = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, WaveReduction,
4825 Size, DAG.getTargetConstant(0, dl, MVT::i32));
4826 SDValue ScaledSize = Size;
4827 if (!HasFlatScratch) {
4828 ScaledSize =
4829 DAG.getNode(ISD::SHL, dl, VT, Size,
4830 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4831 }
4832 NewSP =
4833 DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value in vgpr.
4834 SDValue ReadFirstLaneID =
4835 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, dl, MVT::i32);
4836 NewSP = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, ReadFirstLaneID,
4837 NewSP);
4838 }
4839
4840 Chain = DAG.getCopyToReg(Chain, dl, SPReg, NewSP); // Output chain
4841 SDValue CallSeqEnd = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), dl);
4842
4843 return DAG.getMergeValues({BaseAddr, CallSeqEnd}, dl);
4844}
4845
4847 if (Op.getValueType() != MVT::i32)
4848 return Op; // Defer to cannot select error.
4849
4851 SDLoc SL(Op);
4852
4853 SDValue CopyFromSP = DAG.getCopyFromReg(Op->getOperand(0), SL, SP, MVT::i32);
4854
4855 // Convert from wave uniform to swizzled vector address. This should protect
4856 // from any edge cases where the stacksave result isn't directly used with
4857 // stackrestore.
4858 SDValue VectorAddress =
4859 DAG.getNode(AMDGPUISD::WAVE_ADDRESS, SL, MVT::i32, CopyFromSP);
4860 return DAG.getMergeValues({VectorAddress, CopyFromSP.getValue(1)}, SL);
4861}
4862
4864 SelectionDAG &DAG) const {
4865 SDLoc SL(Op);
4866 assert(Op.getValueType() == MVT::i32);
4867
4868 uint32_t BothRoundHwReg =
4870 SDValue GetRoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
4871
4872 SDValue IntrinID =
4873 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
4874 SDValue GetReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, Op->getVTList(),
4875 Op.getOperand(0), IntrinID, GetRoundBothImm);
4876
4877 // There are two rounding modes, one for f32 and one for f64/f16. We only
4878 // report in the standard value range if both are the same.
4879 //
4880 // The raw values also differ from the expected FLT_ROUNDS values. Nearest
4881 // ties away from zero is not supported, and the other values are rotated by
4882 // 1.
4883 //
4884 // If the two rounding modes are not the same, report a target defined value.
4885
4886 // Mode register rounding mode fields:
4887 //
4888 // [1:0] Single-precision round mode.
4889 // [3:2] Double/Half-precision round mode.
4890 //
4891 // 0=nearest even; 1= +infinity; 2= -infinity, 3= toward zero.
4892 //
4893 // Hardware Spec
4894 // Toward-0 3 0
4895 // Nearest Even 0 1
4896 // +Inf 1 2
4897 // -Inf 2 3
4898 // NearestAway0 N/A 4
4899 //
4900 // We have to handle 16 permutations of a 4-bit value, so we create a 64-bit
4901 // table we can index by the raw hardware mode.
4902 //
4903 // (trunc (FltRoundConversionTable >> MODE.fp_round)) & 0xf
4904
4905 SDValue BitTable =
4907
4908 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4909 SDValue RoundModeTimesNumBits =
4910 DAG.getNode(ISD::SHL, SL, MVT::i32, GetReg, Two);
4911
4912 // TODO: We could possibly avoid a 64-bit shift and use a simpler table if we
4913 // knew only one mode was demanded.
4914 SDValue TableValue =
4915 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
4916 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
4917
4918 SDValue EntryMask = DAG.getConstant(0xf, SL, MVT::i32);
4919 SDValue TableEntry =
4920 DAG.getNode(ISD::AND, SL, MVT::i32, TruncTable, EntryMask);
4921
4922 // There's a gap in the 4-bit encoded table and actual enum values, so offset
4923 // if it's an extended value.
4924 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
4925 SDValue IsStandardValue =
4926 DAG.getSetCC(SL, MVT::i1, TableEntry, Four, ISD::SETULT);
4927 SDValue EnumOffset = DAG.getNode(ISD::ADD, SL, MVT::i32, TableEntry, Four);
4928 SDValue Result = DAG.getNode(ISD::SELECT, SL, MVT::i32, IsStandardValue,
4929 TableEntry, EnumOffset);
4930
4931 return DAG.getMergeValues({Result, GetReg.getValue(1)}, SL);
4932}
4933
4935 SelectionDAG &DAG) const {
4936 SDLoc SL(Op);
4937
4938 SDValue NewMode = Op.getOperand(1);
4939 assert(NewMode.getValueType() == MVT::i32);
4940
4941 // Index a table of 4-bit entries mapping from the C FLT_ROUNDS values to the
4942 // hardware MODE.fp_round values.
4943 if (auto *ConstMode = dyn_cast<ConstantSDNode>(NewMode)) {
4944 uint32_t ClampedVal = std::min(
4945 static_cast<uint32_t>(ConstMode->getZExtValue()),
4947 NewMode = DAG.getConstant(
4948 AMDGPU::decodeFltRoundToHWConversionTable(ClampedVal), SL, MVT::i32);
4949 } else {
4950 // If we know the input can only be one of the supported standard modes in
4951 // the range 0-3, we can use a simplified mapping to hardware values.
4952 KnownBits KB = DAG.computeKnownBits(NewMode);
4953 const bool UseReducedTable = KB.countMinLeadingZeros() >= 30;
4954 // The supported standard values are 0-3. The extended values start at 8. We
4955 // need to offset by 4 if the value is in the extended range.
4956
4957 if (UseReducedTable) {
4958 // Truncate to the low 32-bits.
4959 SDValue BitTable = DAG.getConstant(
4960 AMDGPU::FltRoundToHWConversionTable & 0xffff, SL, MVT::i32);
4961
4962 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4963 SDValue RoundModeTimesNumBits =
4964 DAG.getNode(ISD::SHL, SL, MVT::i32, NewMode, Two);
4965
4966 NewMode =
4967 DAG.getNode(ISD::SRL, SL, MVT::i32, BitTable, RoundModeTimesNumBits);
4968
4969 // TODO: SimplifyDemandedBits on the setreg source here can likely reduce
4970 // the table extracted bits into inline immediates.
4971 } else {
4972 // table_index = umin(value, value - 4)
4973 // MODE.fp_round = (bit_table >> (table_index << 2)) & 0xf
4974 SDValue BitTable =
4976
4977 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
4978 SDValue OffsetEnum = DAG.getNode(ISD::SUB, SL, MVT::i32, NewMode, Four);
4979 SDValue IndexVal =
4980 DAG.getNode(ISD::UMIN, SL, MVT::i32, NewMode, OffsetEnum);
4981
4982 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4983 SDValue RoundModeTimesNumBits =
4984 DAG.getNode(ISD::SHL, SL, MVT::i32, IndexVal, Two);
4985
4986 SDValue TableValue =
4987 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
4988 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
4989
4990 // No need to mask out the high bits since the setreg will ignore them
4991 // anyway.
4992 NewMode = TruncTable;
4993 }
4994
4995 // Insert a readfirstlane in case the value is a VGPR. We could do this
4996 // earlier and keep more operations scalar, but that interferes with
4997 // combining the source.
4998 SDValue ReadFirstLaneID =
4999 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
5000 NewMode = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5001 ReadFirstLaneID, NewMode);
5002 }
5003
5004 // N.B. The setreg will be later folded into s_round_mode on supported
5005 // targets.
5006 SDValue IntrinID =
5007 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
5008 uint32_t BothRoundHwReg =
5010 SDValue RoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
5011
5012 SDValue SetReg =
5013 DAG.getNode(ISD::INTRINSIC_VOID, SL, Op->getVTList(), Op.getOperand(0),
5014 IntrinID, RoundBothImm, NewMode);
5015
5016 return SetReg;
5017}
5018
5020 if (Op->isDivergent() &&
5021 (!Subtarget->hasVmemPrefInsts() || !Op.getConstantOperandVal(4)))
5022 // Cannot do I$ prefetch with divergent pointer.
5023 return SDValue();
5024
5025 switch (cast<MemSDNode>(Op)->getAddressSpace()) {
5029 break;
5031 if (Subtarget->hasSafeSmemPrefetch())
5032 break;
5033 [[fallthrough]];
5034 default:
5035 return SDValue();
5036 }
5037
5038 // I$ prefetch
5039 if (!Subtarget->hasSafeSmemPrefetch() && !Op.getConstantOperandVal(4))
5040 return SDValue();
5041
5042 return Op;
5043}
5044
5045// Work around DAG legality rules only based on the result type.
5047 bool IsStrict = Op.getOpcode() == ISD::STRICT_FP_EXTEND;
5048 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
5049 EVT SrcVT = Src.getValueType();
5050
5051 if (SrcVT.getScalarType() != MVT::bf16)
5052 return Op;
5053
5054 SDLoc SL(Op);
5055 SDValue BitCast =
5056 DAG.getNode(ISD::BITCAST, SL, SrcVT.changeTypeToInteger(), Src);
5057
5058 EVT DstVT = Op.getValueType();
5059 if (IsStrict)
5060 llvm_unreachable("Need STRICT_BF16_TO_FP");
5061
5062 return DAG.getNode(ISD::BF16_TO_FP, SL, DstVT, BitCast);
5063}
5064
5066 SDLoc SL(Op);
5067 if (Op.getValueType() != MVT::i64)
5068 return Op;
5069
5070 uint32_t ModeHwReg =
5072 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5073 uint32_t TrapHwReg =
5075 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5076
5077 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::Other);
5078 SDValue IntrinID =
5079 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
5080 SDValue GetModeReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5081 Op.getOperand(0), IntrinID, ModeHwRegImm);
5082 SDValue GetTrapReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5083 Op.getOperand(0), IntrinID, TrapHwRegImm);
5084 SDValue TokenReg =
5085 DAG.getNode(ISD::TokenFactor, SL, MVT::Other, GetModeReg.getValue(1),
5086 GetTrapReg.getValue(1));
5087
5088 SDValue CvtPtr =
5089 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, GetModeReg, GetTrapReg);
5090 SDValue Result = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
5091
5092 return DAG.getMergeValues({Result, TokenReg}, SL);
5093}
5094
5096 SDLoc SL(Op);
5097 if (Op.getOperand(1).getValueType() != MVT::i64)
5098 return Op;
5099
5100 SDValue Input = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op.getOperand(1));
5101 SDValue NewModeReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5102 DAG.getConstant(0, SL, MVT::i32));
5103 SDValue NewTrapReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5104 DAG.getConstant(1, SL, MVT::i32));
5105
5106 SDValue ReadFirstLaneID =
5107 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
5108 NewModeReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5109 ReadFirstLaneID, NewModeReg);
5110 NewTrapReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5111 ReadFirstLaneID, NewTrapReg);
5112
5113 unsigned ModeHwReg =
5115 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5116 unsigned TrapHwReg =
5118 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5119
5120 SDValue IntrinID =
5121 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
5122 SDValue SetModeReg =
5123 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5124 IntrinID, ModeHwRegImm, NewModeReg);
5125 SDValue SetTrapReg =
5126 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5127 IntrinID, TrapHwRegImm, NewTrapReg);
5128 return DAG.getNode(ISD::TokenFactor, SL, MVT::Other, SetTrapReg, SetModeReg);
5129}
5130
5132 const MachineFunction &MF) const {
5133 const Function &Fn = MF.getFunction();
5134
5135 Register Reg =
5137 .Case("m0", AMDGPU::M0)
5138 .Case("exec", AMDGPU::EXEC)
5139 .Case("exec_lo", AMDGPU::EXEC_LO)
5140 .Case("exec_hi", AMDGPU::EXEC_HI)
5141 .Case("flat_scratch", AMDGPU::FLAT_SCR)
5142 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5143 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5144 .Case("src_flat_scratch_base", AMDGPU::SRC_FLAT_SCRATCH_BASE)
5145 .Case("src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
5146 .Case("src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
5147 .Default(Register());
5148 if (!Reg)
5149 return Reg;
5150
5151 if (!Subtarget->hasFlatScrRegister() &&
5152 Subtarget->getRegisterInfo()->regsOverlap(Reg, AMDGPU::FLAT_SCR)) {
5153 Fn.getContext().emitError(Twine("invalid register \"" + StringRef(RegName) +
5154 "\" for subtarget."));
5155 }
5156
5157 if (!Subtarget->hasGloballyAddressableScratch() &&
5158 Subtarget->getRegisterInfo()->regsOverlap(
5159 Reg, AMDGPU::SRC_FLAT_SCRATCH_BASE)) {
5160 Fn.getContext().emitError(Twine("invalid register \"" + StringRef(RegName) +
5161 "\" for subtarget."));
5162 }
5163
5164 switch (Reg) {
5165 case AMDGPU::M0:
5166 case AMDGPU::EXEC_LO:
5167 case AMDGPU::EXEC_HI:
5168 case AMDGPU::FLAT_SCR_LO:
5169 case AMDGPU::FLAT_SCR_HI:
5170 case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
5171 case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
5172 if (VT.getSizeInBits() == 32)
5173 return Reg;
5174 break;
5175 case AMDGPU::EXEC:
5176 case AMDGPU::FLAT_SCR:
5177 case AMDGPU::SRC_FLAT_SCRATCH_BASE:
5178 if (VT.getSizeInBits() == 64)
5179 return Reg;
5180 break;
5181 default:
5182 llvm_unreachable("missing register type checking");
5183 }
5184
5186 Twine("invalid type for register \"" + StringRef(RegName) + "\"."));
5187}
5188
5189// If kill is not the last instruction, split the block so kill is always a
5190// proper terminator.
5193 MachineBasicBlock *BB) const {
5194 MachineBasicBlock *SplitBB = BB->splitAt(MI, /*UpdateLiveIns=*/true);
5196 MI.setDesc(TII->getKillTerminatorFromPseudo(MI.getOpcode()));
5197 return SplitBB;
5198}
5199
5200// Split block \p MBB at \p MI, as to insert a loop. If \p InstInLoop is true,
5201// \p MI will be the only instruction in the loop body block. Otherwise, it will
5202// be the first instruction in the remainder block.
5203//
5204/// \returns { LoopBody, Remainder }
5205static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5207 MachineFunction *MF = MBB.getParent();
5209
5210 // To insert the loop we need to split the block. Move everything after this
5211 // point to a new block, and insert a new empty block between the two.
5213 MachineBasicBlock *RemainderBB = MF->CreateMachineBasicBlock();
5215 ++MBBI;
5216
5217 MF->insert(MBBI, LoopBB);
5218 MF->insert(MBBI, RemainderBB);
5219
5220 LoopBB->addSuccessor(LoopBB);
5221 LoopBB->addSuccessor(RemainderBB);
5222
5223 // Move the rest of the block into a new block.
5224 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
5225
5226 if (InstInLoop) {
5227 auto Next = std::next(I);
5228
5229 // Move instruction to loop body.
5230 LoopBB->splice(LoopBB->begin(), &MBB, I, Next);
5231
5232 // Move the rest of the block.
5233 RemainderBB->splice(RemainderBB->begin(), &MBB, Next, MBB.end());
5234 } else {
5235 RemainderBB->splice(RemainderBB->begin(), &MBB, I, MBB.end());
5236 }
5237
5238 MBB.addSuccessor(LoopBB);
5239
5240 return std::pair(LoopBB, RemainderBB);
5241}
5242
5243/// Insert \p MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
5245 MachineBasicBlock *MBB = MI.getParent();
5247 auto I = MI.getIterator();
5248 auto E = std::next(I);
5249
5250 // clang-format off
5251 BuildMI(*MBB, E, MI.getDebugLoc(), TII->get(AMDGPU::S_WAITCNT))
5252 .addImm(0);
5253 // clang-format on
5254
5255 MIBundleBuilder Bundler(*MBB, I, E);
5256 finalizeBundle(*MBB, Bundler.begin());
5257}
5258
5261 MachineBasicBlock *BB) const {
5262 const DebugLoc &DL = MI.getDebugLoc();
5263
5265
5267
5268 // Apparently kill flags are only valid if the def is in the same block?
5269 if (MachineOperand *Src = TII->getNamedOperand(MI, AMDGPU::OpName::data0))
5270 Src->setIsKill(false);
5271
5272 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, *BB, true);
5273
5274 MachineBasicBlock::iterator I = LoopBB->end();
5275
5276 const unsigned EncodedReg = AMDGPU::Hwreg::HwregEncoding::encode(
5278
5279 // Clear TRAP_STS.MEM_VIOL
5280 BuildMI(*LoopBB, LoopBB->begin(), DL, TII->get(AMDGPU::S_SETREG_IMM32_B32))
5281 .addImm(0)
5282 .addImm(EncodedReg);
5283
5285
5286 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5287
5288 // Load and check TRAP_STS.MEM_VIOL
5289 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_GETREG_B32), Reg)
5290 .addImm(EncodedReg);
5291
5292 // FIXME: Do we need to use an isel pseudo that may clobber scc?
5293 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CMP_LG_U32))
5294 .addReg(Reg, RegState::Kill)
5295 .addImm(0);
5296 // clang-format off
5297 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
5298 .addMBB(LoopBB);
5299 // clang-format on
5300
5301 return RemainderBB;
5302}
5303
5304// Do a v_movrels_b32 or v_movreld_b32 for each unique value of \p IdxReg in the
5305// wavefront. If the value is uniform and just happens to be in a VGPR, this
5306// will only do one iteration. In the worst case, this will loop 64 times.
5307//
5308// TODO: Just use v_readlane_b32 if we know the VGPR has a uniform value.
5311 MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB,
5312 const DebugLoc &DL, const MachineOperand &Idx,
5313 unsigned InitReg, unsigned ResultReg, unsigned PhiReg,
5314 unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode,
5315 Register &SGPRIdxReg) {
5316
5317 MachineFunction *MF = OrigBB.getParent();
5318 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5319 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5322
5323 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5324 Register PhiExec = MRI.createVirtualRegister(BoolRC);
5325 Register NewExec = MRI.createVirtualRegister(BoolRC);
5326 Register CurrentIdxReg =
5327 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5328 Register CondReg = MRI.createVirtualRegister(BoolRC);
5329
5330 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiReg)
5331 .addReg(InitReg)
5332 .addMBB(&OrigBB)
5333 .addReg(ResultReg)
5334 .addMBB(&LoopBB);
5335
5336 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiExec)
5337 .addReg(InitSaveExecReg)
5338 .addMBB(&OrigBB)
5339 .addReg(NewExec)
5340 .addMBB(&LoopBB);
5341
5342 // Read the next variant <- also loop target.
5343 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5344 .addReg(Idx.getReg(), getUndefRegState(Idx.isUndef()));
5345
5346 // Compare the just read M0 value to all possible Idx values.
5347 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5348 .addReg(CurrentIdxReg)
5349 .addReg(Idx.getReg(), {}, Idx.getSubReg());
5350
5351 // Update EXEC, save the original EXEC value to VCC.
5352 BuildMI(LoopBB, I, DL, TII->get(LMC.AndSaveExecOpc), NewExec)
5353 .addReg(CondReg, RegState::Kill);
5354
5355 MRI.setSimpleHint(NewExec, CondReg);
5356
5357 if (UseGPRIdxMode) {
5358 if (Offset == 0) {
5359 SGPRIdxReg = CurrentIdxReg;
5360 } else {
5361 SGPRIdxReg = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
5362 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5363 .addReg(CurrentIdxReg, RegState::Kill)
5364 .addImm(Offset);
5365 }
5366 } else {
5367 // Move index from VCC into M0
5368 if (Offset == 0) {
5369 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5370 .addReg(CurrentIdxReg, RegState::Kill);
5371 } else {
5372 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5373 .addReg(CurrentIdxReg, RegState::Kill)
5374 .addImm(Offset);
5375 }
5376 }
5377
5378 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
5379 MachineInstr *InsertPt =
5380 BuildMI(LoopBB, I, DL, TII->get(LMC.XorTermOpc), LMC.ExecReg)
5381 .addReg(LMC.ExecReg)
5382 .addReg(NewExec);
5383
5384 // XXX - s_xor_b64 sets scc to 1 if the result is nonzero, so can we use
5385 // s_cbranch_scc0?
5386
5387 // Loop back to V_READFIRSTLANE_B32 if there are still variants to cover.
5388 // clang-format off
5389 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
5390 .addMBB(&LoopBB);
5391 // clang-format on
5392
5393 return InsertPt->getIterator();
5394}
5395
5396// This has slightly sub-optimal regalloc when the source vector is killed by
5397// the read. The register allocator does not understand that the kill is
5398// per-workitem, so is kept alive for the whole loop so we end up not re-using a
5399// subregister from it, using 1 more VGPR than necessary. This was saved when
5400// this was expanded after register allocation.
5403 unsigned InitResultReg, unsigned PhiReg, int Offset,
5404 bool UseGPRIdxMode, Register &SGPRIdxReg) {
5405 MachineFunction *MF = MBB.getParent();
5406 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5407 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5408 MachineRegisterInfo &MRI = MF->getRegInfo();
5409 const DebugLoc &DL = MI.getDebugLoc();
5411
5412 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
5413 Register DstReg = MI.getOperand(0).getReg();
5414 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
5415 Register TmpExec = MRI.createVirtualRegister(BoolXExecRC);
5417
5418 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), TmpExec);
5419
5420 // Save the EXEC mask
5421 // clang-format off
5422 BuildMI(MBB, I, DL, TII->get(LMC.MovOpc), SaveExec)
5423 .addReg(LMC.ExecReg);
5424 // clang-format on
5425
5426 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, MBB, false);
5427
5428 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5429
5430 auto InsPt = emitLoadM0FromVGPRLoop(TII, MRI, MBB, *LoopBB, DL, *Idx,
5431 InitResultReg, DstReg, PhiReg, TmpExec,
5432 Offset, UseGPRIdxMode, SGPRIdxReg);
5433
5434 MachineBasicBlock *LandingPad = MF->CreateMachineBasicBlock();
5436 ++MBBI;
5437 MF->insert(MBBI, LandingPad);
5438 LoopBB->removeSuccessor(RemainderBB);
5439 LandingPad->addSuccessor(RemainderBB);
5440 LoopBB->addSuccessor(LandingPad);
5441 MachineBasicBlock::iterator First = LandingPad->begin();
5442 // clang-format off
5443 BuildMI(*LandingPad, First, DL, TII->get(LMC.MovOpc), LMC.ExecReg)
5444 .addReg(SaveExec);
5445 // clang-format on
5446
5447 return InsPt;
5448}
5449
5450// Returns subreg index, offset
5451static std::pair<unsigned, int>
5453 const TargetRegisterClass *SuperRC, unsigned VecReg,
5454 int Offset) {
5455 int NumElts = TRI.getRegSizeInBits(*SuperRC) / 32;
5456
5457 // Skip out of bounds offsets, or else we would end up using an undefined
5458 // register.
5459 if (Offset >= NumElts || Offset < 0)
5460 return std::pair(AMDGPU::sub0, Offset);
5461
5462 return std::pair(SIRegisterInfo::getSubRegFromChannel(Offset), 0);
5463}
5464
5467 int Offset) {
5468 MachineBasicBlock *MBB = MI.getParent();
5469 const DebugLoc &DL = MI.getDebugLoc();
5471
5472 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5473
5474 assert(Idx->getReg() != AMDGPU::NoRegister);
5475
5476 if (Offset == 0) {
5477 // clang-format off
5478 BuildMI(*MBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5479 .add(*Idx);
5480 // clang-format on
5481 } else {
5482 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5483 .add(*Idx)
5484 .addImm(Offset);
5485 }
5486}
5487
5490 int Offset) {
5491 MachineBasicBlock *MBB = MI.getParent();
5492 const DebugLoc &DL = MI.getDebugLoc();
5494
5495 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5496
5497 if (Offset == 0)
5498 return Idx->getReg();
5499
5500 Register Tmp = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5501 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), Tmp)
5502 .add(*Idx)
5503 .addImm(Offset);
5504 return Tmp;
5505}
5506
5509 const GCNSubtarget &ST) {
5510 const SIInstrInfo *TII = ST.getInstrInfo();
5511 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5512 MachineFunction *MF = MBB.getParent();
5513 MachineRegisterInfo &MRI = MF->getRegInfo();
5514
5515 Register Dst = MI.getOperand(0).getReg();
5516 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5517 Register SrcReg = TII->getNamedOperand(MI, AMDGPU::OpName::src)->getReg();
5518 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5519
5520 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcReg);
5521 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5522
5523 unsigned SubReg;
5524 std::tie(SubReg, Offset) =
5525 computeIndirectRegAndOffset(TRI, VecRC, SrcReg, Offset);
5526
5527 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5528
5529 // Check for a SGPR index.
5530 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5532 const DebugLoc &DL = MI.getDebugLoc();
5533
5534 if (UseGPRIdxMode) {
5535 // TODO: Look at the uses to avoid the copy. This may require rescheduling
5536 // to avoid interfering with other uses, so probably requires a new
5537 // optimization pass.
5538 Register Idx = getIndirectSGPRIdx(TII, MRI, MI, Offset);
5539
5540 const MCInstrDesc &GPRIDXDesc =
5541 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5542 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5543 .addReg(SrcReg)
5544 .addReg(Idx)
5545 .addImm(SubReg);
5546 } else {
5548
5549 BuildMI(MBB, I, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5550 .addReg(SrcReg, {}, SubReg)
5551 .addReg(SrcReg, RegState::Implicit);
5552 }
5553
5554 MI.eraseFromParent();
5555
5556 return &MBB;
5557 }
5558
5559 // Control flow needs to be inserted if indexing with a VGPR.
5560 const DebugLoc &DL = MI.getDebugLoc();
5562
5563 Register PhiReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5564 Register InitReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5565
5566 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), InitReg);
5567
5568 Register SGPRIdxReg;
5569 auto InsPt = loadM0FromVGPR(TII, MBB, MI, InitReg, PhiReg, Offset,
5570 UseGPRIdxMode, SGPRIdxReg);
5571
5572 MachineBasicBlock *LoopBB = InsPt->getParent();
5573
5574 if (UseGPRIdxMode) {
5575 const MCInstrDesc &GPRIDXDesc =
5576 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5577
5578 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5579 .addReg(SrcReg)
5580 .addReg(SGPRIdxReg)
5581 .addImm(SubReg);
5582 } else {
5583 BuildMI(*LoopBB, InsPt, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5584 .addReg(SrcReg, {}, SubReg)
5585 .addReg(SrcReg, RegState::Implicit);
5586 }
5587
5588 MI.eraseFromParent();
5589
5590 return LoopBB;
5591}
5592
5595 const GCNSubtarget &ST) {
5596 const SIInstrInfo *TII = ST.getInstrInfo();
5597 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5598 MachineFunction *MF = MBB.getParent();
5599 MachineRegisterInfo &MRI = MF->getRegInfo();
5600
5601 Register Dst = MI.getOperand(0).getReg();
5602 const MachineOperand *SrcVec = TII->getNamedOperand(MI, AMDGPU::OpName::src);
5603 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5604 const MachineOperand *Val = TII->getNamedOperand(MI, AMDGPU::OpName::val);
5605 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5606 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcVec->getReg());
5607 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5608
5609 // This can be an immediate, but will be folded later.
5610 assert(Val->getReg());
5611
5612 unsigned SubReg;
5613 std::tie(SubReg, Offset) =
5614 computeIndirectRegAndOffset(TRI, VecRC, SrcVec->getReg(), Offset);
5615 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5616
5617 if (Idx->getReg() == AMDGPU::NoRegister) {
5619 const DebugLoc &DL = MI.getDebugLoc();
5620
5621 assert(Offset == 0);
5622
5623 BuildMI(MBB, I, DL, TII->get(TargetOpcode::INSERT_SUBREG), Dst)
5624 .add(*SrcVec)
5625 .add(*Val)
5626 .addImm(SubReg);
5627
5628 MI.eraseFromParent();
5629 return &MBB;
5630 }
5631
5632 // Check for a SGPR index.
5633 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5635 const DebugLoc &DL = MI.getDebugLoc();
5636
5637 if (UseGPRIdxMode) {
5638 Register Idx = getIndirectSGPRIdx(TII, MRI, MI, Offset);
5639
5640 const MCInstrDesc &GPRIDXDesc =
5641 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5642 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5643 .addReg(SrcVec->getReg())
5644 .add(*Val)
5645 .addReg(Idx)
5646 .addImm(SubReg);
5647 } else {
5649
5650 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5651 TRI.getRegSizeInBits(*VecRC), 32, false);
5652 BuildMI(MBB, I, DL, MovRelDesc, Dst)
5653 .addReg(SrcVec->getReg())
5654 .add(*Val)
5655 .addImm(SubReg);
5656 }
5657 MI.eraseFromParent();
5658 return &MBB;
5659 }
5660
5661 // Control flow needs to be inserted if indexing with a VGPR.
5662 if (Val->isReg())
5663 MRI.clearKillFlags(Val->getReg());
5664
5665 const DebugLoc &DL = MI.getDebugLoc();
5666
5667 Register PhiReg = MRI.createVirtualRegister(VecRC);
5668
5669 Register SGPRIdxReg;
5670 auto InsPt = loadM0FromVGPR(TII, MBB, MI, SrcVec->getReg(), PhiReg, Offset,
5671 UseGPRIdxMode, SGPRIdxReg);
5672 MachineBasicBlock *LoopBB = InsPt->getParent();
5673
5674 if (UseGPRIdxMode) {
5675 const MCInstrDesc &GPRIDXDesc =
5676 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5677
5678 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5679 .addReg(PhiReg)
5680 .add(*Val)
5681 .addReg(SGPRIdxReg)
5682 .addImm(SubReg);
5683 } else {
5684 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5685 TRI.getRegSizeInBits(*VecRC), 32, false);
5686 BuildMI(*LoopBB, InsPt, DL, MovRelDesc, Dst)
5687 .addReg(PhiReg)
5688 .add(*Val)
5689 .addImm(SubReg);
5690 }
5691
5692 MI.eraseFromParent();
5693 return LoopBB;
5694}
5695
5697 MachineBasicBlock *BB) {
5698 // For targets older than GFX12, we emit a sequence of 32-bit operations.
5699 // For GFX12, we emit s_add_u64 and s_sub_u64.
5700 MachineFunction *MF = BB->getParent();
5701 const SIInstrInfo *TII = MF->getSubtarget<GCNSubtarget>().getInstrInfo();
5702 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5704 const DebugLoc &DL = MI.getDebugLoc();
5705 MachineOperand &Dest = MI.getOperand(0);
5706 MachineOperand &Src0 = MI.getOperand(1);
5707 MachineOperand &Src1 = MI.getOperand(2);
5708 bool IsAdd = (MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5709 if (ST.hasScalarAddSub64()) {
5710 // FIXME: If scc is used, this deletes the def
5711 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5712 // clang-format off
5713 BuildMI(*BB, MI, DL, TII->get(Opc), Dest.getReg())
5714 .add(Src0)
5715 .add(Src1);
5716 // clang-format on
5717 } else {
5718 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5719 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5720
5721 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5722 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5723
5724 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5725 MI, MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5726 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5727 MI, MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5728
5729 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5730 MI, MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5731 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5732 MI, MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5733
5734 const MachineOperand &ImpDefSCC = MI.getOperand(3);
5735 assert(ImpDefSCC.getReg() == AMDGPU::SCC && ImpDefSCC.isDef());
5736
5737 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5738 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5739 BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0).add(Src0Sub0).add(Src1Sub0);
5740 auto Hi = BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1)
5741 .add(Src0Sub1)
5742 .add(Src1Sub1);
5743 if (ImpDefSCC.isDead())
5744 Hi.setOperandDead(3);
5745 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
5746 .addReg(DestSub0)
5747 .addImm(AMDGPU::sub0)
5748 .addReg(DestSub1)
5749 .addImm(AMDGPU::sub1);
5750 }
5751 MI.eraseFromParent();
5752 return BB;
5753}
5754
5756 MachineFunction *MF = BB->getParent();
5757 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5758 const SIInstrInfo *TII = ST.getInstrInfo();
5759 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5760 MachineRegisterInfo &MRI = MF->getRegInfo();
5761 const DebugLoc &DL = MI.getDebugLoc();
5762 Register Dst = MI.getOperand(0).getReg();
5763 const MachineOperand &Src0 = MI.getOperand(1);
5764 const MachineOperand &Src1 = MI.getOperand(2);
5765 Register SrcCond = MI.getOperand(3).getReg();
5766
5767 Register DstLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5768 Register DstHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5769 const TargetRegisterClass *CondRC = TRI->getWaveMaskRegClass();
5770 Register SrcCondCopy = MRI.createVirtualRegister(CondRC);
5771
5772 int Src0Idx =
5773 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
5774 int Src1Idx =
5775 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);
5776 const TargetRegisterClass *Src0RC =
5777 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src0Idx));
5778 const TargetRegisterClass *Src1RC =
5779 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src1Idx));
5780
5781 const TargetRegisterClass *Src0SubRC =
5782 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5783 const TargetRegisterClass *Src1SubRC =
5784 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5785
5786 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5787 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5788 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5789 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5790
5791 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5792 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5793 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5794 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5795
5796 BuildMI(*BB, MI, DL, TII->get(AMDGPU::COPY), SrcCondCopy).addReg(SrcCond);
5797 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstLo)
5798 .addImm(0)
5799 .add(Src0Sub0)
5800 .addImm(0)
5801 .add(Src1Sub0)
5802 .addReg(SrcCondCopy);
5803
5804 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstHi)
5805 .addImm(0)
5806 .add(Src0Sub1)
5807 .addImm(0)
5808 .add(Src1Sub1)
5809 .addReg(SrcCondCopy);
5810
5811 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE), Dst)
5812 .addReg(DstLo)
5813 .addImm(AMDGPU::sub0)
5814 .addReg(DstHi)
5815 .addImm(AMDGPU::sub1);
5816 MI.eraseFromParent();
5817}
5818
5820 switch (Opc) {
5821 case AMDGPU::S_MIN_U32:
5822 return std::numeric_limits<uint32_t>::max();
5823 case AMDGPU::S_MIN_I32:
5824 return std::numeric_limits<int32_t>::max();
5825 case AMDGPU::S_MAX_U32:
5826 return std::numeric_limits<uint32_t>::min();
5827 case AMDGPU::S_MAX_I32:
5828 return std::numeric_limits<int32_t>::min();
5829 case AMDGPU::V_ADD_F32_e64: // -0.0
5830 return 0x80000000;
5831 case AMDGPU::V_SUB_F32_e64: // +0.0
5832 return 0x0;
5833 case AMDGPU::S_ADD_I32:
5834 case AMDGPU::S_SUB_I32:
5835 case AMDGPU::S_OR_B32:
5836 case AMDGPU::S_XOR_B32:
5837 return std::numeric_limits<uint32_t>::min();
5838 case AMDGPU::S_AND_B32:
5839 return std::numeric_limits<uint32_t>::max();
5840 case AMDGPU::V_MIN_F32_e64:
5841 case AMDGPU::V_MAX_F32_e64:
5842 return 0x7fc00000; // qNAN
5843 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5844 return std::numeric_limits<uint64_t>::max();
5845 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5846 return std::numeric_limits<int64_t>::max();
5847 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5848 return std::numeric_limits<uint64_t>::min();
5849 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5850 return std::numeric_limits<int64_t>::min();
5851 case AMDGPU::V_MIN_F64_e64:
5852 case AMDGPU::V_MAX_F64_e64:
5853 case AMDGPU::V_MIN_NUM_F64_e64:
5854 case AMDGPU::V_MAX_NUM_F64_e64:
5855 return 0x7FF8000000000000; // qNAN
5856 case AMDGPU::S_ADD_U64_PSEUDO:
5857 case AMDGPU::S_SUB_U64_PSEUDO:
5858 case AMDGPU::S_OR_B64:
5859 case AMDGPU::S_XOR_B64:
5860 return std::numeric_limits<uint64_t>::min();
5861 case AMDGPU::S_AND_B64:
5862 return std::numeric_limits<uint64_t>::max();
5863 case AMDGPU::V_ADD_F64_e64:
5864 case AMDGPU::V_ADD_F64_pseudo_e64:
5865 return 0x8000000000000000; // -0.0
5866 default:
5867 llvm_unreachable("Unexpected opcode in getIdentityValueForWaveReduction");
5868 }
5869}
5870
5871static bool is32bitWaveReduceOperation(unsigned Opc) {
5872 return Opc == AMDGPU::S_MIN_U32 || Opc == AMDGPU::S_MIN_I32 ||
5873 Opc == AMDGPU::S_MAX_U32 || Opc == AMDGPU::S_MAX_I32 ||
5874 Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32 ||
5875 Opc == AMDGPU::S_AND_B32 || Opc == AMDGPU::S_OR_B32 ||
5876 Opc == AMDGPU::S_XOR_B32 || Opc == AMDGPU::V_MIN_F32_e64 ||
5877 Opc == AMDGPU::V_MAX_F32_e64 || Opc == AMDGPU::V_ADD_F32_e64 ||
5878 Opc == AMDGPU::V_SUB_F32_e64;
5879}
5880
5882 return Opc == AMDGPU::V_MIN_F32_e64 || Opc == AMDGPU::V_MAX_F32_e64 ||
5883 Opc == AMDGPU::V_ADD_F32_e64 || Opc == AMDGPU::V_SUB_F32_e64 ||
5884 Opc == AMDGPU::V_MIN_F64_e64 || Opc == AMDGPU::V_MAX_F64_e64 ||
5885 Opc == AMDGPU::V_MIN_NUM_F64_e64 || Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5886 Opc == AMDGPU::V_ADD_F64_e64 || Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5887}
5888
5889static std::tuple<unsigned, unsigned>
5891 unsigned DPPOpc;
5892 switch (Opc) {
5893 case AMDGPU::S_MIN_U32:
5894 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5895 break;
5896 case AMDGPU::S_MIN_I32:
5897 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5898 break;
5899 case AMDGPU::S_MAX_U32:
5900 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5901 break;
5902 case AMDGPU::S_MAX_I32:
5903 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5904 break;
5905 case AMDGPU::S_ADD_I32:
5906 case AMDGPU::S_SUB_I32:
5907 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5908 : AMDGPU::V_ADD_CO_U32_dpp;
5909 break;
5910 case AMDGPU::S_AND_B32:
5911 DPPOpc = AMDGPU::V_AND_B32_dpp;
5912 break;
5913 case AMDGPU::S_OR_B32:
5914 DPPOpc = AMDGPU::V_OR_B32_dpp;
5915 break;
5916 case AMDGPU::S_XOR_B32:
5917 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5918 break;
5919 case AMDGPU::V_ADD_F32_e64:
5920 case AMDGPU::V_SUB_F32_e64:
5921 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5922 break;
5923 case AMDGPU::V_MIN_F32_e64:
5924 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5925 break;
5926 case AMDGPU::V_MAX_F32_e64:
5927 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5928 break;
5929 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5930 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5931 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5932 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5933 case AMDGPU::S_ADD_U64_PSEUDO:
5934 case AMDGPU::S_SUB_U64_PSEUDO:
5935 case AMDGPU::S_AND_B64:
5936 case AMDGPU::S_OR_B64:
5937 case AMDGPU::S_XOR_B64:
5938 case AMDGPU::V_MIN_NUM_F64_e64:
5939 case AMDGPU::V_MIN_F64_e64:
5940 case AMDGPU::V_MAX_NUM_F64_e64:
5941 case AMDGPU::V_MAX_F64_e64:
5942 case AMDGPU::V_ADD_F64_pseudo_e64:
5943 case AMDGPU::V_ADD_F64_e64:
5944 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5945 break;
5946 default:
5947 llvm_unreachable("unhandled lane op");
5948 }
5949 unsigned ClampOpc = Opc;
5950 if (!ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
5951 if (Opc == AMDGPU::S_SUB_I32)
5952 ClampOpc = AMDGPU::S_ADD_I32;
5953 if (Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO)
5954 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5955 else if (Opc == AMDGPU::S_AND_B64)
5956 ClampOpc = AMDGPU::V_AND_B32_e64;
5957 else if (Opc == AMDGPU::S_OR_B64)
5958 ClampOpc = AMDGPU::V_OR_B32_e64;
5959 else if (Opc == AMDGPU::S_XOR_B64)
5960 ClampOpc = AMDGPU::V_XOR_B32_e64;
5961 else
5962 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5963 }
5964 return {DPPOpc, ClampOpc};
5965}
5966
5967static std::pair<Register, Register>
5969 const TargetRegisterClass *SrcRC, const GCNSubtarget &ST,
5970 MachineRegisterInfo &MRI) {
5971 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5972 const SIInstrInfo *TII = ST.getInstrInfo();
5973 const TargetRegisterClass *SrcSubRC =
5974 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5975 Register Op1L =
5976 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5977 Register Op1H =
5978 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub1, SrcSubRC);
5979 return {Op1L, Op1H};
5980}
5981
5984 const GCNSubtarget &ST,
5985 unsigned Opc) {
5987 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5988 const DebugLoc &DL = MI.getDebugLoc();
5989 const SIInstrInfo *TII = ST.getInstrInfo();
5990
5991 // Reduction operations depend on whether the input operand is SGPR or VGPR.
5992 Register SrcReg = MI.getOperand(1).getReg();
5993 bool isSGPR = TRI->isSGPRClass(MRI.getRegClass(SrcReg));
5994 Register DstReg = MI.getOperand(0).getReg();
5995 unsigned Stratergy = static_cast<unsigned>(MI.getOperand(2).getImm());
5996 enum WAVE_REDUCE_STRATEGY : unsigned { DEFAULT = 0, ITERATIVE = 1, DPP = 2 };
5997 MachineBasicBlock *RetBB = nullptr;
5998 unsigned MIOpc = MI.getOpcode();
5999 auto BuildRegSequence = [&](MachineBasicBlock &BB,
6001 Register Src0, Register Src1) {
6002 auto RegSequence =
6003 BuildMI(BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dst)
6004 .addReg(Src0)
6005 .addImm(AMDGPU::sub0)
6006 .addReg(Src1)
6007 .addImm(AMDGPU::sub1);
6008 return RegSequence;
6009 };
6010 if (isSGPR) {
6011 switch (Opc) {
6012 case AMDGPU::S_MIN_U32:
6013 case AMDGPU::S_MIN_I32:
6014 case AMDGPU::V_MIN_F32_e64:
6015 case AMDGPU::S_MAX_U32:
6016 case AMDGPU::S_MAX_I32:
6017 case AMDGPU::V_MAX_F32_e64:
6018 case AMDGPU::S_AND_B32:
6019 case AMDGPU::S_OR_B32: {
6020 // Idempotent operations.
6021 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstReg).addReg(SrcReg);
6022 RetBB = &BB;
6023 break;
6024 }
6025 case AMDGPU::V_CMP_LT_U64_e64: // umin
6026 case AMDGPU::V_CMP_LT_I64_e64: // min
6027 case AMDGPU::V_CMP_GT_U64_e64: // umax
6028 case AMDGPU::V_CMP_GT_I64_e64: // max
6029 case AMDGPU::V_MIN_F64_e64:
6030 case AMDGPU::V_MIN_NUM_F64_e64:
6031 case AMDGPU::V_MAX_F64_e64:
6032 case AMDGPU::V_MAX_NUM_F64_e64:
6033 case AMDGPU::S_AND_B64:
6034 case AMDGPU::S_OR_B64: {
6035 // Idempotent operations.
6036 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B64), DstReg).addReg(SrcReg);
6037 RetBB = &BB;
6038 break;
6039 }
6040 case AMDGPU::S_XOR_B32:
6041 case AMDGPU::S_XOR_B64:
6042 case AMDGPU::S_ADD_I32:
6043 case AMDGPU::S_ADD_U64_PSEUDO:
6044 case AMDGPU::V_ADD_F32_e64:
6045 case AMDGPU::V_ADD_F64_e64:
6046 case AMDGPU::V_ADD_F64_pseudo_e64:
6047 case AMDGPU::S_SUB_I32:
6048 case AMDGPU::S_SUB_U64_PSEUDO:
6049 case AMDGPU::V_SUB_F32_e64: {
6050 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
6051 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
6052 Register ExecMask = MRI.createVirtualRegister(WaveMaskRegClass);
6053 Register NumActiveLanes =
6054 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6055
6056 bool IsWave32 = ST.isWave32();
6057 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6058 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6059 unsigned BitCountOpc =
6060 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
6061
6062 BuildMI(BB, MI, DL, TII->get(MovOpc), ExecMask).addReg(ExecReg);
6063
6064 auto NewAccumulator =
6065 BuildMI(BB, MI, DL, TII->get(BitCountOpc), NumActiveLanes)
6066 .addReg(ExecMask)
6067 .setOperandDead(2); // Dead scc
6068
6069 switch (Opc) {
6070 case AMDGPU::S_XOR_B32:
6071 case AMDGPU::S_XOR_B64: {
6072 // Performing an XOR operation on a uniform value
6073 // depends on the parity of the number of active lanes.
6074 // For even parity, the result will be 0, for odd
6075 // parity the result will be the same as the input value.
6076 Register ParityRegister =
6077 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6078 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_AND_B32), ParityRegister)
6079 .addReg(NewAccumulator->getOperand(0).getReg())
6080 .addImm(1)
6081 .setOperandDead(3); // Dead scc
6082 // Check if Src is a known identity constant.
6083 MachineInstr *SrcDef = MRI.getVRegDef(SrcReg);
6084 if (SrcDef && SrcDef->isMoveImmediate()) {
6085 int64_t Imm = SrcDef->getOperand(1).getImm();
6086 if (Imm == 1) { // 1 * parity(exec) = parity(exec)
6087 if (Opc == AMDGPU::S_XOR_B32) {
6088 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstReg)
6089 .addReg(ParityRegister);
6090 } else {
6091 Register DstHi =
6092 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6093 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstHi).addImm(0);
6094 BuildRegSequence(BB, MI, DstReg, ParityRegister, DstHi);
6095 }
6096 break;
6097 }
6098 }
6099 if (Opc == AMDGPU::S_XOR_B32) {
6100 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6101 .addReg(SrcReg)
6102 .addReg(ParityRegister);
6103 } else {
6104 Register DestSub0 =
6105 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6106 Register DestSub1 =
6107 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6108 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6109 MRI.getRegClass(SrcReg), ST, MRI);
6110 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6111 .addReg(Op1L)
6112 .addReg(ParityRegister);
6113 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub1)
6114 .addReg(Op1H)
6115 .addReg(ParityRegister);
6116 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6117 }
6118 break;
6119 }
6120 case AMDGPU::S_SUB_I32: {
6121 Register NegatedVal = MRI.createVirtualRegister(DstRegClass);
6122 // Take the negation of the source operand.
6123 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedVal)
6124 .addImm(0)
6125 .addReg(SrcReg)
6126 .setOperandDead(3); // Dead scc
6127 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6128 .addReg(NegatedVal)
6129 .addReg(NewAccumulator->getOperand(0).getReg());
6130 break;
6131 }
6132 case AMDGPU::S_ADD_I32: {
6133 // Check if Src is a known identity constant.
6134 MachineInstr *SrcDef = MRI.getVRegDef(SrcReg);
6135 if (SrcDef && SrcDef->isMoveImmediate()) {
6136 int64_t Imm = SrcDef->getOperand(1).getImm();
6137 if (Imm == 1) { // 1 * bitcount(exec) = bitcount(exec)
6138 BuildMI(BB, MI, DL, TII->get(AMDGPU::COPY), DstReg)
6139 .addReg(NewAccumulator->getOperand(0).getReg());
6140 break;
6141 }
6142 }
6143 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6144 .addReg(SrcReg)
6145 .addReg(NewAccumulator->getOperand(0).getReg());
6146 break;
6147 }
6148 case AMDGPU::S_ADD_U64_PSEUDO:
6149 case AMDGPU::S_SUB_U64_PSEUDO: {
6150 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6151 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6152 Register Op1H_Op0L_Reg =
6153 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6154 Register Op1L_Op0H_Reg =
6155 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6156 Register CarryReg =
6157 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6158 Register AddReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6159 Register NegatedValLo =
6160 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6161 Register NegatedValHi =
6162 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6163 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6164 MRI.getRegClass(SrcReg), ST, MRI);
6165 // Check if Src is a known identity constant.
6166 MachineInstr *SrcDef = MRI.getVRegDef(SrcReg);
6167 if (SrcDef && SrcDef->isMoveImmediate()) {
6168 int64_t Imm = SrcDef->getOperand(1).getImm();
6169 if (Imm == 1 && Opc == AMDGPU::S_ADD_U64_PSEUDO) {
6170 // 1 * bitcount(exec) = bitcount(exec)
6171 Register DstHi =
6172 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6173 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstHi).addImm(0);
6174 BuildRegSequence(BB, MI, DstReg,
6175 NewAccumulator->getOperand(0).getReg(), DstHi);
6176 break;
6177 }
6178 }
6179 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6180 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedValLo)
6181 .addImm(0)
6182 .addReg(NewAccumulator->getOperand(0).getReg())
6183 .setOperandDead(3); // Dead scc
6184 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ASHR_I32), NegatedValHi)
6185 .addReg(NegatedValLo)
6186 .addImm(31)
6187 .setOperandDead(3); // Dead scc
6188 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1L_Op0H_Reg)
6189 .addReg(Op1L)
6190 .addReg(NegatedValHi);
6191 }
6192 Register LowOpcode = Opc == AMDGPU::S_SUB_U64_PSEUDO
6193 ? NegatedValLo
6194 : NewAccumulator->getOperand(0).getReg();
6195 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6196 .addReg(Op1L)
6197 .addReg(LowOpcode);
6198 if (ST.hasScalarMulHiInsts()) {
6199 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_HI_U32), CarryReg)
6200 .addReg(Op1L)
6201 .addReg(LowOpcode);
6202 } else {
6203 Register VCarryReg =
6204 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6205 Register LowOpVGPR =
6206 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6207 BuildMI(BB, MI, DL, TII->get(AMDGPU::COPY), LowOpVGPR)
6208 .addReg(LowOpcode);
6209 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6210 .addReg(Op1L)
6211 .addReg(LowOpVGPR);
6212 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6213 .addReg(VCarryReg);
6214 }
6215 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1H_Op0L_Reg)
6216 .addReg(Op1H)
6217 .addReg(LowOpcode);
6218
6219 Register HiVal = Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6220 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), HiVal)
6221 .addReg(CarryReg)
6222 .addReg(Op1H_Op0L_Reg)
6223 .setOperandDead(3); // Dead scc
6224
6225 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6226 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), DestSub1)
6227 .addReg(HiVal)
6228 .addReg(Op1L_Op0H_Reg)
6229 .setOperandDead(3); // Dead scc
6230 }
6231 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6232 break;
6233 }
6234 case AMDGPU::V_ADD_F32_e64:
6235 case AMDGPU::V_ADD_F64_e64:
6236 case AMDGPU::V_ADD_F64_pseudo_e64:
6237 case AMDGPU::V_SUB_F32_e64: {
6238 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6239 const TargetRegisterClass *VregRC = TII->getRegClass(TII->get(Opc), 0);
6240 Register ActiveLanesVreg = MRI.createVirtualRegister(VregRC);
6241 Register DstVreg = MRI.createVirtualRegister(VregRC);
6242 // Get number of active lanes as a float val.
6243 BuildMI(BB, MI, DL,
6244 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6245 : AMDGPU::V_CVT_F64_I32_e64),
6246 ActiveLanesVreg)
6247 .addReg(NewAccumulator->getOperand(0).getReg())
6248 .addImm(0) // clamp
6249 .addImm(0); // output-modifier
6250
6251 // Take negation of input for SUB reduction
6252 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6253 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6256 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6257 : ST.getGeneration() >= AMDGPUSubtarget::GFX12
6258 ? AMDGPU::V_MUL_F64_pseudo_e64
6259 : AMDGPU::V_MUL_F64_e64;
6260 auto DestVregInst = BuildMI(BB, MI, DL, TII->get(MulOpc),
6261 DstVreg)
6262 .addImm(srcMod) // src0 modifier
6263 .addReg(SrcReg)
6264 .addImm(SISrcMods::NONE) // src1 modifier
6265 .addReg(ActiveLanesVreg)
6266 .addImm(SISrcMods::NONE) // clamp
6267 .addImm(SISrcMods::NONE); // output-mod
6268 if (is32BitOpc) {
6269 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6270 .addReg(DstVreg);
6271 } else {
6272 Register LaneValueLoReg =
6273 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6274 Register LaneValueHiReg =
6275 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6276 auto [Op1L, Op1H] =
6277 ExtractSubRegs(MI, DestVregInst->getOperand(0), VregRC, ST, MRI);
6278 // lane value input should be in an sgpr
6279 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6280 LaneValueLoReg)
6281 .addReg(Op1L);
6282 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6283 LaneValueHiReg)
6284 .addReg(Op1H);
6285 NewAccumulator =
6286 BuildRegSequence(BB, MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6287 }
6288 }
6289 }
6290 RetBB = &BB;
6291 }
6292 }
6293 } else {
6295 Register SrcReg = MI.getOperand(1).getReg();
6296 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6298 bool NeedsMovDPP = !is32BitOpc;
6299 // Create virtual registers required for lowering.
6300 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
6301 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
6302 const TargetRegisterClass *SrcRegClass = MRI.getRegClass(SrcReg);
6303 bool IsWave32 = ST.isWave32();
6304 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6305 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6306 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6307 !ST.hasDPP()) { // If target doesn't support DPP operations, default to
6308 // iterative stratergy
6309
6310 // To reduce the VGPR using iterative approach, we need to iterate
6311 // over all the active lanes. Lowering consists of ComputeLoop,
6312 // which iterate over only active lanes. We use copy of EXEC register
6313 // as induction variable and every active lane modifies it using bitset0
6314 // so that we will get the next active lane for next iteration.
6315
6316 // Create Control flow for loop
6317 // Split MI's Machine Basic block into For loop
6318 auto [ComputeLoop, ComputeEnd] = splitBlockForLoop(MI, BB, true);
6319
6320 Register LoopIterator = MRI.createVirtualRegister(WaveMaskRegClass);
6321 Register IdentityValReg = MRI.createVirtualRegister(DstRegClass);
6322 Register AccumulatorReg = MRI.createVirtualRegister(DstRegClass);
6323 Register ActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6324 Register NewActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6325 Register FF1Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6326 Register LaneValueReg = MRI.createVirtualRegister(DstRegClass);
6327
6328 // Create initial values of induction variable from Exec, Accumulator and
6329 // insert branch instr to newly created ComputeBlock
6330 BuildMI(BB, I, DL, TII->get(MovOpcForExec), LoopIterator).addReg(ExecReg);
6331 uint64_t IdentityValue =
6332 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6333 ? 0x0 // +0.0 for double sub reduction
6335 BuildMI(BB, I, DL,
6336 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6337 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6338 IdentityValReg)
6339 .addImm(IdentityValue);
6340 // clang-format off
6341 BuildMI(BB, I, DL, TII->get(AMDGPU::S_BRANCH))
6342 .addMBB(ComputeLoop);
6343 // clang-format on
6344
6345 // Start constructing ComputeLoop
6346 I = ComputeLoop->begin();
6347 auto Accumulator =
6348 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), AccumulatorReg)
6349 .addReg(IdentityValReg)
6350 .addMBB(&BB);
6351 auto ActiveBits =
6352 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), ActiveBitsReg)
6353 .addReg(LoopIterator)
6354 .addMBB(&BB);
6355
6356 I = ComputeLoop->end();
6357 MachineInstr *NewAccumulator;
6358 // Perform the computations
6359 unsigned SFFOpc =
6360 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6361 BuildMI(*ComputeLoop, I, DL, TII->get(SFFOpc), FF1Reg)
6362 .addReg(ActiveBitsReg);
6363 if (is32BitOpc) {
6364 Register OpDstReg = DstReg;
6365 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6366 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6367 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6368 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6369 bool hasClamp =
6370 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1;
6371 bool hasOpSel =
6372 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel) != -1;
6373 bool hasOMod =
6374 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1;
6375 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6376 LaneValueReg)
6377 .addReg(SrcReg)
6378 .addReg(FF1Reg);
6379 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6380 // Get the Lane Value in VGPR to avoid the Constant Bus Restriction
6381 Register LaneValVgpr = MRI.createVirtualRegister(SrcRegClass);
6382 Register VgprResultReg = MRI.createVirtualRegister(SrcRegClass);
6383 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), LaneValVgpr)
6384 .addReg(LaneValueReg);
6385 OpDstReg = VgprResultReg;
6386 LaneValueReg = LaneValVgpr;
6387 }
6388 auto OpInstr = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), OpDstReg);
6389 if (hasSrc0Modifier)
6390 OpInstr.addImm(SISrcMods::NONE); // src0 modifier
6391 OpInstr.addReg(AccumulatorReg); // src0
6392 if (hasSrc1Modifier)
6393 OpInstr.addImm(SISrcMods::NONE); // src1 modifier
6394 OpInstr.addReg(LaneValueReg); // src1
6395 if (hasClamp)
6396 OpInstr.addImm(0); // clamp
6397 if (hasOpSel)
6398 OpInstr.addImm(0); // opsel
6399 if (hasOMod)
6400 OpInstr.addImm(0); // omod
6401 if (TII->isSALU(Opc))
6402 OpInstr.setOperandDead(3); // Dead scc
6403 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6404 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6405 DstReg)
6406 .addReg(OpDstReg);
6407 }
6408 } else {
6409 Register LaneValueLoReg =
6410 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6411 Register LaneValueHiReg =
6412 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6413 Register LaneValReg =
6414 MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
6415 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6416 MRI.getRegClass(SrcReg), ST, MRI);
6417 // lane value input should be in an sgpr
6418 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6419 LaneValueLoReg)
6420 .addReg(Op1L)
6421 .addReg(FF1Reg);
6422 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6423 LaneValueHiReg)
6424 .addReg(Op1H)
6425 .addReg(FF1Reg);
6426 auto LaneValue = BuildRegSequence(*ComputeLoop, I, LaneValReg,
6427 LaneValueLoReg, LaneValueHiReg);
6428 switch (Opc) {
6429 case AMDGPU::S_OR_B64:
6430 case AMDGPU::S_AND_B64:
6431 case AMDGPU::S_XOR_B64: {
6432 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6433 .addReg(Accumulator->getOperand(0).getReg())
6434 .addReg(LaneValue->getOperand(0).getReg())
6435 .setOperandDead(3); // Dead scc
6436 break;
6437 }
6438 case AMDGPU::V_CMP_GT_I64_e64:
6439 case AMDGPU::V_CMP_GT_U64_e64:
6440 case AMDGPU::V_CMP_LT_I64_e64:
6441 case AMDGPU::V_CMP_LT_U64_e64: {
6442 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6443 Register ComparisonResultReg =
6444 MRI.createVirtualRegister(WaveMaskRegClass);
6445 int SrcIdx =
6446 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6447 const TargetRegisterClass *VregClass =
6448 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6449 Register AccumulatorVReg = MRI.createVirtualRegister(VregClass);
6450 auto [SrcReg0Sub0, SrcReg0Sub1] = ExtractSubRegs(
6451 MI, Accumulator->getOperand(0), VregClass, ST, MRI);
6452 BuildRegSequence(*ComputeLoop, I, AccumulatorVReg, SrcReg0Sub0,
6453 SrcReg0Sub1);
6454 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), LaneMaskReg)
6455 .addReg(LaneValue->getOperand(0).getReg())
6456 .addReg(AccumulatorVReg);
6457
6458 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6459 BuildMI(*ComputeLoop, I, DL, TII->get(AndOpc), ComparisonResultReg)
6460 .addReg(LaneMaskReg)
6461 .addReg(ActiveBitsReg);
6462
6463 NewAccumulator = BuildMI(*ComputeLoop, I, DL,
6464 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6465 .addReg(LaneValue->getOperand(0).getReg())
6466 .addReg(Accumulator->getOperand(0).getReg());
6467 break;
6468 }
6469 case AMDGPU::V_MIN_F64_e64:
6470 case AMDGPU::V_MIN_NUM_F64_e64:
6471 case AMDGPU::V_MAX_F64_e64:
6472 case AMDGPU::V_MAX_NUM_F64_e64:
6473 case AMDGPU::V_ADD_F64_e64:
6474 case AMDGPU::V_ADD_F64_pseudo_e64: {
6475 int SrcIdx =
6476 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6477 const TargetRegisterClass *VregRC =
6478 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6479 Register AccumulatorVReg = MRI.createVirtualRegister(VregRC);
6480 Register DstVreg = MRI.createVirtualRegister(VregRC);
6481 Register LaneValLo =
6482 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6483 Register LaneValHi =
6484 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6485 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), AccumulatorVReg)
6486 .addReg(Accumulator->getOperand(0).getReg());
6487 unsigned Modifier =
6488 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6491 auto DstVregInst =
6492 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstVreg)
6493 .addImm(Modifier) // src0 modifiers
6494 .addReg(LaneValue->getOperand(0).getReg())
6495 .addImm(SISrcMods::NONE) // src1 modifiers
6496 .addReg(AccumulatorVReg)
6497 .addImm(SISrcMods::NONE) // clamp
6498 .addImm(SISrcMods::NONE); // omod
6499 auto ReadLaneLo =
6500 BuildMI(*ComputeLoop, I, DL,
6501 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6502 auto ReadLaneHi =
6503 BuildMI(*ComputeLoop, I, DL,
6504 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6505 MachineBasicBlock::iterator Iters = *ReadLaneLo;
6506 auto [Op1L, Op1H] = ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6507 VregRC, ST, MRI);
6508 ReadLaneLo.addReg(Op1L);
6509 ReadLaneHi.addReg(Op1H);
6510 NewAccumulator =
6511 BuildRegSequence(*ComputeLoop, I, DstReg, LaneValLo, LaneValHi);
6512 break;
6513 }
6514 case AMDGPU::S_ADD_U64_PSEUDO:
6515 case AMDGPU::S_SUB_U64_PSEUDO: {
6516 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6517 .addReg(Accumulator->getOperand(0).getReg())
6518 .addReg(LaneValue->getOperand(0).getReg())
6519 .setOperandDead(3); // Dead scc
6520 ComputeLoop =
6521 expand64BitScalarArithmetic(*NewAccumulator, ComputeLoop);
6522 break;
6523 }
6524 }
6525 }
6526 // Manipulate the iterator to get the next active lane
6527 unsigned BITSETOpc =
6528 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6529 BuildMI(*ComputeLoop, I, DL, TII->get(BITSETOpc), NewActiveBitsReg)
6530 .addReg(FF1Reg)
6531 .addReg(ActiveBitsReg);
6532
6533 // Add phi nodes
6534 Accumulator.addReg(DstReg).addMBB(ComputeLoop);
6535 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6536
6537 // Creating branching
6538 MachineInstrBuilder SetSCCInstr;
6539 if (!ST.hasScalarCompareEq64()) {
6540 // For targets <= gfx7, use an S_OR_B32/B64 instruction to set SCC.
6541 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6542 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6543 SetSCCInstr =
6544 BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc), LaneMaskReg);
6545 } else {
6546 unsigned CMPOpc =
6547 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6548 SetSCCInstr = BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc));
6549 }
6550 SetSCCInstr.addReg(NewActiveBitsReg);
6551 if (ST.hasScalarCompareEq64())
6552 SetSCCInstr.addImm(0);
6553 else
6554 SetSCCInstr.addReg(NewActiveBitsReg);
6555 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
6556 .addMBB(ComputeLoop);
6557
6558 RetBB = ComputeEnd;
6559 } else {
6560 assert(ST.hasDPP() && "Sub Target does not support DPP Operations");
6561 MachineBasicBlock *CurrBB = &BB;
6562 Register SrcWithIdentity = MRI.createVirtualRegister(SrcRegClass);
6563 Register IdentityVGPR = MRI.createVirtualRegister(SrcRegClass);
6564 Register IdentitySGPR = MRI.createVirtualRegister(DstRegClass);
6565 Register DPPRowShr1 = MRI.createVirtualRegister(SrcRegClass);
6566 Register DPPRowShr2 = MRI.createVirtualRegister(SrcRegClass);
6567 Register DPPRowShr4 = MRI.createVirtualRegister(SrcRegClass);
6568 Register DPPRowShr8 = MRI.createVirtualRegister(SrcRegClass);
6569 Register RowBcast15 = MRI.createVirtualRegister(SrcRegClass);
6570 Register ReducedValSGPR = MRI.createVirtualRegister(DstRegClass);
6571 Register NegatedReducedVal = MRI.createVirtualRegister(DstRegClass);
6572 Register RowBcast31 = MRI.createVirtualRegister(SrcRegClass);
6573 Register UndefExec = MRI.createVirtualRegister(WaveMaskRegClass);
6574 Register FinalDPPResult;
6575 MachineInstr *SrcWithIdentityInstr;
6576 MachineInstr *LastBcastInstr;
6577 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6578
6580 BuildMI(*CurrBB, MI, DL,
6581 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6582 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6583 IdentitySGPR)
6584 .addImm(IdentityValue);
6585 auto IdentityCopyInstr =
6586 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::COPY), IdentityVGPR)
6587 .addReg(IdentitySGPR);
6588 auto DPPClampOpcPair = getDPPOpcForWaveReduction(Opc, ST);
6589 unsigned DPPOpc = std::get<0>(DPPClampOpcPair);
6590 unsigned ClampOpc = std::get<1>(DPPClampOpcPair);
6591 auto BuildSetInactiveInstr = [&](Register Dst, Register Src0,
6592 Register Src1) {
6593 return BuildMI(BB, MI, DL, TII->get(AMDGPU::V_SET_INACTIVE_B32),
6594 Dst)
6595 .addImm(0) // src0 modifiers
6596 .addReg(Src0) // src0
6597 .addImm(0) // src1 modifiers
6598 .addReg(Src1) // identity value for inactive lanes
6599 .addReg(UndefExec); // bool i1
6600 };
6601 auto BuildDPPMachineInstr = [&](Register Dst, Register Src,
6602 unsigned DPPCtrl) {
6603 auto DPPInstr =
6604 BuildMI(*CurrBB, MI, DL, TII->get(DPPOpc), Dst).addReg(Src); // old
6605 if (isFPOp && !NeedsMovDPP)
6606 DPPInstr.addImm(SISrcMods::NONE); // src0 modifier
6607 DPPInstr.addReg(Src); // src0
6608 if (isFPOp && !NeedsMovDPP)
6609 DPPInstr.addImm(SISrcMods::NONE); // src1 modifier
6610 if (!NeedsMovDPP)
6611 DPPInstr.addReg(Src); // src1
6612 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6613 DPPInstr.addImm(0); // clamp
6614 DPPInstr
6615 .addImm(DPPCtrl) // dpp-ctrl
6616 .addImm(0xf) // row-mask
6617 .addImm(0xf) // bank-mask
6618 .addImm(0); // bound-control
6619 };
6620 auto BuildClampInstr = [&](Register Dst, Register Src0, Register Src1,
6621 bool isAddSub = false,
6622 bool needsCarryIn = false,
6623 Register CarryIn = Register()) {
6624 unsigned InstrOpc = ClampOpc;
6625 Register CarryOutReg = MRI.createVirtualRegister(WaveMaskRegClass);
6626 if (needsCarryIn)
6627 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6628 auto ClampInstr = BuildMI(*CurrBB, MI, DL, TII->get(InstrOpc), Dst);
6629 if (isFPOp)
6630 ClampInstr.addImm(SISrcMods::NONE); // src0 mod
6631 if (isAddSub) {
6632 if (needsCarryIn)
6633 ClampInstr.addReg(CarryOutReg,
6635 RegState::Dead); // killed carry-out reg
6636 else
6637 ClampInstr.addReg(CarryOutReg, RegState::Define); // carry-out reg
6638 }
6639 ClampInstr.addReg(Src0); // src0
6640 if (isFPOp)
6641 ClampInstr.addImm(SISrcMods::NONE); // src1 mod
6642 ClampInstr.addReg(Src1); // src1
6643 if (needsCarryIn)
6644 ClampInstr.addReg(CarryIn, RegState::Kill); // carry-in reg
6645 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6646 ClampInstr.addImm(0); // clamp
6647 if (isFPOp)
6648 ClampInstr.addImm(0); // omod
6649 LastBcastInstr = ClampInstr;
6650 return CarryOutReg;
6651 };
6652 auto BuildPostDPPInstr = [&](Register Src0, Register Src1) {
6653 bool isAddSubOpc =
6654 Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO;
6655 bool isBitWiseOpc = Opc == AMDGPU::S_AND_B64 ||
6656 Opc == AMDGPU::S_OR_B64 || Opc == AMDGPU::S_XOR_B64;
6657 Register ReturnReg = MRI.createVirtualRegister(SrcRegClass);
6658 if (isAddSubOpc || isBitWiseOpc) {
6659 Register ResLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6660 Register ResHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6661 MachineOperand Src0Operand =
6662 MachineOperand::CreateReg(Src0, /*isDef=*/false);
6663 MachineOperand Src1Operand =
6664 MachineOperand::CreateReg(Src1, /*isDef=*/false);
6665 auto [Src0Lo, Src0Hi] =
6666 ExtractSubRegs(MI, Src0Operand, SrcRegClass, ST, MRI);
6667 auto [Src1Lo, Src1Hi] =
6668 ExtractSubRegs(MI, Src1Operand, SrcRegClass, ST, MRI);
6669 Register CarryReg = BuildClampInstr(
6670 ResLo, Src0Lo, Src1Lo, isAddSubOpc, /*needsCarryIn*/ false);
6671 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6672 /*needsCarryIn*/ isAddSubOpc, CarryReg);
6673 BuildRegSequence(*CurrBB, MI, ReturnReg, ResLo, ResHi);
6674 } else {
6675 if (isFPOp) {
6676 BuildMI(*CurrBB, MI, DL, TII->get(Opc), ReturnReg)
6677 .addImm(SISrcMods::NONE) // src0 modifiers
6678 .addReg(Src0)
6679 .addImm(SISrcMods::NONE) // src1 modifiers
6680 .addReg(Src1)
6681 .addImm(SISrcMods::NONE) // clamp
6682 .addImm(SISrcMods::NONE); // omod
6683 } else {
6684 Register CmpMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6685 BuildMI(*CurrBB, MI, DL, TII->get(Opc), CmpMaskReg)
6686 .addReg(Src0) // src0
6687 .addReg(Src1); // src1
6688 LastBcastInstr =
6689 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B64_PSEUDO),
6690 ReturnReg)
6691 .addReg(Src1) // src0
6692 .addReg(Src0) // src1
6693 .addReg(CmpMaskReg); // src2
6694 expand64BitV_CNDMASK(*LastBcastInstr, CurrBB);
6695 }
6696 }
6697 return ReturnReg;
6698 };
6699
6700 // Set inactive lanes to the identity value.
6701 if (is32BitOpc) {
6702 SrcWithIdentityInstr =
6703 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6704 } else {
6705 Register SrcWithIdentitylo =
6706 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6707 Register SrcWithIdentityhi =
6708 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6709 auto [Reg0Sub0, Reg0Sub1] = ExtractSubRegs(
6710 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST, MRI);
6711 auto [SrcReg0Sub0, SrcReg0Sub1] =
6712 ExtractSubRegs(MI, MI.getOperand(1), SrcRegClass, ST, MRI);
6713 MachineInstr *SetInactiveLoInstr =
6714 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6715 MachineInstr *SetInactiveHiInstr =
6716 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6717 SrcWithIdentityInstr =
6718 BuildRegSequence(*CurrBB, MI, SrcWithIdentity,
6719 SetInactiveLoInstr->getOperand(0).getReg(),
6720 SetInactiveHiInstr->getOperand(0).getReg());
6721 }
6722 // DPP reduction
6723 Register SrcWithIdentityReg =
6724 SrcWithIdentityInstr->getOperand(0).getReg();
6725 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6727 if (NeedsMovDPP)
6728 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6729
6730 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6732 if (NeedsMovDPP)
6733 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6734
6735 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6737 if (NeedsMovDPP)
6738 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6739
6740 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6742 if (NeedsMovDPP)
6743 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6744
6745 if (ST.hasDPPBroadcasts()) {
6746 BuildDPPMachineInstr(RowBcast15, DPPRowShr8, AMDGPU::DPP::BCAST15);
6747 if (NeedsMovDPP)
6748 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6749 } else {
6750 // magic constant: 0x1E0
6751 // To Set BIT_MODE : bit 15 = 0
6752 // XOR mask : bit [14:10] = 0
6753 // OR mask : bit [9:5] = 15
6754 // AND mask : bit [4:0] = 0
6755 if (is32BitOpc) {
6756 Register SwizzledValue =
6757 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6758 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6759 SwizzledValue)
6760 .addReg(DPPRowShr8) // addr
6761 .addImm(0x1E0) // swizzle offset (i16)
6762 .addImm(0x0); // gds (i1)
6763 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6764 } else {
6765 Register SwizzledValuelo =
6766 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6767 Register SwizzledValuehi =
6768 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6769 Register SwizzledValue64 = MRI.createVirtualRegister(SrcRegClass);
6770 MachineOperand DPPRowShr8Op =
6771 MachineOperand::CreateReg(DPPRowShr8, /*isDef=*/false);
6772 auto [Op1L, Op1H] =
6773 ExtractSubRegs(MI, DPPRowShr8Op, SrcRegClass, ST, MRI);
6774 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6775 SwizzledValuelo)
6776 .addReg(Op1L) // addr
6777 .addImm(0x1E0) // swizzle offset (i16)
6778 .addImm(0x0); // gds (i1)
6779 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6780 SwizzledValuehi)
6781 .addReg(Op1H) // addr
6782 .addImm(0x1E0) // swizzle offset (i16)
6783 .addImm(0x0); // gds (i1)
6784 BuildRegSequence(*CurrBB, MI, SwizzledValue64, SwizzledValuelo,
6785 SwizzledValuehi);
6786 if (NeedsMovDPP)
6787 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6788 else
6789 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6790 }
6791 }
6792 FinalDPPResult = RowBcast15;
6793 if (!IsWave32) {
6794 if (ST.hasDPPBroadcasts()) {
6795 BuildDPPMachineInstr(RowBcast31, RowBcast15, AMDGPU::DPP::BCAST31);
6796 if (NeedsMovDPP)
6797 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6798 } else {
6799 Register ShiftedThreadID =
6800 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6801 Register PermuteByteOffset =
6802 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6803 Register PermutedValue = MRI.createVirtualRegister(SrcRegClass);
6804 Register Lane32Offset =
6805 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6806 Register WordSizeConst =
6807 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6808 Register ThreadIDRegLo =
6809 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6810 Register ThreadIDReg =
6811 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6812 // Get the thread ID.
6813 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6814 ThreadIDRegLo)
6815 .addImm(-1)
6816 .addImm(0);
6817 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6818 ThreadIDReg)
6819 .addImm(-1)
6820 .addReg(ThreadIDRegLo);
6821 // shift each lane over by 32 positions, so value in 31st lane is
6822 // present in 63rd lane.
6823 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6824 .addImm(0x20);
6825 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_ADD_U32_e64),
6826 ShiftedThreadID)
6827 .addReg(ThreadIDReg)
6828 .addReg(Lane32Offset)
6829 .addImm(0); // clamp
6830 // multiply by reg size.
6831 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6832 .addImm(0x4);
6833 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MUL_LO_U32_e64),
6834 PermuteByteOffset)
6835 .addReg(WordSizeConst)
6836 .addReg(ShiftedThreadID);
6837 // Permute the lanes
6838 if (is32BitOpc) {
6839 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6840 PermutedValue)
6841 .addReg(PermuteByteOffset) // addr
6842 .addReg(RowBcast15) // data
6843 .addImm(0); // offset
6844 } else {
6845 Register PermutedValuelo =
6846 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6847 Register PermutedValuehi =
6848 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6849 MachineOperand RowBcast15Op =
6850 MachineOperand::CreateReg(RowBcast15, /*isDef=*/false);
6851 auto [RowBcast15Lo, RowBcast15Hi] =
6852 ExtractSubRegs(MI, RowBcast15Op, SrcRegClass, ST, MRI);
6853 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6854 PermutedValuelo)
6855 .addReg(PermuteByteOffset) // addr
6856 .addReg(RowBcast15Lo) // swizzle offset (i16)
6857 .addImm(0x0); // gds (i1)
6858 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6859 PermutedValuehi)
6860 .addReg(PermuteByteOffset) // addr
6861 .addReg(RowBcast15Hi) // swizzle offset (i16)
6862 .addImm(0x0); // gds (i1)
6863 BuildRegSequence(*CurrBB, MI, PermutedValue, PermutedValuelo,
6864 PermutedValuehi);
6865 }
6866 if (NeedsMovDPP)
6867 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6868 else
6869 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6870 }
6871 FinalDPPResult = RowBcast31;
6872 }
6873 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6874 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6875 Register NegatedValVGPR = MRI.createVirtualRegister(SrcRegClass);
6876 // Opc for f32 reduction is V_SUB_F32.
6877 // For f64, there is no equivalent V_SUB_F64 opcode, so use
6878 // V_ADD_F64/V_ADD_F64_pseudo, and negate the second operand.
6879 BuildMI(*CurrBB, MI, DL, TII->get(Opc),
6880 NegatedValVGPR)
6881 .addImm(SISrcMods::NONE) // src0 mods
6882 .addReg(IdentityVGPR) // src0
6883 .addImm(is32BitOpc ? SISrcMods::NONE : SISrcMods::NEG) // src1 mods
6884 .addReg(IsWave32 ? RowBcast15 : RowBcast31) // src1
6885 .addImm(SISrcMods::NONE) // clamp
6886 .addImm(SISrcMods::NONE); // omod
6887 FinalDPPResult = NegatedValVGPR;
6888 }
6889 // The final reduced value is in the last lane.
6890 if (is32BitOpc) {
6891 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6892 ReducedValSGPR)
6893 .addReg(FinalDPPResult)
6894 .addImm(ST.getWavefrontSize() - 1);
6895 } else {
6896 Register LaneValueLoReg =
6897 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6898 Register LaneValueHiReg =
6899 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6900 const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
6901 MachineOperand FinalDPPResultOperand =
6902 MachineOperand::CreateReg(FinalDPPResult, /*isDef=*/false);
6903 auto [Op1L, Op1H] =
6904 ExtractSubRegs(MI, FinalDPPResultOperand, SrcRC, ST, MRI);
6905 // lane value input should be in an sgpr
6906 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6907 LaneValueLoReg)
6908 .addReg(Op1L)
6909 .addImm(ST.getWavefrontSize() - 1);
6910 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6911 LaneValueHiReg)
6912 .addReg(Op1H)
6913 .addImm(ST.getWavefrontSize() - 1);
6914 BuildRegSequence(*CurrBB, MI, ReducedValSGPR, LaneValueLoReg,
6915 LaneValueHiReg);
6916 }
6917 if (Opc == AMDGPU::S_SUB_I32) {
6918 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6919 .addImm(0)
6920 .addReg(ReducedValSGPR)
6921 .setOperandDead(3); // Dead scc
6922 } else if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6923 auto NegatedValInstr =
6924 BuildMI(*CurrBB, MI, DL, TII->get(Opc), NegatedReducedVal)
6925 .addImm(0)
6926 .addReg(ReducedValSGPR)
6927 .setOperandDead(3); // Dead scc
6928 CurrBB = expand64BitScalarArithmetic(*NegatedValInstr, CurrBB);
6929 }
6930 // Mark the final result as a whole-wave-mode calculation.
6931 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::STRICT_WWM), DstReg)
6932 .addReg(Opc == AMDGPU::S_SUB_I32 || Opc == AMDGPU::S_SUB_U64_PSEUDO
6933 ? NegatedReducedVal
6934 : ReducedValSGPR);
6935 RetBB = CurrBB;
6936 }
6937 }
6938 MI.eraseFromParent();
6939 return RetBB;
6940}
6941
6944 MachineBasicBlock *BB) const {
6945 MachineFunction *MF = BB->getParent();
6947 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
6949 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
6950 MachineRegisterInfo &MRI = MF->getRegInfo();
6951 const DebugLoc &DL = MI.getDebugLoc();
6952
6953 switch (MI.getOpcode()) {
6954 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6955 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_U32);
6956 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6957 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_U64_e64);
6958 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6959 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_I32);
6960 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6961 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_I64_e64);
6962 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6963 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MIN_F32_e64);
6964 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6965 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6966 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6967 ? AMDGPU::V_MIN_NUM_F64_e64
6968 : AMDGPU::V_MIN_F64_e64);
6969 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6970 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_U32);
6971 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6972 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_U64_e64);
6973 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6974 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_I32);
6975 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6976 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_I64_e64);
6977 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6978 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MAX_F32_e64);
6979 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6980 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6981 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6982 ? AMDGPU::V_MAX_NUM_F64_e64
6983 : AMDGPU::V_MAX_F64_e64);
6984 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6985 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_I32);
6986 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6987 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_U64_PSEUDO);
6988 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6989 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_ADD_F32_e64);
6990 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
6991 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6992 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6993 ? AMDGPU::V_ADD_F64_pseudo_e64
6994 : AMDGPU::V_ADD_F64_e64);
6995 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
6996 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_I32);
6997 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
6998 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_U64_PSEUDO);
6999 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
7000 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_SUB_F32_e64);
7001 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
7002 // There is no S/V_SUB_F64 opcode. Double type subtraction is expanded as
7003 // fadd + neg, by setting the NEG bit in the instruction.
7004 return lowerWaveReduce(MI, *BB, *getSubtarget(),
7005 ST.getGeneration() >= AMDGPUSubtarget::GFX12
7006 ? AMDGPU::V_ADD_F64_pseudo_e64
7007 : AMDGPU::V_ADD_F64_e64);
7008 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
7009 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B32);
7010 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
7011 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B64);
7012 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
7013 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B32);
7014 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
7015 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B64);
7016 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
7017 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B32);
7018 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
7019 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B64);
7020 case AMDGPU::S_UADDO_PSEUDO:
7021 case AMDGPU::S_USUBO_PSEUDO: {
7022 MachineOperand &Dest0 = MI.getOperand(0);
7023 MachineOperand &Dest1 = MI.getOperand(1);
7024 MachineOperand &Src0 = MI.getOperand(2);
7025 MachineOperand &Src1 = MI.getOperand(3);
7026
7027 unsigned Opc = (MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
7028 ? AMDGPU::S_ADD_U32
7029 : AMDGPU::S_SUB_U32;
7030 // clang-format off
7031 BuildMI(*BB, MI, DL, TII->get(Opc), Dest0.getReg())
7032 .add(Src0)
7033 .add(Src1);
7034 // clang-format on
7035
7036 unsigned SelOpc =
7037 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7038 BuildMI(*BB, MI, DL, TII->get(SelOpc), Dest1.getReg()).addImm(-1).addImm(0);
7039
7040 MI.eraseFromParent();
7041 return BB;
7042 }
7043 case AMDGPU::S_ADD_U64_PSEUDO:
7044 case AMDGPU::S_SUB_U64_PSEUDO: {
7045 return expand64BitScalarArithmetic(MI, BB);
7046 }
7047 case AMDGPU::V_ADD_U64_PSEUDO:
7048 case AMDGPU::V_SUB_U64_PSEUDO: {
7049 bool IsAdd = (MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
7050
7051 MachineOperand &Dest = MI.getOperand(0);
7052 MachineOperand &Src0 = MI.getOperand(1);
7053 MachineOperand &Src1 = MI.getOperand(2);
7054
7055 if (ST.hasAddSubU64Insts()) {
7056 auto I = BuildMI(*BB, MI, DL,
7057 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
7058 : AMDGPU::V_SUB_U64_e64),
7059 Dest.getReg())
7060 .add(Src0)
7061 .add(Src1)
7062 .addImm(0); // clamp
7063 TII->legalizeOperands(*I);
7064 MI.eraseFromParent();
7065 return BB;
7066 }
7067
7068 if (IsAdd && ST.hasLshlAddU64Inst()) {
7069 auto Add = BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_LSHL_ADD_U64_e64),
7070 Dest.getReg())
7071 .add(Src0)
7072 .addImm(0)
7073 .add(Src1);
7074 TII->legalizeOperands(*Add);
7075 MI.eraseFromParent();
7076 return BB;
7077 }
7078
7079 const auto *CarryRC = TRI->getWaveMaskRegClass();
7080
7081 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7082 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7083
7084 Register CarryReg = MRI.createVirtualRegister(CarryRC);
7085 Register DeadCarryReg = MRI.createVirtualRegister(CarryRC);
7086
7087 const TargetRegisterClass *Src0RC = Src0.isReg()
7088 ? MRI.getRegClass(Src0.getReg())
7089 : &AMDGPU::VReg_64RegClass;
7090 const TargetRegisterClass *Src1RC = Src1.isReg()
7091 ? MRI.getRegClass(Src1.getReg())
7092 : &AMDGPU::VReg_64RegClass;
7093
7094 const TargetRegisterClass *Src0SubRC =
7095 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
7096 const TargetRegisterClass *Src1SubRC =
7097 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
7098
7099 MachineOperand SrcReg0Sub0 = TII->buildExtractSubRegOrImm(
7100 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
7101 MachineOperand SrcReg1Sub0 = TII->buildExtractSubRegOrImm(
7102 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
7103
7104 MachineOperand SrcReg0Sub1 = TII->buildExtractSubRegOrImm(
7105 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
7106 MachineOperand SrcReg1Sub1 = TII->buildExtractSubRegOrImm(
7107 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
7108
7109 unsigned LoOpc =
7110 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7111 MachineInstr *LoHalf = BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0)
7112 .addReg(CarryReg, RegState::Define)
7113 .add(SrcReg0Sub0)
7114 .add(SrcReg1Sub0)
7115 .addImm(0); // clamp bit
7116
7117 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7118 MachineInstr *HiHalf =
7119 BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1)
7120 .addReg(DeadCarryReg, RegState::Define | RegState::Dead)
7121 .add(SrcReg0Sub1)
7122 .add(SrcReg1Sub1)
7123 .addReg(CarryReg, RegState::Kill)
7124 .addImm(0); // clamp bit
7125
7126 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
7127 .addReg(DestSub0)
7128 .addImm(AMDGPU::sub0)
7129 .addReg(DestSub1)
7130 .addImm(AMDGPU::sub1);
7131 TII->legalizeOperands(*LoHalf);
7132 TII->legalizeOperands(*HiHalf);
7133 MI.eraseFromParent();
7134 return BB;
7135 }
7136 case AMDGPU::S_ADD_CO_PSEUDO:
7137 case AMDGPU::S_SUB_CO_PSEUDO: {
7138 // This pseudo has a chance to be selected
7139 // only from uniform add/subcarry node. All the VGPR operands
7140 // therefore assumed to be splat vectors.
7142 MachineOperand &Dest = MI.getOperand(0);
7143 MachineOperand &CarryDest = MI.getOperand(1);
7144 MachineOperand &Src0 = MI.getOperand(2);
7145 MachineOperand &Src1 = MI.getOperand(3);
7146 MachineOperand &Src2 = MI.getOperand(4);
7147 if (Src0.isReg() && TRI->isVectorRegister(MRI, Src0.getReg())) {
7148 Register RegOp0 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7149 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7150 .addReg(Src0.getReg());
7151 Src0.setReg(RegOp0);
7152 }
7153 if (Src1.isReg() && TRI->isVectorRegister(MRI, Src1.getReg())) {
7154 Register RegOp1 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7155 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7156 .addReg(Src1.getReg());
7157 Src1.setReg(RegOp1);
7158 }
7159 Register RegOp2 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7160 if (TRI->isVectorRegister(MRI, Src2.getReg())) {
7161 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7162 .addReg(Src2.getReg());
7163 Src2.setReg(RegOp2);
7164 }
7165
7166 if (ST.isWave64()) {
7167 if (ST.hasScalarCompareEq64()) {
7168 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U64))
7169 .addReg(Src2.getReg())
7170 .addImm(0);
7171 } else {
7172 const TargetRegisterClass *Src2RC = MRI.getRegClass(Src2.getReg());
7173 const TargetRegisterClass *SubRC =
7174 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7175 MachineOperand Src2Sub0 = TII->buildExtractSubRegOrImm(
7176 MII, MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7177 MachineOperand Src2Sub1 = TII->buildExtractSubRegOrImm(
7178 MII, MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7179 Register Src2_32 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7180
7181 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_OR_B32), Src2_32)
7182 .add(Src2Sub0)
7183 .add(Src2Sub1);
7184
7185 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7186 .addReg(Src2_32, RegState::Kill)
7187 .addImm(0);
7188 }
7189 } else {
7190 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7191 .addReg(Src2.getReg())
7192 .addImm(0);
7193 }
7194
7195 unsigned Opc = MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7196 ? AMDGPU::S_ADDC_U32
7197 : AMDGPU::S_SUBB_U32;
7198
7199 BuildMI(*BB, MII, DL, TII->get(Opc), Dest.getReg()).add(Src0).add(Src1);
7200
7201 unsigned SelOpc =
7202 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7203
7204 BuildMI(*BB, MII, DL, TII->get(SelOpc), CarryDest.getReg())
7205 .addImm(-1)
7206 .addImm(0);
7207
7208 MI.eraseFromParent();
7209 return BB;
7210 }
7211 case AMDGPU::SI_INIT_M0: {
7212 MachineOperand &M0Init = MI.getOperand(0);
7213 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7214 TII->get(M0Init.isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7215 AMDGPU::M0)
7216 .add(M0Init);
7217 MI.eraseFromParent();
7218 return BB;
7219 }
7220 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7221 // Set SCC to true, in case the barrier instruction gets converted to a NOP.
7222 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7223 TII->get(AMDGPU::S_CMP_EQ_U32))
7224 .addImm(0)
7225 .addImm(0);
7226 return BB;
7227 }
7228 case AMDGPU::GET_GROUPSTATICSIZE: {
7229 assert(getTargetMachine().getTargetTriple().getOS() == Triple::AMDHSA ||
7230 getTargetMachine().getTargetTriple().getOS() == Triple::AMDPAL);
7231 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_MOV_B32))
7232 .add(MI.getOperand(0))
7233 .addImm(MFI->getLDSSize());
7234 MI.eraseFromParent();
7235 return BB;
7236 }
7237 case AMDGPU::GET_SHADERCYCLESHILO: {
7238 assert(MF->getSubtarget<GCNSubtarget>().hasShaderCyclesHiLoRegisters());
7239 // The algorithm is:
7240 //
7241 // hi1 = getreg(SHADER_CYCLES_HI)
7242 // lo1 = getreg(SHADER_CYCLES_LO)
7243 // hi2 = getreg(SHADER_CYCLES_HI)
7244 //
7245 // If hi1 == hi2 then there was no overflow and the result is hi2:lo1.
7246 // Otherwise there was overflow and the result is hi2:0. In both cases the
7247 // result should represent the actual time at some point during the sequence
7248 // of three getregs.
7249 using namespace AMDGPU::Hwreg;
7250 Register RegHi1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7251 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi1)
7252 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7253 Register RegLo1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7254 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegLo1)
7255 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7256 Register RegHi2 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7257 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi2)
7258 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7259 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CMP_EQ_U32))
7260 .addReg(RegHi1)
7261 .addReg(RegHi2);
7262 Register RegLo = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7263 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CSELECT_B32), RegLo)
7264 .addReg(RegLo1)
7265 .addImm(0);
7266 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE))
7267 .add(MI.getOperand(0))
7268 .addReg(RegLo)
7269 .addImm(AMDGPU::sub0)
7270 .addReg(RegHi2)
7271 .addImm(AMDGPU::sub1);
7272 MI.eraseFromParent();
7273 return BB;
7274 }
7275 case AMDGPU::SI_INDIRECT_SRC_V1:
7276 case AMDGPU::SI_INDIRECT_SRC_V2:
7277 case AMDGPU::SI_INDIRECT_SRC_V3:
7278 case AMDGPU::SI_INDIRECT_SRC_V4:
7279 case AMDGPU::SI_INDIRECT_SRC_V5:
7280 case AMDGPU::SI_INDIRECT_SRC_V6:
7281 case AMDGPU::SI_INDIRECT_SRC_V7:
7282 case AMDGPU::SI_INDIRECT_SRC_V8:
7283 case AMDGPU::SI_INDIRECT_SRC_V9:
7284 case AMDGPU::SI_INDIRECT_SRC_V10:
7285 case AMDGPU::SI_INDIRECT_SRC_V11:
7286 case AMDGPU::SI_INDIRECT_SRC_V12:
7287 case AMDGPU::SI_INDIRECT_SRC_V16:
7288 case AMDGPU::SI_INDIRECT_SRC_V32:
7289 return emitIndirectSrc(MI, *BB, *getSubtarget());
7290 case AMDGPU::SI_INDIRECT_DST_V1:
7291 case AMDGPU::SI_INDIRECT_DST_V2:
7292 case AMDGPU::SI_INDIRECT_DST_V3:
7293 case AMDGPU::SI_INDIRECT_DST_V4:
7294 case AMDGPU::SI_INDIRECT_DST_V5:
7295 case AMDGPU::SI_INDIRECT_DST_V6:
7296 case AMDGPU::SI_INDIRECT_DST_V7:
7297 case AMDGPU::SI_INDIRECT_DST_V8:
7298 case AMDGPU::SI_INDIRECT_DST_V9:
7299 case AMDGPU::SI_INDIRECT_DST_V10:
7300 case AMDGPU::SI_INDIRECT_DST_V11:
7301 case AMDGPU::SI_INDIRECT_DST_V12:
7302 case AMDGPU::SI_INDIRECT_DST_V16:
7303 case AMDGPU::SI_INDIRECT_DST_V32:
7304 return emitIndirectDst(MI, *BB, *getSubtarget());
7305 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7306 case AMDGPU::SI_KILL_I1_PSEUDO:
7307 return splitKillBlock(MI, BB);
7308 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7310 return BB;
7311 }
7312 case AMDGPU::SI_BR_UNDEF: {
7313 MachineInstr *Br = BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
7314 .add(MI.getOperand(0));
7315 Br->getOperand(1).setIsUndef(); // read undef SCC
7316 MI.eraseFromParent();
7317 return BB;
7318 }
7319 case AMDGPU::ADJCALLSTACKUP:
7320 case AMDGPU::ADJCALLSTACKDOWN: {
7322 MachineInstrBuilder MIB(*MF, &MI);
7323 MIB.addReg(Info->getStackPtrOffsetReg(), RegState::ImplicitDefine)
7324 .addReg(Info->getStackPtrOffsetReg(), RegState::Implicit);
7325 return BB;
7326 }
7327 case AMDGPU::SI_CALL_ISEL: {
7328 unsigned ReturnAddrReg = TII->getRegisterInfo().getReturnAddressReg(*MF);
7329
7331 MIB = BuildMI(*BB, MI, DL, TII->get(AMDGPU::SI_CALL), ReturnAddrReg);
7332
7333 for (const MachineOperand &MO : MI.operands())
7334 MIB.add(MO);
7335
7336 MIB.cloneMemRefs(MI);
7337 MI.eraseFromParent();
7338 return BB;
7339 }
7340 case AMDGPU::V_ADDC_U32_e32:
7341 case AMDGPU::V_SUBB_U32_e32:
7342 case AMDGPU::V_SUBBREV_U32_e32:
7343 // These instructions have an implicit use of vcc which counts towards the
7344 // constant bus limit.
7345 TII->legalizeOperands(MI);
7346 return BB;
7347 case AMDGPU::DS_GWS_INIT:
7348 case AMDGPU::DS_GWS_SEMA_BR:
7349 case AMDGPU::DS_GWS_BARRIER:
7350 case AMDGPU::DS_GWS_SEMA_V:
7351 case AMDGPU::DS_GWS_SEMA_P:
7352 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7353 // A s_waitcnt 0 is required to be the instruction immediately following.
7354 if (getSubtarget()->hasGWSAutoReplay()) {
7356 return BB;
7357 }
7358
7359 return emitGWSMemViolTestLoop(MI, BB);
7360 case AMDGPU::S_SETREG_B32: {
7361 // Try to optimize cases that only set the denormal mode or rounding mode.
7362 //
7363 // If the s_setreg_b32 fully sets all of the bits in the rounding mode or
7364 // denormal mode to a constant, we can use s_round_mode or s_denorm_mode
7365 // instead.
7366 //
7367 // FIXME: This could be predicates on the immediate, but tablegen doesn't
7368 // allow you to have a no side effect instruction in the output of a
7369 // sideeffecting pattern.
7370 auto [ID, Offset, Width] =
7371 AMDGPU::Hwreg::HwregEncoding::decode(MI.getOperand(1).getImm());
7372 if (ID != AMDGPU::Hwreg::ID_MODE)
7373 return BB;
7374
7375 const unsigned WidthMask = maskTrailingOnes<unsigned>(Width);
7376 const unsigned SetMask = WidthMask << Offset;
7377
7378 if (getSubtarget()->hasDenormModeInst()) {
7379 unsigned SetDenormOp = 0;
7380 unsigned SetRoundOp = 0;
7381
7382 // The dedicated instructions can only set the whole denorm or round mode
7383 // at once, not a subset of bits in either.
7384 if (SetMask ==
7386 // If this fully sets both the round and denorm mode, emit the two
7387 // dedicated instructions for these.
7388 SetRoundOp = AMDGPU::S_ROUND_MODE;
7389 SetDenormOp = AMDGPU::S_DENORM_MODE;
7390 } else if (SetMask == AMDGPU::Hwreg::FP_ROUND_MASK) {
7391 SetRoundOp = AMDGPU::S_ROUND_MODE;
7392 } else if (SetMask == AMDGPU::Hwreg::FP_DENORM_MASK) {
7393 SetDenormOp = AMDGPU::S_DENORM_MODE;
7394 }
7395
7396 if (SetRoundOp || SetDenormOp) {
7397 MachineInstr *Def = MRI.getVRegDef(MI.getOperand(0).getReg());
7398 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7399 unsigned ImmVal = Def->getOperand(1).getImm();
7400 if (SetRoundOp) {
7401 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetRoundOp))
7402 .addImm(ImmVal & 0xf);
7403
7404 // If we also have the denorm mode, get just the denorm mode bits.
7405 ImmVal >>= 4;
7406 }
7407
7408 if (SetDenormOp) {
7409 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetDenormOp))
7410 .addImm(ImmVal & 0xf);
7411 }
7412
7413 MI.eraseFromParent();
7414 return BB;
7415 }
7416 }
7417 }
7418
7419 // If only FP bits are touched, used the no side effects pseudo.
7420 if ((SetMask & (AMDGPU::Hwreg::FP_ROUND_MASK |
7421 AMDGPU::Hwreg::FP_DENORM_MASK)) == SetMask)
7422 MI.setDesc(TII->get(AMDGPU::S_SETREG_B32_mode));
7423
7424 return BB;
7425 }
7426 case AMDGPU::S_INVERSE_BALLOT_U32:
7427 case AMDGPU::S_INVERSE_BALLOT_U64:
7428 // These opcodes only exist to let SIFixSGPRCopies insert a readfirstlane if
7429 // necessary. After that they are equivalent to a COPY.
7430 MI.setDesc(TII->get(AMDGPU::COPY));
7431 return BB;
7432 case AMDGPU::ENDPGM_TRAP: {
7433 if (BB->succ_empty() && std::next(MI.getIterator()) == BB->end()) {
7434 MI.setDesc(TII->get(AMDGPU::S_ENDPGM));
7435 MI.addOperand(MachineOperand::CreateImm(0));
7436 return BB;
7437 }
7438
7439 // We need a block split to make the real endpgm a terminator. We also don't
7440 // want to break phis in successor blocks, so we can't just delete to the
7441 // end of the block.
7442
7443 MachineBasicBlock *SplitBB = BB->splitAt(MI, false /*UpdateLiveIns*/);
7445 MF->push_back(TrapBB);
7446 // clang-format off
7447 BuildMI(*TrapBB, TrapBB->end(), DL, TII->get(AMDGPU::S_ENDPGM))
7448 .addImm(0);
7449 BuildMI(*BB, &MI, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
7450 .addMBB(TrapBB);
7451 // clang-format on
7452
7453 BB->addSuccessor(TrapBB);
7454 MI.eraseFromParent();
7455 return SplitBB;
7456 }
7457 case AMDGPU::SIMULATED_TRAP: {
7458 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7459 MachineBasicBlock *SplitBB =
7460 TII->insertSimulatedTrap(MRI, *BB, MI, MI.getDebugLoc());
7461 MI.eraseFromParent();
7462 return SplitBB;
7463 }
7464 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7465 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7467
7468 // During ISel, it's difficult to propagate the original EXEC mask to use as
7469 // an input to SI_WHOLE_WAVE_FUNC_RETURN. Set it up here instead.
7470 MachineInstr *Setup = TII->getWholeWaveFunctionSetup(*BB->getParent());
7471 assert(Setup && "Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7472 Register OriginalExec = Setup->getOperand(0).getReg();
7473 MF->getRegInfo().clearKillFlags(OriginalExec);
7474 MI.getOperand(0).setReg(OriginalExec);
7475 return BB;
7476 }
7477 case AMDGPU::V_DOT2_F32_F16:
7478 case AMDGPU::V_DOT2_F32_BF16: {
7479 // Hint RA to assign dst and src2 the same physical register.
7480 // For targets without VOP2, but with VOPD, variant of the instruction this
7481 // is one of the conditions to attempt converting VOP3P to VOPD.
7482 MRI.setSimpleHint(MI.getOperand(0).getReg(), MI.getOperand(6).getReg());
7483 return BB;
7484 }
7485 case AMDGPU::SCHED_BARRIER:
7486 case AMDGPU::SCHED_GROUP_BARRIER:
7487 MI.getOperand(0).setImm(MI.getOperand(0).getImm() &
7488 static_cast<unsigned>(AMDGPU::SchedGroupMask::ALL));
7489 return BB;
7490 default:
7491 if (TII->isImage(MI) || TII->isMUBUF(MI)) {
7492 if (!MI.mayStore())
7494 return BB;
7495 }
7497 }
7498}
7499
7501 // This currently forces unfolding various combinations of fsub into fma with
7502 // free fneg'd operands. As long as we have fast FMA (controlled by
7503 // isFMAFasterThanFMulAndFAdd), we should perform these.
7504
7505 // When fma is quarter rate, for f64 where add / sub are at best half rate,
7506 // most of these combines appear to be cycle neutral but save on instruction
7507 // count / code size.
7508 return true;
7509}
7510
7512
7514 EVT VT) const {
7515 if (!VT.isVector()) {
7516 return MVT::i1;
7517 }
7518 return EVT::getVectorVT(Ctx, MVT::i1, VT.getVectorNumElements());
7519}
7520
7522 // TODO: Should i16 be used always if legal? For now it would force VALU
7523 // shifts.
7524 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7525}
7526
7528 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7529 ? Ty.changeElementSize(16)
7530 : Ty.changeElementSize(32);
7531}
7532
7533// Answering this is somewhat tricky and depends on the specific device which
7534// have different rates for fma or all f64 operations.
7535//
7536// v_fma_f64 and v_mul_f64 always take the same number of cycles as each other
7537// regardless of which device (although the number of cycles differs between
7538// devices), so it is always profitable for f64.
7539//
7540// v_fma_f32 takes 4 or 16 cycles depending on the device, so it is profitable
7541// only on full rate devices. Normally, we should prefer selecting v_mad_f32
7542// which we can always do even without fused FP ops since it returns the same
7543// result as the separate operations and since it is always full
7544// rate. Therefore, we lie and report that it is not faster for f32. v_mad_f32
7545// however does not support denormals, so we do report fma as faster if we have
7546// a fast fma device and require denormals.
7547//
7549 DenormalFPEnv FPEnv) const {
7550 VT = VT.getScalarType();
7551 if (!VT.isSimple())
7552 return false;
7553
7554 switch (VT.getSimpleVT().SimpleTy) {
7555 case MVT::f32: {
7556 // If mad is not available this depends only on if f32 fma is full rate.
7557 if (!Subtarget->hasMadMacF32Insts())
7558 return Subtarget->hasFastFMAF32();
7559
7560 // Otherwise f32 mad is always full rate and returns the same result as
7561 // the separate operations so should be preferred over fma.
7562 // However does not support denormals.
7564 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7565
7566 // If the subtarget has v_fmac_f32, that's just as good as v_mac_f32.
7567 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7568 }
7569 case MVT::f64:
7570 return true;
7571 case MVT::f16:
7572 case MVT::bf16:
7573 return Subtarget->has16BitInsts() &&
7575 default:
7576 break;
7577 }
7578
7579 return false;
7580}
7581
7586
7588 Type *Ty) const {
7590 getValueType(F.getDataLayout(), Ty, /*AllowUnknown=*/true),
7591 F.getDenormalFPEnv());
7592}
7593
7595 LLT Ty) const {
7596 switch (Ty.getScalarSizeInBits()) {
7597 case 16:
7598 return isFMAFasterThanFMulAndFAdd(MF, MVT::f16);
7599 case 32:
7600 return isFMAFasterThanFMulAndFAdd(MF, MVT::f32);
7601 case 64:
7602 return isFMAFasterThanFMulAndFAdd(MF, MVT::f64);
7603 default:
7604 break;
7605 }
7606
7607 return false;
7608}
7609
7611 // TODO: Check future ftz flag
7612 // v_mad_f32/v_mac_f32 do not support denormals.
7613 if (VT == MVT::f32)
7614 return Subtarget->hasMadMacF32Insts() &&
7616 if (VT == MVT::f16)
7617 return Subtarget->hasMadF16() &&
7619
7620 return false;
7621}
7622
7624 if (!Ty.isScalar())
7625 return false;
7626
7627 DenormalFPEnv FPEnv = getDenormalFPEnv(*MI.getMF());
7628 if (Ty.getScalarSizeInBits() == 16)
7629 return isFMADLegal(MVT::f16, FPEnv);
7630 if (Ty.getScalarSizeInBits() == 32)
7631 return isFMADLegal(MVT::f32, FPEnv);
7632
7633 return false;
7634}
7635
7637 const SDNode *N) const {
7638 return isFMADLegal(N->getValueType(0),
7640}
7641
7643 return isFMADLegal(getValueType(F.getDataLayout(), Ty->getScalarType(),
7644 /*AllowUnknown=*/true),
7645 F.getDenormalFPEnv());
7646}
7647
7648//===----------------------------------------------------------------------===//
7649// Custom DAG Lowering Operations
7650//===----------------------------------------------------------------------===//
7651
7652// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7653// wider vector type is legal.
7655 SelectionDAG &DAG) const {
7656 unsigned Opc = Op.getOpcode();
7657 EVT VT = Op.getValueType();
7659
7660 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
7661 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VT);
7662
7663 SDLoc SL(Op);
7664
7665 // Forward any trailing scalar operands unchanged to both halves.
7666 SmallVector<SDValue, 2> LoOps = {Lo};
7667 SmallVector<SDValue, 2> HiOps = {Hi};
7668 auto TrailingOps = drop_begin(Op->ops());
7669 LoOps.append(TrailingOps.begin(), TrailingOps.end());
7670 HiOps.append(TrailingOps.begin(), TrailingOps.end());
7671
7672 SDValue OpLo = DAG.getNode(Opc, SL, LoVT, LoOps, Op->getFlags());
7673 SDValue OpHi = DAG.getNode(Opc, SL, HiVT, HiOps, Op->getFlags());
7674
7675 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7676}
7677
7678// Enable lowering of ROTR for vxi32 types. This is a workaround for a
7679// regression whereby extra unnecessary instructions were added to codegen
7680// for rotr operations, casued by legalising v2i32 or. This resulted in extra
7681// instructions to extract the result from the vector.
7683 [[maybe_unused]] EVT VT = Op.getValueType();
7684
7685 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7686 VT == MVT::v16i32) &&
7687 "Unexpected ValueType.");
7688
7689 return DAG.UnrollVectorOp(Op.getNode());
7690}
7691
7692// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7693// wider vector type is legal.
7695 SelectionDAG &DAG) const {
7696 unsigned Opc = Op.getOpcode();
7697 EVT VT = Op.getValueType();
7699
7700 auto [Lo0, Hi0] = DAG.SplitVectorOperand(Op.getNode(), 0);
7701 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7702
7703 SDLoc SL(Op);
7704
7705 SDValue OpLo =
7706 DAG.getNode(Opc, SL, Lo0.getValueType(), Lo0, Lo1, Op->getFlags());
7707 SDValue OpHi =
7708 DAG.getNode(Opc, SL, Hi0.getValueType(), Hi0, Hi1, Op->getFlags());
7709
7710 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7711}
7712
7714 SelectionDAG &DAG) const {
7715 unsigned Opc = Op.getOpcode();
7716 EVT VT = Op.getValueType();
7718
7719 SDValue Op0 = Op.getOperand(0);
7720 SDValue Lo0, Hi0;
7721 if (Op0.getValueType().isVector())
7722 std::tie(Lo0, Hi0) = DAG.SplitVectorOperand(Op.getNode(), 0);
7723 else
7724 Lo0 = Hi0 = DAG.getFreeze(Op0);
7725
7726 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7727 auto [Lo2, Hi2] = DAG.SplitVectorOperand(Op.getNode(), 2);
7728
7729 SDLoc SL(Op);
7730 auto ResVT = DAG.GetSplitDestVTs(VT);
7731
7732 SDValue OpLo =
7733 DAG.getNode(Opc, SL, ResVT.first, Lo0, Lo1, Lo2, Op->getFlags());
7734 SDValue OpHi =
7735 DAG.getNode(Opc, SL, ResVT.second, Hi0, Hi1, Hi2, Op->getFlags());
7736
7737 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7738}
7739
7741 switch (Op.getOpcode()) {
7742 default:
7744 case ISD::BRCOND:
7745 return LowerBRCOND(Op, DAG);
7746 case ISD::RETURNADDR:
7747 return LowerRETURNADDR(Op, DAG);
7748 case ISD::SPONENTRY:
7749 return LowerSPONENTRY(Op, DAG);
7750 case ISD::LOAD: {
7751 SDValue Result = LowerLOAD(Op, DAG);
7752 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7753 "Load should return a value and a chain");
7754 return Result;
7755 }
7756 case ISD::FSQRT: {
7757 EVT VT = Op.getValueType();
7758 if (VT == MVT::f32)
7759 return lowerFSQRTF32(Op, DAG);
7760 if (VT == MVT::f64)
7761 return lowerFSQRTF64(Op, DAG);
7762 return SDValue();
7763 }
7764 case ISD::FSIN:
7765 case ISD::FCOS:
7766 return LowerTrig(Op, DAG);
7767 case ISD::SELECT:
7768 return LowerSELECT(Op, DAG);
7769 case ISD::FDIV:
7770 return LowerFDIV(Op, DAG);
7771 case ISD::FFREXP:
7772 return LowerFFREXP(Op, DAG);
7774 return LowerATOMIC_CMP_SWAP(Op, DAG);
7775 case ISD::STORE:
7776 return LowerSTORE(Op, DAG);
7777 case ISD::GlobalAddress: {
7780 return LowerGlobalAddress(MFI, Op, DAG);
7781 }
7782 case ISD::BlockAddress:
7783 return LowerBlockAddress(Op, DAG);
7785 return LowerExternalSymbol(Op, DAG);
7787 return LowerINTRINSIC_WO_CHAIN(Op, DAG);
7789 return LowerCONVERT_FROM_ARBITRARY_FP(Op, DAG);
7791 return LowerCONVERT_TO_ARBITRARY_FP(Op, DAG);
7793 return LowerINTRINSIC_W_CHAIN(Op, DAG);
7795 return LowerINTRINSIC_VOID(Op, DAG);
7796 case ISD::ADDRSPACECAST:
7797 return lowerADDRSPACECAST(Op, DAG);
7799 return lowerINSERT_SUBVECTOR(Op, DAG);
7801 return lowerINSERT_VECTOR_ELT(Op, DAG);
7803 return lowerEXTRACT_VECTOR_ELT(Op, DAG);
7805 return lowerVECTOR_SHUFFLE(Op, DAG);
7807 return lowerSCALAR_TO_VECTOR(Op, DAG);
7808 case ISD::BUILD_VECTOR:
7809 return lowerBUILD_VECTOR(Op, DAG);
7810 case ISD::FP_ROUND:
7812 return lowerFP_ROUND(Op, DAG);
7813 case ISD::TRAP:
7814 return lowerTRAP(Op, DAG);
7815 case ISD::DEBUGTRAP:
7816 return lowerDEBUGTRAP(Op, DAG);
7817 case ISD::ABS:
7818 case ISD::FABS:
7819 case ISD::FNEG:
7820 case ISD::FCANONICALIZE:
7821 case ISD::BSWAP:
7822 return splitUnaryVectorOp(Op, DAG);
7825 if (Op.getValueType().isVector() && Op.getValueType() != MVT::v2i16 &&
7826 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7827 return splitUnaryVectorOp(Op, DAG);
7828 return LowerFP_TO_INT_SAT(Op, DAG);
7829 case ISD::FSUB:
7830 if (Op.getValueType() == MVT::bf16) {
7831 // Custom expansion:
7832 // fsub bf16 %a, %b -> fadd v2bf16(widen %a), fneg v2bf16(widen %b)
7833 // Then extract back to bf16.
7834 //
7835 // We create fneg on v2bf16 (not bf16) so the instruction selector can
7836 // fold the negation into the packed add's neg_lo/neg_hi modifiers,
7837 // generating a single v_pk_add_bf16 instruction. If we negate bf16 first,
7838 // it becomes a separate v_xor instruction before widening.
7839 SDLoc DL(Op);
7840 SDValue Op0 = Op.getOperand(0);
7841 SDValue Op1 = Op.getOperand(1);
7842
7843 // Widen both operands to v2bf16
7844 SDValue Vec0 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op0);
7845 SDValue Vec1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op1);
7846
7847 // Create FNEG v2bf16 for the second operand
7848 SDValue NegVec1 = DAG.getNode(ISD::FNEG, DL, MVT::v2bf16, Vec1);
7849
7850 // Perform FADD v2bf16
7851 SDValue Result = DAG.getNode(ISD::FADD, DL, MVT::v2bf16, Vec0, NegVec1);
7852
7853 // Extract element 0 back to bf16
7854 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::bf16, Result,
7855 DAG.getConstant(0, DL, MVT::i32));
7856 }
7857 return SDValue();
7858 case ISD::FMINNUM:
7859 case ISD::FMAXNUM:
7860 return lowerFMINNUM_FMAXNUM(Op, DAG);
7861 case ISD::FMINIMUMNUM:
7862 case ISD::FMAXIMUMNUM:
7863 return lowerFMINIMUMNUM_FMAXIMUMNUM(Op, DAG);
7864 case ISD::FLDEXP:
7865 case ISD::STRICT_FLDEXP:
7866 return lowerFLDEXP(Op, DAG);
7867 case ISD::FMA:
7868 return splitTernaryVectorOp(Op, DAG);
7869 case ISD::FP_TO_SINT:
7870 case ISD::FP_TO_UINT:
7871 if (Subtarget->hasVCvtPkIU16F32() && Op.getValueType() == MVT::i16 &&
7872 Op.getOperand(0).getValueType() == MVT::f32) {
7873 // Make f32->i16 legal so we can select V_CVT_PK_[IU]16_F32.
7874 return Op;
7875 }
7876 return LowerFP_TO_INT(Op, DAG);
7877 case ISD::SHL:
7878 case ISD::SRA:
7879 case ISD::SRL:
7880 case ISD::ADD:
7881 case ISD::SUB:
7882 case ISD::SMIN:
7883 case ISD::SMAX:
7884 case ISD::UMIN:
7885 case ISD::UMAX:
7886 case ISD::FMINNUM_IEEE:
7887 case ISD::FMAXNUM_IEEE:
7888 case ISD::FMINIMUM:
7889 case ISD::FMAXIMUM:
7890 case ISD::UADDSAT:
7891 case ISD::USUBSAT:
7892 case ISD::SADDSAT:
7893 case ISD::SSUBSAT:
7894 case ISD::FADD:
7895 case ISD::FMUL:
7896 return splitBinaryVectorOp(Op, DAG);
7897 case ISD::FCOPYSIGN:
7898 return lowerFCOPYSIGN(Op, DAG);
7899 case ISD::MUL:
7900 return lowerMUL(Op, DAG);
7901 case ISD::SMULO:
7902 case ISD::UMULO:
7903 return lowerXMULO(Op, DAG);
7904 case ISD::SMUL_LOHI:
7905 case ISD::UMUL_LOHI:
7906 return lowerXMUL_LOHI(Op, DAG);
7908 return LowerDYNAMIC_STACKALLOC(Op, DAG);
7909 case ISD::STACKSAVE:
7910 return LowerSTACKSAVE(Op, DAG);
7911 case ISD::GET_ROUNDING:
7912 return lowerGET_ROUNDING(Op, DAG);
7913 case ISD::SET_ROUNDING:
7914 return lowerSET_ROUNDING(Op, DAG);
7915 case ISD::PREFETCH:
7916 return lowerPREFETCH(Op, DAG);
7917 case ISD::FP_EXTEND:
7919 return lowerFP_EXTEND(Op, DAG);
7920 case ISD::GET_FPENV:
7921 return lowerGET_FPENV(Op, DAG);
7922 case ISD::SET_FPENV:
7923 return lowerSET_FPENV(Op, DAG);
7924 case ISD::ROTR:
7925 return lowerROTR(Op, DAG);
7926 case ISD::INLINEASM:
7927 return LowerINLINEASM(Op, DAG);
7928 }
7929 return SDValue();
7930}
7931
7932// TFE results are dword granular: value dwords followed by one status dword.
7933static std::pair<SDValue, SDValue>
7935 LLVMContext &C = *DAG.getContext();
7936 unsigned NumValueDWords = divideCeil(VT.getSizeInBits(), 32);
7938 DAG.getVectorIdxConstant(NumValueDWords, DL));
7939 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, DL);
7940 SDValue ValueDWords =
7941 NumValueDWords == 1
7942 ? DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op, ZeroIdx)
7944 EVT::getVectorVT(C, MVT::i32, NumValueDWords), Op,
7945 ZeroIdx);
7946 if (!VT.isVector() && VT.getSizeInBits() < 32)
7947 ValueDWords =
7948 DAG.getNode(ISD::TRUNCATE, DL, VT.changeTypeToInteger(), ValueDWords);
7949 return {DAG.getNode(ISD::BITCAST, DL, VT, ValueDWords), Status};
7950}
7951
7952// Used for D16: Casts the result of an instruction into the right vector,
7953// packs values if loads return unpacked values.
7955 const SDLoc &DL, SelectionDAG &DAG,
7956 bool Unpacked) {
7957 if (!LoadVT.isVector())
7958 return Result;
7959
7960 // Cast back to the original packed type or to a larger type that is a
7961 // multiple of 32 bit for D16. Widening the return type is a required for
7962 // legalization.
7963 EVT FittingLoadVT = LoadVT;
7964 if ((LoadVT.getVectorNumElements() % 2) == 1) {
7965 FittingLoadVT =
7967 LoadVT.getVectorNumElements() + 1);
7968 }
7969
7970 if (Unpacked) { // From v2i32/v4i32 back to v2f16/v4f16.
7971 // Truncate to v2i16/v4i16.
7972 EVT IntLoadVT = FittingLoadVT.changeTypeToInteger();
7973
7974 // Workaround legalizer not scalarizing truncate after vector op
7975 // legalization but not creating intermediate vector trunc.
7977 DAG.ExtractVectorElements(Result, Elts);
7978 for (SDValue &Elt : Elts)
7979 Elt = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Elt);
7980
7981 // Pad illegal v1i16/v3fi6 to v4i16
7982 if ((LoadVT.getVectorNumElements() % 2) == 1)
7983 Elts.push_back(DAG.getPOISON(MVT::i16));
7984
7985 Result = DAG.getBuildVector(IntLoadVT, DL, Elts);
7986
7987 // Bitcast to original type (v2f16/v4f16).
7988 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
7989 }
7990
7991 // Cast back to the original packed type.
7992 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
7993}
7994
7995SDValue SITargetLowering::adjustLoadValueType(unsigned Opcode, MemSDNode *M,
7996 SelectionDAG &DAG,
7998 bool IsIntrinsic) const {
7999 SDLoc DL(M);
8000
8001 bool IsTFE = M->getNumValues() == 3;
8002 bool Unpacked = Subtarget->hasUnpackedD16VMem();
8003 EVT LoadVT = M->getValueType(0);
8004
8005 EVT EquivLoadVT = LoadVT;
8006 if (LoadVT.isVector()) {
8007 if (Unpacked) {
8008 EquivLoadVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
8009 LoadVT.getVectorNumElements());
8010 } else if ((LoadVT.getVectorNumElements() % 2) == 1) {
8011 // Widen v3f16 to legal type
8012 EquivLoadVT =
8014 LoadVT.getVectorNumElements() + 1);
8015 }
8016 }
8017
8018 if (IsTFE) {
8019 unsigned NumValueDWords = divideCeil(EquivLoadVT.getSizeInBits(), 32);
8020 EVT LoadDWordsVT =
8021 EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumValueDWords + 1);
8022 SDVTList VTList = DAG.getVTList(LoadDWordsVT, MVT::Other);
8023 SDValue Load = DAG.getMemIntrinsicNode(
8024 Opcode, DL, VTList, Ops, M->getMemoryVT(), M->getMemOperand());
8025 auto [Value, Status] = splitTFEValueAndStatus(Load, EquivLoadVT, DL, DAG);
8026 SDValue Adjusted =
8027 adjustLoadValueTypeImpl(Value, LoadVT, DL, DAG, Unpacked);
8028 return DAG.getMergeValues({Adjusted, Status, Load.getValue(1)}, DL);
8029 }
8030
8031 // Change from v4f16/v2f16 to EquivLoadVT.
8032 SDVTList VTList = DAG.getVTList(EquivLoadVT, MVT::Other);
8033
8034 SDValue Load = DAG.getMemIntrinsicNode(
8035 IsIntrinsic ? (unsigned)ISD::INTRINSIC_W_CHAIN : Opcode, DL, VTList, Ops,
8036 M->getMemoryVT(), M->getMemOperand());
8037
8038 SDValue Adjusted = adjustLoadValueTypeImpl(Load, LoadVT, DL, DAG, Unpacked);
8039
8040 return DAG.getMergeValues({Adjusted, Load.getValue(1)}, DL);
8041}
8042
8043SDValue SITargetLowering::lowerIntrinsicLoad(MemSDNode *M, bool IsFormat,
8044 SelectionDAG &DAG,
8045 ArrayRef<SDValue> Ops) const {
8046 SDLoc DL(M);
8047 EVT LoadVT = M->getValueType(0);
8048 EVT EltType = LoadVT.getScalarType();
8049 EVT IntVT = LoadVT.changeTypeToInteger();
8050
8051 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
8052
8053 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
8054 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
8056 "unsupported sub-dword format buffer load", DL.getDebugLoc()));
8057 return DAG.getMergeValues({DAG.getPOISON(LoadVT), M->getOperand(0)}, DL);
8058 }
8059
8060 assert(M->getNumValues() == 2 || M->getNumValues() == 3);
8061 bool IsTFE = M->getNumValues() == 3;
8062
8063 if (IsD16 && IsTFE && !Subtarget->hasBufferTFEFormatD16()) {
8064 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
8066 "TFE D16 format buffer load is not supported on this GPU",
8067 DL.getDebugLoc()));
8068 return DAG.getErrorMergeValues({M->value_begin(), M->value_end()},
8069 M->getOperand(0), DL);
8070 }
8071
8072 unsigned Opc = IsD16 ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_D16_TFE
8073 : AMDGPUISD::BUFFER_LOAD_FORMAT_D16)
8074 : IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
8075 : AMDGPUISD::BUFFER_LOAD_FORMAT)
8076 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
8077 : AMDGPUISD::BUFFER_LOAD;
8078
8079 if (IsD16)
8080 return adjustLoadValueType(Opc, M, DAG, Ops);
8081
8082 // Handle BUFFER_LOAD_BYTE/UBYTE/SHORT/USHORT overloaded intrinsics
8083 if (!IsD16 && !LoadVT.isVector() && EltType.getSizeInBits() < 32)
8084 return handleByteShortBufferLoads(DAG, LoadVT, DL, Ops, M->getMemOperand(),
8085 IsTFE);
8086
8087 if (isTypeLegal(LoadVT)) {
8088 return getMemIntrinsicNode(Opc, DL, M->getVTList(), Ops, IntVT,
8089 M->getMemOperand(), DAG);
8090 }
8091
8092 EVT CastVT = getEquivalentMemType(*DAG.getContext(), LoadVT);
8093 SDVTList VTList = IsTFE ? DAG.getVTList(CastVT, MVT::i32, MVT::Other)
8094 : DAG.getVTList(CastVT, MVT::Other);
8095 SDValue MemNode = getMemIntrinsicNode(Opc, DL, VTList, Ops, CastVT,
8096 M->getMemOperand(), DAG);
8097 SDValue Data = DAG.getNode(ISD::BITCAST, DL, LoadVT, MemNode);
8098 if (IsTFE)
8099 return DAG.getMergeValues({Data, MemNode.getValue(1), MemNode.getValue(2)},
8100 DL);
8101 return DAG.getMergeValues({Data, MemNode.getValue(1)}, DL);
8102}
8103
8105 SelectionDAG &DAG) {
8106 EVT VT = N->getValueType(0);
8107 SDValue Src = N->getOperand(1);
8108 SDLoc SL(N);
8109
8110 if (Src.getOpcode() == ISD::SETCC) {
8111 SDValue Op0 = Src.getOperand(0);
8112 SDValue Op1 = Src.getOperand(1);
8113 // Need to expand bfloat to float for comparison (setcc).
8114 if (Op0.getValueType() == MVT::bf16) {
8115 Op0 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op0);
8116 Op1 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op1);
8117 }
8118 // (ballot (ISD::SETCC ...)) -> (AMDGPUISD::SETCC ...)
8119 return DAG.getNode(AMDGPUISD::SETCC, SL, VT, Op0, Op1, Src.getOperand(2));
8120 }
8121 if (const ConstantSDNode *Arg = dyn_cast<ConstantSDNode>(Src)) {
8122 // (ballot 0) -> 0
8123 if (Arg->isZero())
8124 return DAG.getConstant(0, SL, VT);
8125
8126 // (ballot 1) -> EXEC/EXEC_LO
8127 if (Arg->isOne()) {
8128 Register Exec;
8129 if (VT.getScalarSizeInBits() == 32)
8130 Exec = AMDGPU::EXEC_LO;
8131 else if (VT.getScalarSizeInBits() == 64)
8132 Exec = AMDGPU::EXEC;
8133 else
8134 return SDValue();
8135
8136 return DAG.getCopyFromReg(DAG.getEntryNode(), SL, Exec, VT);
8137 }
8138 }
8139
8140 // (ballot (i1 $src)) -> (AMDGPUISD::SETCC (i32 (zext $src)) (i32 0)
8141 // ISD::SETNE)
8142 return DAG.getNode(
8143 AMDGPUISD::SETCC, SL, VT, DAG.getZExtOrTrunc(Src, SL, MVT::i32),
8144 DAG.getConstant(0, SL, MVT::i32), DAG.getCondCode(ISD::SETNE));
8145}
8146
8148 Intrinsic::ID IntrinsicID) {
8149 bool Signed = IntrinsicID == Intrinsic::amdgcn_sbfe;
8150 SDLoc DL(Op);
8151 EVT VT = Op.getValueType();
8152 SDValue Src = Op.getOperand(1);
8153 SDValue Offset = Op.getOperand(2);
8154 SDValue Width = Op.getOperand(3);
8155
8156 if (VT != MVT::i32) {
8159 Twine(Intrinsic::getBaseName(IntrinsicID)) + " only supports i32",
8160 DL.getDebugLoc()));
8161 return DAG.getPOISON(VT);
8162 }
8163
8164 return DAG.getNode(Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32, DL, VT,
8165 Src, Offset, Width);
8166}
8167
8169 EVT VT);
8170
8172 SelectionDAG &DAG) {
8173 EVT VT = N->getValueType(0);
8174 unsigned ValSize = VT.getSizeInBits();
8175 unsigned IID = N->getConstantOperandVal(0);
8176 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8177 IID == Intrinsic::amdgcn_permlanex16;
8178 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8179 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8180 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8181 IID == Intrinsic::amdgcn_permlane_up ||
8182 IID == Intrinsic::amdgcn_permlane_down ||
8183 IID == Intrinsic::amdgcn_permlane_xor;
8184 SDLoc SL(N);
8185 MVT IntVT = MVT::getIntegerVT(ValSize);
8186 const GCNSubtarget *ST = TLI.getSubtarget();
8187
8188 unsigned SplitSize = 32;
8189 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8190 ST->hasDPALU_DPP() &&
8191 AMDGPU::isLegalDPALU_DPPControl(*ST, N->getConstantOperandVal(3)))
8192 SplitSize = 64;
8193
8194 auto createLaneOp = [&DAG, &SL, N, IID](SDValue Src0, SDValue Src1,
8195 SDValue Src2, MVT ValT) -> SDValue {
8197 switch (IID) {
8198 case Intrinsic::amdgcn_permlane16:
8199 case Intrinsic::amdgcn_permlanex16:
8200 case Intrinsic::amdgcn_update_dpp:
8201 Operands.push_back(N->getOperand(6));
8202 Operands.push_back(N->getOperand(5));
8203 Operands.push_back(N->getOperand(4));
8204 [[fallthrough]];
8205 case Intrinsic::amdgcn_writelane:
8206 case Intrinsic::amdgcn_permlane_bcast:
8207 case Intrinsic::amdgcn_permlane_up:
8208 case Intrinsic::amdgcn_permlane_down:
8209 case Intrinsic::amdgcn_permlane_xor:
8210 Operands.push_back(Src2);
8211 [[fallthrough]];
8212 case Intrinsic::amdgcn_readlane:
8213 case Intrinsic::amdgcn_set_inactive:
8214 case Intrinsic::amdgcn_set_inactive_chain_arg:
8215 case Intrinsic::amdgcn_mov_dpp8:
8216 Operands.push_back(Src1);
8217 [[fallthrough]];
8218 case Intrinsic::amdgcn_readfirstlane:
8219 case Intrinsic::amdgcn_permlane64:
8220 Operands.push_back(Src0);
8221 break;
8222 default:
8223 llvm_unreachable("unhandled lane op");
8224 }
8225
8226 Operands.push_back(DAG.getTargetConstant(IID, SL, MVT::i32));
8227 std::reverse(Operands.begin(), Operands.end());
8228
8229 if (SDNode *GL = N->getGluedNode()) {
8230 assert(GL->getOpcode() == ISD::CONVERGENCECTRL_GLUE);
8231 GL = GL->getOperand(0).getNode();
8232 Operands.push_back(DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8233 SDValue(GL, 0)));
8234 }
8235
8236 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, ValT, Operands);
8237 };
8238
8239 SDValue Src0 = N->getOperand(1);
8240 SDValue Src1, Src2;
8241 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8242 IID == Intrinsic::amdgcn_mov_dpp8 ||
8243 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8244 IsPermlaneShuffle) {
8245 Src1 = N->getOperand(2);
8246 if (IID == Intrinsic::amdgcn_writelane ||
8247 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8248 IsPermlaneShuffle)
8249 Src2 = N->getOperand(3);
8250 }
8251
8252 if (ValSize == SplitSize) {
8253 // Already legal
8254 return SDValue();
8255 }
8256
8257 if (ValSize < 32) {
8258 bool IsFloat = VT.isFloatingPoint();
8259 Src0 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src0) : Src0,
8260 SL, MVT::i32);
8261
8262 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8263 Src1 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src1) : Src1,
8264 SL, MVT::i32);
8265 }
8266
8267 if (IID == Intrinsic::amdgcn_writelane) {
8268 Src2 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src2) : Src2,
8269 SL, MVT::i32);
8270 }
8271
8272 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8273 SDValue Trunc = DAG.getAnyExtOrTrunc(LaneOp, SL, IntVT);
8274 return IsFloat ? DAG.getBitcast(VT, Trunc) : Trunc;
8275 }
8276
8277 if (ValSize % SplitSize != 0)
8278 return SDValue();
8279
8280 auto unrollLaneOp = [&DAG, &SL](SDNode *N) -> SDValue {
8281 EVT VT = N->getValueType(0);
8282 unsigned NE = VT.getVectorNumElements();
8283 EVT EltVT = VT.getVectorElementType();
8285 unsigned NumOperands = N->getNumOperands();
8286 SmallVector<SDValue, 4> Operands(NumOperands);
8287 SDNode *GL = N->getGluedNode();
8288
8289 // only handle convergencectrl_glue
8291
8292 for (unsigned i = 0; i != NE; ++i) {
8293 for (unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8294 ++j) {
8295 SDValue Operand = N->getOperand(j);
8296 EVT OperandVT = Operand.getValueType();
8297 if (OperandVT.isVector()) {
8298 // A vector operand; extract a single element.
8299 EVT OperandEltVT = OperandVT.getVectorElementType();
8300 Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, OperandEltVT,
8301 Operand, DAG.getVectorIdxConstant(i, SL));
8302 } else {
8303 // A scalar operand; just use it as is.
8304 Operands[j] = Operand;
8305 }
8306 }
8307
8308 if (GL)
8309 Operands[NumOperands - 1] =
8310 DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8311 SDValue(GL->getOperand(0).getNode(), 0));
8312
8313 Scalars.push_back(DAG.getNode(N->getOpcode(), SL, EltVT, Operands));
8314 }
8315
8316 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NE);
8317 return DAG.getBuildVector(VecVT, SL, Scalars);
8318 };
8319
8320 if (VT.isVector()) {
8321 switch (MVT::SimpleValueType EltTy =
8323 case MVT::i32:
8324 case MVT::f32:
8325 if (SplitSize == 32) {
8326 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VT.getSimpleVT());
8327 return unrollLaneOp(LaneOp.getNode());
8328 }
8329 [[fallthrough]];
8330 case MVT::i16:
8331 case MVT::f16:
8332 case MVT::bf16: {
8333 unsigned SubVecNumElt =
8334 SplitSize / VT.getVectorElementType().getSizeInBits();
8335 MVT SubVecVT = MVT::getVectorVT(EltTy, SubVecNumElt);
8337 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8338 for (unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8339 Src0SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src0,
8340 DAG.getConstant(EltIdx, SL, MVT::i32));
8341
8342 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8343 IsPermLane16) {
8344 Src1SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src1,
8345 DAG.getConstant(EltIdx, SL, MVT::i32));
8346
8347 Pieces.push_back(
8348 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8349 } else if (IID == Intrinsic::amdgcn_writelane) {
8350 Src2SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src2,
8351 DAG.getConstant(EltIdx, SL, MVT::i32));
8352 Pieces.push_back(
8353 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8354 } else {
8355 Pieces.push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8356 }
8357
8358 EltIdx += SubVecNumElt;
8359 }
8360 return DAG.getNode(ISD::CONCAT_VECTORS, SL, VT, Pieces);
8361 }
8362 default:
8363 // Handle all other cases by bitcasting to i32 vectors
8364 break;
8365 }
8366 }
8367
8368 MVT VecVT =
8369 MVT::getVectorVT(MVT::getIntegerVT(SplitSize), ValSize / SplitSize);
8370 Src0 = DAG.getBitcast(VecVT, Src0);
8371
8372 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8373 Src1 = DAG.getBitcast(VecVT, Src1);
8374
8375 if (IID == Intrinsic::amdgcn_writelane)
8376 Src2 = DAG.getBitcast(VecVT, Src2);
8377
8378 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8379 SDValue UnrolledLaneOp = unrollLaneOp(LaneOp.getNode());
8380 return DAG.getBitcast(VT, UnrolledLaneOp);
8381}
8382
8384 SelectionDAG &DAG) {
8385 EVT VT = N->getValueType(0);
8386
8387 if (VT.getSizeInBits() != 32)
8388 return SDValue();
8389
8390 SDLoc SL(N);
8391
8392 SDValue Value = N->getOperand(1);
8393 SDValue Index = N->getOperand(2);
8394
8395 // ds_bpermute requires index to be multiplied by 4
8396 SDValue ShiftAmount = DAG.getShiftAmountConstant(2, MVT::i32, SL);
8397 SDValue ShiftedIndex =
8398 DAG.getNode(ISD::SHL, SL, Index.getValueType(), Index, ShiftAmount);
8399
8400 // Intrinsics will require i32 to operate on
8401 SDValue ValueI32 = DAG.getBitcast(MVT::i32, Value);
8402
8403 auto MakeIntrinsic = [&DAG, &SL](unsigned IID, MVT RetVT,
8404 SmallVector<SDValue> IntrinArgs) -> SDValue {
8406 Operands[0] = DAG.getTargetConstant(IID, SL, MVT::i32);
8407 Operands.append(IntrinArgs);
8408 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, RetVT, Operands);
8409 };
8410
8411 // If we can bpermute across the whole wave, then just do that
8413 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8414 {ShiftedIndex, ValueI32});
8415 return DAG.getBitcast(VT, BPermute);
8416 }
8417
8418 assert(TLI.getSubtarget()->isWave64());
8419
8420 // Otherwise, we need to make use of whole wave mode
8421 SDValue PoisonVal = DAG.getPOISON(ValueI32->getValueType(0));
8422
8423 // Set inactive lanes to poison
8424 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8425 {ValueI32, PoisonVal});
8426 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8427 {ShiftedIndex, PoisonVal});
8428
8429 SDValue Swapped =
8430 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8431
8432 // Get permutation of each half, then we'll select which one to use
8433 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8434 {WWMIndex, WWMValue});
8435 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8436 MVT::i32, {WWMIndex, Swapped});
8437 SDValue BPermOtherHalfWWM =
8438 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8439
8440 // Select which side to take the permute from
8441 SDValue ThreadIDMask = DAG.getAllOnesConstant(SL, MVT::i32);
8442 // We can get away with only using mbcnt_lo here since we're only
8443 // trying to detect which side of 32 each lane is on, and mbcnt_lo
8444 // returns 32 for lanes 32-63.
8445 SDValue ThreadID =
8446 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8447 {ThreadIDMask, DAG.getTargetConstant(0, SL, MVT::i32)});
8448
8449 SDValue SameOrOtherHalf =
8450 DAG.getNode(ISD::AND, SL, MVT::i32,
8451 DAG.getNode(ISD::XOR, SL, MVT::i32, ThreadID, Index),
8452 DAG.getTargetConstant(32, SL, MVT::i32));
8453 SDValue UseSameHalf =
8454 DAG.getSetCC(SL, MVT::i1, SameOrOtherHalf,
8455 DAG.getConstant(0, SL, MVT::i32), ISD::SETEQ);
8456 SDValue Result = DAG.getSelect(SL, MVT::i32, UseSameHalf, BPermSameHalf,
8457 BPermOtherHalfWWM);
8458 return DAG.getBitcast(VT, Result);
8459}
8460
8463 SelectionDAG &DAG) const {
8464 switch (N->getOpcode()) {
8466 if (SDValue Res = lowerINSERT_VECTOR_ELT(SDValue(N, 0), DAG))
8467 Results.push_back(Res);
8468 return;
8469 }
8471 if (SDValue Res = lowerEXTRACT_VECTOR_ELT(SDValue(N, 0), DAG))
8472 Results.push_back(Res);
8473 return;
8474 }
8476 if (SDValue Res = LowerCONVERT_TO_ARBITRARY_FP(SDValue(N, 0), DAG))
8477 Results.push_back(Res);
8478 return;
8479 }
8481 unsigned IID = N->getConstantOperandVal(0);
8482 switch (IID) {
8483 case Intrinsic::amdgcn_wave_reduce_min:
8484 case Intrinsic::amdgcn_wave_reduce_umin:
8485 case Intrinsic::amdgcn_wave_reduce_max:
8486 case Intrinsic::amdgcn_wave_reduce_umax:
8487 case Intrinsic::amdgcn_wave_reduce_add:
8488 case Intrinsic::amdgcn_wave_reduce_sub:
8489 case Intrinsic::amdgcn_wave_reduce_and:
8490 case Intrinsic::amdgcn_wave_reduce_or:
8491 case Intrinsic::amdgcn_wave_reduce_xor: {
8492 EVT VT = N->getValueType(0);
8493 if (isTypeLegal(VT))
8494 return;
8495 SDLoc SL(N);
8496 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8497 IID == Intrinsic::amdgcn_wave_reduce_max ||
8498 IID == Intrinsic::amdgcn_wave_reduce_add ||
8499 IID == Intrinsic::amdgcn_wave_reduce_sub;
8500 unsigned ExtOpc = NeedsSignExt ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
8501 SDValue ExtSrc = DAG.getNode(ExtOpc, SL, MVT::i32, N->getOperand(1));
8502 SDValue Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
8503 N->getOperand(0), ExtSrc, N->getOperand(2));
8504 Results.push_back(DAG.getNode(ISD::TRUNCATE, SL, VT, Result));
8505 return;
8506 }
8507 case Intrinsic::amdgcn_make_buffer_rsrc:
8508 Results.push_back(lowerPointerAsRsrcIntrin(N, DAG));
8509 return;
8510 case Intrinsic::amdgcn_cvt_pkrtz: {
8511 SDValue Src0 = N->getOperand(1);
8512 SDValue Src1 = N->getOperand(2);
8513 SDLoc SL(N);
8514 SDValue Cvt =
8515 DAG.getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8516 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Cvt));
8517 return;
8518 }
8519 case Intrinsic::amdgcn_cvt_pknorm_i16:
8520 case Intrinsic::amdgcn_cvt_pknorm_u16:
8521 case Intrinsic::amdgcn_cvt_pk_i16:
8522 case Intrinsic::amdgcn_cvt_pk_u16: {
8523 SDValue Src0 = N->getOperand(1);
8524 SDValue Src1 = N->getOperand(2);
8525 SDLoc SL(N);
8526 unsigned Opcode;
8527
8528 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8529 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8530 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8531 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8532 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8533 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8534 else
8535 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8536
8537 EVT VT = N->getValueType(0);
8538 if (isTypeLegal(VT))
8539 Results.push_back(DAG.getNode(Opcode, SL, VT, Src0, Src1));
8540 else {
8541 SDValue Cvt = DAG.getNode(Opcode, SL, MVT::i32, Src0, Src1);
8542 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, Cvt));
8543 }
8544 return;
8545 }
8546 case Intrinsic::amdgcn_s_buffer_load: {
8547 SDValue Op = SDValue(N, 0);
8548 EVT VT = Op.getValueType();
8549 Results.push_back(lowerSBuffer(VT, VT, SDLoc(Op), DAG.getEntryNode(),
8550 Op.getOperand(1), Op.getOperand(2),
8551 Op.getOperand(3), DAG));
8552 return;
8553 }
8554 case Intrinsic::amdgcn_dead: {
8555 for (unsigned I = 0, E = N->getNumValues(); I < E; ++I)
8556 Results.push_back(DAG.getPOISON(N->getValueType(I)));
8557 return;
8558 }
8559 }
8560 break;
8561 }
8563 if (N->getConstantOperandVal(1) != Intrinsic::amdgcn_ptr_s_buffer_load &&
8564 N->getValueType(0).isSimple() &&
8565 SBufferLoadDiagnosticVTs[N->getSimpleValueType(0).SimpleTy])
8566 break;
8567 if (SDValue Res = LowerINTRINSIC_W_CHAIN(SDValue(N, 0), DAG)) {
8568 if (Res.getOpcode() == ISD::MERGE_VALUES) {
8569 // FIXME: Hacky
8570 for (unsigned I = 0; I < Res.getNumOperands(); I++) {
8571 Results.push_back(Res.getOperand(I));
8572 }
8573 } else {
8574 for (unsigned I = 0; I < N->getNumValues(); ++I)
8575 Results.push_back(Res.getValue(I));
8576 }
8577 return;
8578 }
8579
8580 break;
8581 }
8582 case ISD::SELECT: {
8583 SDLoc SL(N);
8584 EVT VT = N->getValueType(0);
8585 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
8586 SDValue LHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(1));
8587 SDValue RHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(2));
8588
8589 EVT SelectVT = NewVT;
8590 if (NewVT.bitsLT(MVT::i32)) {
8591 LHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, LHS);
8592 RHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, RHS);
8593 SelectVT = MVT::i32;
8594 }
8595
8596 SDValue NewSelect =
8597 DAG.getNode(ISD::SELECT, SL, SelectVT, N->getOperand(0), LHS, RHS);
8598
8599 if (NewVT != SelectVT)
8600 NewSelect = DAG.getNode(ISD::TRUNCATE, SL, NewVT, NewSelect);
8601 Results.push_back(DAG.getNode(ISD::BITCAST, SL, VT, NewSelect));
8602 return;
8603 }
8604 case ISD::FNEG: {
8605 if (N->getValueType(0) != MVT::v2f16)
8606 break;
8607
8608 SDLoc SL(N);
8609 SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::i32, N->getOperand(0));
8610
8611 SDValue Op = DAG.getNode(ISD::XOR, SL, MVT::i32, BC,
8612 DAG.getConstant(0x80008000, SL, MVT::i32));
8613 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8614 return;
8615 }
8616 case ISD::FABS: {
8617 if (N->getValueType(0) != MVT::v2f16)
8618 break;
8619
8620 SDLoc SL(N);
8621 SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::i32, N->getOperand(0));
8622
8623 SDValue Op = DAG.getNode(ISD::AND, SL, MVT::i32, BC,
8624 DAG.getConstant(0x7fff7fff, SL, MVT::i32));
8625 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8626 return;
8627 }
8628 case ISD::FSQRT: {
8629 if (N->getValueType(0) != MVT::f16)
8630 break;
8631 Results.push_back(lowerFSQRTF16(SDValue(N, 0), DAG));
8632 break;
8633 }
8634 default:
8636 break;
8637 }
8638}
8639
8640/// Helper function for LowerBRCOND
8641static SDNode *findUser(SDValue Value, unsigned Opcode) {
8642
8643 for (SDUse &U : Value->uses()) {
8644 if (U.get() != Value)
8645 continue;
8646
8647 if (U.getUser()->getOpcode() == Opcode)
8648 return U.getUser();
8649 }
8650 return nullptr;
8651}
8652
8653unsigned SITargetLowering::isCFIntrinsic(const SDNode *Intr) const {
8654 if (Intr->getOpcode() == ISD::INTRINSIC_W_CHAIN) {
8655 switch (Intr->getConstantOperandVal(1)) {
8656 case Intrinsic::amdgcn_if:
8657 return AMDGPUISD::IF;
8658 case Intrinsic::amdgcn_else:
8659 return AMDGPUISD::ELSE;
8660 case Intrinsic::amdgcn_loop:
8661 return AMDGPUISD::LOOP;
8662 case Intrinsic::amdgcn_end_cf:
8663 llvm_unreachable("should not occur");
8664 default:
8665 return 0;
8666 }
8667 }
8668
8669 // break, if_break, else_break are all only used as inputs to loop, not
8670 // directly as branch conditions.
8671 return 0;
8672}
8673
8680
8682 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8683 return false;
8684
8685 // FIXME: Either avoid relying on address space here or change the default
8686 // address space for functions to avoid the explicit check.
8687 return (GV->getValueType()->isFunctionTy() ||
8690}
8691
8693 return !shouldEmitFixup(GV) && !shouldEmitGOTReloc(GV);
8694}
8695
8697 if (!GV->hasExternalLinkage())
8698 return true;
8699
8700 // With object linking, external LDS declarations need relocations so the
8701 // linker can assign their offsets.
8703 if (const auto *GVar = dyn_cast<GlobalVariable>(GV)) {
8704 if (GVar->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
8705 GVar->getAddressSpace() == AMDGPUAS::BARRIER) {
8706 assert(GVar->isDeclaration() &&
8707 "AS 3 & 13 GVs should be declaration here "
8708 "when object linking is enabled");
8709 return false;
8710 }
8711 }
8712 }
8713
8714 const auto OS = getTargetMachine().getTargetTriple().getOS();
8715 return OS == Triple::AMDHSA || OS == Triple::AMDPAL;
8716}
8717
8718/// This transforms the control flow intrinsics to get the branch destination as
8719/// last parameter, also switches branch target with BR if the need arise
8720SDValue SITargetLowering::LowerBRCOND(SDValue BRCOND, SelectionDAG &DAG) const {
8721 SDLoc DL(BRCOND);
8722
8723 SDNode *Intr = BRCOND.getOperand(1).getNode();
8724 SDValue Target = BRCOND.getOperand(2);
8725 SDNode *BR = nullptr;
8726 SDNode *SetCC = nullptr;
8727
8728 switch (Intr->getOpcode()) {
8729 case ISD::SETCC: {
8730 // As long as we negate the condition everything is fine
8731 SetCC = Intr;
8732 Intr = SetCC->getOperand(0).getNode();
8733 break;
8734 }
8735 case ISD::XOR: {
8736 // Similar to SETCC, if we have (xor c, -1), we will be fine.
8737 SDValue LHS = Intr->getOperand(0);
8738 SDValue RHS = Intr->getOperand(1);
8739 if (auto *C = dyn_cast<ConstantSDNode>(RHS); C && C->getZExtValue()) {
8740 Intr = LHS.getNode();
8741 break;
8742 }
8743 [[fallthrough]];
8744 }
8745 default: {
8746 // Get the target from BR if we don't negate the condition
8747 BR = findUser(BRCOND, ISD::BR);
8748 assert(BR && "brcond missing unconditional branch user");
8749 Target = BR->getOperand(1);
8750 }
8751 }
8752
8753 unsigned CFNode = isCFIntrinsic(Intr);
8754 if (CFNode == 0) {
8755 // This is a uniform branch so we don't need to legalize.
8756 return BRCOND;
8757 }
8758
8759 bool HaveChain = Intr->getOpcode() == ISD::INTRINSIC_VOID ||
8761
8762 assert(!SetCC ||
8763 (SetCC->getConstantOperandVal(1) == 1 &&
8764 cast<CondCodeSDNode>(SetCC->getOperand(2).getNode())->get() ==
8765 ISD::SETNE));
8766
8767 // operands of the new intrinsic call
8769 if (HaveChain)
8770 Ops.push_back(BRCOND.getOperand(0));
8771
8772 Ops.append(Intr->op_begin() + (HaveChain ? 2 : 1), Intr->op_end());
8773 Ops.push_back(Target);
8774
8775 ArrayRef<EVT> Res(Intr->value_begin() + 1, Intr->value_end());
8776
8777 // build the new intrinsic call
8778 SDNode *Result = DAG.getNode(CFNode, DL, DAG.getVTList(Res), Ops).getNode();
8779
8780 if (!HaveChain) {
8781 SDValue Ops[] = {SDValue(Result, 0), BRCOND.getOperand(0)};
8782
8784 }
8785
8786 if (BR) {
8787 // Give the branch instruction our target
8788 SDValue Ops[] = {BR->getOperand(0), BRCOND.getOperand(2)};
8789 SDValue NewBR = DAG.getNode(ISD::BR, DL, BR->getVTList(), Ops);
8790 DAG.ReplaceAllUsesWith(BR, NewBR.getNode());
8791 }
8792
8793 SDValue Chain = SDValue(Result, Result->getNumValues() - 1);
8794
8795 // Copy the intrinsic results to registers
8796 for (unsigned i = 1, e = Intr->getNumValues() - 1; i != e; ++i) {
8797 SDNode *CopyToReg = findUser(SDValue(Intr, i), ISD::CopyToReg);
8798 if (!CopyToReg)
8799 continue;
8800
8801 Chain = DAG.getCopyToReg(Chain, DL, CopyToReg->getOperand(1),
8802 SDValue(Result, i - 1), SDValue());
8803
8804 DAG.ReplaceAllUsesWith(SDValue(CopyToReg, 0), CopyToReg->getOperand(0));
8805 }
8806
8807 // Remove the old intrinsic from the chain
8808 DAG.ReplaceAllUsesOfValueWith(SDValue(Intr, Intr->getNumValues() - 1),
8809 Intr->getOperand(0));
8810
8811 return Chain;
8812}
8813
8814SDValue SITargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
8815 MVT VT = Op.getSimpleValueType();
8816 SDLoc DL(Op);
8817 // Checking the depth
8818 if (Op.getConstantOperandVal(0) != 0)
8819 return DAG.getConstant(0, DL, VT);
8820
8822 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8823 // Check for kernel and shader functions
8824 if (Info->isEntryFunction())
8825 return DAG.getConstant(0, DL, VT);
8826
8827 MachineFrameInfo &MFI = MF.getFrameInfo();
8828 // There is a call to @llvm.returnaddress in this function
8829 MFI.setReturnAddressIsTaken(true);
8830
8831 const SIRegisterInfo *TRI = getSubtarget()->getRegisterInfo();
8832 // Get the return address reg and mark it as an implicit live-in
8833 Register Reg = MF.addLiveIn(TRI->getReturnAddressReg(MF),
8834 getRegClassFor(VT, Op.getNode()->isDivergent()));
8835
8836 return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT);
8837}
8838
8839SDValue SITargetLowering::LowerSPONENTRY(SDValue Op, SelectionDAG &DAG) const {
8841 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
8842
8843 // For functions that set up their own stack, select the GET_STACK_BASE
8844 // pseudo.
8845 if (MFI->isBottomOfStack())
8846 return Op;
8847
8848 // For everything else, create a dummy stack object.
8849 int FI = MF.getFrameInfo().CreateFixedObject(1, 0, /*IsImmutable=*/false);
8850 return DAG.getFrameIndex(FI, Op.getValueType());
8851}
8852
8853SDValue SITargetLowering::getFPExtOrFPRound(SelectionDAG &DAG, SDValue Op,
8854 const SDLoc &DL, EVT VT) const {
8855 return Op.getValueType().bitsLE(VT)
8856 ? DAG.getNode(ISD::FP_EXTEND, DL, VT, Op)
8857 : DAG.getNode(ISD::FP_ROUND, DL, VT, Op,
8858 DAG.getTargetConstant(0, DL, MVT::i32));
8859}
8860
8861SDValue SITargetLowering::splitFP_ROUNDVectorOp(SDValue Op,
8862 SelectionDAG &DAG) const {
8863 EVT DstVT = Op.getValueType();
8864 unsigned NumElts = DstVT.getVectorNumElements();
8865 assert(NumElts > 2 && isPowerOf2_32(NumElts));
8866
8867 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
8868
8869 SDLoc DL(Op);
8870 unsigned Opc = Op.getOpcode();
8871 SDValue Flags = Op.getOperand(1);
8872 EVT HalfDstVT =
8873 EVT::getVectorVT(*DAG.getContext(), DstVT.getScalarType(), NumElts / 2);
8874 SDValue OpLo = DAG.getNode(Opc, DL, HalfDstVT, Lo, Flags);
8875 SDValue OpHi = DAG.getNode(Opc, DL, HalfDstVT, Hi, Flags);
8876
8877 return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, OpLo, OpHi);
8878}
8879
8880SDValue SITargetLowering::lowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const {
8881 bool IsStrict = Op->isStrictFPOpcode();
8882 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
8883 EVT SrcVT = Src.getValueType();
8884 EVT DstVT = Op.getValueType();
8885
8886 if (DstVT.isVectorOf(MVT::f16)) {
8887 assert(Subtarget->hasCvtPkF16F32Inst() && "support v_cvt_pk_f16_f32");
8888 if (SrcVT.getScalarType() != MVT::f32)
8889 return SDValue();
8890 return SrcVT == MVT::v2f32 ? Op : splitFP_ROUNDVectorOp(Op, DAG);
8891 }
8892
8893 if (SrcVT.getScalarType() != MVT::f64)
8894 return Op;
8895
8896 SDLoc DL(Op);
8897 if (DstVT == MVT::f16) {
8898 // TODO: Handle strictfp
8899 if (Op.getOpcode() != ISD::FP_ROUND)
8900 return Op;
8901
8902 if (!Subtarget->has16BitInsts()) {
8903 SDValue FpToFp16 = DAG.getNode(ISD::FP_TO_FP16, DL, MVT::i32, Src);
8904 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8905 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8906 }
8907 if (Op->getFlags().hasApproximateFuncs()) {
8908 SDValue Flags = Op.getOperand(1);
8909 SDValue Src32 = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, Src, Flags);
8910 return DAG.getNode(ISD::FP_ROUND, DL, MVT::f16, Src32, Flags);
8911 }
8912 SDValue FpToFp16 = LowerF64ToF16Safe(Src, DL, DAG);
8913 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8914 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8915 }
8916
8917 assert(DstVT.getScalarType() == MVT::bf16 &&
8918 "custom lower FP_ROUND for f16 or bf16");
8919 assert(Subtarget->hasBF16ConversionInsts() && "f32 -> bf16 is legal");
8920
8921 // Round-inexact-to-odd f64 to f32, then do the final rounding using the
8922 // hardware f32 -> bf16 instruction.
8923 EVT F32VT = SrcVT.changeElementType(*DAG.getContext(), MVT::f32);
8924 SDValue Rod = expandRoundInexactToOdd(F32VT, Src, DL, DAG);
8925 if (IsStrict) {
8926 return DAG.getNode(
8927 ISD::STRICT_FP_ROUND, DL, {DstVT, MVT::Other},
8928 {Op.getOperand(0), Rod, DAG.getTargetConstant(0, DL, MVT::i32)});
8929 }
8930 return DAG.getNode(ISD::FP_ROUND, DL, DstVT, Rod,
8931 DAG.getTargetConstant(0, DL, MVT::i32));
8932}
8933
8934SDValue SITargetLowering::lowerFMINNUM_FMAXNUM(SDValue Op,
8935 SelectionDAG &DAG) const {
8936 EVT VT = Op.getValueType();
8937 const MachineFunction &MF = DAG.getMachineFunction();
8938 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8939 bool IsIEEEMode = Info->getMode().IEEE;
8940
8941 // FIXME: Assert during selection that this is only selected for
8942 // ieee_mode. Currently a combine can produce the ieee version for non-ieee
8943 // mode functions, but this happens to be OK since it's only done in cases
8944 // where there is known no sNaN.
8945 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8946 return expandFMINNUM_FMAXNUM(Op.getNode(), DAG);
8947
8948 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8949 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8950 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8951 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8952 return splitBinaryVectorOp(Op, DAG);
8953 return Op;
8954}
8955
8956SDValue
8957SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(SDValue Op,
8958 SelectionDAG &DAG) const {
8959 EVT VT = Op.getValueType();
8960 const MachineFunction &MF = DAG.getMachineFunction();
8961 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8962 bool IsIEEEMode = Info->getMode().IEEE;
8963
8964 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8965 return expandFMINIMUMNUM_FMAXIMUMNUM(Op.getNode(), DAG);
8966
8967 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8968 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8969 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8970 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8971 return splitBinaryVectorOp(Op, DAG);
8972 return Op;
8973}
8974
8975SDValue SITargetLowering::lowerFLDEXP(SDValue Op, SelectionDAG &DAG) const {
8976 bool IsStrict = Op.getOpcode() == ISD::STRICT_FLDEXP;
8977 EVT VT = Op.getValueType();
8978 assert(VT == MVT::f16);
8979
8980 SDValue Exp = Op.getOperand(IsStrict ? 2 : 1);
8981 EVT ExpVT = Exp.getValueType();
8982 if (ExpVT == MVT::i16)
8983 return Op;
8984
8985 SDLoc DL(Op);
8986
8987 // Correct the exponent type for f16 to i16.
8988 // Clamp the range of the exponent to the instruction's range.
8989
8990 // TODO: This should be a generic narrowing legalization, and can easily be
8991 // for GlobalISel.
8992
8993 SDValue MinExp = DAG.getSignedConstant(minIntN(16), DL, ExpVT);
8994 SDValue ClampMin = DAG.getNode(ISD::SMAX, DL, ExpVT, Exp, MinExp);
8995
8996 SDValue MaxExp = DAG.getSignedConstant(maxIntN(16), DL, ExpVT);
8997 SDValue Clamp = DAG.getNode(ISD::SMIN, DL, ExpVT, ClampMin, MaxExp);
8998
8999 SDValue TruncExp = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Clamp);
9000
9001 if (IsStrict) {
9002 return DAG.getNode(ISD::STRICT_FLDEXP, DL, {VT, MVT::Other},
9003 {Op.getOperand(0), Op.getOperand(1), TruncExp});
9004 }
9005
9006 return DAG.getNode(ISD::FLDEXP, DL, VT, Op.getOperand(0), TruncExp);
9007}
9008
9010 switch (Op->getOpcode()) {
9011 case ISD::ABS:
9012 case ISD::SRA:
9013 case ISD::SMIN:
9014 case ISD::SMAX:
9015 return ISD::SIGN_EXTEND;
9016 case ISD::SRL:
9017 case ISD::UMIN:
9018 case ISD::UMAX:
9019 case ISD::USUBSAT:
9020 case ISD::UADDSAT:
9021 return ISD::ZERO_EXTEND;
9022 case ISD::ADD:
9023 case ISD::SUB:
9024 case ISD::AND:
9025 case ISD::OR:
9026 case ISD::XOR:
9027 case ISD::SHL:
9028 case ISD::SELECT:
9029 case ISD::MUL:
9030 // operation result won't be influenced by garbage high bits.
9031 // TODO: are all of those cases correct, and are there more?
9032 return ISD::ANY_EXTEND;
9033 case ISD::SETCC: {
9034 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
9036 }
9037 default:
9038 llvm_unreachable("unexpected opcode!");
9039 }
9040}
9041
9042SDValue
9043SITargetLowering::promoteUniformUnaryOpToI32(SDValue Op,
9044 DAGCombinerInfo &DCI) const {
9045 EVT OpTy = Op.getValueType();
9046 SelectionDAG &DAG = DCI.DAG;
9047 EVT ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
9048
9049 if (isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
9050 return SDValue();
9051
9052 SDLoc DL(Op);
9053 SDValue Input = Op.getOperand(0);
9054 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
9055 Input = DAG.getNode(ExtOp, DL, ExtTy, Input);
9056
9057 SDValue NewVal = DAG.getNode(Op.getOpcode(), DL, ExtTy, Input);
9058
9059 return DAG.getNode(ISD::TRUNCATE, DL, OpTy, NewVal);
9060}
9061
9062SDValue SITargetLowering::promoteUniformOpToI32(SDValue Op,
9063 DAGCombinerInfo &DCI) const {
9064 const unsigned Opc = Op.getOpcode();
9065 assert(Opc == ISD::ADD || Opc == ISD::SUB || Opc == ISD::SHL ||
9066 Opc == ISD::SRL || Opc == ISD::SRA || Opc == ISD::AND ||
9067 Opc == ISD::OR || Opc == ISD::XOR || Opc == ISD::MUL ||
9068 Opc == ISD::SETCC || Opc == ISD::SELECT || Opc == ISD::SMIN ||
9069 Opc == ISD::SMAX || Opc == ISD::UMIN || Opc == ISD::UMAX ||
9070 Opc == ISD::USUBSAT || Opc == ISD::UADDSAT);
9071
9072 EVT OpTy = (Opc != ISD::SETCC) ? Op.getValueType()
9073 : Op->getOperand(0).getValueType();
9074 auto &DAG = DCI.DAG;
9075 auto ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
9076
9077 if (DCI.isBeforeLegalizeOps() ||
9078 isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
9079 return SDValue();
9080
9081 SDLoc DL(Op);
9082 SDValue LHS;
9083 SDValue RHS;
9084 if (Opc == ISD::SELECT) {
9085 LHS = Op->getOperand(1);
9086 RHS = Op->getOperand(2);
9087 } else {
9088 LHS = Op->getOperand(0);
9089 RHS = Op->getOperand(1);
9090 }
9091
9092 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
9093 LHS = DAG.getNode(ExtOp, DL, ExtTy, {LHS});
9094
9095 // Special case: for shifts, the RHS always needs a zext.
9096 if (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA)
9097 RHS = DAG.getNode(ISD::ZERO_EXTEND, DL, ExtTy, {RHS});
9098 else
9099 RHS = DAG.getNode(ExtOp, DL, ExtTy, {RHS});
9100
9101 // setcc always return i1/i1 vec so no need to truncate after.
9102 if (Opc == ISD::SETCC) {
9103 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
9104 return DAG.getSetCC(DL, Op.getValueType(), LHS, RHS, CC);
9105 }
9106
9107 // For other ops, we extend the operation's return type as well so we need to
9108 // truncate back to the original type.
9109 SDValue NewVal;
9110 if (Opc == ISD::SELECT)
9111 NewVal = DAG.getNode(ISD::SELECT, DL, ExtTy, {Op->getOperand(0), LHS, RHS});
9112 else if (Opc == ISD::UADDSAT) {
9113 SDValue Sum = DAG.getNode(ISD::ADD, DL, ExtTy, LHS, RHS);
9114 SDValue MaxVal = DAG.getConstant(
9115 APInt::getMaxValue(OpTy.getScalarSizeInBits()).zext(32), DL, ExtTy);
9116 NewVal = DAG.getNode(ISD::UMIN, DL, ExtTy, Sum, MaxVal);
9117 } else
9118 NewVal = DAG.getNode(Opc, DL, ExtTy, {LHS, RHS});
9119
9120 return DAG.getZExtOrTrunc(NewVal, DL, OpTy);
9121}
9122
9123SDValue SITargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
9124 SDValue Mag = Op.getOperand(0);
9125 EVT MagVT = Mag.getValueType();
9126
9127 if (MagVT.getVectorNumElements() > 2)
9128 return splitBinaryVectorOp(Op, DAG);
9129
9130 SDValue Sign = Op.getOperand(1);
9131 EVT SignVT = Sign.getValueType();
9132
9133 if (MagVT == SignVT)
9134 return Op;
9135
9136 // fcopysign v2f16:mag, v2f32:sign ->
9137 // fcopysign v2f16:mag,
9138 // bitcast (trunc (srl (bitcast sign to v2i32), 16) to v2i16)
9139
9140 SDLoc SL(Op);
9141 SDValue SignAsInt32 = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Sign);
9142 SDValue ShiftAmt = DAG.getShiftAmountConstant(16, MVT::v2i32, SL);
9143 SDValue SignShifted =
9144 DAG.getNode(ISD::SRL, SL, MVT::v2i32, SignAsInt32, ShiftAmt);
9145 SDValue SignAsInt16 = DAG.getNode(ISD::TRUNCATE, SL, MVT::v2i16, SignShifted);
9146
9147 SDValue SignAsHalf16 = DAG.getNode(ISD::BITCAST, SL, MagVT, SignAsInt16);
9148
9149 return DAG.getNode(ISD::FCOPYSIGN, SL, MagVT, Mag, SignAsHalf16);
9150}
9151
9152// Custom lowering for vector multiplications and s_mul_u64.
9153SDValue SITargetLowering::lowerMUL(SDValue Op, SelectionDAG &DAG) const {
9154 EVT VT = Op.getValueType();
9155
9156 // Split vector operands.
9157 if (VT.isVector())
9158 return splitBinaryVectorOp(Op, DAG);
9159
9160 assert(VT == MVT::i64 && "The following code is a special for s_mul_u64");
9161
9162 // There are four ways to lower s_mul_u64:
9163 //
9164 // 1. If all the operands are uniform, then we lower it as it is.
9165 //
9166 // 2. If the operands are divergent, then we have to split s_mul_u64 in 32-bit
9167 // multiplications because there is not a vector equivalent of s_mul_u64.
9168 //
9169 // 3. If the cost model decides that it is more efficient to use vector
9170 // registers, then we have to split s_mul_u64 in 32-bit multiplications.
9171 // This happens in splitScalarSMULU64() in SIInstrInfo.cpp .
9172 //
9173 // 4. If the cost model decides to use vector registers and both of the
9174 // operands are zero-extended/sign-extended from 32-bits, then we split the
9175 // s_mul_u64 in two 32-bit multiplications. The problem is that it is not
9176 // possible to check if the operands are zero-extended or sign-extended in
9177 // SIInstrInfo.cpp. For this reason, here, we replace s_mul_u64 with
9178 // s_mul_u64_u32_pseudo if both operands are zero-extended and we replace
9179 // s_mul_u64 with s_mul_i64_i32_pseudo if both operands are sign-extended.
9180 // If the cost model decides that we have to use vector registers, then
9181 // splitScalarSMulPseudo() (in SIInstrInfo.cpp) split s_mul_u64_u32/
9182 // s_mul_i64_i32_pseudo in two vector multiplications. If the cost model
9183 // decides that we should use scalar registers, then s_mul_u64_u32_pseudo/
9184 // s_mul_i64_i32_pseudo is lowered as s_mul_u64 in expandPostRAPseudo() in
9185 // SIInstrInfo.cpp .
9186
9187 if (Op->isDivergent())
9188 return SDValue();
9189
9190 SDValue Op0 = Op.getOperand(0);
9191 SDValue Op1 = Op.getOperand(1);
9192 // If all the operands are zero-enteted to 32-bits, then we replace s_mul_u64
9193 // with s_mul_u64_u32_pseudo. If all the operands are sign-extended to
9194 // 32-bits, then we replace s_mul_u64 with s_mul_i64_i32_pseudo.
9195 KnownBits Op0KnownBits = DAG.computeKnownBits(Op0);
9196 unsigned Op0LeadingZeros = Op0KnownBits.countMinLeadingZeros();
9197 KnownBits Op1KnownBits = DAG.computeKnownBits(Op1);
9198 unsigned Op1LeadingZeros = Op1KnownBits.countMinLeadingZeros();
9199 SDLoc SL(Op);
9200 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9201 return SDValue(
9202 DAG.getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9203 unsigned Op0SignBits = DAG.ComputeNumSignBits(Op0);
9204 unsigned Op1SignBits = DAG.ComputeNumSignBits(Op1);
9205 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9206 return SDValue(
9207 DAG.getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9208 // If all the operands are uniform, then we lower s_mul_u64 as it is.
9209 return Op;
9210}
9211
9212SDValue SITargetLowering::lowerXMULO(SDValue Op, SelectionDAG &DAG) const {
9213 EVT VT = Op.getValueType();
9214 SDLoc SL(Op);
9215 SDValue LHS = Op.getOperand(0);
9216 SDValue RHS = Op.getOperand(1);
9217 bool isSigned = Op.getOpcode() == ISD::SMULO;
9218
9219 if (ConstantSDNode *RHSC = isConstOrConstSplat(RHS)) {
9220 const APInt &C = RHSC->getAPIntValue();
9221 // mulo(X, 1 << S) -> { X << S, (X << S) >> S != X }
9222 if (C.isPowerOf2()) {
9223 // smulo(x, signed_min) is same as umulo(x, signed_min).
9224 bool UseArithShift = isSigned && !C.isMinSignedValue();
9225 SDValue ShiftAmt = DAG.getConstant(C.logBase2(), SL, MVT::i32);
9226 SDValue Result = DAG.getNode(ISD::SHL, SL, VT, LHS, ShiftAmt);
9227 SDValue Overflow =
9228 DAG.getSetCC(SL, MVT::i1,
9229 DAG.getNode(UseArithShift ? ISD::SRA : ISD::SRL, SL, VT,
9230 Result, ShiftAmt),
9231 LHS, ISD::SETNE);
9232 return DAG.getMergeValues({Result, Overflow}, SL);
9233 }
9234 }
9235
9236 SDValue Result = DAG.getNode(ISD::MUL, SL, VT, LHS, RHS);
9237 SDValue Top =
9238 DAG.getNode(isSigned ? ISD::MULHS : ISD::MULHU, SL, VT, LHS, RHS);
9239
9240 SDValue Sign = isSigned
9241 ? DAG.getNode(ISD::SRA, SL, VT, Result,
9242 DAG.getConstant(VT.getScalarSizeInBits() - 1,
9243 SL, MVT::i32))
9244 : DAG.getConstant(0, SL, VT);
9245 SDValue Overflow = DAG.getSetCC(SL, MVT::i1, Top, Sign, ISD::SETNE);
9246
9247 return DAG.getMergeValues({Result, Overflow}, SL);
9248}
9249
9250SDValue SITargetLowering::lowerXMUL_LOHI(SDValue Op, SelectionDAG &DAG) const {
9251 if (Op->isDivergent()) {
9252 // Select to V_MAD_[IU]64_[IU]32.
9253 return Op;
9254 }
9255 if (Subtarget->hasSMulHi()) {
9256 // Expand to S_MUL_I32 + S_MUL_HI_[IU]32.
9257 return SDValue();
9258 }
9259 // The multiply is uniform but we would have to use V_MUL_HI_[IU]32 to
9260 // calculate the high part, so we might as well do the whole thing with
9261 // V_MAD_[IU]64_[IU]32.
9262 return Op;
9263}
9264
9265SDValue SITargetLowering::lowerTRAP(SDValue Op, SelectionDAG &DAG) const {
9266 if (!Subtarget->hasTrapHandler() ||
9267 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA)
9268 return lowerTrapEndpgm(Op, DAG);
9269
9270 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(Op, DAG)
9271 : lowerTrapHsaQueuePtr(Op, DAG);
9272}
9273
9274SDValue SITargetLowering::lowerTrapEndpgm(SDValue Op, SelectionDAG &DAG) const {
9275 SDLoc SL(Op);
9276 SDValue Chain = Op.getOperand(0);
9277 return DAG.getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9278}
9279
9280SDValue
9281SITargetLowering::loadImplicitKernelArgument(SelectionDAG &DAG, MVT VT,
9282 const SDLoc &DL, Align Alignment,
9283 ImplicitParameter Param) const {
9286 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, DAG.getEntryNode(), Offset);
9287 MachinePointerInfo PtrInfo =
9289 return DAG.getLoad(
9290 VT, DL, DAG.getEntryNode(), Ptr, PtrInfo.getWithOffset(Offset), Alignment,
9292}
9293
9294SDValue SITargetLowering::lowerTrapHsaQueuePtr(SDValue Op,
9295 SelectionDAG &DAG) const {
9296 SDLoc SL(Op);
9297 SDValue Chain = Op.getOperand(0);
9298
9299 SDValue QueuePtr;
9300 // For code object version 5, QueuePtr is passed through implicit kernarg.
9301 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9303 QueuePtr =
9304 loadImplicitKernelArgument(DAG, MVT::i64, SL, Align(8), QUEUE_PTR);
9305 } else {
9307 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9308 Register UserSGPR = Info->getQueuePtrUserSGPR();
9309
9310 if (UserSGPR == AMDGPU::NoRegister) {
9311 // We probably are in a function incorrectly marked with
9312 // amdgpu-no-queue-ptr. This is undefined. We don't want to delete the
9313 // trap, so just use a null pointer.
9314 QueuePtr = DAG.getConstant(0, SL, MVT::i64);
9315 } else {
9316 QueuePtr = CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR,
9317 MVT::i64);
9318 }
9319 }
9320
9321 SDValue SGPR01 = DAG.getRegister(AMDGPU::SGPR0_SGPR1, MVT::i64);
9322 SDValue ToReg = DAG.getCopyToReg(Chain, SL, SGPR01, QueuePtr, SDValue());
9323
9325 SDValue Ops[] = {ToReg, DAG.getTargetConstant(TrapID, SL, MVT::i16), SGPR01,
9326 ToReg.getValue(1)};
9327 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9328}
9329
9330SDValue SITargetLowering::lowerTrapHsa(SDValue Op, SelectionDAG &DAG) const {
9331 SDLoc SL(Op);
9332 SDValue Chain = Op.getOperand(0);
9333
9334 // We need to simulate the 's_trap 2' instruction on targets that run in
9335 // PRIV=1 (where it is treated as a nop).
9336 if (Subtarget->hasPrivEnabledTrap2NopBug())
9337 return DAG.getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9338
9340 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9341 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9342}
9343
9344SDValue SITargetLowering::lowerDEBUGTRAP(SDValue Op, SelectionDAG &DAG) const {
9345 SDLoc SL(Op);
9346 SDValue Chain = Op.getOperand(0);
9348
9349 if (!Subtarget->hasTrapHandler() ||
9350 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA) {
9351 LLVMContext &Ctx = MF.getFunction().getContext();
9352 Ctx.diagnose(DiagnosticInfoUnsupported(MF.getFunction(),
9353 "debugtrap handler not supported",
9354 Op.getDebugLoc(), DS_Warning));
9355 return Chain;
9356 }
9357
9358 uint64_t TrapID =
9360 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9361 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9362}
9363
9364/// When a divergent value (in VGPR) is passed to an inline asm with an SGPR
9365/// constraint ('s'), we need to insert v_readfirstlane to move the value from
9366/// VGPR to SGPR. This is done by modifying the CopyToReg nodes in the glue
9367/// chain that feed into the INLINEASM node.
9368SDValue SITargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
9369 unsigned NumOps = Op.getNumOperands();
9370
9371 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
9372 SmallSet<Register, 8> SGPRInputRegs;
9373
9374 unsigned NumVals = 0;
9375 for (unsigned I = InlineAsm::Op_FirstOperand; I < NumOps - 1;
9376 I += 1 + NumVals) {
9377 const InlineAsm::Flag Flags(Op.getConstantOperandVal(I));
9378 NumVals = Flags.getNumOperandRegisters();
9379
9380 unsigned RCID;
9381 bool IsSGPRInput = Flags.getKind() == InlineAsm::Kind::RegUse &&
9382 NumVals > 0 && Flags.hasRegClassConstraint(RCID) &&
9383 TRI->isSGPRClass(TRI->getRegClass(RCID));
9384
9385 for (unsigned J = 0; J < NumVals; ++J) {
9386 SDValue Val = Op.getOperand(I + 1 + J);
9387 if (const RegisterSDNode *RegNode =
9389 Register Reg = RegNode->getReg();
9390 if (IsSGPRInput || (Reg.isPhysical() && TRI->isSGPRPhysReg(Reg)))
9391 SGPRInputRegs.insert(Reg);
9392 }
9393 }
9394 }
9395
9396 if (SGPRInputRegs.empty())
9397 return Op;
9398
9399 // Walk the glue chain and insert readfirstlane for divergent SGPR inputs.
9400 SDLoc DL(Op);
9401 SDNode *N = Op.getOperand(NumOps - 1).getNode();
9402
9403 while (N && N->getOpcode() == ISD::CopyToReg) {
9404 Register Reg = cast<RegisterSDNode>(N->getOperand(1))->getReg();
9405 SDValue SrcVal = N->getOperand(2);
9406
9407 // Insert readfirstlane if copying a divergent value to an SGPR input.
9408 if (SrcVal->isDivergent() && SGPRInputRegs.count(Reg)) {
9409 SDValue ReadFirstLaneID =
9410 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
9411 SDValue ReadFirstLane =
9413 ReadFirstLaneID, SrcVal);
9414
9415 SmallVector<SDValue, 4> Ops = {N->getOperand(0), N->getOperand(1),
9416 ReadFirstLane};
9417 if (N->getNumOperands() > 3)
9418 Ops.push_back(N->getOperand(3)); // Glue input
9419
9420 DAG.UpdateNodeOperands(N, Ops);
9421 }
9422
9423 // Follow glue chain to next CopyToReg.
9424 SDNode *Next = nullptr;
9425 for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I) {
9426 if (N->getOperand(I).getValueType() == MVT::Glue) {
9427 Next = N->getOperand(I).getNode();
9428 break;
9429 }
9430 }
9431 N = Next;
9432 }
9433
9434 return Op;
9435}
9436
9437SDValue SITargetLowering::getSegmentAperture(unsigned AS, const SDLoc &DL,
9438 SelectionDAG &DAG) const {
9439 unsigned BaseAS = AS;
9440 unsigned SANum = AMDGPU::getSyntheticApertureNumber(AS);
9442 BaseAS = AMDGPUAS::LOCAL_ADDRESS;
9443
9444 SDValue Aperture = getBaseSegmentAperture(BaseAS, DL, DAG);
9445
9446 if (SANum != AMDGPU::SyntheticAperture::None) {
9447 SDValue Tag = DAG.getConstant(SANum, DL, MVT::i32);
9448 return DAG.getNode(ISD::OR, DL, MVT::i32, Aperture, Tag);
9449 }
9450
9451 return Aperture;
9452}
9453
9454SDValue SITargetLowering::getBaseSegmentAperture(unsigned AS, const SDLoc &DL,
9455 SelectionDAG &DAG) const {
9456 const bool IsLDS = (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::BARRIER);
9457
9458 if (Subtarget->hasApertureRegs()) {
9459 const unsigned ApertureRegNo =
9460 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
9461 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9462 !Subtarget->hasGloballyAddressableScratch()) &&
9463 "Cannot use src_private_base with globally addressable scratch!");
9464 // Note: this feature (register) is broken. When used as a 32-bit operand,
9465 // it returns a wrong value (all zeroes?). The real value is in the upper 32
9466 // bits.
9467 //
9468 // To work around the issue, emit a 64 bit copy from this register
9469 // then extract the high bits. Note that this shouldn't even result in a
9470 // shift being emitted and simply become a pair of registers (e.g.):
9471 // s_mov_b64 s[6:7], src_shared_base
9472 // v_mov_b32_e32 v1, s7
9473 SDValue Copy =
9474 DAG.getCopyFromReg(DAG.getEntryNode(), DL, ApertureRegNo, MVT::v2i32);
9475 return DAG.getExtractVectorElt(DL, MVT::i32, Copy, 1);
9476 }
9477
9478 // For code object version 5, private_base and shared_base are passed through
9479 // implicit kernargs.
9480 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9483 return loadImplicitKernelArgument(DAG, MVT::i32, DL, Align(4), Param);
9484 }
9485
9487 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9488 Register UserSGPR = Info->getQueuePtrUserSGPR();
9489 if (UserSGPR == AMDGPU::NoRegister) {
9490 // We probably are in a function incorrectly marked with
9491 // amdgpu-no-queue-ptr. This is undefined.
9492 return DAG.getPOISON(MVT::i32);
9493 }
9494
9495 SDValue QueuePtr =
9496 CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR, MVT::i64);
9497
9498 // Offset into amd_queue_t for group_segment_aperture_base_hi /
9499 // private_segment_aperture_base_hi.
9500 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
9501
9502 SDValue Ptr =
9503 DAG.getObjectPtrOffset(DL, QueuePtr, TypeSize::getFixed(StructOffset));
9504
9505 // TODO: Use custom target PseudoSourceValue.
9506 // TODO: We should use the value from the IR intrinsic call, but it might not
9507 // be available and how do we get it?
9508 MachinePointerInfo PtrInfo(AMDGPUAS::CONSTANT_ADDRESS);
9509 return DAG.getLoad(MVT::i32, DL, QueuePtr.getValue(1), Ptr, PtrInfo,
9510 commonAlignment(Align(64), StructOffset),
9513}
9514
9515/// Return true if the value is a known valid address, such that a null check is
9516/// not necessary.
9518 const AMDGPUTargetMachine &TM, unsigned AddrSpace) {
9520 return true;
9521
9522 if (auto *ConstVal = dyn_cast<ConstantSDNode>(Val))
9523 return ConstVal->getSExtValue() != AMDGPU::getNullPointerValue(AddrSpace);
9524
9525 // TODO: Search through arithmetic, handle arguments and loads
9526 // marked nonnull.
9527 return false;
9528}
9529
9530SDValue SITargetLowering::lowerADDRSPACECAST(SDValue Op,
9531 SelectionDAG &DAG) const {
9532 SDLoc SL(Op);
9533
9534 const AMDGPUTargetMachine &TM =
9535 static_cast<const AMDGPUTargetMachine &>(getTargetMachine());
9536
9537 const auto *ASC = cast<AddrSpaceCastSDNode>(Op);
9538 unsigned SrcAS = ASC->getSrcAddressSpace();
9539 SDValue Src = ASC->getOperand(0);
9540 unsigned DestAS = ASC->getDestAddressSpace();
9541 bool IsNonNull = ASC->getFlags().hasNonNull();
9542
9543 SDValue FlatNullPtr = DAG.getConstant(0, SL, MVT::i64);
9544
9545 // flat -> local/private/barrier
9546 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
9547 if (DestAS == AMDGPUAS::LOCAL_ADDRESS ||
9548 DestAS == AMDGPUAS::PRIVATE_ADDRESS || DestAS == AMDGPUAS::BARRIER) {
9549 SDValue Ptr = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9550
9551 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
9552 Subtarget->hasGloballyAddressableScratch()) {
9553 // flat -> private with globally addressable scratch: subtract
9554 // src_flat_scratch_base_lo.
9555 SDValue FlatScratchBaseLo(
9556 DAG.getMachineNode(
9557 AMDGPU::S_MOV_B32, SL, MVT::i32,
9558 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9559 0);
9560 Ptr = DAG.getNode(ISD::SUB, SL, MVT::i32, Ptr, FlatScratchBaseLo);
9561 }
9562
9563 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9564 return Ptr;
9565
9566 unsigned NullVal = AMDGPU::getNullPointerValue(DestAS);
9567 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9568 SDValue NonNull = DAG.getSetCC(SL, MVT::i1, Src, FlatNullPtr, ISD::SETNE);
9569
9570 return DAG.getNode(ISD::SELECT, SL, MVT::i32, NonNull, Ptr,
9571 SegmentNullPtr);
9572 }
9573 }
9574
9575 // local/private/barrier -> flat
9576 if (DestAS == AMDGPUAS::FLAT_ADDRESS) {
9577 if (SrcAS == AMDGPUAS::LOCAL_ADDRESS ||
9578 SrcAS == AMDGPUAS::PRIVATE_ADDRESS || SrcAS == AMDGPUAS::BARRIER) {
9579 SDValue CvtPtr;
9580 if (SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
9581 Subtarget->hasGloballyAddressableScratch()) {
9582 // For wave32: Addr = (TID[4:0] << 52) + FLAT_SCRATCH_BASE + privateAddr
9583 // For wave64: Addr = (TID[5:0] << 51) + FLAT_SCRATCH_BASE + privateAddr
9584 SDValue AllOnes = DAG.getSignedTargetConstant(-1, SL, MVT::i32);
9585 SDValue ThreadID = DAG.getConstant(0, SL, MVT::i32);
9586 ThreadID = DAG.getNode(
9587 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9588 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_lo, SL, MVT::i32),
9589 AllOnes, ThreadID);
9590 if (Subtarget->isWave64())
9591 ThreadID = DAG.getNode(
9592 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9593 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_hi, SL, MVT::i32),
9594 AllOnes, ThreadID);
9595 SDValue ShAmt = DAG.getShiftAmountConstant(
9596 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9597 SDValue SrcHi = DAG.getNode(ISD::SHL, SL, MVT::i32, ThreadID, ShAmt);
9598 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, SrcHi);
9599 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9600 // Accessing src_flat_scratch_base_lo as a 64-bit operand gives the full
9601 // 64-bit hi:lo value.
9602 SDValue FlatScratchBase = {
9603 DAG.getMachineNode(
9604 AMDGPU::S_MOV_B64, SL, MVT::i64,
9605 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9606 0};
9607 CvtPtr = DAG.getNode(ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9608 } else {
9609 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9610
9611 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Aperture);
9612 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9613 }
9614
9615 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9616 return CvtPtr;
9617
9618 unsigned NullVal = AMDGPU::getNullPointerValue(SrcAS);
9619 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9620
9621 SDValue NonNull =
9622 DAG.getSetCC(SL, MVT::i1, Src, SegmentNullPtr, ISD::SETNE);
9623
9624 return DAG.getNode(ISD::SELECT, SL, MVT::i64, NonNull, CvtPtr,
9625 FlatNullPtr);
9626 }
9627 }
9628
9629 if (SrcAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9630 Op.getValueType() == MVT::i64) {
9631 const SIMachineFunctionInfo *Info =
9632 DAG.getMachineFunction().getInfo<SIMachineFunctionInfo>();
9633 if (Info->get32BitAddressHighBits() == 0)
9634 return DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i64, Src);
9635
9636 SDValue Hi = DAG.getConstant(Info->get32BitAddressHighBits(), SL, MVT::i32);
9637 SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Hi);
9638 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
9639 }
9640
9641 if (DestAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9642 Src.getValueType() == MVT::i64)
9643 return DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9644
9645 // global <-> flat are no-ops and never emitted.
9646
9647 // Invalid casts are poison.
9648 return DAG.getPOISON(Op->getValueType(0));
9649}
9650
9651// This lowers an INSERT_SUBVECTOR by extracting the individual elements from
9652// the small vector and inserting them into the big vector. That is better than
9653// the default expansion of doing it via a stack slot. Even though the use of
9654// the stack slot would be optimized away afterwards, the stack slot itself
9655// remains.
9656SDValue SITargetLowering::lowerINSERT_SUBVECTOR(SDValue Op,
9657 SelectionDAG &DAG) const {
9658 SDValue Vec = Op.getOperand(0);
9659 SDValue Ins = Op.getOperand(1);
9660 SDValue Idx = Op.getOperand(2);
9661 EVT VecVT = Vec.getValueType();
9662 EVT InsVT = Ins.getValueType();
9663 EVT EltVT = VecVT.getVectorElementType();
9664 unsigned InsNumElts = InsVT.getVectorNumElements();
9665 unsigned IdxVal = Idx->getAsZExtVal();
9666 SDLoc SL(Op);
9667
9668 if (EltVT.getScalarSizeInBits() == 16 && IdxVal % 2 == 0) {
9669 // Insert 32-bit registers at a time.
9670 assert(InsNumElts % 2 == 0 && "expect legal vector types");
9671
9672 unsigned VecNumElts = VecVT.getVectorNumElements();
9673 EVT NewVecVT =
9674 EVT::getVectorVT(*DAG.getContext(), MVT::i32, VecNumElts / 2);
9675 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9677 MVT::i32, InsNumElts / 2);
9678
9679 Vec = DAG.getNode(ISD::BITCAST, SL, NewVecVT, Vec);
9680 Ins = DAG.getNode(ISD::BITCAST, SL, NewInsVT, Ins);
9681
9682 for (unsigned I = 0; I != InsNumElts / 2; ++I) {
9683 SDValue Elt;
9684 if (InsNumElts == 2) {
9685 Elt = Ins;
9686 } else {
9687 Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Ins,
9688 DAG.getConstant(I, SL, MVT::i32));
9689 }
9690 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, NewVecVT, Vec, Elt,
9691 DAG.getConstant(IdxVal / 2 + I, SL, MVT::i32));
9692 }
9693
9694 return DAG.getNode(ISD::BITCAST, SL, VecVT, Vec);
9695 }
9696
9697 for (unsigned I = 0; I != InsNumElts; ++I) {
9698 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Ins,
9699 DAG.getConstant(I, SL, MVT::i32));
9700 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, VecVT, Vec, Elt,
9701 DAG.getConstant(IdxVal + I, SL, MVT::i32));
9702 }
9703 return Vec;
9704}
9705
9706SDValue SITargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,
9707 SelectionDAG &DAG) const {
9708 SDValue Vec = Op.getOperand(0);
9709 SDValue InsVal = Op.getOperand(1);
9710 SDValue Idx = Op.getOperand(2);
9711 EVT VecVT = Vec.getValueType();
9712 EVT EltVT = VecVT.getVectorElementType();
9713 unsigned VecSize = VecVT.getSizeInBits();
9714 unsigned EltSize = EltVT.getSizeInBits();
9715 SDLoc SL(Op);
9716
9717 // Specially handle the case of v4i16 with static indexing.
9718 unsigned NumElts = VecVT.getVectorNumElements();
9719 auto *KIdx = dyn_cast<ConstantSDNode>(Idx);
9720 if (NumElts == 4 && EltSize == 16 && KIdx) {
9721 SDValue BCVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Vec);
9722
9723 SDValue LoHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9724 DAG.getConstant(0, SL, MVT::i32));
9725 SDValue HiHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9726 DAG.getConstant(1, SL, MVT::i32));
9727
9728 SDValue LoVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, LoHalf);
9729 SDValue HiVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, HiHalf);
9730
9731 unsigned Idx = KIdx->getZExtValue();
9732 bool InsertLo = Idx < 2;
9733 SDValue InsHalf = DAG.getNode(
9734 ISD::INSERT_VECTOR_ELT, SL, MVT::v2i16, InsertLo ? LoVec : HiVec,
9735 DAG.getNode(ISD::BITCAST, SL, MVT::i16, InsVal),
9736 DAG.getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9737
9738 InsHalf = DAG.getNode(ISD::BITCAST, SL, MVT::i32, InsHalf);
9739
9740 SDValue Concat =
9741 InsertLo ? DAG.getBuildVector(MVT::v2i32, SL, {InsHalf, HiHalf})
9742 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9743
9744 return DAG.getNode(ISD::BITCAST, SL, VecVT, Concat);
9745 }
9746
9747 // Static indexing does not lower to stack access, and hence there is no need
9748 // for special custom lowering to avoid stack access.
9749 if (isa<ConstantSDNode>(Idx))
9750 return SDValue();
9751
9752 // Avoid stack access for dynamic indexing by custom lowering to
9753 // v_bfi_b32 (v_bfm_b32 16, (shl idx, 16)), val, vec
9754
9755 assert(VecSize <= 64 && "Expected target vector size to be <= 64 bits");
9756
9757 MVT IntVT = MVT::getIntegerVT(VecSize);
9758
9759 // Convert vector index to bit-index and get the required bit mask.
9760 assert(isPowerOf2_32(EltSize));
9761 const auto EltMask = maskTrailingOnes<uint64_t>(EltSize);
9762 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9763 SDValue ScaledIdx = DAG.getNode(ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9764 SDValue BFM = DAG.getNode(ISD::SHL, SL, IntVT,
9765 DAG.getConstant(EltMask, SL, IntVT), ScaledIdx);
9766
9767 // 1. Create a congruent vector with the target value in each element.
9768 SDValue ExtVal = DAG.getNode(ISD::BITCAST, SL, IntVT,
9769 DAG.getSplatBuildVector(VecVT, SL, InsVal));
9770
9771 // 2. Mask off all other indices except the required index within (1).
9772 SDValue LHS = DAG.getNode(ISD::AND, SL, IntVT, BFM, ExtVal);
9773
9774 // 3. Mask off the required index within the target vector.
9775 SDValue BCVec = DAG.getNode(ISD::BITCAST, SL, IntVT, Vec);
9776 SDValue RHS =
9777 DAG.getNode(ISD::AND, SL, IntVT, DAG.getNOT(SL, BFM, IntVT), BCVec);
9778
9779 // 4. Get (2) and (3) ORed into the target vector.
9780 SDValue BFI =
9781 DAG.getNode(ISD::OR, SL, IntVT, LHS, RHS, SDNodeFlags::Disjoint);
9782
9783 return DAG.getNode(ISD::BITCAST, SL, VecVT, BFI);
9784}
9785
9786SDValue SITargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op,
9787 SelectionDAG &DAG) const {
9788 SDLoc SL(Op);
9789
9790 EVT ResultVT = Op.getValueType();
9791 SDValue Vec = Op.getOperand(0);
9792 SDValue Idx = Op.getOperand(1);
9793 EVT VecVT = Vec.getValueType();
9794 unsigned VecSize = VecVT.getSizeInBits();
9795 EVT EltVT = VecVT.getVectorElementType();
9796
9797 DAGCombinerInfo DCI(DAG, AfterLegalizeVectorOps, true, nullptr);
9798
9799 // Make sure we do any optimizations that will make it easier to fold
9800 // source modifiers before obscuring it with bit operations.
9801
9802 // XXX - Why doesn't this get called when vector_shuffle is expanded?
9803 if (SDValue Combined = performExtractVectorEltCombine(Op.getNode(), DCI))
9804 return Combined;
9805
9806 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9807 SDValue Lo, Hi;
9808 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VecVT);
9809
9810 if (VecSize == 128) {
9811 SDValue V2 = DAG.getBitcast(MVT::v2i64, Vec);
9812 Lo = DAG.getBitcast(LoVT,
9813 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9814 DAG.getConstant(0, SL, MVT::i32)));
9815 Hi = DAG.getBitcast(HiVT,
9816 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9817 DAG.getConstant(1, SL, MVT::i32)));
9818 } else if (VecSize == 256) {
9819 SDValue V2 = DAG.getBitcast(MVT::v4i64, Vec);
9820 SDValue Parts[4];
9821 for (unsigned P = 0; P < 4; ++P) {
9822 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9823 DAG.getConstant(P, SL, MVT::i32));
9824 }
9825
9826 Lo = DAG.getBitcast(LoVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9827 Parts[0], Parts[1]));
9828 Hi = DAG.getBitcast(HiVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9829 Parts[2], Parts[3]));
9830 } else {
9831 assert(VecSize == 512);
9832
9833 SDValue V2 = DAG.getBitcast(MVT::v8i64, Vec);
9834 SDValue Parts[8];
9835 for (unsigned P = 0; P < 8; ++P) {
9836 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9837 DAG.getConstant(P, SL, MVT::i32));
9838 }
9839
9840 Lo = DAG.getBitcast(LoVT,
9841 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9842 Parts[0], Parts[1], Parts[2], Parts[3]));
9843 Hi = DAG.getBitcast(HiVT,
9844 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9845 Parts[4], Parts[5], Parts[6], Parts[7]));
9846 }
9847
9848 EVT IdxVT = Idx.getValueType();
9849 unsigned NElem = VecVT.getVectorNumElements();
9850 assert(isPowerOf2_32(NElem));
9851 SDValue IdxMask = DAG.getConstant(NElem / 2 - 1, SL, IdxVT);
9852 SDValue NewIdx = DAG.getNode(ISD::AND, SL, IdxVT, Idx, IdxMask);
9853 SDValue Half = DAG.getSelectCC(SL, Idx, IdxMask, Hi, Lo, ISD::SETUGT);
9854 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Half, NewIdx);
9855 }
9856
9857 assert(VecSize <= 64);
9858
9859 MVT IntVT = MVT::getIntegerVT(VecSize);
9860
9861 // If Vec is just a SCALAR_TO_VECTOR, then use the scalar integer directly.
9862 SDValue VecBC = peekThroughBitcasts(Vec);
9863 if (VecBC.getOpcode() == ISD::SCALAR_TO_VECTOR) {
9864 SDValue Src = VecBC.getOperand(0);
9865 Src = DAG.getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9866 Vec = DAG.getAnyExtOrTrunc(Src, SL, IntVT);
9867 }
9868
9869 unsigned EltSize = EltVT.getSizeInBits();
9870 assert(isPowerOf2_32(EltSize));
9871
9872 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9873
9874 // Convert vector index to bit-index (* EltSize)
9875 SDValue ScaledIdx = DAG.getNode(ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9876
9877 SDValue BC = DAG.getNode(ISD::BITCAST, SL, IntVT, Vec);
9878 SDValue Elt = DAG.getNode(ISD::SRL, SL, IntVT, BC, ScaledIdx);
9879
9880 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9881 SDValue Result = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Elt);
9882 return DAG.getNode(ISD::BITCAST, SL, ResultVT, Result);
9883 }
9884
9885 return DAG.getAnyExtOrTrunc(Elt, SL, ResultVT);
9886}
9887
9888static bool elementPairIsContiguous(ArrayRef<int> Mask, int Elt) {
9889 assert(Elt % 2 == 0);
9890 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9891}
9892
9893static bool elementPairIsOddToEven(ArrayRef<int> Mask, int Elt) {
9894 assert(Elt % 2 == 0);
9895 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9896 !(Mask[Elt + 1] & 1);
9897}
9898
9899SDValue SITargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
9900 SelectionDAG &DAG) const {
9901 SDLoc SL(Op);
9902 EVT ResultVT = Op.getValueType();
9903 ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
9904 MVT EltVT = ResultVT.getVectorElementType().getSimpleVT();
9905 const int NewSrcNumElts = 2;
9906 MVT PackVT = MVT::getVectorVT(EltVT, NewSrcNumElts);
9907 int SrcNumElts = Op.getOperand(0).getValueType().getVectorNumElements();
9908
9909 // Break up the shuffle into registers sized pieces.
9910 //
9911 // We're trying to form sub-shuffles that the register allocation pipeline
9912 // won't be able to figure out, like how to use v_pk_mov_b32 to do a register
9913 // blend or 16-bit op_sel. It should be able to figure out how to reassemble a
9914 // pair of copies into a consecutive register copy, so use the ordinary
9915 // extract_vector_elt lowering unless we can use the shuffle.
9916 //
9917 // TODO: This is a bit of hack, and we should probably always use
9918 // extract_subvector for the largest possible subvector we can (or at least
9919 // use it for PackVT aligned pieces). However we have worse support for
9920 // combines on them don't directly treat extract_subvector / insert_subvector
9921 // as legal. The DAG scheduler also ends up doing a worse job with the
9922 // extract_subvectors.
9923 const bool ShouldUseConsecutiveExtract = EltVT.getSizeInBits() == 16;
9924
9925 // vector_shuffle <0,1,6,7> lhs, rhs
9926 // -> concat_vectors (extract_subvector lhs, 0), (extract_subvector rhs, 2)
9927 //
9928 // vector_shuffle <6,7,2,3> lhs, rhs
9929 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 2)
9930 //
9931 // vector_shuffle <6,7,0,1> lhs, rhs
9932 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 0)
9933
9934 // Avoid scalarizing when both halves are reading from consecutive elements.
9935
9936 // If we're treating 2 element shuffles as legal, also create odd-to-even
9937 // shuffles of neighboring pairs.
9938 //
9939 // vector_shuffle <3,2,7,6> lhs, rhs
9940 // -> concat_vectors vector_shuffle <1, 0> (extract_subvector lhs, 0)
9941 // vector_shuffle <1, 0> (extract_subvector rhs, 2)
9942
9944 for (int I = 0, N = ResultVT.getVectorNumElements(); I != N; I += 2) {
9945 if (ShouldUseConsecutiveExtract &&
9947 const int Idx = SVN->getMaskElt(I);
9948 int VecIdx = Idx < SrcNumElts ? 0 : 1;
9949 int EltIdx = Idx < SrcNumElts ? Idx : Idx - SrcNumElts;
9950 SDValue SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT,
9951 SVN->getOperand(VecIdx),
9952 DAG.getConstant(EltIdx, SL, MVT::i32));
9953 Pieces.push_back(SubVec);
9954 } else if (elementPairIsOddToEven(SVN->getMask(), I) &&
9956 int Idx0 = SVN->getMaskElt(I);
9957 int Idx1 = SVN->getMaskElt(I + 1);
9958
9959 SDValue SrcOp0 = SVN->getOperand(0);
9960 SDValue SrcOp1 = SrcOp0;
9961 if (Idx0 >= SrcNumElts) {
9962 SrcOp0 = SVN->getOperand(1);
9963 Idx0 -= SrcNumElts;
9964 }
9965
9966 if (Idx1 >= SrcNumElts) {
9967 SrcOp1 = SVN->getOperand(1);
9968 Idx1 -= SrcNumElts;
9969 }
9970
9971 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
9972 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
9973
9974 // Extract nearest even aligned piece.
9975 SDValue SubVec0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp0,
9976 DAG.getConstant(AlignedIdx0, SL, MVT::i32));
9977 SDValue SubVec1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp1,
9978 DAG.getConstant(AlignedIdx1, SL, MVT::i32));
9979
9980 int NewMaskIdx0 = Idx0 - AlignedIdx0;
9981 int NewMaskIdx1 = Idx1 - AlignedIdx1;
9982
9983 SDValue Result0 = SubVec0;
9984 SDValue Result1 = SubVec0;
9985
9986 if (SubVec0 != SubVec1) {
9987 NewMaskIdx1 += NewSrcNumElts;
9988 Result1 = SubVec1;
9989 } else {
9990 Result1 = DAG.getPOISON(PackVT);
9991 }
9992
9993 SDValue Shuf = DAG.getVectorShuffle(PackVT, SL, Result0, Result1,
9994 {NewMaskIdx0, NewMaskIdx1});
9995 Pieces.push_back(Shuf);
9996 } else {
9997 const int Idx0 = SVN->getMaskElt(I);
9998 const int Idx1 = SVN->getMaskElt(I + 1);
9999 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
10000 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
10001 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
10002 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
10003
10004 SDValue Vec0 = SVN->getOperand(VecIdx0);
10005 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec0,
10006 DAG.getSignedConstant(EltIdx0, SL, MVT::i32));
10007
10008 SDValue Vec1 = SVN->getOperand(VecIdx1);
10009 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec1,
10010 DAG.getSignedConstant(EltIdx1, SL, MVT::i32));
10011 Pieces.push_back(DAG.getBuildVector(PackVT, SL, {Elt0, Elt1}));
10012 }
10013 }
10014
10015 return DAG.getNode(ISD::CONCAT_VECTORS, SL, ResultVT, Pieces);
10016}
10017
10018SDValue SITargetLowering::lowerSCALAR_TO_VECTOR(SDValue Op,
10019 SelectionDAG &DAG) const {
10020 SDValue SVal = Op.getOperand(0);
10021 EVT ResultVT = Op.getValueType();
10022 EVT SValVT = SVal.getValueType();
10023 SDValue UndefVal = DAG.getPOISON(SValVT);
10024 SDLoc SL(Op);
10025
10027 VElts.push_back(SVal);
10028 for (int I = 1, E = ResultVT.getVectorNumElements(); I < E; ++I)
10029 VElts.push_back(UndefVal);
10030
10031 return DAG.getBuildVector(ResultVT, SL, VElts);
10032}
10033
10034SDValue SITargetLowering::lowerBUILD_VECTOR(SDValue Op,
10035 SelectionDAG &DAG) const {
10036 SDLoc SL(Op);
10037 EVT VT = Op.getValueType();
10038
10039 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
10040 assert(!Subtarget->hasVOP3PInsts() && "this should be legal");
10041
10042 SDValue Lo = Op.getOperand(0);
10043 SDValue Hi = Op.getOperand(1);
10044
10045 // Avoid adding defined bits with the zero_extend.
10046 if (Hi.isUndef()) {
10047 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
10048 SDValue ExtLo = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Lo);
10049 return DAG.getNode(ISD::BITCAST, SL, VT, ExtLo);
10050 }
10051
10052 Hi = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Hi);
10053 Hi = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Hi);
10054
10055 SDValue ShlHi = DAG.getNode(ISD::SHL, SL, MVT::i32, Hi,
10056 DAG.getConstant(16, SL, MVT::i32));
10057 if (Lo.isUndef())
10058 return DAG.getNode(ISD::BITCAST, SL, VT, ShlHi);
10059
10060 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
10061 Lo = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Lo);
10062
10063 SDValue Or =
10064 DAG.getNode(ISD::OR, SL, MVT::i32, Lo, ShlHi, SDNodeFlags::Disjoint);
10065 return DAG.getNode(ISD::BITCAST, SL, VT, Or);
10066 }
10067
10068 // Split into 2-element chunks.
10069 const unsigned NumParts = VT.getVectorNumElements() / 2;
10070 EVT PartVT = MVT::getVectorVT(VT.getVectorElementType().getSimpleVT(), 2);
10071 MVT PartIntVT = MVT::getIntegerVT(PartVT.getSizeInBits());
10072
10074 for (unsigned P = 0; P < NumParts; ++P) {
10075 SDValue Vec = DAG.getBuildVector(
10076 PartVT, SL, {Op.getOperand(P * 2), Op.getOperand(P * 2 + 1)});
10077 Casts.push_back(DAG.getNode(ISD::BITCAST, SL, PartIntVT, Vec));
10078 }
10079
10080 SDValue Blend =
10081 DAG.getBuildVector(MVT::getVectorVT(PartIntVT, NumParts), SL, Casts);
10082 return DAG.getNode(ISD::BITCAST, SL, VT, Blend);
10083}
10084
10086 const GlobalAddressSDNode *GA) const {
10087 // Named barriers have fixed, non-relocated LDS addresses, so a constant
10088 // offset into an array of them can be folded into the address.
10090 const auto *GV = dyn_cast<GlobalVariable>(GA->getGlobal());
10091 return GV && AMDGPU::isNamedBarrier(*GV);
10092 }
10093
10094 // OSes that use ELF REL relocations (instead of RELA) can only store a
10095 // 32-bit addend in the instruction, so it is not safe to allow offset folding
10096 // which can create arbitrary 64-bit addends. (This is only a problem for
10097 // R_AMDGPU_*32_HI relocations since other relocation types are unaffected by
10098 // the high 32 bits of the addend.)
10099 //
10100 // This should be kept in sync with how HasRelocationAddend is initialized in
10101 // the constructor of ELFAMDGPUAsmBackend.
10102 if (!Subtarget->isAmdHsaOS())
10103 return false;
10104
10105 // We can fold offsets for anything that doesn't require a GOT relocation.
10106 return (GA->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS ||
10110}
10111
10112static SDValue
10114 const SDLoc &DL, int64_t Offset, EVT PtrVT,
10115 unsigned GAFlags = SIInstrInfo::MO_NONE) {
10116 assert(isInt<32>(Offset + 4) && "32-bit offset is expected!");
10117 // In order to support pc-relative addressing, the PC_ADD_REL_OFFSET SDNode is
10118 // lowered to the following code sequence:
10119 //
10120 // For constant address space:
10121 // s_getpc_b64 s[0:1]
10122 // s_add_u32 s0, s0, $symbol
10123 // s_addc_u32 s1, s1, 0
10124 //
10125 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10126 // a fixup or relocation is emitted to replace $symbol with a literal
10127 // constant, which is a pc-relative offset from the encoding of the $symbol
10128 // operand to the global variable.
10129 //
10130 // For global address space:
10131 // s_getpc_b64 s[0:1]
10132 // s_add_u32 s0, s0, $symbol@{gotpc}rel32@lo
10133 // s_addc_u32 s1, s1, $symbol@{gotpc}rel32@hi
10134 //
10135 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10136 // fixups or relocations are emitted to replace $symbol@*@lo and
10137 // $symbol@*@hi with lower 32 bits and higher 32 bits of a literal constant,
10138 // which is a 64-bit pc-relative offset from the encoding of the $symbol
10139 // operand to the global variable.
10140 if (((const GCNSubtarget &)DAG.getSubtarget()).has64BitLiterals()) {
10141 assert(GAFlags != SIInstrInfo::MO_NONE);
10142
10143 SDValue Ptr =
10144 DAG.getTargetGlobalAddress(GV, DL, MVT::i64, Offset, GAFlags + 2);
10145 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET64, DL, PtrVT, Ptr);
10146 }
10147
10148 SDValue PtrLo = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags);
10149 SDValue PtrHi;
10150 if (GAFlags == SIInstrInfo::MO_NONE)
10151 PtrHi = DAG.getTargetConstant(0, DL, MVT::i32);
10152 else
10153 PtrHi = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags + 1);
10154 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET, DL, PtrVT, PtrLo, PtrHi);
10155}
10156
10157SDValue SITargetLowering::LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI,
10158 SDValue Op,
10159 SelectionDAG &DAG) const {
10160 GlobalAddressSDNode *GSD = cast<GlobalAddressSDNode>(Op);
10161 SDLoc DL(GSD);
10162 EVT PtrVT = Op.getValueType();
10163
10164 const GlobalValue *GV = GSD->getGlobal();
10165 const unsigned AS = GSD->getAddressSpace();
10166 if (((AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::BARRIER) &&
10169 if (AS == AMDGPUAS::LOCAL_ADDRESS && GV->hasExternalLinkage()) {
10170 const GlobalVariable &GVar = *cast<GlobalVariable>(GV);
10171 // HIP uses an unsized array `extern __shared__ T s[]` or similar
10172 // zero-sized type in other languages to declare the dynamic shared
10173 // memory which size is not known at the compile time. They will be
10174 // allocated by the runtime and placed directly after the static
10175 // allocated ones. They all share the same offset.
10176 if (GVar.getGlobalSize(GVar.getDataLayout()) == 0) {
10177 assert(PtrVT == MVT::i32 && "32-bit pointer is expected.");
10178 // Adjust alignment for that dynamic shared memory array.
10180 MFI->setDynLDSAlign(F, GVar);
10181 MFI->setUsesDynamicLDS(true);
10182 return SDValue(
10183 DAG.getMachineNode(AMDGPU::GET_GROUPSTATICSIZE, DL, PtrVT), 0);
10184 }
10185 }
10187 }
10188
10189 if (AS == AMDGPUAS::BARRIER) {
10190 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, GSD->getOffset(),
10192 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0);
10193 }
10194
10195 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
10196 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, GSD->getOffset(),
10198 return DAG.getNode(AMDGPUISD::LDS, DL, MVT::i32, GA);
10199 }
10200
10201 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10202 if (Subtarget->has64BitLiterals()) {
10203 SDValue Addr = DAG.getTargetGlobalAddress(
10204 GV, DL, MVT::i64, GSD->getOffset(), SIInstrInfo::MO_ABS64);
10205 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B64, DL, MVT::i64, Addr),
10206 0);
10207 }
10208
10209 SDValue AddrLo = DAG.getTargetGlobalAddress(
10210 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_LO);
10211 AddrLo = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrLo), 0};
10212
10213 SDValue AddrHi = DAG.getTargetGlobalAddress(
10214 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_HI);
10215 AddrHi = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrHi), 0};
10216
10217 return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, AddrLo, AddrHi);
10218 }
10219
10220 if (shouldEmitFixup(GV))
10221 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT);
10222
10223 if (shouldEmitPCReloc(GV))
10224 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT,
10226
10227 SDValue GOTAddr = buildPCRelGlobalAddress(DAG, GV, DL, 0, PtrVT,
10229 PointerType *PtrTy =
10231 const DataLayout &DataLayout = DAG.getDataLayout();
10232 Align Alignment = DataLayout.getABITypeAlign(PtrTy);
10233 MachinePointerInfo PtrInfo =
10235
10236 return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), GOTAddr, PtrInfo, Alignment,
10239}
10240
10241SDValue SITargetLowering::LowerExternalSymbol(SDValue Op,
10242 SelectionDAG &DAG) const {
10243 // TODO: Handle this. It should be mostly the same as LowerGlobalAddress.
10244 const Function &Fn = DAG.getMachineFunction().getFunction();
10245 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10246 Fn, "unsupported external symbol", Op.getDebugLoc()));
10247 return DAG.getPOISON(Op.getValueType());
10248}
10249
10251 const SDLoc &DL, SDValue V) const {
10252 // We can't use S_MOV_B32 directly, because there is no way to specify m0 as
10253 // the destination register.
10254 //
10255 // We can't use CopyToReg, because MachineCSE won't combine COPY instructions,
10256 // so we will end up with redundant moves to m0.
10257 //
10258 // We use a pseudo to ensure we emit s_mov_b32 with m0 as the direct result.
10259
10260 // A Null SDValue creates a glue result.
10261 SDNode *M0 = DAG.getMachineNode(AMDGPU::SI_INIT_M0, DL, MVT::Other, MVT::Glue,
10262 V, Chain);
10263 return SDValue(M0, 0);
10264}
10265
10266SDValue SITargetLowering::lowerImplicitZextParam(SelectionDAG &DAG, SDValue Op,
10267 MVT VT,
10268 unsigned Offset) const {
10269 SDLoc SL(Op);
10270 SDValue Param = lowerKernargMemParameter(
10271 DAG, MVT::i32, MVT::i32, SL, DAG.getEntryNode(), Offset, Align(4), false);
10272 // The local size values will have the hi 16-bits as zero.
10273 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Param,
10274 DAG.getValueType(VT));
10275}
10276
10278 EVT VT) {
10281 "non-hsa intrinsic with hsa target", DL.getDebugLoc()));
10282 return DAG.getPOISON(VT);
10283}
10284
10286 EVT VT) {
10289 "intrinsic not supported on subtarget", DL.getDebugLoc()));
10290 return DAG.getPOISON(VT);
10291}
10292
10294 ArrayRef<SDValue> Elts) {
10295 assert(!Elts.empty());
10296 MVT Type;
10297 unsigned NumElts = Elts.size();
10298
10299 if (NumElts <= 12) {
10300 Type = MVT::getVectorVT(MVT::f32, NumElts);
10301 } else {
10302 assert(Elts.size() <= 16);
10303 Type = MVT::v16f32;
10304 NumElts = 16;
10305 }
10306
10307 SmallVector<SDValue, 16> VecElts(NumElts);
10308 for (unsigned i = 0; i < Elts.size(); ++i) {
10309 SDValue Elt = Elts[i];
10310 if (Elt.getValueType() != MVT::f32)
10311 Elt = DAG.getBitcast(MVT::f32, Elt);
10312 VecElts[i] = Elt;
10313 }
10314 for (unsigned i = Elts.size(); i < NumElts; ++i)
10315 VecElts[i] = DAG.getPOISON(MVT::f32);
10316
10317 if (NumElts == 1)
10318 return VecElts[0];
10319 return DAG.getBuildVector(Type, DL, VecElts);
10320}
10321
10322static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT,
10323 SDValue Src, int ExtraElts) {
10324 EVT SrcVT = Src.getValueType();
10325
10327
10328 if (SrcVT.isVector())
10329 DAG.ExtractVectorElements(Src, Elts);
10330 else
10331 Elts.push_back(Src);
10332
10333 SDValue Undef = DAG.getPOISON(SrcVT.getScalarType());
10334 while (ExtraElts--)
10335 Elts.push_back(Undef);
10336
10337 return DAG.getBuildVector(CastVT, DL, Elts);
10338}
10339
10340// Re-construct the required return value for a image load intrinsic.
10341// This is more complicated due to the optional use TexFailCtrl which means the
10342// required return type is an aggregate
10344 ArrayRef<EVT> ResultTypes, bool IsTexFail,
10345 bool Unpacked, bool IsD16, int DMaskPop,
10346 int NumVDataDwords, bool IsAtomicPacked16Bit,
10347 const SDLoc &DL) {
10348 // Determine the required return type. This is the same regardless of
10349 // IsTexFail flag
10350 EVT ReqRetVT = ResultTypes[0];
10351 int ReqRetNumElts = ReqRetVT.isVector() ? ReqRetVT.getVectorNumElements() : 1;
10352 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10353 ? (ReqRetNumElts + 1) / 2
10354 : ReqRetNumElts;
10355
10356 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10357
10358 MVT DataDwordVT =
10359 NumDataDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, NumDataDwords);
10360
10361 MVT MaskPopVT =
10362 MaskPopDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, MaskPopDwords);
10363
10364 SDValue Data(Result, 0);
10365 SDValue TexFail;
10366
10367 if (DMaskPop > 0 && Data.getValueType() != MaskPopVT) {
10368 SDValue ZeroIdx = DAG.getConstant(0, DL, MVT::i32);
10369 if (MaskPopVT.isVector()) {
10370 Data = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, MaskPopVT,
10371 SDValue(Result, 0), ZeroIdx);
10372 } else {
10373 Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MaskPopVT,
10374 SDValue(Result, 0), ZeroIdx);
10375 }
10376 }
10377
10378 if (DataDwordVT.isVector() && !IsAtomicPacked16Bit)
10379 Data = padEltsToUndef(DAG, DL, DataDwordVT, Data,
10380 NumDataDwords - MaskPopDwords);
10381
10382 if (IsD16)
10383 Data = adjustLoadValueTypeImpl(Data, ReqRetVT, DL, DAG, Unpacked);
10384
10385 EVT LegalReqRetVT = ReqRetVT;
10386 if (!ReqRetVT.isVector()) {
10387 if (!Data.getValueType().isInteger())
10388 Data = DAG.getNode(ISD::BITCAST, DL,
10389 Data.getValueType().changeTypeToInteger(), Data);
10390 Data = DAG.getNode(ISD::TRUNCATE, DL, ReqRetVT.changeTypeToInteger(), Data);
10391 } else {
10392 // We need to widen the return vector to a legal type
10393 if ((ReqRetVT.getVectorNumElements() % 2) == 1 &&
10394 ReqRetVT.getVectorElementType().getSizeInBits() == 16) {
10395 LegalReqRetVT =
10397 ReqRetVT.getVectorNumElements() + 1);
10398 }
10399 }
10400 Data = DAG.getNode(ISD::BITCAST, DL, LegalReqRetVT, Data);
10401
10402 if (IsTexFail) {
10403 TexFail =
10404 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, SDValue(Result, 0),
10405 DAG.getConstant(MaskPopDwords, DL, MVT::i32));
10406
10407 return DAG.getMergeValues({Data, TexFail, SDValue(Result, 1)}, DL);
10408 }
10409
10410 if (Result->getNumValues() == 1)
10411 return Data;
10412
10413 return DAG.getMergeValues({Data, SDValue(Result, 1)}, DL);
10414}
10415
10416static bool parseTexFail(SDValue TexFailCtrl, SelectionDAG &DAG, SDValue *TFE,
10417 SDValue *LWE, bool &IsTexFail) {
10418 auto *TexFailCtrlConst = cast<ConstantSDNode>(TexFailCtrl.getNode());
10419
10420 uint64_t Value = TexFailCtrlConst->getZExtValue();
10421 if (Value) {
10422 IsTexFail = true;
10423 }
10424
10425 SDLoc DL(TexFailCtrlConst);
10426 *TFE = DAG.getTargetConstant((Value & 0x1) ? 1 : 0, DL, MVT::i32);
10427 Value &= ~(uint64_t)0x1;
10428 *LWE = DAG.getTargetConstant((Value & 0x2) ? 1 : 0, DL, MVT::i32);
10429 Value &= ~(uint64_t)0x2;
10430
10431 return Value == 0;
10432}
10433
10435 MVT PackVectorVT,
10436 SmallVectorImpl<SDValue> &PackedAddrs,
10437 unsigned DimIdx, unsigned EndIdx,
10438 unsigned NumGradients) {
10439 SDLoc DL(Op);
10440 for (unsigned I = DimIdx; I < EndIdx; I++) {
10441 SDValue Addr = Op.getOperand(I);
10442
10443 // Gradients are packed with undef for each coordinate.
10444 // In <hi 16 bit>,<lo 16 bit> notation, the registers look like this:
10445 // 1D: undef,dx/dh; undef,dx/dv
10446 // 2D: dy/dh,dx/dh; dy/dv,dx/dv
10447 // 3D: dy/dh,dx/dh; undef,dz/dh; dy/dv,dx/dv; undef,dz/dv
10448 if (((I + 1) >= EndIdx) ||
10449 ((NumGradients / 2) % 2 == 1 && (I == DimIdx + (NumGradients / 2) - 1 ||
10450 I == DimIdx + NumGradients - 1))) {
10451 if (Addr.getValueType() != MVT::i16)
10452 Addr = DAG.getBitcast(MVT::i16, Addr);
10453 Addr = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Addr);
10454 } else {
10455 Addr = DAG.getBuildVector(PackVectorVT, DL, {Addr, Op.getOperand(I + 1)});
10456 I++;
10457 }
10458 Addr = DAG.getBitcast(MVT::f32, Addr);
10459 PackedAddrs.push_back(Addr);
10460 }
10461}
10462
10463/// Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and
10464/// return poison values of \p ResultTypes, preserving the chain if present.
10466 ArrayRef<EVT> ResultTypes,
10467 const SDLoc &DL, const Twine &Msg) {
10469 DAG.getMachineFunction().getFunction(), Msg, DL.getDebugLoc()));
10470 return DAG.getErrorMergeValues(ResultTypes, Op.getOperand(0), DL);
10471}
10472
10473SDValue SITargetLowering::lowerImage(SDValue Op,
10475 SelectionDAG &DAG, bool WithChain) const {
10476 SDLoc DL(Op);
10478 const GCNSubtarget *ST = &MF.getSubtarget<GCNSubtarget>();
10479 unsigned IntrOpcode = Intr->BaseOpcode;
10480 // For image atomic: use no-return opcode if result is unused.
10481 if (Intr->AtomicNoRetBaseOpcode != Intr->BaseOpcode &&
10482 !Op.getNode()->hasAnyUseOfValue(0))
10483 IntrOpcode = Intr->AtomicNoRetBaseOpcode;
10484 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10486 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfo(Intr->Dim);
10487 bool IsGFX10Plus = AMDGPU::isGFX10Plus(*Subtarget);
10488 bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
10489 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
10490 bool IsGFX13 = AMDGPU::isGFX13(*Subtarget);
10491
10492 SmallVector<EVT, 3> ResultTypes(Op->values());
10493 SmallVector<EVT, 3> OrigResultTypes(Op->values());
10494 if (BaseOpcode->NoReturn && BaseOpcode->Atomic)
10495 ResultTypes.erase(&ResultTypes[0]);
10496
10497 bool IsD16 = false;
10498 bool IsG16 = false;
10499 bool IsA16 = false;
10500 SDValue VData;
10501 int NumVDataDwords = 0;
10502 bool AdjustRetType = false;
10503 bool IsAtomicPacked16Bit = false;
10504
10505 // Offset of intrinsic arguments
10506 const unsigned ArgOffset = WithChain ? 2 : 1;
10507
10508 unsigned DMask;
10509 unsigned DMaskLanes = 0;
10510
10511 if (BaseOpcode->Atomic) {
10512 VData = Op.getOperand(2);
10513
10514 IsAtomicPacked16Bit =
10515 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10516 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10517 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10518 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10519
10520 if (!IsAtomicPacked16Bit && VData.getValueSizeInBits() != 32 &&
10521 VData.getValueSizeInBits() != 64) {
10522 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10523 "unsupported image atomic data type");
10524 }
10525
10526 bool Is64Bit = VData.getValueSizeInBits() == 64;
10527 if (BaseOpcode->AtomicX2) {
10528 SDValue VData2 = Op.getOperand(3);
10529 VData = DAG.getBuildVector(Is64Bit ? MVT::v2i64 : MVT::v2i32, DL,
10530 {VData, VData2});
10531 if (Is64Bit)
10532 VData = DAG.getBitcast(MVT::v4i32, VData);
10533
10534 if (!BaseOpcode->NoReturn)
10535 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10536
10537 DMask = Is64Bit ? 0xf : 0x3;
10538 NumVDataDwords = Is64Bit ? 4 : 2;
10539 } else {
10540 DMask = Is64Bit ? 0x3 : 0x1;
10541 NumVDataDwords = Is64Bit ? 2 : 1;
10542 }
10543 } else {
10544 DMask = Op->getConstantOperandVal(ArgOffset + Intr->DMaskIndex);
10545 DMaskLanes = BaseOpcode->Gather4 ? 4 : llvm::popcount(DMask);
10546
10547 if (BaseOpcode->Store) {
10548 VData = Op.getOperand(2);
10549
10550 MVT StoreVT = VData.getSimpleValueType();
10551 MVT StoreScalarVT = StoreVT.getScalarType();
10552 if (StoreScalarVT != MVT::f16 && StoreScalarVT.getSizeInBits() != 32 &&
10553 StoreScalarVT.getSizeInBits() != 64) {
10554 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10555 "unsupported image store data type");
10556 }
10557 if (StoreScalarVT == MVT::f16) {
10558 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10559 return Op; // D16 is unsupported for this instruction
10560
10561 IsD16 = true;
10562 VData = handleD16VData(VData, DAG, true);
10563 }
10564
10565 NumVDataDwords = (VData.getValueType().getSizeInBits() + 31) / 32;
10566 } else if (!BaseOpcode->NoReturn) {
10567 // Work out the num dwords based on the dmask popcount and underlying type
10568 // and whether packing is supported.
10569 MVT LoadVT = ResultTypes[0].getSimpleVT();
10570 MVT LoadScalarVT = LoadVT.getScalarType();
10571 if (LoadScalarVT != MVT::f16 && LoadScalarVT.getSizeInBits() != 32 &&
10572 LoadScalarVT.getSizeInBits() != 64) {
10573 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10574 "unsupported image load data type");
10575 }
10576 if (LoadScalarVT == MVT::f16) {
10577 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10578 return Op; // D16 is unsupported for this instruction
10579
10580 IsD16 = true;
10581 }
10582
10583 // Confirm that the return type is large enough for the dmask specified
10584 if ((LoadVT.isVector() && LoadVT.getVectorNumElements() < DMaskLanes) ||
10585 (!LoadVT.isVector() && DMaskLanes > 1))
10586 return Op;
10587
10588 // The sq block of gfx8 and gfx9 do not estimate register use correctly
10589 // for d16 image_gather4, image_gather4_l, and image_gather4_lz
10590 // instructions.
10591 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10592 !(BaseOpcode->Gather4 && Subtarget->hasImageGather4D16Bug()))
10593 NumVDataDwords = (DMaskLanes + 1) / 2;
10594 else
10595 NumVDataDwords = DMaskLanes;
10596
10597 AdjustRetType = true;
10598 }
10599 }
10600
10601 unsigned VAddrEnd = ArgOffset + Intr->VAddrEnd;
10603
10604 // Check for 16 bit addresses or derivatives and pack if true.
10605 MVT VAddrVT =
10606 Op.getOperand(ArgOffset + Intr->GradientStart).getSimpleValueType();
10607 MVT VAddrScalarVT = VAddrVT.getScalarType();
10608 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10609 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10610
10611 VAddrVT = Op.getOperand(ArgOffset + Intr->CoordStart).getSimpleValueType();
10612 VAddrScalarVT = VAddrVT.getScalarType();
10613 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10614 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10615
10616 // Push back extra arguments.
10617 for (unsigned I = Intr->VAddrStart; I < Intr->GradientStart; I++) {
10618 if (IsA16 && (Op.getOperand(ArgOffset + I).getValueType() == MVT::f16)) {
10619 assert(I == Intr->BiasIndex && "Got unexpected 16-bit extra argument");
10620 // Special handling of bias when A16 is on. Bias is of type half but
10621 // occupies full 32-bit.
10622 SDValue Bias = DAG.getBuildVector(
10623 MVT::v2f16, DL,
10624 {Op.getOperand(ArgOffset + I), DAG.getPOISON(MVT::f16)});
10625 VAddrs.push_back(Bias);
10626 } else {
10627 assert((!IsA16 || Intr->NumBiasArgs == 0 || I != Intr->BiasIndex) &&
10628 "Bias needs to be converted to 16 bit in A16 mode");
10629 VAddrs.push_back(Op.getOperand(ArgOffset + I));
10630 }
10631 }
10632
10633 if (BaseOpcode->Gradients && !ST->hasG16() && (IsA16 != IsG16)) {
10634 // 16 bit gradients are supported, but are tied to the A16 control
10635 // so both gradients and addresses must be 16 bit
10636 LLVM_DEBUG(
10637 dbgs() << "Failed to lower image intrinsic: 16 bit addresses "
10638 "require 16 bit args for both gradients and addresses");
10639 return Op;
10640 }
10641
10642 if (IsA16) {
10643 if (!ST->hasA16()) {
10644 LLVM_DEBUG(dbgs() << "Failed to lower image intrinsic: Target does not "
10645 "support 16 bit addresses\n");
10646 return Op;
10647 }
10648 }
10649
10650 // We've dealt with incorrect input so we know that if IsA16, IsG16
10651 // are set then we have to compress/pack operands (either address,
10652 // gradient or both)
10653 // In the case where a16 and gradients are tied (no G16 support) then we
10654 // have already verified that both IsA16 and IsG16 are true
10655 if (BaseOpcode->Gradients && IsG16 && ST->hasG16()) {
10656 // Activate g16
10657 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10659 IntrOpcode = G16MappingInfo->G16; // set new opcode to variant with _g16
10660 }
10661
10662 // Add gradients (packed or unpacked)
10663 if (IsG16) {
10664 // Pack the gradients
10665 // const int PackEndIdx = IsA16 ? VAddrEnd : (ArgOffset + Intr->CoordStart);
10666 packImage16bitOpsToDwords(DAG, Op, GradPackVectorVT, VAddrs,
10667 ArgOffset + Intr->GradientStart,
10668 ArgOffset + Intr->CoordStart, Intr->NumGradients);
10669 } else {
10670 for (unsigned I = ArgOffset + Intr->GradientStart;
10671 I < ArgOffset + Intr->CoordStart; I++)
10672 VAddrs.push_back(Op.getOperand(I));
10673 }
10674
10675 // Add addresses (packed or unpacked)
10676 if (IsA16) {
10677 packImage16bitOpsToDwords(DAG, Op, AddrPackVectorVT, VAddrs,
10678 ArgOffset + Intr->CoordStart, VAddrEnd,
10679 0 /* No gradients */);
10680 } else {
10681 // Add uncompressed address
10682 for (unsigned I = ArgOffset + Intr->CoordStart; I < VAddrEnd; I++)
10683 VAddrs.push_back(Op.getOperand(I));
10684 }
10685
10686 // If the register allocator cannot place the address registers contiguously
10687 // without introducing moves, then using the non-sequential address encoding
10688 // is always preferable, since it saves VALU instructions and is usually a
10689 // wash in terms of code size or even better.
10690 //
10691 // However, we currently have no way of hinting to the register allocator that
10692 // MIMG addresses should be placed contiguously when it is possible to do so,
10693 // so force non-NSA for the common 2-address case as a heuristic.
10694 //
10695 // SIShrinkInstructions will convert NSA encodings to non-NSA after register
10696 // allocation when possible.
10697 //
10698 // Partial NSA is allowed on GFX11+ where the final register is a contiguous
10699 // set of the remaining addresses.
10700 const unsigned NSAMaxSize = ST->getNSAMaxSize(BaseOpcode->Sampler);
10701 const bool HasPartialNSAEncoding = ST->hasPartialNSAEncoding();
10702 const bool UseNSA = ST->hasNSAEncoding() &&
10703 VAddrs.size() >= ST->getNSAThreshold(MF) &&
10704 (VAddrs.size() <= NSAMaxSize || HasPartialNSAEncoding);
10705 const bool UsePartialNSA =
10706 UseNSA && HasPartialNSAEncoding && VAddrs.size() > NSAMaxSize;
10707
10708 SDValue VAddr;
10709 if (UsePartialNSA) {
10710 VAddr = getBuildDwordsVector(DAG, DL,
10711 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10712 } else if (!UseNSA) {
10713 VAddr = getBuildDwordsVector(DAG, DL, VAddrs);
10714 }
10715
10716 SDValue True = DAG.getTargetConstant(1, DL, MVT::i1);
10717 SDValue False = DAG.getTargetConstant(0, DL, MVT::i1);
10718 SDValue Unorm;
10719 if (!BaseOpcode->Sampler) {
10720 Unorm = True;
10721 } else {
10722 uint64_t UnormConst =
10723 Op.getConstantOperandVal(ArgOffset + Intr->UnormIndex);
10724
10725 Unorm = UnormConst ? True : False;
10726 }
10727
10728 SDValue TFE;
10729 SDValue LWE;
10730 SDValue TexFail = Op.getOperand(ArgOffset + Intr->TexFailCtrlIndex);
10731 bool IsTexFail = false;
10732 if (!parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10733 return Op;
10734
10735 if (IsTexFail) {
10736 if (!DMaskLanes) {
10737 // Expecting to get an error flag since TFC is on - and dmask is 0
10738 // Force dmask to be at least 1 otherwise the instruction will fail
10739 DMask = 0x1;
10740 DMaskLanes = 1;
10741 NumVDataDwords = 1;
10742 }
10743 NumVDataDwords += 1;
10744 AdjustRetType = true;
10745 }
10746
10747 // Has something earlier tagged that the return type needs adjusting
10748 // This happens if the instruction is a load or has set TexFailCtrl flags
10749 if (AdjustRetType) {
10750 // NumVDataDwords reflects the true number of dwords required in the return
10751 // type
10752 if (DMaskLanes == 0 && !BaseOpcode->Store) {
10753 // This is a no-op load. This can be eliminated
10754 SDValue Undef = DAG.getPOISON(Op.getValueType());
10755 if (isa<MemSDNode>(Op))
10756 return DAG.getMergeValues({Undef, Op.getOperand(0)}, DL);
10757 return Undef;
10758 }
10759
10760 EVT NewVT = NumVDataDwords > 1 ? EVT::getVectorVT(*DAG.getContext(),
10761 MVT::i32, NumVDataDwords)
10762 : MVT::i32;
10763
10764 ResultTypes[0] = NewVT;
10765 if (ResultTypes.size() == 3) {
10766 // Original result was aggregate type used for TexFailCtrl results
10767 // The actual instruction returns as a vector type which has now been
10768 // created. Remove the aggregate result.
10769 ResultTypes.erase(&ResultTypes[1]);
10770 }
10771 }
10772
10773 unsigned CPol = Op.getConstantOperandVal(ArgOffset + Intr->CachePolicyIndex);
10774 // Keep GLC only when the atomic's result is actually used.
10775 if (BaseOpcode->Atomic && !BaseOpcode->NoReturn)
10777 if (CPol & ~((IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12) |
10779 return Op;
10780
10782 if (BaseOpcode->Store || BaseOpcode->Atomic)
10783 Ops.push_back(VData); // vdata
10784 if (UsePartialNSA) {
10785 append_range(Ops, ArrayRef(VAddrs).take_front(NSAMaxSize - 1));
10786 Ops.push_back(VAddr);
10787 } else if (UseNSA)
10788 append_range(Ops, VAddrs);
10789 else
10790 Ops.push_back(VAddr);
10791 SDValue Rsrc = Op.getOperand(ArgOffset + Intr->RsrcIndex);
10792 EVT RsrcVT = Rsrc.getValueType();
10793 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32)
10794 return Op;
10795 Ops.push_back(Rsrc);
10796 if (BaseOpcode->Sampler) {
10797 SDValue Samp = Op.getOperand(ArgOffset + Intr->SampIndex);
10798 if (Samp.getValueType() != MVT::v4i32)
10799 return Op;
10800 Ops.push_back(Samp);
10801 }
10802 Ops.push_back(DAG.getTargetConstant(DMask, DL, MVT::i32));
10803 if (IsGFX10Plus)
10804 Ops.push_back(DAG.getTargetConstant(DimInfo->Encoding, DL, MVT::i32));
10805 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10806 Ops.push_back(Unorm);
10807 Ops.push_back(DAG.getTargetConstant(CPol, DL, MVT::i32));
10808 Ops.push_back(IsA16 && // r128, a16 for gfx9
10809 ST->hasFeature(AMDGPU::FeatureR128A16)
10810 ? True
10811 : False);
10812 if (IsGFX10Plus)
10813 Ops.push_back(IsA16 ? True : False);
10814
10815 if (!Subtarget->hasGFX90AInsts())
10816 Ops.push_back(TFE); // tfe
10817 else if (TFE->getAsZExtVal()) {
10818 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10820 "TFE is not supported on this GPU", DL.getDebugLoc()));
10821 }
10822
10823 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10824 Ops.push_back(LWE); // lwe
10825 if (!IsGFX10Plus)
10826 Ops.push_back(DimInfo->DA ? True : False);
10827 if (BaseOpcode->HasD16)
10828 Ops.push_back(IsD16 ? True : False);
10829 if (isa<MemSDNode>(Op))
10830 Ops.push_back(Op.getOperand(0)); // chain
10831
10832 int NumVAddrDwords =
10833 UseNSA ? VAddrs.size() : VAddr.getValueType().getSizeInBits() / 32;
10834 int Opcode = -1;
10835
10836 if (IsGFX13) {
10837 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx13,
10838 NumVDataDwords, NumVAddrDwords);
10839 } else if (IsGFX12Plus) {
10840 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx12,
10841 NumVDataDwords, NumVAddrDwords);
10842 } else if (IsGFX11Plus) {
10843 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10844 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10845 : AMDGPU::MIMGEncGfx11Default,
10846 NumVDataDwords, NumVAddrDwords);
10847 } else if (IsGFX10Plus) {
10848 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10849 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10850 : AMDGPU::MIMGEncGfx10Default,
10851 NumVDataDwords, NumVAddrDwords);
10852 } else {
10853 if (Subtarget->hasGFX90AInsts()) {
10854 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx90a,
10855 NumVDataDwords, NumVAddrDwords);
10856 if (Opcode == -1) {
10858 DAG, Op, OrigResultTypes, DL,
10859 "requested image instruction is not supported on this GPU");
10860 }
10861 }
10862 if (Opcode == -1 &&
10863 Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10864 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx8,
10865 NumVDataDwords, NumVAddrDwords);
10866 if (Opcode == -1)
10867 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx6,
10868 NumVDataDwords, NumVAddrDwords);
10869 }
10870 if (Opcode == -1)
10871 return Op;
10872
10873 MachineSDNode *NewNode = DAG.getMachineNode(Opcode, DL, ResultTypes, Ops);
10874 if (auto *MemOp = dyn_cast<MemSDNode>(Op)) {
10875 MachineMemOperand *MemRef = MemOp->getMemOperand();
10876 DAG.setNodeMemRefs(NewNode, {MemRef});
10877 }
10878
10879 if (BaseOpcode->NoReturn) {
10880 if (BaseOpcode->Atomic)
10881 return DAG.getMergeValues(
10882 {DAG.getPOISON(OrigResultTypes[0]), SDValue(NewNode, 0)}, DL);
10883
10884 return SDValue(NewNode, 0);
10885 }
10886
10887 if (BaseOpcode->AtomicX2) {
10889 DAG.ExtractVectorElements(SDValue(NewNode, 0), Elt, 0, 1);
10890 return DAG.getMergeValues({Elt[0], SDValue(NewNode, 1)}, DL);
10891 }
10892
10893 return constructRetValue(DAG, NewNode, OrigResultTypes, IsTexFail,
10894 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10895 NumVDataDwords, IsAtomicPacked16Bit, DL);
10896}
10897
10898SDValue SITargetLowering::lowerSBuffer(EVT VT, EVT MemVT, SDLoc DL,
10899 SDValue Chain, SDValue Rsrc,
10900 SDValue Offset, SDValue CachePolicy,
10901 SelectionDAG &DAG,
10902 MachineMemOperand *MMO) const {
10904 bool HasChainResult = MMO != nullptr;
10905
10906 // SBUFFER_LOAD only produces values that fill whole SGPRs, apart from the
10907 // subword loads below.
10908 bool IsSubwordLoad = (MemVT == MVT::i8 || MemVT == MVT::i16) &&
10909 Subtarget->hasScalarSubwordLoads();
10910 if ((!isTypeLegal(VT) || VT.getSizeInBits() % 32 != 0) && !IsSubwordLoad) {
10911 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10912 MF.getFunction(), "unsupported s_buffer_load result type",
10913 DL.getDebugLoc()));
10914 EVT ResultTypes[] = {VT, MVT::Other};
10915 return DAG.getErrorMergeValues(
10916 ArrayRef(ResultTypes, HasChainResult ? 2 : 1), Chain, DL);
10917 }
10918
10919 if (!HasChainResult) {
10920 const DataLayout &DataLayout = DAG.getDataLayout();
10922 DataLayout.getABITypeAlign(MemVT.getTypeForEVT(*DAG.getContext()));
10923
10924 MMO = MF.getMachineMemOperand(MachinePointerInfo(),
10928 MemVT.getStoreSize(), Alignment);
10929 }
10930
10931 if (!Offset->isDivergent()) {
10932 SDValue Ops[] = {Chain, Rsrc, Offset, CachePolicy};
10933
10934 // Lower llvm.amdgcn.*s.buffer.load.{i,u}N intrinsics. First, generate
10935 // s_buffer_load_u* for signed and unsigned load instructions. Next, DAG
10936 // combiner tries to merge the s_buffer_load_uN with a sext instruction
10937 // (performSignExtendInRegCombine()) and it replaces s_buffer_load_uN with
10938 // s_buffer_load_iN.
10939 auto HandleScalarSubwordLoads = [&](unsigned Opcode) -> SDValue {
10940 SDValue BufferLoad = DAG.getMemIntrinsicNode(
10941 Opcode, DL, DAG.getVTList(MVT::i32, MVT::Other), Ops, MemVT, MMO);
10942 SDValue LoadVal = DAG.getAnyExtOrTrunc(
10943 DAG.getNode(ISD::TRUNCATE, DL, MemVT, BufferLoad), DL, VT);
10944 if (HasChainResult)
10945 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
10946 return LoadVal;
10947 };
10948 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10949 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10950
10951 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10952 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10953
10954 // Widen vec3 load to vec4. Only 32-bit elements have a vec4 pattern.
10955 if (VT.isVector() && VT.getVectorNumElements() == 3 &&
10956 VT.getVectorElementType().getSizeInBits() == 32 &&
10957 !Subtarget->hasScalarDwordx3Loads()) {
10958 EVT WidenedVT =
10960 auto WidenedOp = DAG.getMemIntrinsicNode(
10961 AMDGPUISD::SBUFFER_LOAD, DL, DAG.getVTList(WidenedVT, MVT::Other),
10962 Ops, WidenedVT,
10963 MF.getMachineMemOperand(MMO, 0, WidenedVT.getStoreSize()));
10964 auto Subvector = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, WidenedOp,
10965 DAG.getVectorIdxConstant(0, DL));
10966 if (HasChainResult)
10967 return DAG.getMergeValues({Subvector, WidenedOp.getValue(1)}, DL);
10968 return Subvector;
10969 }
10970
10971 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_LOAD, DL,
10972 DAG.getVTList(VT, MVT::Other), Ops, MemVT,
10973 MMO);
10974 }
10975
10976 // We have a divergent offset. Emit a MUBUF buffer load instead. We can
10977 // assume that the buffer is unswizzled.
10978 SDValue Ops[] = {
10979 Chain, // Chain
10980 Rsrc, // rsrc
10981 DAG.getConstant(0, DL, MVT::i32), // vindex
10982 {}, // voffset
10983 {}, // soffset
10984 {}, // offset
10985 CachePolicy, // cachepolicy
10986 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
10987 };
10988 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10989 Subtarget->hasScalarSubwordLoads()) {
10990 setBufferOffsets(Offset, DAG, &Ops[3], Align(4));
10991 SDValue Load = handleByteShortBufferLoads(DAG, MemVT, DL, Ops, MMO);
10992 SDValue LoadVal = DAG.getAnyExtOrTrunc(Load.getOperand(0), DL, VT);
10993 if (HasChainResult)
10994 return DAG.getMergeValues({LoadVal, Load.getOperand(1)}, DL);
10995 return LoadVal;
10996 }
10997
10999 unsigned NumLoads = 1;
11000 MVT LoadVT = VT.getSimpleVT();
11001 unsigned NumElts = LoadVT.isVector() ? LoadVT.getVectorNumElements() : 1;
11002 assert((LoadVT.getScalarType() == MVT::i32 ||
11003 LoadVT.getScalarType() == MVT::f32));
11004
11005 if (NumElts == 8 || NumElts == 16) {
11006 NumLoads = NumElts / 4;
11007 LoadVT = MVT::getVectorVT(LoadVT.getScalarType(), 4);
11008 }
11009
11010 SDVTList VTList = DAG.getVTList({LoadVT, MVT::Other});
11011
11012 // Use the alignment to ensure that the required offsets will fit into the
11013 // immediate offsets.
11014 setBufferOffsets(Offset, DAG, &Ops[3],
11015 NumLoads > 1 ? Align(16 * NumLoads) : Align(4));
11016
11017 uint64_t InstOffset = Ops[5]->getAsZExtVal();
11018 unsigned LoadSize = LoadVT.getStoreSize();
11019 for (unsigned i = 0; i < NumLoads; ++i) {
11020 Ops[5] = DAG.getTargetConstant(InstOffset + 16 * i, DL, MVT::i32);
11021 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(MMO, 16 * i, LoadSize);
11022 Loads.push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD, DL, VTList, Ops,
11023 LoadVT, LoadMMO, DAG));
11024 }
11025
11026 if (NumElts == 8 || NumElts == 16) {
11027 SDValue LoadVal = DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Loads);
11028 if (HasChainResult) {
11029 SmallVector<SDValue, 4> LoadChains;
11030 for (SDValue Load : Loads)
11031 LoadChains.push_back(Load.getValue(1));
11032 SDValue Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, LoadChains);
11033 return DAG.getMergeValues({LoadVal, Chain}, DL);
11034 }
11035 return LoadVal;
11036 }
11037
11038 return Loads[0];
11039}
11040
11041SDValue SITargetLowering::lowerWaveID(SelectionDAG &DAG, SDValue Op) const {
11042 // With architected SGPRs, waveIDinGroup is in TTMP8[29:25].
11043 if (!Subtarget->hasArchitectedSGPRs())
11044 return {};
11045 SDLoc SL(Op);
11046 MVT VT = MVT::i32;
11047 SDValue TTMP8 = DAG.getCopyFromReg(DAG.getEntryNode(), SL, AMDGPU::TTMP8, VT);
11048 return DAG.getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
11049 DAG.getConstant(25, SL, VT), DAG.getConstant(5, SL, VT));
11050}
11051
11052SDValue SITargetLowering::lowerConstHwRegRead(SelectionDAG &DAG, SDValue Op,
11053 AMDGPU::Hwreg::Id HwReg,
11054 unsigned LowBit,
11055 unsigned Width) const {
11056 SDLoc SL(Op);
11057 using namespace AMDGPU::Hwreg;
11058 return {DAG.getMachineNode(
11059 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
11060 DAG.getTargetConstant(HwregEncoding::encode(HwReg, LowBit, Width),
11061 SL, MVT::i32)),
11062 0};
11063}
11064
11065SDValue SITargetLowering::lowerWorkitemID(SelectionDAG &DAG, SDValue Op,
11066 unsigned Dim,
11067 const ArgDescriptor &Arg) const {
11068 SDLoc SL(Op);
11070 unsigned MaxID = Subtarget->getMaxWorkitemID(MF.getFunction(), Dim);
11071 if (MaxID == 0)
11072 return DAG.getConstant(0, SL, MVT::i32);
11073
11074 // It's undefined behavior if a function marked with the amdgpu-no-*
11075 // attributes uses the corresponding intrinsic.
11076 if (!Arg)
11077 return DAG.getPOISON(Op->getValueType(0));
11078
11079 SDValue Val = loadInputValue(DAG, &AMDGPU::VGPR_32RegClass, MVT::i32,
11080 SDLoc(DAG.getEntryNode()), Arg);
11081
11082 // Don't bother inserting AssertZext for packed IDs since we're emitting the
11083 // masking operations anyway.
11084 //
11085 // TODO: We could assert the top bit is 0 for the source copy.
11086 if (Arg.isMasked())
11087 return Val;
11088
11089 // Preserve the known bits after expansion to a copy.
11090 EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), llvm::bit_width(MaxID));
11091 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Val,
11092 DAG.getValueType(SmallVT));
11093}
11094
11095SDValue SITargetLowering::lowerFromFP8(SDValue Op, bool IsBF8,
11096 SelectionDAG &DAG) const {
11097 SDLoc SL(Op);
11098 SDValue Src = Op.getOperand(0);
11099 EVT DstVT = Op.getValueType();
11100 bool IsF16 = DstVT.getVectorElementType() == MVT::f16;
11101 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
11102 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11103
11104 unsigned Opc;
11105 if (IsF16)
11106 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11107 else
11108 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11109
11110 // Pack the two i8 lanes into the integer type the packed HW node reads. The
11111 // f16 form takes i16 and the f32 form takes i32. v2i8 bitcasts to i16
11112 // directly and the f32 node reads the low half of an any-extended i32.
11113 EVT PackedVT =
11115 SDValue AsI16 = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
11116 SDValue Packed = DAG.getAnyExtOrTrunc(AsI16, SL, PackedVT);
11117 return DAG.getNode(Opc, SL, DstVT, Packed);
11118}
11119
11120SDValue
11121SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(SDValue Op,
11122 SelectionDAG &DAG) const {
11123 // Handle the OCP FP8 formats (E4M3FN, E5M2) and unsigned E5M3 on subtargets
11124 // with matching HW conversions. Other formats use the generic expansion.
11125 APFloatBase::Semantics FPSemantic =
11126 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11127 const bool IsFP8 = FPSemantic == APFloatBase::S_Float8E4M3FN;
11128 const bool IsBF8 = FPSemantic == APFloatBase::S_Float8E5M2;
11129 const bool IsE5M3 = FPSemantic == APFloatBase::S_Float8E5M3FNU;
11130 const bool HasE5M3ConversionInsts =
11131 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11132 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11133 if (!IsSupported)
11134 return SDValue();
11135
11136 EVT DstVT = Op.getValueType();
11137 // The custom action for a v2i8 source also reaches half conversions on
11138 // targets which only have FP8-to-f32 instructions.
11139 if (DstVT.getScalarType() == MVT::f16 &&
11140 !Subtarget->hasFP8F16ConversionInsts())
11141 return SDValue();
11142
11143 if (IsE5M3) {
11144 if (DstVT.getScalarType() != MVT::f32)
11145 return SDValue();
11146
11147 SDLoc SL(Op);
11148 SDValue Src = Op.getOperand(0);
11149 assert((!DstVT.isVector() || DstVT == MVT::v2f32) &&
11150 "only the v2f32 vector result is custom lowered");
11151
11152 if (DstVT.isVector())
11153 Src = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
11154 Src = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
11155
11156 auto ConvertByte = [&](unsigned ByteSel) {
11157 return DAG.getNode(AMDGPUISD::CVT_F32_FP8_E5M3, SL, MVT::f32, Src,
11158 DAG.getTargetConstant(ByteSel, SL, MVT::i32));
11159 };
11160
11161 if (!DstVT.isVector())
11162 return ConvertByte(0);
11163 return DAG.getBuildVector(DstVT, SL, {ConvertByte(0), ConvertByte(1)});
11164 }
11165
11166 if (!DstVT.isVector()) {
11167 SDValue Src = Op.getOperand(0);
11168 if (Src.getValueType() != MVT::i32) {
11169 SDLoc SL(Op);
11170 SDValue SrcI32 = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
11171 return DAG.getNode(ISD::CONVERT_FROM_ARBITRARY_FP, SL, DstVT, SrcI32,
11172 Op.getOperand(1));
11173 }
11174 return Op;
11175 }
11176
11177 EVT EltVT = DstVT.getVectorElementType();
11178 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11179 return lowerFromFP8(Op, IsBF8, DAG);
11180 return SDValue();
11181}
11182
11183SDValue SITargetLowering::lowerToFP8(SDValue Op, bool IsBF8, bool IsE5M3,
11184 SelectionDAG &DAG) const {
11185 SDLoc SL(Op);
11186 SDValue Src = Op.getOperand(0);
11187 EVT ResVT = Op.getValueType();
11188 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11189 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11190 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11191 assert((!ResVT.isVector() || ResVT == MVT::v2i8) &&
11192 "only the v2i8 vector result is custom lowered");
11193
11194 if (IsF16) {
11195 unsigned Opc =
11196 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11197 SDValue Bytes = DAG.getNode(Opc, SL, MVT::i16, Src);
11198 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11199 }
11200
11201 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32
11202 : IsE5M3 ? AMDGPUISD::CVT_PK_FP8_F32_E5M3
11203 : AMDGPUISD::CVT_PK_FP8_F32;
11204 SDValue PoisonI32 = DAG.getPOISON(MVT::i32);
11205 SDValue WordSel = DAG.getTargetConstant(0, SL, MVT::i1);
11206
11207 if (!ResVT.isVector()) {
11208 // Convert one lane, the second is unused. Feed it the same source so the
11209 // instruction does not read an undefined register.
11210 SDValue Packed =
11211 DAG.getNode(Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11212 return DAG.getAnyExtOrTrunc(Packed, SL, ResVT);
11213 }
11214
11215 SDValue A = DAG.getExtractVectorElt(SL, MVT::f32, Src, 0);
11216 SDValue B = DAG.getExtractVectorElt(SL, MVT::f32, Src, 1);
11217 SDValue Packed = DAG.getNode(Opc, SL, MVT::i32, A, B, PoisonI32, WordSel);
11218 SDValue Bytes = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Packed);
11219 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11220}
11221
11222SDValue
11223SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(SDValue Op,
11224 SelectionDAG &DAG) const {
11225 // The OCP FP8 formats (E4M3FN, E5M2) and unsigned E5M3 map to HW conversions
11226 // on subtargets that support them. Everything else uses generic expansion.
11228 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11229 const bool IsFP8 = Sem == APFloatBase::S_Float8E4M3FN;
11230 const bool IsBF8 = Sem == APFloatBase::S_Float8E5M2;
11231 const bool IsE5M3 = Sem == APFloatBase::S_Float8E5M3FNU;
11232 const bool HasE5M3ConversionInsts =
11233 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11234 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11235 if (!IsSupported)
11236 return SDValue();
11237
11238 // The HW conversions only support nearest-even. The OCP conversions do not
11239 // saturate. The unsigned E5M3 conversion always clamps out-of-range inputs,
11240 // which also refines the non-saturating form where those inputs are poison.
11241 if (static_cast<RoundingMode>(Op.getConstantOperandVal(2)) !=
11243 return SDValue();
11244 if (!IsE5M3 && Op.getConstantOperandVal(3) != 0)
11245 return SDValue();
11246
11247 EVT SrcEltVT = Op.getOperand(0).getValueType().getScalarType();
11248 // The f32 form is built here rather than by a tablegen pattern because the
11249 // HW result is i32 while the node result is i16 after the i8 promotion.
11250 if (SrcEltVT == MVT::f32)
11251 return lowerToFP8(Op, IsBF8, IsE5M3, DAG);
11252 if (!IsE5M3 && SrcEltVT == MVT::f16 &&
11253 Subtarget->hasF16FP8ConversionInsts()) {
11254 // A scalar conversion is selected from the generic node by tablegen, only
11255 // the illegal v2i8 result type needs lowering here.
11256 if (!Op.getValueType().isVector())
11257 return Op;
11258 return lowerToFP8(Op, IsBF8, false, DAG);
11259 }
11260 return SDValue();
11261}
11262
11263SDValue SITargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
11264 SelectionDAG &DAG) const {
11266 auto *MFI = MF.getInfo<SIMachineFunctionInfo>();
11267
11268 EVT VT = Op.getValueType();
11269 SDLoc DL(Op);
11270 unsigned IntrinsicID = Op.getConstantOperandVal(0);
11271
11272 // TODO: Should this propagate fast-math-flags?
11273
11274 switch (IntrinsicID) {
11275 case Intrinsic::amdgcn_wave_reduce_min:
11276 case Intrinsic::amdgcn_wave_reduce_umin:
11277 case Intrinsic::amdgcn_wave_reduce_fmin:
11278 case Intrinsic::amdgcn_wave_reduce_max:
11279 case Intrinsic::amdgcn_wave_reduce_umax:
11280 case Intrinsic::amdgcn_wave_reduce_fmax:
11281 case Intrinsic::amdgcn_wave_reduce_add:
11282 case Intrinsic::amdgcn_wave_reduce_fadd:
11283 case Intrinsic::amdgcn_wave_reduce_sub:
11284 case Intrinsic::amdgcn_wave_reduce_fsub:
11285 case Intrinsic::amdgcn_wave_reduce_and:
11286 case Intrinsic::amdgcn_wave_reduce_or:
11287 case Intrinsic::amdgcn_wave_reduce_xor: {
11288 EVT SrcVT = Op.getOperand(1).getValueType();
11289 if (SrcVT.getFixedSizeInBits() == 16) {
11290 bool IsFPOp = SrcVT.isFloatingPoint();
11291 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11292 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11293 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11294 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11295 unsigned ExtOpc = IsFPOp ? ISD::FP_EXTEND
11296 : NeedsSignExt ? ISD::SIGN_EXTEND
11298 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11299 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11300 SDValue ExtendedSrc = DAG.getNode(ExtOpc, DL, ExtType, Op.getOperand(1));
11301 SDValue Strategy = Op.getOperand(2);
11302 SDValue Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, ExtType,
11303 Op.getOperand(0), ExtendedSrc, Strategy);
11304 if (IsFPOp)
11305 return DAG.getNode(ISD::FP_ROUND, DL, SrcType, Result,
11306 DAG.getTargetConstant(1, DL, MVT::i32));
11307 else
11308 return DAG.getNode(ISD::TRUNCATE, DL, SrcType, Result);
11309 }
11310 return SDValue();
11311 }
11312 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11313 if (getSubtarget()->isAmdHsaOrMesa(MF.getFunction()))
11314 return emitNonHSAIntrinsicError(DAG, DL, VT);
11315 return getPreloadedValue(DAG, *MFI, VT,
11317 }
11318 case Intrinsic::amdgcn_dispatch_ptr:
11319 case Intrinsic::amdgcn_queue_ptr: {
11320 if (!Subtarget->isAmdHsaOrMesa(MF.getFunction())) {
11321 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11322 MF.getFunction(), "unsupported hsa intrinsic without hsa target",
11323 DL.getDebugLoc()));
11324 return DAG.getPOISON(VT);
11325 }
11326
11327 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11330 return getPreloadedValue(DAG, *MFI, VT, RegID);
11331 }
11332 case Intrinsic::amdgcn_implicitarg_ptr: {
11333 if (MFI->isEntryFunction())
11334 return getImplicitArgPtr(DAG, DL);
11335 return getPreloadedValue(DAG, *MFI, VT,
11337 }
11338 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11339 if (!AMDGPU::isKernel(MF.getFunction())) {
11340 // This only makes sense to call in a kernel, so just lower to null.
11341 return DAG.getConstant(0, DL, VT);
11342 }
11343
11344 return getPreloadedValue(DAG, *MFI, VT,
11346 }
11347 case Intrinsic::amdgcn_dispatch_id: {
11348 return getPreloadedValue(DAG, *MFI, VT, AMDGPUFunctionArgInfo::DISPATCH_ID);
11349 }
11350 case Intrinsic::amdgcn_rcp:
11351 return DAG.getNode(AMDGPUISD::RCP, DL, VT, Op.getOperand(1));
11352 case Intrinsic::amdgcn_rsq:
11353 return DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11354 case Intrinsic::amdgcn_rsq_legacy:
11355 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11356 return emitRemovedIntrinsicError(DAG, DL, VT);
11357 return SDValue();
11358 case Intrinsic::amdgcn_rcp_legacy:
11359 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11360 return emitRemovedIntrinsicError(DAG, DL, VT);
11361 return DAG.getNode(AMDGPUISD::RCP_LEGACY, DL, VT, Op.getOperand(1));
11362 case Intrinsic::amdgcn_fma_legacy:
11363 case Intrinsic::amdgcn_sudot4:
11364 case Intrinsic::amdgcn_sudot8:
11365 case Intrinsic::amdgcn_tanh:
11366 return SDValue();
11367 case Intrinsic::amdgcn_rsq_clamp: {
11368 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11369 return DAG.getNode(AMDGPUISD::RSQ_CLAMP, DL, VT, Op.getOperand(1));
11370
11371 Type *Type = VT.getTypeForEVT(*DAG.getContext());
11372 APFloat Max = APFloat::getLargest(Type->getFltSemantics());
11373 APFloat Min = APFloat::getLargest(Type->getFltSemantics(), true);
11374
11375 SDValue Rsq = DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11376 SDValue Tmp =
11377 DAG.getNode(ISD::FMINNUM, DL, VT, Rsq, DAG.getConstantFP(Max, DL, VT));
11378 return DAG.getNode(ISD::FMAXNUM, DL, VT, Tmp,
11379 DAG.getConstantFP(Min, DL, VT));
11380 }
11381 case Intrinsic::r600_read_ngroups_x:
11382 if (Subtarget->isAmdHsaOS())
11383 return emitNonHSAIntrinsicError(DAG, DL, VT);
11384
11385 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11387 false);
11388 case Intrinsic::r600_read_ngroups_y:
11389 if (Subtarget->isAmdHsaOS())
11390 return emitNonHSAIntrinsicError(DAG, DL, VT);
11391
11392 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11394 false);
11395 case Intrinsic::r600_read_ngroups_z:
11396 if (Subtarget->isAmdHsaOS())
11397 return emitNonHSAIntrinsicError(DAG, DL, VT);
11398
11399 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11401 false);
11402 case Intrinsic::r600_read_local_size_x:
11403 if (Subtarget->isAmdHsaOS())
11404 return emitNonHSAIntrinsicError(DAG, DL, VT);
11405
11406 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11408 case Intrinsic::r600_read_local_size_y:
11409 if (Subtarget->isAmdHsaOS())
11410 return emitNonHSAIntrinsicError(DAG, DL, VT);
11411
11412 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11414 case Intrinsic::r600_read_local_size_z:
11415 if (Subtarget->isAmdHsaOS())
11416 return emitNonHSAIntrinsicError(DAG, DL, VT);
11417
11418 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11420 case Intrinsic::amdgcn_workgroup_id_x:
11421 return lowerWorkGroupId(DAG, *MFI, VT,
11425 case Intrinsic::amdgcn_workgroup_id_y:
11426 return lowerWorkGroupId(DAG, *MFI, VT,
11430 case Intrinsic::amdgcn_workgroup_id_z:
11431 return lowerWorkGroupId(DAG, *MFI, VT,
11435 case Intrinsic::amdgcn_cluster_id_x:
11436 return Subtarget->hasClusters()
11437 ? getPreloadedValue(DAG, *MFI, VT,
11439 : DAG.getPOISON(VT);
11440 case Intrinsic::amdgcn_cluster_id_y:
11441 return Subtarget->hasClusters()
11442 ? getPreloadedValue(DAG, *MFI, VT,
11444 : DAG.getPOISON(VT);
11445 case Intrinsic::amdgcn_cluster_id_z:
11446 return Subtarget->hasClusters()
11447 ? getPreloadedValue(DAG, *MFI, VT,
11449 : DAG.getPOISON(VT);
11450 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11451 return Subtarget->hasClusters()
11452 ? getPreloadedValue(
11453 DAG, *MFI, VT,
11455 : DAG.getPOISON(VT);
11456 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11457 return Subtarget->hasClusters()
11458 ? getPreloadedValue(
11459 DAG, *MFI, VT,
11461 : DAG.getPOISON(VT);
11462 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11463 return Subtarget->hasClusters()
11464 ? getPreloadedValue(
11465 DAG, *MFI, VT,
11467 : DAG.getPOISON(VT);
11468 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11469 return Subtarget->hasClusters()
11470 ? lowerConstHwRegRead(DAG, Op, AMDGPU::Hwreg::ID_IB_STS2, 21, 4)
11471 : SDValue();
11472 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11473 return Subtarget->hasClusters()
11474 ? getPreloadedValue(
11475 DAG, *MFI, VT,
11477 : DAG.getPOISON(VT);
11478 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11479 return Subtarget->hasClusters()
11480 ? getPreloadedValue(
11481 DAG, *MFI, VT,
11483 : DAG.getPOISON(VT);
11484 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11485 return Subtarget->hasClusters()
11486 ? getPreloadedValue(
11487 DAG, *MFI, VT,
11489 : DAG.getPOISON(VT);
11490 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11491 return Subtarget->hasClusters()
11492 ? getPreloadedValue(
11493 DAG, *MFI, VT,
11495 : DAG.getPOISON(VT);
11496 case Intrinsic::amdgcn_wave_id:
11497 return lowerWaveID(DAG, Op);
11498 case Intrinsic::amdgcn_lds_kernel_id: {
11499 if (MFI->isEntryFunction())
11500 return getLDSKernelId(DAG, DL);
11501 return getPreloadedValue(DAG, *MFI, VT,
11503 }
11504 case Intrinsic::amdgcn_workitem_id_x:
11505 return lowerWorkitemID(DAG, Op, 0, MFI->getArgInfo().WorkItemIDX);
11506 case Intrinsic::amdgcn_workitem_id_y:
11507 return lowerWorkitemID(DAG, Op, 1, MFI->getArgInfo().WorkItemIDY);
11508 case Intrinsic::amdgcn_workitem_id_z:
11509 return lowerWorkitemID(DAG, Op, 2, MFI->getArgInfo().WorkItemIDZ);
11510 case Intrinsic::amdgcn_wavefrontsize:
11511 return DAG.getConstant(MF.getSubtarget<GCNSubtarget>().getWavefrontSize(),
11512 SDLoc(Op), MVT::i32);
11513 case Intrinsic::amdgcn_s_buffer_load: {
11514 unsigned CPol = Op.getConstantOperandVal(3);
11515 // s_buffer_load, because of how it's optimized, can't be volatile
11516 // so reject ones with the volatile bit set.
11517 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
11520 return Op;
11521 return lowerSBuffer(VT, VT, DL, DAG.getEntryNode(), Op.getOperand(1),
11522 Op.getOperand(2), Op.getOperand(3), DAG);
11523 }
11524 case Intrinsic::amdgcn_fdiv_fast:
11525 return lowerFDIV_FAST(Op, DAG);
11526 case Intrinsic::amdgcn_sin:
11527 return DAG.getNode(AMDGPUISD::SIN_HW, DL, VT, Op.getOperand(1));
11528
11529 case Intrinsic::amdgcn_cos:
11530 return DAG.getNode(AMDGPUISD::COS_HW, DL, VT, Op.getOperand(1));
11531
11532 case Intrinsic::amdgcn_mul_u24:
11533 return DAG.getNode(AMDGPUISD::MUL_U24, DL, VT, Op.getOperand(1),
11534 Op.getOperand(2));
11535 case Intrinsic::amdgcn_mul_i24:
11536 return DAG.getNode(AMDGPUISD::MUL_I24, DL, VT, Op.getOperand(1),
11537 Op.getOperand(2));
11538
11539 case Intrinsic::amdgcn_log_clamp: {
11540 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11541 return SDValue();
11542
11543 return emitRemovedIntrinsicError(DAG, DL, VT);
11544 }
11545 case Intrinsic::amdgcn_fract:
11546 return DAG.getNode(AMDGPUISD::FRACT, DL, VT, Op.getOperand(1));
11547
11548 case Intrinsic::amdgcn_class: {
11549 SDValue Src = Op.getOperand(1);
11550 EVT SrcVT = Src.getValueType();
11551 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11552 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11553 if (!IsLegal) {
11554 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11556 "llvm.amdgcn.class only supports f16, f32, and f64",
11557 DL.getDebugLoc()));
11558 return DAG.getPOISON(VT);
11559 }
11560 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, VT, Src, Op.getOperand(2));
11561 }
11562 case Intrinsic::amdgcn_div_fmas:
11563 return DAG.getNode(AMDGPUISD::DIV_FMAS, DL, VT, Op.getOperand(1),
11564 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11565
11566 case Intrinsic::amdgcn_div_fixup:
11567 return DAG.getNode(AMDGPUISD::DIV_FIXUP, DL, VT, Op.getOperand(1),
11568 Op.getOperand(2), Op.getOperand(3));
11569
11570 case Intrinsic::amdgcn_div_scale: {
11571 const ConstantSDNode *Param = cast<ConstantSDNode>(Op.getOperand(3));
11572
11573 // Translate to the operands expected by the machine instruction. The
11574 // first parameter must be the same as the first instruction.
11575 SDValue Numerator = Op.getOperand(1);
11576 SDValue Denominator = Op.getOperand(2);
11577
11578 // Note this order is opposite of the machine instruction's operations,
11579 // which is s0.f = Quotient, s1.f = Denominator, s2.f = Numerator. The
11580 // intrinsic has the numerator as the first operand to match a normal
11581 // division operation.
11582
11583 SDValue Src0 = Param->isAllOnes() ? Numerator : Denominator;
11584
11585 return DAG.getNode(AMDGPUISD::DIV_SCALE, DL, Op->getVTList(), Src0,
11586 Denominator, Numerator);
11587 }
11588 case Intrinsic::amdgcn_ballot:
11589 return lowerBALLOTIntrinsic(*this, Op.getNode(), DAG);
11590 case Intrinsic::amdgcn_fmed3:
11591 return DAG.getNode(AMDGPUISD::FMED3, DL, VT, Op.getOperand(1),
11592 Op.getOperand(2), Op.getOperand(3), Op->getFlags());
11593 case Intrinsic::amdgcn_fdot2:
11594 return DAG.getNode(AMDGPUISD::FDOT2, DL, VT, Op.getOperand(1),
11595 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11596 case Intrinsic::amdgcn_fmul_legacy:
11597 return DAG.getNode(AMDGPUISD::FMUL_LEGACY, DL, VT, Op.getOperand(1),
11598 Op.getOperand(2));
11599 case Intrinsic::amdgcn_sbfe:
11600 case Intrinsic::amdgcn_ubfe:
11601 return lowerBFEIntrinsic(Op, DAG, IntrinsicID);
11602 case Intrinsic::amdgcn_cvt_pkrtz:
11603 case Intrinsic::amdgcn_cvt_pknorm_i16:
11604 case Intrinsic::amdgcn_cvt_pknorm_u16:
11605 case Intrinsic::amdgcn_cvt_pk_i16:
11606 case Intrinsic::amdgcn_cvt_pk_u16: {
11607 // FIXME: Stop adding cast if v2f16/v2i16 are legal.
11608 EVT VT = Op.getValueType();
11609 unsigned Opcode;
11610
11611 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11612 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11613 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11614 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11615 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11616 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11617 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11618 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11619 else
11620 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11621
11622 if (isTypeLegal(VT))
11623 return DAG.getNode(Opcode, DL, VT, Op.getOperand(1), Op.getOperand(2));
11624
11625 SDValue Node =
11626 DAG.getNode(Opcode, DL, MVT::i32, Op.getOperand(1), Op.getOperand(2));
11627 return DAG.getNode(ISD::BITCAST, DL, VT, Node);
11628 }
11629 case Intrinsic::amdgcn_fmad_ftz:
11630 return DAG.getNode(AMDGPUISD::FMAD_FTZ, DL, VT, Op.getOperand(1),
11631 Op.getOperand(2), Op.getOperand(3));
11632
11633 case Intrinsic::amdgcn_if_break:
11634 return SDValue(DAG.getMachineNode(AMDGPU::SI_IF_BREAK, DL, VT,
11635 Op->getOperand(1), Op->getOperand(2)),
11636 0);
11637
11638 case Intrinsic::amdgcn_groupstaticsize: {
11640 if (OS == Triple::AMDHSA || OS == Triple::AMDPAL)
11641 return Op;
11642
11643 const Module *M = MF.getFunction().getParent();
11644 const GlobalValue *GV =
11645 Intrinsic::getDeclarationIfExists(M, Intrinsic::amdgcn_groupstaticsize);
11646 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, 0,
11648 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11649 }
11650 case Intrinsic::amdgcn_is_shared:
11651 case Intrinsic::amdgcn_is_private: {
11652 SDLoc SL(Op);
11653 SDValue SrcVec =
11654 DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
11655 SDValue SrcHi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, SrcVec,
11656 DAG.getConstant(1, SL, MVT::i32));
11657
11658 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11660 : AMDGPUAS::PRIVATE_ADDRESS;
11661 if (AS == AMDGPUAS::PRIVATE_ADDRESS &&
11662 Subtarget->hasGloballyAddressableScratch()) {
11663 SDValue FlatScratchBaseHi(
11664 DAG.getMachineNode(
11665 AMDGPU::S_MOV_B32, DL, MVT::i32,
11666 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11667 0);
11668 // Test bits 63..58 against the aperture address.
11669 return DAG.getSetCC(
11670 SL, MVT::i1,
11671 DAG.getNode(ISD::XOR, SL, MVT::i32, SrcHi, FlatScratchBaseHi),
11672 DAG.getConstant(1u << 26, SL, MVT::i32), ISD::SETULT);
11673 }
11674
11675 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11676 return DAG.getSetCC(SL, MVT::i1, SrcHi, Aperture, ISD::SETEQ);
11677 }
11678 case Intrinsic::amdgcn_perm:
11679 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op.getOperand(1),
11680 Op.getOperand(2), Op.getOperand(3));
11681 case Intrinsic::amdgcn_reloc_constant: {
11682 Module *M = MF.getFunction().getParent();
11683 const MDNode *Metadata = cast<MDNodeSDNode>(Op.getOperand(1))->getMD();
11684 auto SymbolName = cast<MDString>(Metadata->getOperand(0))->getString();
11685 auto *RelocSymbol = cast<GlobalVariable>(
11686 M->getOrInsertGlobal(SymbolName, Type::getInt32Ty(M->getContext())));
11687 SDValue GA = DAG.getTargetGlobalAddress(RelocSymbol, DL, MVT::i32, 0,
11689 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11690 }
11691 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11692 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11693 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11694 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11695 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11696 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11697 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11698 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11699 if (Op.getOperand(4).getValueType() == MVT::i32)
11700 return SDValue();
11701
11702 SDLoc SL(Op);
11703 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i32);
11704 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11705 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11706 Op.getOperand(3), IndexKeyi32);
11707 }
11708 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11709 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11710 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11711 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11712 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11713 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11714 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11715 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11716 if (Op.getOperand(4).getValueType() == MVT::i64)
11717 return SDValue();
11718
11719 SDLoc SL(Op);
11720 auto IndexKeyi64 =
11721 Op.getOperand(4).getValueType() == MVT::v2i32
11722 ? DAG.getBitcast(MVT::i64, Op.getOperand(4))
11723 : DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i64);
11724 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11725 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11726 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11727 Op.getOperand(6)});
11728 }
11729 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11730 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11731 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11732 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11733 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11734 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11735 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11736 ? MVT::i64
11737 : MVT::i32;
11738 if (Op.getOperand(6).getValueType() == IndexKeyTy)
11739 return SDValue();
11740
11741 SDLoc SL(Op);
11742 auto IndexKey =
11743 Op.getOperand(6).getValueType().isVector()
11744 ? DAG.getBitcast(IndexKeyTy, Op.getOperand(6))
11745 : DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, IndexKeyTy);
11747 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11748 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11749 IndexKey, Op.getOperand(7), Op.getOperand(8)};
11750 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11751 Args.push_back(Op.getOperand(9));
11752 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(), Args);
11753 }
11754 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11755 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11756 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11757 if (Op.getOperand(6).getValueType() == MVT::i32)
11758 return SDValue();
11759
11760 SDLoc SL(Op);
11761 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, MVT::i32);
11762 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11763 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11764 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11765 IndexKeyi32, Op.getOperand(7)});
11766 }
11767 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11768 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11769 unsigned AFmt = (unsigned)Op.getConstantOperandVal(1);
11770 unsigned BFmt = (unsigned)Op.getConstantOperandVal(3);
11771 unsigned AScaleFmt = (unsigned)Op.getConstantOperandVal(8);
11772 unsigned BScaleFmt = (unsigned)Op.getConstantOperandVal(11);
11773 if (!AMDGPU::isValidWMMAScaleFmtCombination(AFmt, AScaleFmt, BFmt,
11774 BScaleFmt)) {
11776 "invalid matrix and scale format combination in wmma call");
11777 Op->print(errs());
11778 errs() << '\n';
11779 }
11780 return SDValue();
11781 }
11782 case Intrinsic::amdgcn_readlane:
11783 case Intrinsic::amdgcn_readfirstlane:
11784 case Intrinsic::amdgcn_writelane:
11785 case Intrinsic::amdgcn_permlane16:
11786 case Intrinsic::amdgcn_permlanex16:
11787 case Intrinsic::amdgcn_permlane64:
11788 case Intrinsic::amdgcn_set_inactive:
11789 case Intrinsic::amdgcn_set_inactive_chain_arg:
11790 case Intrinsic::amdgcn_mov_dpp8:
11791 case Intrinsic::amdgcn_update_dpp:
11792 case Intrinsic::amdgcn_permlane_bcast:
11793 case Intrinsic::amdgcn_permlane_up:
11794 case Intrinsic::amdgcn_permlane_down:
11795 case Intrinsic::amdgcn_permlane_xor:
11796 return lowerLaneOp(*this, Op.getNode(), DAG);
11797 case Intrinsic::amdgcn_dead: {
11799 for (const EVT ValTy : Op.getNode()->values())
11800 Poisons.push_back(DAG.getPOISON(ValTy));
11801 return DAG.getMergeValues(Poisons, SDLoc(Op));
11802 }
11803 case Intrinsic::amdgcn_wave_shuffle:
11804 return lowerWaveShuffle(*this, Op.getNode(), DAG);
11805 default:
11806 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11808 return lowerImage(Op, ImageDimIntr, DAG, false);
11809
11810 return Op;
11811 }
11812}
11813
11814// On targets not supporting constant in soffset field, turn zero to
11815// SGPR_NULL to avoid generating an extra s_mov with zero.
11817 const GCNSubtarget *Subtarget) {
11818 if (Subtarget->hasRestrictedSOffset() && isNullConstant(SOffset))
11819 return DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11820 return SOffset;
11821}
11822
11823SDValue SITargetLowering::lowerRawBufferAtomicIntrin(SDValue Op,
11824 SelectionDAG &DAG,
11825 unsigned NewOpcode) const {
11826 SDLoc DL(Op);
11827
11828 SDValue VData = Op.getOperand(2);
11829 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11830 SmallVector<EVT, 2> ResultTypes(Op->values());
11831 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11832 "unsupported buffer atomic data type");
11833 }
11834 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11835 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
11836 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
11837 SDValue Ops[] = {
11838 Op.getOperand(0), // Chain
11839 VData, // vdata
11840 Rsrc, // rsrc
11841 DAG.getConstant(0, DL, MVT::i32), // vindex
11842 VOffset, // voffset
11843 SOffset, // soffset
11844 Offset, // offset
11845 Op.getOperand(6), // cachepolicy
11846 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11847 };
11848
11849 auto *M = cast<MemSDNode>(Op);
11850
11851 EVT MemVT = VData.getValueType();
11852 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11853 M->getMemOperand());
11854}
11855
11856SDValue
11857SITargetLowering::lowerStructBufferAtomicIntrin(SDValue Op, SelectionDAG &DAG,
11858 unsigned NewOpcode) const {
11859 SDLoc DL(Op);
11860
11861 SDValue VData = Op.getOperand(2);
11862 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11863 SmallVector<EVT, 2> ResultTypes(Op->values());
11864 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11865 "unsupported buffer atomic data type");
11866 }
11867 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11868 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
11869 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
11870 SDValue Ops[] = {
11871 Op.getOperand(0), // Chain
11872 VData, // vdata
11873 Rsrc, // rsrc
11874 Op.getOperand(4), // vindex
11875 VOffset, // voffset
11876 SOffset, // soffset
11877 Offset, // offset
11878 Op.getOperand(7), // cachepolicy
11879 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
11880 };
11881
11882 auto *M = cast<MemSDNode>(Op);
11883
11884 EVT MemVT = VData.getValueType();
11885 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11886 M->getMemOperand());
11887}
11888
11890 SDLoc DL) {
11891 SDNode *N = Op.getNode();
11892 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
11893 unsigned NumOperands = N->getNumOperands();
11894 if (N->getOperand(NumOperands - 1) == Zero)
11895 return;
11897 Ops[NumOperands - 1] = Zero; // M0 = 0
11898 DAG.UpdateNodeOperands(N, Ops);
11899}
11900
11901SDValue SITargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
11902 SelectionDAG &DAG) const {
11903 unsigned IntrID = Op.getConstantOperandVal(1);
11904 SDLoc DL(Op);
11905
11906 switch (IntrID) {
11907 case Intrinsic::amdgcn_cluster_load_b32:
11908 case Intrinsic::amdgcn_cluster_load_b64:
11909 case Intrinsic::amdgcn_cluster_load_b128: {
11910 if (Subtarget->hasGFX1250_STRICT())
11912 return SDValue();
11913 }
11914 case Intrinsic::amdgcn_ds_ordered_add:
11915 case Intrinsic::amdgcn_ds_ordered_swap: {
11916 MemSDNode *M = cast<MemSDNode>(Op);
11917 SDValue Chain = M->getOperand(0);
11918 SDValue M0 = M->getOperand(2);
11919 SDValue Value = M->getOperand(3);
11920 unsigned IndexOperand = M->getConstantOperandVal(7);
11921 unsigned WaveRelease = M->getConstantOperandVal(8);
11922 unsigned WaveDone = M->getConstantOperandVal(9);
11923
11924 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11925 IndexOperand &= ~0x3f;
11926 unsigned CountDw = 0;
11927
11928 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10) {
11929 CountDw = (IndexOperand >> 24) & 0xf;
11930 IndexOperand &= ~(0xf << 24);
11931
11932 if (CountDw < 1 || CountDw > 4) {
11933 const Function &Fn = DAG.getMachineFunction().getFunction();
11934 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11935 Fn, "ds_ordered_count: dword count must be between 1 and 4",
11936 DL.getDebugLoc()));
11937 CountDw = 1;
11938 }
11939 }
11940
11941 if (IndexOperand) {
11942 const Function &Fn = DAG.getMachineFunction().getFunction();
11943 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11944 Fn, "ds_ordered_count: bad index operand", DL.getDebugLoc()));
11945 }
11946
11947 if (WaveDone && !WaveRelease) {
11948 // TODO: Move this to IR verifier
11949 const Function &Fn = DAG.getMachineFunction().getFunction();
11950 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11951 Fn, "ds_ordered_count: wave_done requires wave_release",
11952 DL.getDebugLoc()));
11953 }
11954
11955 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
11956 unsigned ShaderType =
11958 unsigned Offset0 = OrderedCountIndex << 2;
11959 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
11960
11961 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10)
11962 Offset1 |= (CountDw - 1) << 6;
11963
11964 if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX11)
11965 Offset1 |= ShaderType << 2;
11966
11967 unsigned Offset = Offset0 | (Offset1 << 8);
11968
11969 SDValue Ops[] = {
11970 Chain, Value, DAG.getTargetConstant(Offset, DL, MVT::i16),
11971 copyToM0(DAG, Chain, DL, M0).getValue(1), // Glue
11972 };
11973 return DAG.getMemIntrinsicNode(AMDGPUISD::DS_ORDERED_COUNT, DL,
11974 M->getVTList(), Ops, M->getMemoryVT(),
11975 M->getMemOperand());
11976 }
11977 case Intrinsic::amdgcn_ptr_s_buffer_load: {
11978 unsigned CPol = Op.getConstantOperandVal(4);
11979 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
11982 return Op;
11983
11984 MemSDNode *M = cast<MemSDNode>(Op);
11985 return lowerSBuffer(
11986 Op.getValueType(), M->getMemoryVT(), DL, Op.getOperand(0),
11987 bufferRsrcPtrToVector(Op.getOperand(2), DAG), Op.getOperand(3),
11988 Op.getOperand(4), DAG, M->getMemOperand());
11989 }
11990 case Intrinsic::amdgcn_raw_buffer_load:
11991 case Intrinsic::amdgcn_raw_ptr_buffer_load:
11992 case Intrinsic::amdgcn_raw_atomic_buffer_load:
11993 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
11994 case Intrinsic::amdgcn_raw_buffer_load_format:
11995 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
11996 const bool IsFormat =
11997 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
11998 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
11999
12000 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12001 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
12002 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
12003 SDValue Ops[] = {
12004 Op.getOperand(0), // Chain
12005 Rsrc, // rsrc
12006 DAG.getConstant(0, DL, MVT::i32), // vindex
12007 VOffset, // voffset
12008 SOffset, // soffset
12009 Offset, // offset
12010 Op.getOperand(5), // cachepolicy, swizzled buffer
12011 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12012 };
12013
12014 auto *M = cast<MemSDNode>(Op);
12015 return lowerIntrinsicLoad(M, IsFormat, DAG, Ops);
12016 }
12017 case Intrinsic::amdgcn_struct_buffer_load:
12018 case Intrinsic::amdgcn_struct_ptr_buffer_load:
12019 case Intrinsic::amdgcn_struct_buffer_load_format:
12020 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
12021 case Intrinsic::amdgcn_struct_atomic_buffer_load:
12022 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
12023 const bool IsFormat =
12024 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
12025 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
12026
12027 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12028 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12029 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12030 SDValue Ops[] = {
12031 Op.getOperand(0), // Chain
12032 Rsrc, // rsrc
12033 Op.getOperand(3), // vindex
12034 VOffset, // voffset
12035 SOffset, // soffset
12036 Offset, // offset
12037 Op.getOperand(6), // cachepolicy, swizzled buffer
12038 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12039 };
12040
12041 return lowerIntrinsicLoad(cast<MemSDNode>(Op), IsFormat, DAG, Ops);
12042 }
12043 case Intrinsic::amdgcn_raw_tbuffer_load:
12044 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
12045 MemSDNode *M = cast<MemSDNode>(Op);
12046 EVT LoadVT = Op.getValueType();
12047 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12048 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
12049 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
12050
12051 SDValue Ops[] = {
12052 Op.getOperand(0), // Chain
12053 Rsrc, // rsrc
12054 DAG.getConstant(0, DL, MVT::i32), // vindex
12055 VOffset, // voffset
12056 SOffset, // soffset
12057 Offset, // offset
12058 Op.getOperand(5), // format
12059 Op.getOperand(6), // cachepolicy, swizzled buffer
12060 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12061 };
12062
12063 if (LoadVT.getScalarSizeInBits() == 16)
12064 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12065 Ops);
12066 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
12067 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
12068 DAG);
12069 }
12070 case Intrinsic::amdgcn_struct_tbuffer_load:
12071 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
12072 MemSDNode *M = cast<MemSDNode>(Op);
12073 EVT LoadVT = Op.getValueType();
12074 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12075 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12076 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12077
12078 SDValue Ops[] = {
12079 Op.getOperand(0), // Chain
12080 Rsrc, // rsrc
12081 Op.getOperand(3), // vindex
12082 VOffset, // voffset
12083 SOffset, // soffset
12084 Offset, // offset
12085 Op.getOperand(6), // format
12086 Op.getOperand(7), // cachepolicy, swizzled buffer
12087 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12088 };
12089
12090 if (LoadVT.getScalarSizeInBits() == 16)
12091 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12092 Ops);
12093 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
12094 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
12095 DAG);
12096 }
12097 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
12098 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
12099 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
12100 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
12101 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
12102 return lowerStructBufferAtomicIntrin(Op, DAG,
12103 AMDGPUISD::BUFFER_ATOMIC_FADD);
12104 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
12105 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
12106 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
12107 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
12108 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
12109 return lowerStructBufferAtomicIntrin(Op, DAG,
12110 AMDGPUISD::BUFFER_ATOMIC_FMIN);
12111 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
12112 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
12113 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
12114 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
12115 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
12116 return lowerStructBufferAtomicIntrin(Op, DAG,
12117 AMDGPUISD::BUFFER_ATOMIC_FMAX);
12118 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
12119 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
12120 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
12121 case Intrinsic::amdgcn_raw_buffer_atomic_add:
12122 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
12123 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12124 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
12125 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
12126 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12127 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
12128 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
12129 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
12130 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
12131 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
12132 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
12133 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
12134 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
12135 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
12136 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
12137 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
12138 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
12139 case Intrinsic::amdgcn_raw_buffer_atomic_and:
12140 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
12141 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12142 case Intrinsic::amdgcn_raw_buffer_atomic_or:
12143 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
12144 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12145 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
12146 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
12147 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12148 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
12149 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
12150 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12151 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12152 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12153 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12154 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12155 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12156 return lowerStructBufferAtomicIntrin(Op, DAG,
12157 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12158 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12159 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12160 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12161 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12162 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12163 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12164 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12165 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12166 return lowerStructBufferAtomicIntrin(Op, DAG,
12167 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12168 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12169 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12170 return lowerStructBufferAtomicIntrin(Op, DAG,
12171 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12172 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12173 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12174 return lowerStructBufferAtomicIntrin(Op, DAG,
12175 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12176 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12177 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12178 return lowerStructBufferAtomicIntrin(Op, DAG,
12179 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12180 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12181 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12182 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12183 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12184 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12185 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12186 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12187 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12188 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12189 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12190 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12191 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12192 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12193 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12194 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12195 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12196 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12197 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12198 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12199 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12200 return lowerStructBufferAtomicIntrin(Op, DAG,
12201 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12202 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12203 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12204 return lowerRawBufferAtomicIntrin(Op, DAG,
12205 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12206 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12207 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12208 return lowerStructBufferAtomicIntrin(Op, DAG,
12209 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12210 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12211 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12212 SDValue Src = Op.getOperand(2);
12213 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12214 SmallVector<EVT, 2> ResultTypes(Op->values());
12215 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12216 "unsupported buffer atomic data type");
12217 }
12218 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(4), DAG);
12219 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12220 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12221 SDValue Ops[] = {
12222 Op.getOperand(0), // Chain
12223 Op.getOperand(2), // src
12224 Op.getOperand(3), // cmp
12225 Rsrc, // rsrc
12226 DAG.getConstant(0, DL, MVT::i32), // vindex
12227 VOffset, // voffset
12228 SOffset, // soffset
12229 Offset, // offset
12230 Op.getOperand(7), // cachepolicy
12231 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12232 };
12233 EVT VT = Op.getValueType();
12234 auto *M = cast<MemSDNode>(Op);
12235
12236 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12237 Op->getVTList(), Ops, VT,
12238 M->getMemOperand());
12239 }
12240 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12241 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12242 SDValue Src = Op.getOperand(2);
12243 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12244 SmallVector<EVT, 2> ResultTypes(Op->values());
12245 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12246 "unsupported buffer atomic data type");
12247 }
12248 SDValue Rsrc = bufferRsrcPtrToVector(Op->getOperand(4), DAG);
12249 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(6), DAG);
12250 auto SOffset = selectSOffset(Op.getOperand(7), DAG, Subtarget);
12251 SDValue Ops[] = {
12252 Op.getOperand(0), // Chain
12253 Op.getOperand(2), // src
12254 Op.getOperand(3), // cmp
12255 Rsrc, // rsrc
12256 Op.getOperand(5), // vindex
12257 VOffset, // voffset
12258 SOffset, // soffset
12259 Offset, // offset
12260 Op.getOperand(8), // cachepolicy
12261 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12262 };
12263 EVT VT = Op.getValueType();
12264 auto *M = cast<MemSDNode>(Op);
12265
12266 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12267 Op->getVTList(), Ops, VT,
12268 M->getMemOperand());
12269 }
12270 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12271 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12272 MemSDNode *M = cast<MemSDNode>(Op);
12273 SDValue NodePtr = M->getOperand(2);
12274 SDValue RayExtent = M->getOperand(3);
12275 SDValue InstanceMask = M->getOperand(4);
12276 SDValue RayOrigin = M->getOperand(5);
12277 SDValue RayDir = M->getOperand(6);
12278 SDValue Offsets = M->getOperand(7);
12279 SDValue TDescr = M->getOperand(8);
12280
12281 assert(NodePtr.getValueType() == MVT::i64);
12282 assert(RayDir.getValueType() == MVT::v3f32);
12283
12284 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12285 const unsigned NumVDataDwords = 10;
12286 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12287 int Opcode = AMDGPU::getMIMGOpcode(
12288 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12289 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12290 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12291 assert(Opcode != -1);
12292
12294 Ops.push_back(NodePtr);
12295 Ops.push_back(DAG.getBuildVector(
12296 MVT::v2i32, DL,
12297 {DAG.getBitcast(MVT::i32, RayExtent),
12298 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12299 Ops.push_back(RayOrigin);
12300 Ops.push_back(RayDir);
12301 Ops.push_back(Offsets);
12302 Ops.push_back(TDescr);
12303 Ops.push_back(M->getChain());
12304
12305 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12306 MachineMemOperand *MemRef = M->getMemOperand();
12307 DAG.setNodeMemRefs(NewNode, {MemRef});
12308 return SDValue(NewNode, 0);
12309 }
12310 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12311 MemSDNode *M = cast<MemSDNode>(Op);
12312 SDValue NodePtr = M->getOperand(2);
12313 SDValue RayExtent = M->getOperand(3);
12314 SDValue RayOrigin = M->getOperand(4);
12315 SDValue RayDir = M->getOperand(5);
12316 SDValue RayInvDir = M->getOperand(6);
12317 SDValue TDescr = M->getOperand(7);
12318
12319 assert(NodePtr.getValueType() == MVT::i32 ||
12320 NodePtr.getValueType() == MVT::i64);
12321 assert(RayDir.getValueType() == MVT::v3f16 ||
12322 RayDir.getValueType() == MVT::v3f32);
12323
12324 const bool IsGFX11 = AMDGPU::isGFX11(*Subtarget);
12325 const bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
12326 const bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
12327 const bool IsA16 = RayDir.getValueType().getVectorElementType() == MVT::f16;
12328 const bool Is64 = NodePtr.getValueType() == MVT::i64;
12329 const unsigned NumVDataDwords = 4;
12330 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12331 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12332 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12333 NumVAddrs <= Subtarget->getNSAMaxSize()) ||
12334 IsGFX12Plus;
12335 const unsigned BaseOpcodes[2][2] = {
12336 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12337 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12338 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12339 int Opcode;
12340 if (UseNSA) {
12341 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12342 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12343 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12344 : AMDGPU::MIMGEncGfx10NSA,
12345 NumVDataDwords, NumVAddrDwords);
12346 } else {
12347 assert(!IsGFX12Plus);
12348 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12349 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12350 : AMDGPU::MIMGEncGfx10Default,
12351 NumVDataDwords, NumVAddrDwords);
12352 }
12353 assert(Opcode != -1);
12354
12356
12357 auto packLanes = [&DAG, &Ops, &DL](SDValue Op, bool IsAligned) {
12359 DAG.ExtractVectorElements(Op, Lanes, 0, 3);
12360 if (Lanes[0].getValueSizeInBits() == 32) {
12361 for (unsigned I = 0; I < 3; ++I)
12362 Ops.push_back(DAG.getBitcast(MVT::i32, Lanes[I]));
12363 } else {
12364 if (IsAligned) {
12365 Ops.push_back(DAG.getBitcast(
12366 MVT::i32,
12367 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[0], Lanes[1]})));
12368 Ops.push_back(Lanes[2]);
12369 } else {
12370 SDValue Elt0 = Ops.pop_back_val();
12371 Ops.push_back(DAG.getBitcast(
12372 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL, {Elt0, Lanes[0]})));
12373 Ops.push_back(DAG.getBitcast(
12374 MVT::i32,
12375 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[1], Lanes[2]})));
12376 }
12377 }
12378 };
12379
12380 if (UseNSA && IsGFX11Plus) {
12381 Ops.push_back(NodePtr);
12382 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12383 Ops.push_back(RayOrigin);
12384 if (IsA16) {
12385 SmallVector<SDValue, 3> DirLanes, InvDirLanes, MergedLanes;
12386 DAG.ExtractVectorElements(RayDir, DirLanes, 0, 3);
12387 DAG.ExtractVectorElements(RayInvDir, InvDirLanes, 0, 3);
12388 for (unsigned I = 0; I < 3; ++I) {
12389 MergedLanes.push_back(DAG.getBitcast(
12390 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL,
12391 {DirLanes[I], InvDirLanes[I]})));
12392 }
12393 Ops.push_back(DAG.getBuildVector(MVT::v3i32, DL, MergedLanes));
12394 } else {
12395 Ops.push_back(RayDir);
12396 Ops.push_back(RayInvDir);
12397 }
12398 } else {
12399 if (Is64)
12400 DAG.ExtractVectorElements(DAG.getBitcast(MVT::v2i32, NodePtr), Ops, 0,
12401 2);
12402 else
12403 Ops.push_back(NodePtr);
12404
12405 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12406 packLanes(RayOrigin, true);
12407 packLanes(RayDir, true);
12408 packLanes(RayInvDir, false);
12409 }
12410
12411 if (!UseNSA) {
12412 // Build a single vector containing all the operands so far prepared.
12413 if (NumVAddrDwords > 12) {
12414 SDValue Undef = DAG.getPOISON(MVT::i32);
12415 Ops.append(16 - Ops.size(), Undef);
12416 }
12417 assert(Ops.size() >= 8 && Ops.size() <= 12);
12418 SDValue MergedOps =
12419 DAG.getBuildVector(MVT::getVectorVT(MVT::i32, Ops.size()), DL, Ops);
12420 Ops.clear();
12421 Ops.push_back(MergedOps);
12422 }
12423
12424 Ops.push_back(TDescr);
12425 Ops.push_back(DAG.getTargetConstant(IsA16, DL, MVT::i1));
12426 Ops.push_back(M->getChain());
12427
12428 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12429 MachineMemOperand *MemRef = M->getMemOperand();
12430 DAG.setNodeMemRefs(NewNode, {MemRef});
12431 return SDValue(NewNode, 0);
12432 }
12433 case Intrinsic::amdgcn_global_atomic_fmin_num:
12434 case Intrinsic::amdgcn_global_atomic_fmax_num:
12435 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12436 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12437 MemSDNode *M = cast<MemSDNode>(Op);
12438 SDValue Ops[] = {
12439 M->getOperand(0), // Chain
12440 M->getOperand(2), // Ptr
12441 M->getOperand(3) // Value
12442 };
12443 unsigned Opcode = 0;
12444 switch (IntrID) {
12445 case Intrinsic::amdgcn_global_atomic_fmin_num:
12446 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12447 Opcode = ISD::ATOMIC_LOAD_FMIN;
12448 break;
12449 }
12450 case Intrinsic::amdgcn_global_atomic_fmax_num:
12451 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12452 Opcode = ISD::ATOMIC_LOAD_FMAX;
12453 break;
12454 }
12455 default:
12456 llvm_unreachable("unhandled atomic opcode");
12457 }
12458 return DAG.getAtomic(Opcode, SDLoc(Op), M->getMemoryVT(), M->getVTList(),
12459 Ops, M->getMemOperand());
12460 }
12461 case Intrinsic::amdgcn_s_alloc_vgpr: {
12462 SDValue NumVGPRs = Op.getOperand(2);
12463 if (!NumVGPRs->isDivergent())
12464 return Op;
12465
12466 SDValue ReadFirstLaneID =
12467 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
12468 NumVGPRs = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
12469 ReadFirstLaneID, NumVGPRs);
12470
12471 return DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, Op->getVTList(),
12472 Op.getOperand(0), Op.getOperand(1), NumVGPRs);
12473 }
12474 case Intrinsic::amdgcn_s_get_barrier_state:
12475 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12476 SDValue Chain = Op->getOperand(0);
12478 unsigned Opc;
12479
12480 if (isa<ConstantSDNode>(Op->getOperand(2))) {
12481 uint64_t BarID = cast<ConstantSDNode>(Op->getOperand(2))->getZExtValue();
12482 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12483 BarID = BarID & 0x3F;
12484 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12485 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
12486 Ops.push_back(K);
12487 Ops.push_back(Chain);
12488 } else {
12489 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12490 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12491 SDValue M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, Op->getOperand(2),
12492 DAG.getConstant(0x3F, DL, MVT::i32));
12493 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
12494 } else
12495 Ops.push_back(copyToM0(DAG, Chain, DL, Op->getOperand(2)).getValue(0));
12496 }
12497
12498 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
12499 return SDValue(NewMI, 0);
12500 }
12501 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12502 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12503 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12504 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12505 SDValue Chain = Op->getOperand(0);
12506 SDValue Ptr = Op->getOperand(2);
12507 EVT VT = Op->getValueType(0);
12508 return DAG.getAtomicLoad(ISD::NON_EXTLOAD, DL, MII->getMemoryVT(), VT,
12509 Chain, Ptr, MII->getMemOperand());
12510 }
12511 case Intrinsic::amdgcn_av_load_b128: {
12512 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12513 SDValue Chain = Op->getOperand(0);
12514 SDValue Ptr = Op->getOperand(2);
12515 EVT VT = Op->getValueType(0);
12516 // Lower to a regular ISD::LOAD. The MachineMemOperand carries Monotonic
12517 // ordering and syncscope so that SIMemoryLegalizer sets cache policy bits.
12518 // Address space filtering in the load_global/load_flat PatFrags selects
12519 // the correct GLOBAL vs FLAT instruction.
12520 return DAG.getLoad(VT, DL, Chain, Ptr, MII->getMemOperand());
12521 }
12522 case Intrinsic::amdgcn_flat_load_monitor_b32:
12523 case Intrinsic::amdgcn_flat_load_monitor_b64:
12524 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12525 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12526 SDValue Chain = Op->getOperand(0);
12527 SDValue Ptr = Op->getOperand(2);
12528 return DAG.getMemIntrinsicNode(AMDGPUISD::FLAT_LOAD_MONITOR, DL,
12529 Op->getVTList(), {Chain, Ptr},
12530 MII->getMemoryVT(), MII->getMemOperand());
12531 }
12532 case Intrinsic::amdgcn_global_load_monitor_b32:
12533 case Intrinsic::amdgcn_global_load_monitor_b64:
12534 case Intrinsic::amdgcn_global_load_monitor_b128: {
12535 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12536 SDValue Chain = Op->getOperand(0);
12537 SDValue Ptr = Op->getOperand(2);
12538 return DAG.getMemIntrinsicNode(AMDGPUISD::GLOBAL_LOAD_MONITOR, DL,
12539 Op->getVTList(), {Chain, Ptr},
12540 MII->getMemoryVT(), MII->getMemOperand());
12541 }
12542 default:
12543
12544 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12546 return lowerImage(Op, ImageDimIntr, DAG, true);
12547
12548 return SDValue();
12549 }
12550}
12551
12552// Call DAG.getMemIntrinsicNode for a load, but first widen a dwordx3 type to
12553// dwordx4 if on SI and handle TFE loads.
12554SDValue SITargetLowering::getMemIntrinsicNode(unsigned Opcode, const SDLoc &DL,
12555 SDVTList VTList,
12556 ArrayRef<SDValue> Ops, EVT MemVT,
12557 MachineMemOperand *MMO,
12558 SelectionDAG &DAG) const {
12559 LLVMContext &C = *DAG.getContext();
12561 EVT VT = VTList.VTs[0];
12562
12563 assert(VTList.NumVTs == 2 || VTList.NumVTs == 3);
12564 bool IsTFE = VTList.NumVTs == 3;
12565 if (IsTFE) {
12566 unsigned NumValueDWords = divideCeil(VT.getSizeInBits(), 32);
12567 unsigned NumOpDWords = NumValueDWords + 1;
12568 EVT OpDWordsVT = EVT::getVectorVT(C, MVT::i32, NumOpDWords);
12569 SDVTList OpDWordsVTList = DAG.getVTList(OpDWordsVT, VTList.VTs[2]);
12570 MachineMemOperand *OpDWordsMMO =
12571 MF.getMachineMemOperand(MMO, 0, NumOpDWords * 4);
12572 SDValue Op = getMemIntrinsicNode(Opcode, DL, OpDWordsVTList, Ops,
12573 OpDWordsVT, OpDWordsMMO, DAG);
12574 auto [Value, Status] = splitTFEValueAndStatus(Op, VT, DL, DAG);
12575 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
12576 }
12577
12578 if (!Subtarget->hasDwordx3LoadStores() &&
12579 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12580 EVT WidenedVT = EVT::getVectorVT(C, VT.getVectorElementType(), 4);
12581 EVT WidenedMemVT = EVT::getVectorVT(C, MemVT.getVectorElementType(), 4);
12582 MachineMemOperand *WidenedMMO = MF.getMachineMemOperand(MMO, 0, 16);
12583 SDVTList WidenedVTList = DAG.getVTList(WidenedVT, VTList.VTs[1]);
12584 SDValue Op = DAG.getMemIntrinsicNode(Opcode, DL, WidenedVTList, Ops,
12585 WidenedMemVT, WidenedMMO);
12586 SDValue Value = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Op,
12587 DAG.getVectorIdxConstant(0, DL));
12588 return DAG.getMergeValues({Value, SDValue(Op.getNode(), 1)}, DL);
12589 }
12590
12591 return DAG.getMemIntrinsicNode(Opcode, DL, VTList, Ops, MemVT, MMO);
12592}
12593
12594SDValue SITargetLowering::handleD16VData(SDValue VData, SelectionDAG &DAG,
12595 bool ImageStore) const {
12596 EVT StoreVT = VData.getValueType();
12597
12598 // No change for f16 and legal vector D16 types.
12599 if (!StoreVT.isVector())
12600 return VData;
12601
12602 SDLoc DL(VData);
12603 unsigned NumElements = StoreVT.getVectorNumElements();
12604
12605 if (Subtarget->hasUnpackedD16VMem()) {
12606 // We need to unpack the packed data to store.
12607 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12608 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12609
12610 EVT EquivStoreVT =
12611 EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumElements);
12612 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, EquivStoreVT, IntVData);
12613 return DAG.UnrollVectorOp(ZExt.getNode());
12614 }
12615
12616 // The sq block of gfx8.1 does not estimate register use correctly for d16
12617 // image store instructions. The data operand is computed as if it were not a
12618 // d16 image instruction.
12619 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12620 // Bitcast to i16
12621 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12622 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12623
12624 // Decompose into scalars
12626 DAG.ExtractVectorElements(IntVData, Elts);
12627
12628 // Group pairs of i16 into v2i16 and bitcast to i32
12629 SmallVector<SDValue, 4> PackedElts;
12630 for (unsigned I = 0; I < Elts.size() / 2; I += 1) {
12631 SDValue Pair =
12632 DAG.getBuildVector(MVT::v2i16, DL, {Elts[I * 2], Elts[I * 2 + 1]});
12633 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12634 PackedElts.push_back(IntPair);
12635 }
12636 if ((NumElements % 2) == 1) {
12637 // Handle v3i16
12638 unsigned I = Elts.size() / 2;
12639 SDValue Pair = DAG.getBuildVector(MVT::v2i16, DL,
12640 {Elts[I * 2], DAG.getPOISON(MVT::i16)});
12641 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12642 PackedElts.push_back(IntPair);
12643 }
12644
12645 // Pad using UNDEF
12646 PackedElts.resize(Elts.size(), DAG.getPOISON(MVT::i32));
12647
12648 // Build final vector
12649 EVT VecVT =
12650 EVT::getVectorVT(*DAG.getContext(), MVT::i32, PackedElts.size());
12651 return DAG.getBuildVector(VecVT, DL, PackedElts);
12652 }
12653
12654 if (NumElements == 3) {
12655 EVT IntStoreVT =
12657 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12658
12659 EVT WidenedStoreVT = EVT::getVectorVT(
12660 *DAG.getContext(), StoreVT.getVectorElementType(), NumElements + 1);
12661 EVT WidenedIntVT = EVT::getIntegerVT(*DAG.getContext(),
12662 WidenedStoreVT.getStoreSizeInBits());
12663 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenedIntVT, IntVData);
12664 return DAG.getNode(ISD::BITCAST, DL, WidenedStoreVT, ZExt);
12665 }
12666
12667 assert(isTypeLegal(StoreVT));
12668 return VData;
12669}
12670
12671static bool isAsyncLDSDMA(Intrinsic::ID Intr) {
12672 switch (Intr) {
12673 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12674 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12675 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12676 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12677 case Intrinsic::amdgcn_load_async_to_lds:
12678 case Intrinsic::amdgcn_global_load_async_lds:
12679 return true;
12680 }
12681 return false;
12682}
12683
12684SDValue SITargetLowering::LowerINTRINSIC_VOID(SDValue Op,
12685 SelectionDAG &DAG) const {
12686 SDLoc DL(Op);
12687 SDValue Chain = Op.getOperand(0);
12688 unsigned IntrinsicID = Op.getConstantOperandVal(1);
12689
12690 switch (IntrinsicID) {
12691 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
12692 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
12693 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
12694 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
12695 if (Subtarget->hasGFX1250_STRICT())
12697 return SDValue();
12698 }
12699 case Intrinsic::amdgcn_exp_compr: {
12700 SDValue Src0 = Op.getOperand(4);
12701 SDValue Src1 = Op.getOperand(5);
12702 // Hack around illegal type on SI by directly selecting it.
12703 if (isTypeLegal(Src0.getValueType()))
12704 return SDValue();
12705
12706 const ConstantSDNode *Done = cast<ConstantSDNode>(Op.getOperand(6));
12707 SDValue Undef = DAG.getPOISON(MVT::f32);
12708 const SDValue Ops[] = {
12709 Op.getOperand(2), // tgt
12710 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src0), // src0
12711 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src1), // src1
12712 Undef, // src2
12713 Undef, // src3
12714 Op.getOperand(7), // vm
12715 DAG.getTargetConstant(1, DL, MVT::i1), // compr
12716 Op.getOperand(3), // en
12717 Op.getOperand(0) // Chain
12718 };
12719
12720 unsigned Opc = Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12721 return SDValue(DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops), 0);
12722 }
12723
12724 case Intrinsic::amdgcn_struct_tbuffer_store:
12725 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12726 SDValue VData = Op.getOperand(2);
12727 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12728 if (IsD16)
12729 VData = handleD16VData(VData, DAG);
12730 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12731 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12732 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12733 SDValue Ops[] = {
12734 Chain,
12735 VData, // vdata
12736 Rsrc, // rsrc
12737 Op.getOperand(4), // vindex
12738 VOffset, // voffset
12739 SOffset, // soffset
12740 Offset, // offset
12741 Op.getOperand(7), // format
12742 Op.getOperand(8), // cachepolicy, swizzled buffer
12743 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12744 };
12745 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12746 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12747 MemSDNode *M = cast<MemSDNode>(Op);
12748 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12749 M->getMemoryVT(), M->getMemOperand());
12750 }
12751
12752 case Intrinsic::amdgcn_raw_tbuffer_store:
12753 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12754 SDValue VData = Op.getOperand(2);
12755 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12756 if (IsD16)
12757 VData = handleD16VData(VData, DAG);
12758 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12759 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12760 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12761 SDValue Ops[] = {
12762 Chain,
12763 VData, // vdata
12764 Rsrc, // rsrc
12765 DAG.getConstant(0, DL, MVT::i32), // vindex
12766 VOffset, // voffset
12767 SOffset, // soffset
12768 Offset, // offset
12769 Op.getOperand(6), // format
12770 Op.getOperand(7), // cachepolicy, swizzled buffer
12771 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12772 };
12773 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12774 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12775 MemSDNode *M = cast<MemSDNode>(Op);
12776 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12777 M->getMemoryVT(), M->getMemOperand());
12778 }
12779
12780 case Intrinsic::amdgcn_raw_buffer_store:
12781 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12782 case Intrinsic::amdgcn_raw_buffer_store_format:
12783 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12784 const bool IsFormat =
12785 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12786 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12787
12788 SDValue VData = Op.getOperand(2);
12789 EVT VDataVT = VData.getValueType();
12790 EVT EltType = VDataVT.getScalarType();
12791 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12792
12793 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12794 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12796 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12797 return Chain;
12798 }
12799
12800 if (IsD16) {
12801 VData = handleD16VData(VData, DAG);
12802 VDataVT = VData.getValueType();
12803 }
12804
12805 if (!isTypeLegal(VDataVT)) {
12806 VData =
12807 DAG.getNode(ISD::BITCAST, DL,
12808 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12809 }
12810
12811 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12812 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12813 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12814 SDValue Ops[] = {
12815 Chain,
12816 VData,
12817 Rsrc,
12818 DAG.getConstant(0, DL, MVT::i32), // vindex
12819 VOffset, // voffset
12820 SOffset, // soffset
12821 Offset, // offset
12822 Op.getOperand(6), // cachepolicy, swizzled buffer
12823 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12824 };
12825 unsigned Opc =
12826 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12827 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12828 MemSDNode *M = cast<MemSDNode>(Op);
12829
12830 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12831 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12832 return handleByteShortBufferStores(DAG, VDataVT, DL, Ops, M);
12833
12834 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12835 M->getMemoryVT(), M->getMemOperand());
12836 }
12837
12838 case Intrinsic::amdgcn_struct_buffer_store:
12839 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12840 case Intrinsic::amdgcn_struct_buffer_store_format:
12841 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12842 const bool IsFormat =
12843 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12844 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12845
12846 SDValue VData = Op.getOperand(2);
12847 EVT VDataVT = VData.getValueType();
12848 EVT EltType = VDataVT.getScalarType();
12849 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12850
12851 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12852 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12854 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12855 return Chain;
12856 }
12857
12858 if (IsD16) {
12859 VData = handleD16VData(VData, DAG);
12860 VDataVT = VData.getValueType();
12861 }
12862
12863 if (!isTypeLegal(VDataVT)) {
12864 VData =
12865 DAG.getNode(ISD::BITCAST, DL,
12866 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12867 }
12868
12869 auto Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12870 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12871 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12872 SDValue Ops[] = {
12873 Chain,
12874 VData,
12875 Rsrc,
12876 Op.getOperand(4), // vindex
12877 VOffset, // voffset
12878 SOffset, // soffset
12879 Offset, // offset
12880 Op.getOperand(7), // cachepolicy, swizzled buffer
12881 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12882 };
12883 unsigned Opc =
12884 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12885 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12886 MemSDNode *M = cast<MemSDNode>(Op);
12887
12888 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12889 EVT VDataType = VData.getValueType().getScalarType();
12890 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12891 return handleByteShortBufferStores(DAG, VDataType, DL, Ops, M);
12892
12893 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12894 M->getMemoryVT(), M->getMemOperand());
12895 }
12896 case Intrinsic::amdgcn_raw_buffer_load_lds:
12897 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12898 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12899 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12900 case Intrinsic::amdgcn_struct_buffer_load_lds:
12901 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12902 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12903 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12904 unsigned Opc;
12905 bool HasVIndex =
12906 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12907 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12908 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12909 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12910 unsigned OpOffset = HasVIndex ? 1 : 0;
12911 SDValue VOffset = Op.getOperand(5 + OpOffset);
12912 bool HasVOffset = !isNullConstant(VOffset);
12913 unsigned Size = Op->getConstantOperandVal(4);
12914
12915 switch (Size) {
12916 default:
12917 return SDValue();
12918 case 1:
12919 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12920 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12921 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12922 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12923 break;
12924 case 2:
12925 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12926 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12927 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12928 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12929 break;
12930 case 4:
12931 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12932 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12933 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12934 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12935 break;
12936 case 12:
12937 if (!Subtarget->hasLDSLoadB96_B128())
12938 return SDValue();
12939 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
12940 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
12941 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
12942 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
12943 break;
12944 case 16:
12945 if (!Subtarget->hasLDSLoadB96_B128())
12946 return SDValue();
12947 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
12948 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
12949 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
12950 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
12951 break;
12952 }
12953
12954 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
12955
12957
12958 if (HasVIndex && HasVOffset)
12959 Ops.push_back(DAG.getBuildVector(MVT::v2i32, DL,
12960 {Op.getOperand(5), // VIndex
12961 VOffset}));
12962 else if (HasVIndex)
12963 Ops.push_back(Op.getOperand(5));
12964 else if (HasVOffset)
12965 Ops.push_back(VOffset);
12966
12967 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12968 Ops.push_back(Rsrc);
12969 Ops.push_back(Op.getOperand(6 + OpOffset)); // soffset
12970 Ops.push_back(Op.getOperand(7 + OpOffset)); // imm offset
12971 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
12972 unsigned Aux = Op.getConstantOperandVal(8 + OpOffset);
12973 Ops.push_back(DAG.getTargetConstant(
12974 Aux & (IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12),
12975 DL, MVT::i8)); // cpol
12976 Ops.push_back(DAG.getTargetConstant(
12977 Aux & (IsGFX12Plus ? AMDGPU::CPol::SWZ : AMDGPU::CPol::SWZ_pregfx12)
12978 ? 1
12979 : 0,
12980 DL, MVT::i8)); // swz
12981 Ops.push_back(
12982 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
12983 Ops.push_back(M0Val.getValue(0)); // Chain
12984 Ops.push_back(M0Val.getValue(1)); // Glue
12985
12986 auto *M = cast<MemSDNode>(Op);
12987 auto *Load = DAG.getMachineNode(Opc, DL, M->getVTList(), Ops);
12988 DAG.setNodeMemRefs(Load, M->memoperands());
12989
12990 return SDValue(Load, 0);
12991 }
12992 // Buffers are handled by LowerBufferFatPointers, and we're going to go
12993 // for "trust me" that the remaining cases are global pointers until
12994 // such time as we can put two mem operands on an intrinsic.
12995 case Intrinsic::amdgcn_load_to_lds:
12996 case Intrinsic::amdgcn_load_async_to_lds:
12997 case Intrinsic::amdgcn_global_load_lds:
12998 case Intrinsic::amdgcn_global_load_async_lds: {
12999 if (!Subtarget->hasVMemToLDSLoad())
13000 return SDValue();
13001
13002 unsigned Opc;
13003 unsigned Size = Op->getConstantOperandVal(4);
13004 switch (Size) {
13005 default:
13006 return SDValue();
13007 case 1:
13008 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
13009 break;
13010 case 2:
13011 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
13012 break;
13013 case 4:
13014 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
13015 break;
13016 case 12:
13017 if (!Subtarget->hasLDSLoadB96_B128())
13018 return SDValue();
13019 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
13020 break;
13021 case 16:
13022 if (!Subtarget->hasLDSLoadB96_B128())
13023 return SDValue();
13024 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
13025 break;
13026 }
13027
13028 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
13029
13031
13032 SDValue Addr = Op.getOperand(2); // Global ptr
13033 SDValue VOffset;
13034 // Try to split SAddr and VOffset. Global and LDS pointers share the same
13035 // immediate offset, so we cannot use a regular SelectGlobalSAddr().
13036 if (Addr->isDivergent() && Addr->isAnyAdd()) {
13037 SDValue LHS = Addr.getOperand(0);
13038 SDValue RHS = Addr.getOperand(1);
13039
13040 if (LHS->isDivergent())
13041 std::swap(LHS, RHS);
13042
13043 if (!LHS->isDivergent() && RHS.getOpcode() == ISD::ZERO_EXTEND &&
13044 RHS.getOperand(0).getValueType() == MVT::i32) {
13045 // add (i64 sgpr), (zero_extend (i32 vgpr))
13046 Addr = LHS;
13047 VOffset = RHS.getOperand(0);
13048 }
13049 }
13050
13051 Ops.push_back(Addr);
13052 if (!Addr->isDivergent()) {
13054 if (!VOffset)
13055 VOffset =
13056 SDValue(DAG.getMachineNode(AMDGPU::V_MOV_B32_e32, DL, MVT::i32,
13057 DAG.getTargetConstant(0, DL, MVT::i32)),
13058 0);
13059 Ops.push_back(VOffset);
13060 }
13061
13062 Ops.push_back(Op.getOperand(5)); // Offset
13063
13064 unsigned Aux = Op.getConstantOperandVal(6);
13065 Ops.push_back(DAG.getTargetConstant(Aux & ~AMDGPU::CPol::VIRTUAL_BITS, DL,
13066 MVT::i32)); // CPol
13067 Ops.push_back(
13068 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
13069
13070 Ops.push_back(M0Val.getValue(0)); // Chain
13071 Ops.push_back(M0Val.getValue(1)); // Glue
13072
13073 auto *M = cast<MemSDNode>(Op);
13074 auto *Load = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13075 DAG.setNodeMemRefs(Load, M->memoperands());
13076
13077 return SDValue(Load, 0);
13078 }
13079 case Intrinsic::amdgcn_end_cf:
13080 return SDValue(DAG.getMachineNode(AMDGPU::SI_END_CF, DL, MVT::Other,
13081 Op->getOperand(2), Chain),
13082 0);
13083 case Intrinsic::amdgcn_s_barrier_signal_var: {
13084 // Member count of 0 means to re-use a previous member count,
13085 // which, if the named barrier is statically chosen, means we can use
13086 // the immarg form. Otherwisee, fall through to constructiong M0 as for
13087 // s_barrier_init.
13088 SDValue CntOp = Op->getOperand(3);
13089 auto *CntC = dyn_cast<ConstantSDNode>(CntOp);
13090 if (CntC && CntC->isZero()) {
13091 SDValue Chain = Op->getOperand(0);
13092 SDValue BarOp = Op->getOperand(2);
13094
13095 std::optional<uint64_t> BarVal;
13096 if (auto *C = dyn_cast<ConstantSDNode>(BarOp))
13097 BarVal = C->getZExtValue();
13098 else if (auto *GA = dyn_cast<GlobalAddressSDNode>(BarOp))
13100 *GA->getGlobal(), AMDGPUAS::BARRIER))
13101 BarVal = *Addr + GA->getOffset();
13102
13103 if (BarVal) {
13104 unsigned BarID = *BarVal & 0x3F;
13105 Ops.push_back(DAG.getTargetConstant(BarID, DL, MVT::i32));
13106 Ops.push_back(Chain);
13107 auto *NewMI = DAG.getMachineNode(AMDGPU::S_BARRIER_SIGNAL_IMM, DL,
13108 Op->getVTList(), Ops);
13109 return SDValue(NewMI, 0);
13110 }
13111 }
13112 [[fallthrough]];
13113 }
13114 case Intrinsic::amdgcn_s_barrier_init: {
13115 // these two intrinsics have two operands: barrier pointer and member count
13116 SDValue Chain = Op->getOperand(0);
13118 SDValue BarOp = Op->getOperand(2);
13119 SDValue CntOp = Op->getOperand(3);
13120 SDValue M0Val;
13121 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
13122 ? AMDGPU::S_BARRIER_INIT_M0
13123 : AMDGPU::S_BARRIER_SIGNAL_M0;
13124 // extract the BarrierID from bits 0-5 of BarOp
13125 SDValue BarID = DAG.getNode(ISD::AND, DL, MVT::i32, BarOp,
13126 DAG.getConstant(0x3F, DL, MVT::i32));
13127 // Member count should be put into M0[ShAmt:+6]
13128 // Barrier ID should be put into M0[5:0]
13129 SDValue MemberCnt = DAG.getNode(ISD::AND, DL, MVT::i32, CntOp,
13130 DAG.getConstant(0x3F, DL, MVT::i32));
13131 constexpr unsigned ShAmt = 16;
13132 M0Val = DAG.getNode(ISD::SHL, DL, MVT::i32, MemberCnt,
13133 DAG.getShiftAmountConstant(ShAmt, MVT::i32, DL));
13134
13135 M0Val = DAG.getNode(ISD::OR, DL, MVT::i32, M0Val, BarID);
13136
13137 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
13138
13139 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13140 return SDValue(NewMI, 0);
13141 }
13142 case Intrinsic::amdgcn_s_wakeup_barrier: {
13143 if (!Subtarget->hasSWakeupBarrier())
13144 return SDValue();
13145 [[fallthrough]];
13146 }
13147 case Intrinsic::amdgcn_s_barrier_join: {
13148 // these three intrinsics have one operand: barrier pointer
13149 SDValue Chain = Op->getOperand(0);
13151 SDValue BarOp = Op->getOperand(2);
13152 unsigned Opc;
13153
13154 if (isa<ConstantSDNode>(BarOp)) {
13155 uint64_t BarVal = cast<ConstantSDNode>(BarOp)->getZExtValue();
13156 switch (IntrinsicID) {
13157 default:
13158 return SDValue();
13159 case Intrinsic::amdgcn_s_barrier_join:
13160 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13161 break;
13162 case Intrinsic::amdgcn_s_wakeup_barrier:
13163 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13164 break;
13165 }
13166 // extract the BarrierID from bits 0-5 of the immediate
13167 unsigned BarID = BarVal & 0x3F;
13168 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
13169 Ops.push_back(K);
13170 Ops.push_back(Chain);
13171 } else {
13172 switch (IntrinsicID) {
13173 default:
13174 return SDValue();
13175 case Intrinsic::amdgcn_s_barrier_join:
13176 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13177 break;
13178 case Intrinsic::amdgcn_s_wakeup_barrier:
13179 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13180 break;
13181 }
13182 // extract the BarrierID from bits 0-5 of BarOp, copy to M0[5:0]
13183 SDValue M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, BarOp,
13184 DAG.getConstant(0x3F, DL, MVT::i32));
13185 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
13186 }
13187
13188 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13189 return SDValue(NewMI, 0);
13190 }
13191 case Intrinsic::amdgcn_s_prefetch_data:
13192 case Intrinsic::amdgcn_s_prefetch_inst: {
13193 // For non-global address space preserve the chain and remove the call.
13195 return Op.getOperand(0);
13196 return Op;
13197 }
13198 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13199 SDValue Ops[] = {
13200 Chain, bufferRsrcPtrToVector(Op.getOperand(2), DAG),
13201 Op.getOperand(3), // offset
13202 Op.getOperand(4), // length
13203 };
13204
13205 MemSDNode *M = cast<MemSDNode>(Op);
13206 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_PREFETCH_DATA, DL,
13207 Op->getVTList(), Ops, M->getMemoryVT(),
13208 M->getMemOperand());
13209 }
13210 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13211 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13212 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13213 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13214 SDValue Chain = Op->getOperand(0);
13215 SDValue Ptr = Op->getOperand(2);
13216 SDValue Val = Op->getOperand(3);
13217 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MII->getMemoryVT(), Chain, Val,
13218 Ptr, MII->getMemOperand());
13219 }
13220 case Intrinsic::amdgcn_av_store_b128: {
13221 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13222 SDValue Chain = Op->getOperand(0);
13223 SDValue Ptr = Op->getOperand(2);
13224 SDValue Val = Op->getOperand(3);
13225 return DAG.getStore(Chain, DL, Val, Ptr, MII->getMemOperand());
13226 }
13227 default: {
13228 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13230 return lowerImage(Op, ImageDimIntr, DAG, true);
13231
13232 return Op;
13233 }
13234 }
13235}
13236
13237// Return whether the operation has NoUnsignedWrap property.
13238static bool isNoUnsignedWrap(SDValue Addr) {
13239 return (Addr.getOpcode() == ISD::ADD &&
13240 Addr->getFlags().hasNoUnsignedWrap()) ||
13241 Addr->getOpcode() == ISD::OR;
13242}
13243
13245 EVT PtrVT) const {
13246 return PtrVT == MVT::i64;
13247}
13248
13250 EVT PtrVT) const {
13251 return true;
13252}
13253
13254// The raw.(t)buffer and struct.(t)buffer intrinsics have two offset args:
13255// offset (the offset that is included in bounds checking and swizzling, to be
13256// split between the instruction's voffset and immoffset fields) and soffset
13257// (the offset that is excluded from bounds checking and swizzling, to go in
13258// the instruction's soffset field). This function takes the first kind of
13259// offset and figures out how to split it between voffset and immoffset.
13260std::pair<SDValue, SDValue>
13261SITargetLowering::splitBufferOffsets(SDValue Offset, SelectionDAG &DAG) const {
13262 SDLoc DL(Offset);
13263 const unsigned MaxImm = SIInstrInfo::getMaxMUBUFImmOffset(*Subtarget);
13264 SDValue N0 = Offset;
13265 ConstantSDNode *C1 = nullptr;
13266
13267 if ((C1 = dyn_cast<ConstantSDNode>(N0)))
13268 N0 = SDValue();
13269 else if (DAG.isBaseWithConstantOffset(N0)) {
13270 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13271 // being added, so we can only safely match a 32-bit addition with no
13272 // unsigned overflow.
13273 bool CheckNUW = Subtarget->hasGFX1250Insts();
13274 if (!CheckNUW || isNoUnsignedWrap(N0)) {
13275 C1 = cast<ConstantSDNode>(N0.getOperand(1));
13276 N0 = N0.getOperand(0);
13277 }
13278 }
13279
13280 if (C1) {
13281 unsigned ImmOffset = C1->getZExtValue();
13282 // If the immediate value is too big for the immoffset field, put only bits
13283 // that would normally fit in the immoffset field. The remaining value that
13284 // is copied/added for the voffset field is a large power of 2, and it
13285 // stands more chance of being CSEd with the copy/add for another similar
13286 // load/store.
13287 // However, do not do that rounding down if that is a negative
13288 // number, as it appears to be illegal to have a negative offset in the
13289 // vgpr, even if adding the immediate offset makes it positive.
13290 unsigned Overflow = ImmOffset & ~MaxImm;
13291 ImmOffset -= Overflow;
13292 if ((int32_t)Overflow < 0) {
13293 Overflow += ImmOffset;
13294 ImmOffset = 0;
13295 }
13296 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(ImmOffset, DL, MVT::i32));
13297 if (Overflow) {
13298 auto OverflowVal = DAG.getConstant(Overflow, DL, MVT::i32);
13299 if (!N0)
13300 N0 = OverflowVal;
13301 else {
13302 SDValue Ops[] = {N0, OverflowVal};
13303 N0 = DAG.getNode(ISD::ADD, DL, MVT::i32, Ops);
13304 }
13305 }
13306 }
13307 if (!N0)
13308 N0 = DAG.getConstant(0, DL, MVT::i32);
13309 if (!C1)
13310 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(0, DL, MVT::i32));
13311 return {N0, SDValue(C1, 0)};
13312}
13313
13314// Analyze a combined offset from an amdgcn_s_buffer_load intrinsic and store
13315// the three offsets (voffset, soffset and instoffset) into the SDValue[3] array
13316// pointed to by Offsets.
13317void SITargetLowering::setBufferOffsets(SDValue CombinedOffset,
13318 SelectionDAG &DAG, SDValue *Offsets,
13319 Align Alignment) const {
13320 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
13321 SDLoc DL(CombinedOffset);
13322 if (auto *C = dyn_cast<ConstantSDNode>(CombinedOffset)) {
13323 uint32_t Imm = C->getZExtValue();
13324 uint32_t SOffset, ImmOffset;
13325 if (TII->splitMUBUFOffset(Imm, SOffset, ImmOffset, Alignment)) {
13326 Offsets[0] = DAG.getConstant(0, DL, MVT::i32);
13327 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13328 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13329 return;
13330 }
13331 }
13332 if (DAG.isBaseWithConstantOffset(CombinedOffset)) {
13333 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13334 // being added, so we can only safely match a 32-bit addition with no
13335 // unsigned overflow.
13336 bool CheckNUW = Subtarget->hasGFX1250Insts();
13337 SDValue N0 = CombinedOffset.getOperand(0);
13338 SDValue N1 = CombinedOffset.getOperand(1);
13339 uint32_t SOffset, ImmOffset;
13340 int Offset = cast<ConstantSDNode>(N1)->getSExtValue();
13341 if (Offset >= 0 && (!CheckNUW || isNoUnsignedWrap(CombinedOffset)) &&
13342 TII->splitMUBUFOffset(Offset, SOffset, ImmOffset, Alignment)) {
13343 Offsets[0] = N0;
13344 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13345 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13346 return;
13347 }
13348 }
13349
13350 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13351 ? DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32)
13352 : DAG.getConstant(0, DL, MVT::i32);
13353
13354 Offsets[0] = CombinedOffset;
13355 Offsets[1] = SOffsetZero;
13356 Offsets[2] = DAG.getTargetConstant(0, DL, MVT::i32);
13357}
13358
13359SDValue SITargetLowering::bufferRsrcPtrToVector(SDValue MaybePointer,
13360 SelectionDAG &DAG) const {
13361 if (!MaybePointer.getValueType().isScalarInteger())
13362 return MaybePointer;
13363
13364 SDValue Rsrc = DAG.getBitcast(MVT::v4i32, MaybePointer);
13365 return Rsrc;
13366}
13367
13368// Wrap a global or flat pointer into a buffer intrinsic using the flags
13369// specified in the intrinsic.
13370SDValue SITargetLowering::lowerPointerAsRsrcIntrin(SDNode *Op,
13371 SelectionDAG &DAG) const {
13372 SDLoc Loc(Op);
13373
13374 SDValue Pointer = Op->getOperand(1);
13375 SDValue Stride = Op->getOperand(2);
13376 SDValue NumRecords = Op->getOperand(3);
13377 SDValue Flags = Op->getOperand(4);
13378
13379 SDValue ExtStride = DAG.getAnyExtOrTrunc(Stride, Loc, MVT::i32);
13380 SDValue Rsrc;
13381
13382 if (Subtarget->getBufferResourceNumRecordsWidth() == 45) {
13383 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i64);
13384 NumRecords = DAG.getNode(ISD::AND, Loc, MVT::i64, NumRecords,
13385 DAG.getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13386 SDValue Zero = DAG.getConstant(0, Loc, MVT::i32);
13387 // Build the lower 64-bit value, which has a 57-bit base and the lower 7-bit
13388 // num_records.
13389 SDValue ExtPointer = DAG.getAnyExtOrTrunc(Pointer, Loc, MVT::i64);
13390 SDValue NumRecordsLHS =
13391 DAG.getNode(ISD::SHL, Loc, MVT::i64, NumRecords,
13392 DAG.getShiftAmountConstant(57, MVT::i32, Loc));
13393 SDValue LowHalf =
13394 DAG.getNode(ISD::OR, Loc, MVT::i64, ExtPointer, NumRecordsLHS);
13395
13396 // Build the higher 64-bit value, which has the higher 38-bit num_records,
13397 // 6-bit zero (omit), 16-bit stride and scale and 4-bit flag.
13398 SDValue NumRecordsRHS =
13399 DAG.getNode(ISD::SRL, Loc, MVT::i64, NumRecords,
13400 DAG.getShiftAmountConstant(7, MVT::i32, Loc));
13401 SDValue ShiftedStride =
13402 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13403 DAG.getShiftAmountConstant(12, MVT::i32, Loc));
13404 SDValue ExtShiftedStrideVec =
13405 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedStride);
13406 SDValue ExtShiftedStride =
13407 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedStrideVec);
13408 SDValue ShiftedFlags =
13409 DAG.getNode(ISD::SHL, Loc, MVT::i32, Flags,
13410 DAG.getShiftAmountConstant(28, MVT::i32, Loc));
13411 SDValue ExtShiftedFlagsVec =
13412 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedFlags);
13413 SDValue ExtShiftedFlags =
13414 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedFlagsVec);
13415 SDValue CombinedFields =
13416 DAG.getNode(ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13417 SDValue HighHalf =
13418 DAG.getNode(ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13419
13420 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i64, LowHalf, HighHalf);
13421 } else {
13422 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i32);
13423 auto [LowHalf, HighHalf] =
13424 DAG.SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13425 SDValue Mask = DAG.getConstant(0x0000ffff, Loc, MVT::i32);
13426 SDValue Masked = DAG.getNode(ISD::AND, Loc, MVT::i32, HighHalf, Mask);
13427 SDValue ShiftedStride =
13428 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13429 DAG.getShiftAmountConstant(16, MVT::i32, Loc));
13430 SDValue NewHighHalf =
13431 DAG.getNode(ISD::OR, Loc, MVT::i32, Masked, ShiftedStride);
13432
13433 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v4i32, LowHalf, NewHighHalf,
13434 NumRecords, Flags);
13435 }
13436
13437 SDValue RsrcPtr = DAG.getNode(ISD::BITCAST, Loc, MVT::i128, Rsrc);
13438 return RsrcPtr;
13439}
13440
13441// Handle 8 bit and 16 bit buffer loads
13442SDValue SITargetLowering::handleByteShortBufferLoads(SelectionDAG &DAG,
13443 EVT LoadVT, SDLoc DL,
13445 MachineMemOperand *MMO,
13446 bool IsTFE) const {
13447 EVT IntVT = LoadVT.changeTypeToInteger();
13448
13449 if (IsTFE) {
13450 unsigned Opc = (LoadVT.getScalarType() == MVT::i8)
13451 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13452 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13454 MachineMemOperand *OpMMO = MF.getMachineMemOperand(MMO, 0, 8);
13455 SDVTList VTs = DAG.getVTList(MVT::v2i32, MVT::Other);
13456 SDValue Op = getMemIntrinsicNode(Opc, DL, VTs, Ops, MVT::v2i32, OpMMO, DAG);
13457 SDValue Status = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13458 DAG.getConstant(1, DL, MVT::i32));
13459 SDValue Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13460 DAG.getConstant(0, DL, MVT::i32));
13461 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Data);
13462 SDValue Value = DAG.getNode(ISD::BITCAST, DL, LoadVT, Trunc);
13463 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
13464 }
13465
13466 unsigned Opc = LoadVT.getScalarType() == MVT::i8
13467 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13468 : AMDGPUISD::BUFFER_LOAD_USHORT;
13469
13470 SDVTList ResList = DAG.getVTList(MVT::i32, MVT::Other);
13471 SDValue BufferLoad =
13472 DAG.getMemIntrinsicNode(Opc, DL, ResList, Ops, IntVT, MMO);
13473 SDValue LoadVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, BufferLoad);
13474 LoadVal = DAG.getNode(ISD::BITCAST, DL, LoadVT, LoadVal);
13475
13476 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
13477}
13478
13479// Handle 8 bit and 16 bit buffer stores
13480SDValue SITargetLowering::handleByteShortBufferStores(SelectionDAG &DAG,
13481 EVT VDataType, SDLoc DL,
13482 SDValue Ops[],
13483 MemSDNode *M) const {
13484 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13485 Ops[1] = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Ops[1]);
13486
13487 SDValue BufferStoreExt = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Ops[1]);
13488 Ops[1] = BufferStoreExt;
13489 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13490 : AMDGPUISD::BUFFER_STORE_SHORT;
13491 ArrayRef<SDValue> OpsRef = ArrayRef(&Ops[0], 9);
13492 return DAG.getMemIntrinsicNode(Opc, DL, M->getVTList(), OpsRef, VDataType,
13493 M->getMemOperand());
13494}
13495
13497 SDValue Op, const SDLoc &SL, EVT VT) {
13498 if (VT.bitsLT(Op.getValueType()))
13499 return DAG.getNode(ISD::TRUNCATE, SL, VT, Op);
13500
13501 switch (ExtType) {
13502 case ISD::SEXTLOAD:
13503 return DAG.getNode(ISD::SIGN_EXTEND, SL, VT, Op);
13504 case ISD::ZEXTLOAD:
13505 return DAG.getNode(ISD::ZERO_EXTEND, SL, VT, Op);
13506 case ISD::EXTLOAD:
13507 return DAG.getNode(ISD::ANY_EXTEND, SL, VT, Op);
13508 case ISD::NON_EXTLOAD:
13509 return Op;
13510 }
13511
13512 llvm_unreachable("invalid ext type");
13513}
13514
13515// Try to turn 8 and 16-bit scalar loads into SMEM eligible 32-bit loads.
13516// TODO: Skip this on GFX12 which does have scalar sub-dword loads.
13517SDValue SITargetLowering::widenLoad(LoadSDNode *Ld,
13518 DAGCombinerInfo &DCI) const {
13519 SelectionDAG &DAG = DCI.DAG;
13520 if (Ld->getAlign() < Align(4) || Ld->isDivergent())
13521 return SDValue();
13522
13523 // FIXME: Constant loads should all be marked invariant.
13524 unsigned AS = Ld->getAddressSpace();
13525 if (AS != AMDGPUAS::CONSTANT_ADDRESS &&
13527 (AS != AMDGPUAS::GLOBAL_ADDRESS || !Ld->isInvariant()))
13528 return SDValue();
13529
13530 // Don't do this early, since it may interfere with adjacent load merging for
13531 // illegal types. We can avoid losing alignment information for exotic types
13532 // pre-legalize.
13533 EVT MemVT = Ld->getMemoryVT();
13534 if ((MemVT.isSimple() && !DCI.isAfterLegalizeDAG()) ||
13535 MemVT.getSizeInBits() >= 32)
13536 return SDValue();
13537
13538 SDLoc SL(Ld);
13539
13540 assert((!MemVT.isVector() || Ld->getExtensionType() == ISD::NON_EXTLOAD) &&
13541 "unexpected vector extload");
13542
13543 // TODO: Drop only high part of range.
13544 SDValue Ptr = Ld->getBasePtr();
13545 SDValue NewLoad = DAG.getLoad(
13546 ISD::UNINDEXED, ISD::NON_EXTLOAD, MVT::i32, SL, Ld->getChain(), Ptr,
13547 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13548 Ld->getMemOperand()->getFlags(), Ld->getAAInfo()); // Drop ranges
13549
13550 EVT TruncVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
13551 if (MemVT.isFloatingPoint()) {
13552 assert(Ld->getExtensionType() == ISD::NON_EXTLOAD &&
13553 "unexpected fp extload");
13554 TruncVT = MemVT.changeTypeToInteger();
13555 }
13556
13557 SDValue Cvt = NewLoad;
13558 if (Ld->getExtensionType() == ISD::SEXTLOAD) {
13559 Cvt = DAG.getNode(ISD::SIGN_EXTEND_INREG, SL, MVT::i32, NewLoad,
13560 DAG.getValueType(TruncVT));
13561 } else if (Ld->getExtensionType() == ISD::ZEXTLOAD ||
13562 Ld->getExtensionType() == ISD::NON_EXTLOAD) {
13563 Cvt = DAG.getZeroExtendInReg(NewLoad, SL, TruncVT);
13564 } else {
13565 assert(Ld->getExtensionType() == ISD::EXTLOAD);
13566 }
13567
13568 EVT VT = Ld->getValueType(0);
13569 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
13570
13571 DCI.AddToWorklist(Cvt.getNode());
13572
13573 // We may need to handle exotic cases, such as i16->i64 extloads, so insert
13574 // the appropriate extension from the 32-bit load.
13575 Cvt = getLoadExtOrTrunc(DAG, Ld->getExtensionType(), Cvt, SL, IntVT);
13576 DCI.AddToWorklist(Cvt.getNode());
13577
13578 // Handle conversion back to floating point if necessary.
13579 Cvt = DAG.getNode(ISD::BITCAST, SL, VT, Cvt);
13580
13581 return DAG.getMergeValues({Cvt, NewLoad.getValue(1)}, SL);
13582}
13583
13585 const SIMachineFunctionInfo &Info) {
13586 // TODO: Should check if the address can definitely not access stack.
13587 if (Info.isEntryFunction())
13588 return Info.getUserSGPRInfo().hasFlatScratchInit();
13589 return true;
13590}
13591
13592SDValue SITargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
13593 SDLoc DL(Op);
13594 LoadSDNode *Load = cast<LoadSDNode>(Op);
13595 ISD::LoadExtType ExtType = Load->getExtensionType();
13596 EVT MemVT = Load->getMemoryVT();
13597 MachineMemOperand *MMO = Load->getMemOperand();
13598
13599 if (ExtType == ISD::NON_EXTLOAD && MemVT.getSizeInBits() < 32) {
13600 if (MemVT == MVT::i16 && isTypeLegal(MVT::i16))
13601 return SDValue();
13602
13603 // FIXME: Copied from PPC
13604 // First, load into 32 bits, then truncate to 1 bit.
13605
13606 SDValue Chain = Load->getChain();
13607 SDValue BasePtr = Load->getBasePtr();
13608
13609 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13610
13611 SDValue NewLD = DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, BasePtr,
13612 RealMemVT, MMO);
13613
13614 if (!MemVT.isVector()) {
13615 SDValue Ops[] = {DAG.getNode(ISD::TRUNCATE, DL, MemVT, NewLD),
13616 NewLD.getValue(1)};
13617
13618 return DAG.getMergeValues(Ops, DL);
13619 }
13620
13622 for (unsigned I = 0, N = MemVT.getVectorNumElements(); I != N; ++I) {
13623 SDValue Elt = DAG.getNode(ISD::SRL, DL, MVT::i32, NewLD,
13624 DAG.getConstant(I, DL, MVT::i32));
13625
13626 Elts.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Elt));
13627 }
13628
13629 SDValue Ops[] = {DAG.getBuildVector(MemVT, DL, Elts), NewLD.getValue(1)};
13630
13631 return DAG.getMergeValues(Ops, DL);
13632 }
13633
13634 if (!MemVT.isVector())
13635 return SDValue();
13636
13637 assert(Op.getValueType().getVectorElementType() == MVT::i32 &&
13638 "Custom lowering for non-i32 vectors hasn't been implemented.");
13639
13640 Align Alignment = Load->getAlign();
13641 unsigned AS = Load->getAddressSpace();
13642 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13643 AS == AMDGPUAS::FLAT_ADDRESS &&
13644 Alignment.value() < MemVT.getStoreSize() && MemVT.getSizeInBits() > 32) {
13645 return SplitVectorLoad(Op, DAG);
13646 }
13647
13649 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
13650 // If there is a possibility that flat instruction access scratch memory
13651 // then we need to use the same legalization rules we use for private.
13652 if (AS == AMDGPUAS::FLAT_ADDRESS &&
13653 !Subtarget->hasMultiDwordFlatScratchAddressing())
13654 AS = addressMayBeAccessedAsPrivate(Load->getMemOperand(), *MFI)
13657
13658 unsigned NumElements = MemVT.getVectorNumElements();
13659
13660 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13662 (AS == AMDGPUAS::GLOBAL_ADDRESS &&
13663 Subtarget->getScalarizeGlobalBehavior() && Load->isSimple() &&
13664 (Load->isInvariant() || isMemOpHasNoClobberedMemOperand(Load)))) {
13665 if ((!Op->isDivergent() || AMDGPU::isUniformMMO(MMO)) &&
13666 Alignment >= Align(4) && NumElements < 32) {
13667 if (MemVT.isPow2VectorType() ||
13668 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13669 return SDValue();
13670 return WidenOrSplitVectorLoad(Op, DAG);
13671 }
13672 // Non-uniform loads will be selected to MUBUF instructions, so they
13673 // have the same legalization requirements as global and private
13674 // loads.
13675 //
13676 }
13677 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13680 if (NumElements > 4)
13681 return SplitVectorLoad(Op, DAG);
13682 // v3 loads not supported on SI.
13683 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13684 return WidenOrSplitVectorLoad(Op, DAG);
13685
13686 // v3 and v4 loads are supported for private and global memory.
13687 return SDValue();
13688 }
13689 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
13690 // Depending on the setting of the private_element_size field in the
13691 // resource descriptor, we can only make private accesses up to a certain
13692 // size.
13693 switch (Subtarget->getMaxPrivateElementSize()) {
13694 case 4: {
13695 auto [Op0, Op1] = scalarizeVectorLoad(Load, DAG);
13696 return DAG.getMergeValues({Op0, Op1}, DL);
13697 }
13698 case 8:
13699 if (NumElements > 2)
13700 return SplitVectorLoad(Op, DAG);
13701 return SDValue();
13702 case 16:
13703 // Same as global/flat
13704 if (NumElements > 4)
13705 return SplitVectorLoad(Op, DAG);
13706 // v3 loads not supported on SI.
13707 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13708 return WidenOrSplitVectorLoad(Op, DAG);
13709
13710 return SDValue();
13711 default:
13712 llvm_unreachable("unsupported private_element_size");
13713 }
13714 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
13715 unsigned Fast = 0;
13716 auto Flags = Load->getMemOperand()->getFlags();
13718 Load->getAlign(), Flags, &Fast) &&
13719 Fast > 1)
13720 return SDValue();
13721
13722 if (MemVT.isVector())
13723 return SplitVectorLoad(Op, DAG);
13724 }
13725
13727 MemVT, *Load->getMemOperand())) {
13728 auto [Op0, Op1] = expandUnalignedLoad(Load, DAG);
13729 return DAG.getMergeValues({Op0, Op1}, DL);
13730 }
13731
13732 return SDValue();
13733}
13734
13735SDValue SITargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
13736 EVT VT = Op.getValueType();
13737 if (VT.getSizeInBits() == 128 || VT.getSizeInBits() == 256 ||
13738 VT.getSizeInBits() == 512)
13739 return splitTernaryVectorOp(Op, DAG);
13740
13741 assert(VT.getSizeInBits() == 64);
13742
13743 SDLoc DL(Op);
13744 SDValue Cond = DAG.getFreeze(Op.getOperand(0));
13745
13746 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
13747 SDValue One = DAG.getConstant(1, DL, MVT::i32);
13748
13749 SDValue LHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
13750 SDValue RHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(2));
13751
13752 SDValue Lo0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, Zero);
13753 SDValue Lo1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, Zero);
13754
13755 SDValue Lo = DAG.getSelect(DL, MVT::i32, Cond, Lo0, Lo1);
13756
13757 SDValue Hi0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, One);
13758 SDValue Hi1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, One);
13759
13760 SDValue Hi = DAG.getSelect(DL, MVT::i32, Cond, Hi0, Hi1);
13761
13762 SDValue Res = DAG.getBuildVector(MVT::v2i32, DL, {Lo, Hi});
13763 return DAG.getNode(ISD::BITCAST, DL, VT, Res);
13764}
13765
13766// Catch division cases where we can use shortcuts with rcp and rsq
13767// instructions.
13768SDValue SITargetLowering::lowerFastUnsafeFDIV(SDValue Op,
13769 SelectionDAG &DAG) const {
13770 SDLoc SL(Op);
13771 SDValue LHS = Op.getOperand(0);
13772 SDValue RHS = Op.getOperand(1);
13773 EVT VT = Op.getValueType();
13774 const SDNodeFlags Flags = Op->getFlags();
13775
13776 bool AllowInaccurateRcp = Flags.hasApproximateFuncs();
13777
13778 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
13779 // Without !fpmath accuracy information, we can't do more because we don't
13780 // know exactly whether rcp is accurate enough to meet !fpmath requirement.
13781 // f16 is always accurate enough
13782 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13783 return SDValue();
13784
13785 if (CLHS->isOne()) {
13786 // v_rcp_f32 and v_rsq_f32 do not support denormals, and according to
13787 // the CI documentation has a worst case error of 1 ulp.
13788 // OpenCL requires <= 2.5 ulp for 1.0 / x, so it should always be OK to
13789 // use it as long as we aren't trying to use denormals.
13790 //
13791 // v_rcp_f16 and v_rsq_f16 DO support denormals and 0.51ulp.
13792
13793 // 1.0 / sqrt(x) -> rsq(x)
13794
13795 // XXX - Is afn sufficient to do this for f64? The maximum ULP
13796 // error seems really high at 2^29 ULP.
13797 // 1.0 / x -> rcp(x)
13798 return DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13799 }
13800
13801 // Same as for 1.0, but expand the sign out of the constant.
13802 if (CLHS->isMinusOne()) {
13803 // -1.0 / x -> rcp (fneg x)
13804 SDValue FNegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
13805 return DAG.getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13806 }
13807 }
13808
13809 // For f16 and bf16 require afn or arcp.
13810 // For f32 require afn.
13811 if (!AllowInaccurateRcp &&
13812 ((VT != MVT::f16 && VT != MVT::bf16) || !Flags.hasAllowReciprocal()))
13813 return SDValue();
13814
13815 // Turn into multiply by the reciprocal.
13816 // x / y -> x * (1.0 / y)
13817 SDValue Recip = DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13818 return DAG.getNode(ISD::FMUL, SL, VT, LHS, Recip, Flags);
13819}
13820
13821SDValue SITargetLowering::lowerFastUnsafeFDIV64(SDValue Op,
13822 SelectionDAG &DAG) const {
13823 SDLoc SL(Op);
13824 SDValue X = Op.getOperand(0);
13825 SDValue Y = Op.getOperand(1);
13826 EVT VT = Op.getValueType();
13827 const SDNodeFlags Flags = Op->getFlags();
13828
13829 bool AllowInaccurateDiv = Flags.hasApproximateFuncs();
13830 if (!AllowInaccurateDiv)
13831 return SDValue();
13832
13833 const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(X);
13834 bool IsNegRcp = CLHS && CLHS->isMinusOne();
13835
13836 // Pull out the negation so it folds for free into the source modifiers.
13837 if (IsNegRcp)
13838 X = DAG.getConstantFP(1.0, SL, VT);
13839
13840 SDValue NegY = IsNegRcp ? Y : DAG.getNode(ISD::FNEG, SL, VT, Y);
13841 SDValue One = DAG.getConstantFP(1.0, SL, VT);
13842
13843 SDValue R = DAG.getNode(AMDGPUISD::RCP, SL, VT, Y);
13844 if (IsNegRcp)
13845 R = DAG.getNode(ISD::FNEG, SL, VT, R);
13846
13847 SDValue Tmp0 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13848
13849 R = DAG.getNode(ISD::FMA, SL, VT, Tmp0, R, R);
13850 SDValue Tmp1 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13851 R = DAG.getNode(ISD::FMA, SL, VT, Tmp1, R, R);
13852
13853 // Skip the last 2 correction terms for reciprocal.
13854 if (IsNegRcp || (CLHS && CLHS->isOne()))
13855 return R;
13856
13857 SDValue Ret = DAG.getNode(ISD::FMUL, SL, VT, X, R);
13858 SDValue Tmp2 = DAG.getNode(ISD::FMA, SL, VT, NegY, Ret, X);
13859 return DAG.getNode(ISD::FMA, SL, VT, Tmp2, R, Ret);
13860}
13861
13862static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13863 EVT VT, SDValue A, SDValue B, SDValue GlueChain,
13864 SDNodeFlags Flags) {
13865 if (GlueChain->getNumValues() <= 1) {
13866 return DAG.getNode(Opcode, SL, VT, A, B, Flags);
13867 }
13868
13869 assert(GlueChain->getNumValues() == 3);
13870
13871 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13872 switch (Opcode) {
13873 default:
13874 llvm_unreachable("no chain equivalent for opcode");
13875 case ISD::FMUL:
13876 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13877 break;
13878 }
13879
13880 return DAG.getNode(Opcode, SL, VTList,
13881 {GlueChain.getValue(1), A, B, GlueChain.getValue(2)},
13882 Flags);
13883}
13884
13885static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13886 EVT VT, SDValue A, SDValue B, SDValue C,
13887 SDValue GlueChain, SDNodeFlags Flags) {
13888 if (GlueChain->getNumValues() <= 1) {
13889 return DAG.getNode(Opcode, SL, VT, {A, B, C}, Flags);
13890 }
13891
13892 assert(GlueChain->getNumValues() == 3);
13893
13894 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13895 switch (Opcode) {
13896 default:
13897 llvm_unreachable("no chain equivalent for opcode");
13898 case ISD::FMA:
13899 Opcode = AMDGPUISD::FMA_W_CHAIN;
13900 break;
13901 }
13902
13903 return DAG.getNode(Opcode, SL, VTList,
13904 {GlueChain.getValue(1), A, B, C, GlueChain.getValue(2)},
13905 Flags);
13906}
13907
13908SDValue SITargetLowering::LowerFDIV16(SDValue Op, SelectionDAG &DAG) const {
13909 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
13910 return FastLowered;
13911
13912 SDLoc SL(Op);
13913 EVT VT = Op.getValueType();
13914 SDValue LHS = Op.getOperand(0);
13915 SDValue RHS = Op.getOperand(1);
13916
13917 SDValue LHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, LHS);
13918 SDValue RHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, RHS);
13919
13920 if (VT == MVT::bf16) {
13921 SDValue ExtDiv =
13922 DAG.getNode(ISD::FDIV, SL, MVT::f32, LHSExt, RHSExt, Op->getFlags());
13923 return DAG.getNode(ISD::FP_ROUND, SL, MVT::bf16, ExtDiv,
13924 DAG.getTargetConstant(0, SL, MVT::i32));
13925 }
13926
13927 assert(VT == MVT::f16);
13928
13929 // a32.u = opx(V_CVT_F32_F16, a.u); // CVT to F32
13930 // b32.u = opx(V_CVT_F32_F16, b.u); // CVT to F32
13931 // r32.u = opx(V_RCP_F32, b32.u); // rcp = 1 / d
13932 // q32.u = opx(V_MUL_F32, a32.u, r32.u); // q = n * rcp
13933 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
13934 // q32.u = opx(V_MAD_F32, e32.u, r32.u, q32.u); // q = n * rcp
13935 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
13936 // tmp.u = opx(V_MUL_F32, e32.u, r32.u);
13937 // tmp.u = opx(V_AND_B32, tmp.u, 0xff800000)
13938 // q32.u = opx(V_ADD_F32, tmp.u, q32.u);
13939 // q16.u = opx(V_CVT_F16_F32, q32.u);
13940 // q16.u = opx(V_DIV_FIXUP_F16, q16.u, b.u, a.u); // q = touchup(q, d, n)
13941
13942 // We will use ISD::FMA on targets that don't support ISD::FMAD.
13943 unsigned FMADOpCode =
13945 SDValue NegRHSExt = DAG.getNode(ISD::FNEG, SL, MVT::f32, RHSExt);
13946 SDValue Rcp =
13947 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt, Op->getFlags());
13948 SDValue Quot =
13949 DAG.getNode(ISD::FMUL, SL, MVT::f32, LHSExt, Rcp, Op->getFlags());
13950 SDValue Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13951 Op->getFlags());
13952 Quot = DAG.getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot, Op->getFlags());
13953 Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13954 Op->getFlags());
13955 SDValue Tmp = DAG.getNode(ISD::FMUL, SL, MVT::f32, Err, Rcp, Op->getFlags());
13956 SDValue TmpCast = DAG.getNode(ISD::BITCAST, SL, MVT::i32, Tmp);
13957 TmpCast = DAG.getNode(ISD::AND, SL, MVT::i32, TmpCast,
13958 DAG.getConstant(0xff800000, SL, MVT::i32));
13959 Tmp = DAG.getNode(ISD::BITCAST, SL, MVT::f32, TmpCast);
13960 Quot = DAG.getNode(ISD::FADD, SL, MVT::f32, Tmp, Quot, Op->getFlags());
13961 SDValue RDst = DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Quot,
13962 DAG.getTargetConstant(0, SL, MVT::i32));
13963 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst, RHS, LHS,
13964 Op->getFlags());
13965}
13966
13967// Faster 2.5 ULP division that does not support denormals.
13968SDValue SITargetLowering::lowerFDIV_FAST(SDValue Op, SelectionDAG &DAG) const {
13969 SDNodeFlags Flags = Op->getFlags();
13970 SDLoc SL(Op);
13971 SDValue LHS = Op.getOperand(1);
13972 SDValue RHS = Op.getOperand(2);
13973
13974 // TODO: The combiner should probably handle elimination of redundant fabs.
13975 SDValue r1 = DAG.SignBitIsZeroFP(RHS)
13976 ? RHS
13977 : DAG.getNode(ISD::FABS, SL, MVT::f32, RHS, Flags);
13978
13979 const APFloat K0Val(0x1p+96f);
13980 const SDValue K0 = DAG.getConstantFP(K0Val, SL, MVT::f32);
13981
13982 const APFloat K1Val(0x1p-32f);
13983 const SDValue K1 = DAG.getConstantFP(K1Val, SL, MVT::f32);
13984
13985 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
13986
13987 EVT SetCCVT =
13988 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
13989
13990 SDValue r2 = DAG.getSetCC(SL, SetCCVT, r1, K0, ISD::SETOGT);
13991
13992 SDValue r3 = DAG.getNode(ISD::SELECT, SL, MVT::f32, r2, K1, One, Flags);
13993
13994 r1 = DAG.getNode(ISD::FMUL, SL, MVT::f32, RHS, r3, Flags);
13995
13996 // rcp does not support denormals.
13997 SDValue r0 = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, r1, Flags);
13998
13999 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f32, LHS, r0, Flags);
14000
14001 return DAG.getNode(ISD::FMUL, SL, MVT::f32, r3, Mul, Flags);
14002}
14003
14004// Returns immediate value for setting the F32 denorm mode when using the
14005// S_DENORM_MODE instruction.
14007 const SIMachineFunctionInfo *Info,
14008 const GCNSubtarget *ST) {
14009 assert(ST->hasDenormModeInst() && "Requires S_DENORM_MODE");
14010 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
14011 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
14012 return DAG.getTargetConstant(Mode, SDLoc(), MVT::i32);
14013}
14014
14015SDValue SITargetLowering::LowerFDIV32(SDValue Op, SelectionDAG &DAG) const {
14016 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
14017 return FastLowered;
14018
14019 // The selection matcher assumes anything with a chain selecting to a
14020 // mayRaiseFPException machine instruction. Since we're introducing a chain
14021 // here, we need to explicitly report nofpexcept for the regular fdiv
14022 // lowering.
14023 SDNodeFlags Flags = Op->getFlags();
14024 Flags.setNoFPExcept(true);
14025
14026 SDLoc SL(Op);
14027 SDValue LHS = Op.getOperand(0);
14028 SDValue RHS = Op.getOperand(1);
14029
14030 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
14031
14032 SDVTList ScaleVT = DAG.getVTList(MVT::f32, MVT::i1);
14033
14034 SDValue DenominatorScaled =
14035 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {RHS, RHS, LHS}, Flags);
14036 SDValue NumeratorScaled =
14037 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {LHS, RHS, LHS}, Flags);
14038
14039 // Denominator is scaled to not be denormal, so using rcp is ok.
14040 SDValue ApproxRcp =
14041 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
14042 SDValue NegDivScale0 =
14043 DAG.getNode(ISD::FNEG, SL, MVT::f32, DenominatorScaled, Flags);
14044
14045 using namespace AMDGPU::Hwreg;
14046 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
14047 const SDValue BitField = DAG.getTargetConstant(Denorm32Reg, SL, MVT::i32);
14048
14049 const MachineFunction &MF = DAG.getMachineFunction();
14050 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
14051 const DenormalMode DenormMode = Info->getMode().FP32Denormals;
14052
14053 const bool PreservesDenormals = DenormMode == DenormalMode::getIEEE();
14054 const bool HasDynamicDenormals =
14055 (DenormMode.Input == DenormalMode::Dynamic) ||
14056 (DenormMode.Output == DenormalMode::Dynamic);
14057
14058 SDValue SavedDenormMode;
14059
14060 if (!PreservesDenormals) {
14061 // Note we can't use the STRICT_FMA/STRICT_FMUL for the non-strict FDIV
14062 // lowering. The chain dependence is insufficient, and we need glue. We do
14063 // not need the glue variants in a strictfp function.
14064
14065 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
14066
14067 SDValue Glue = DAG.getEntryNode();
14068 if (HasDynamicDenormals) {
14069 SDNode *GetReg = DAG.getMachineNode(AMDGPU::S_GETREG_B32, SL,
14070 DAG.getVTList(MVT::i32, MVT::Glue),
14071 {BitField, Glue});
14072 SavedDenormMode = SDValue(GetReg, 0);
14073
14074 Glue = DAG.getMergeValues(
14075 {DAG.getEntryNode(), SDValue(GetReg, 0), SDValue(GetReg, 1)}, SL);
14076 }
14077
14078 SDNode *EnableDenorm;
14079 if (Subtarget->hasDenormModeInst()) {
14080 const SDValue EnableDenormValue =
14081 getSPDenormModeValue(FP_DENORM_FLUSH_NONE, DAG, Info, Subtarget);
14082
14083 EnableDenorm = DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
14084 EnableDenormValue)
14085 .getNode();
14086 } else {
14087 const SDValue EnableDenormValue =
14088 DAG.getConstant(FP_DENORM_FLUSH_NONE, SL, MVT::i32);
14089 EnableDenorm = DAG.getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
14090 {EnableDenormValue, BitField, Glue});
14091 }
14092
14093 SDValue Ops[3] = {NegDivScale0, SDValue(EnableDenorm, 0),
14094 SDValue(EnableDenorm, 1)};
14095
14096 NegDivScale0 = DAG.getMergeValues(Ops, SL);
14097 }
14098
14099 SDValue Fma0 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0,
14100 ApproxRcp, One, NegDivScale0, Flags);
14101
14102 SDValue Fma1 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma0, ApproxRcp,
14103 ApproxRcp, Fma0, Flags);
14104
14105 SDValue Mul = getFPBinOp(DAG, ISD::FMUL, SL, MVT::f32, NumeratorScaled, Fma1,
14106 Fma1, Flags);
14107
14108 SDValue Fma2 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Mul,
14109 NumeratorScaled, Mul, Flags);
14110
14111 SDValue Fma3 =
14112 getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma2, Fma1, Mul, Fma2, Flags);
14113
14114 SDValue Fma4 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Fma3,
14115 NumeratorScaled, Fma3, Flags);
14116
14117 if (!PreservesDenormals) {
14118 SDNode *DisableDenorm;
14119 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
14120 const SDValue DisableDenormValue = getSPDenormModeValue(
14121 FP_DENORM_FLUSH_IN_FLUSH_OUT, DAG, Info, Subtarget);
14122
14123 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
14124 DisableDenorm =
14125 DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
14126 Fma4.getValue(1), DisableDenormValue, Fma4.getValue(2))
14127 .getNode();
14128 } else {
14129 assert(HasDynamicDenormals == (bool)SavedDenormMode);
14130 const SDValue DisableDenormValue =
14131 HasDynamicDenormals
14132 ? SavedDenormMode
14133 : DAG.getConstant(FP_DENORM_FLUSH_IN_FLUSH_OUT, SL, MVT::i32);
14134
14135 DisableDenorm = DAG.getMachineNode(
14136 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14137 {DisableDenormValue, BitField, Fma4.getValue(1), Fma4.getValue(2)});
14138 }
14139
14140 SDValue OutputChain = DAG.getNode(ISD::TokenFactor, SL, MVT::Other,
14141 SDValue(DisableDenorm, 0), DAG.getRoot());
14142 DAG.setRoot(OutputChain);
14143 }
14144
14145 SDValue Scale = NumeratorScaled.getValue(1);
14146 SDValue Fmas = DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f32,
14147 {Fma4, Fma1, Fma3, Scale}, Flags);
14148
14149 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas, RHS, LHS, Flags);
14150}
14151
14152SDValue SITargetLowering::LowerFDIV64(SDValue Op, SelectionDAG &DAG) const {
14153 if (SDValue FastLowered = lowerFastUnsafeFDIV64(Op, DAG))
14154 return FastLowered;
14155
14156 SDLoc SL(Op);
14157 SDValue X = Op.getOperand(0);
14158 SDValue Y = Op.getOperand(1);
14159
14160 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f64);
14161
14162 SDVTList ScaleVT = DAG.getVTList(MVT::f64, MVT::i1);
14163
14164 SDValue DivScale0 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, Y, Y, X);
14165
14166 SDValue NegDivScale0 = DAG.getNode(ISD::FNEG, SL, MVT::f64, DivScale0);
14167
14168 SDValue Rcp = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14169
14170 SDValue Fma0 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Rcp, One);
14171
14172 SDValue Fma1 = DAG.getNode(ISD::FMA, SL, MVT::f64, Rcp, Fma0, Rcp);
14173
14174 SDValue Fma2 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Fma1, One);
14175
14176 SDValue DivScale1 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, X, Y, X);
14177
14178 SDValue Fma3 = DAG.getNode(ISD::FMA, SL, MVT::f64, Fma1, Fma2, Fma1);
14179 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f64, DivScale1, Fma3);
14180
14181 SDValue Fma4 =
14182 DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Mul, DivScale1);
14183
14184 SDValue Scale;
14185
14186 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14187 // Workaround a hardware bug on SI where the condition output from div_scale
14188 // is not usable.
14189
14190 const SDValue Hi = DAG.getConstant(1, SL, MVT::i32);
14191
14192 // Figure out if the scale to use for div_fmas.
14193 SDValue NumBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, X);
14194 SDValue DenBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Y);
14195 SDValue Scale0BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale0);
14196 SDValue Scale1BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale1);
14197
14198 SDValue NumHi =
14199 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, NumBC, Hi);
14200 SDValue DenHi =
14201 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, DenBC, Hi);
14202
14203 SDValue Scale0Hi =
14204 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale0BC, Hi);
14205 SDValue Scale1Hi =
14206 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale1BC, Hi);
14207
14208 SDValue CmpDen = DAG.getSetCC(SL, MVT::i1, DenHi, Scale0Hi, ISD::SETEQ);
14209 SDValue CmpNum = DAG.getSetCC(SL, MVT::i1, NumHi, Scale1Hi, ISD::SETEQ);
14210 Scale = DAG.getNode(ISD::XOR, SL, MVT::i1, CmpNum, CmpDen);
14211 } else {
14212 Scale = DivScale1.getValue(1);
14213 }
14214
14215 SDValue Fmas =
14216 DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3, Mul, Scale);
14217
14218 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas, Y, X);
14219}
14220
14221SDValue SITargetLowering::LowerFDIV(SDValue Op, SelectionDAG &DAG) const {
14222 EVT VT = Op.getValueType();
14223
14224 if (VT == MVT::f32)
14225 return LowerFDIV32(Op, DAG);
14226
14227 if (VT == MVT::f64)
14228 return LowerFDIV64(Op, DAG);
14229
14230 if (VT == MVT::f16 || VT == MVT::bf16)
14231 return LowerFDIV16(Op, DAG);
14232
14233 llvm_unreachable("Unexpected type for fdiv");
14234}
14235
14236SDValue SITargetLowering::LowerFFREXP(SDValue Op, SelectionDAG &DAG) const {
14237 SDLoc dl(Op);
14238 SDValue Val = Op.getOperand(0);
14239 EVT VT = Val.getValueType();
14240 EVT ResultExpVT = Op->getValueType(1);
14241 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14242
14243 SDValue Mant = DAG.getNode(
14245 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_mant, dl, MVT::i32), Val);
14246
14247 SDValue Exp = DAG.getNode(
14248 ISD::INTRINSIC_WO_CHAIN, dl, InstrExpVT,
14249 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_exp, dl, MVT::i32), Val);
14250
14251 if (Subtarget->hasFractBug()) {
14252 SDValue Fabs = DAG.getNode(ISD::FABS, dl, VT, Val);
14253 SDValue Inf =
14255
14256 SDValue IsFinite = DAG.getSetCC(dl, MVT::i1, Fabs, Inf, ISD::SETOLT);
14257 SDValue Zero = DAG.getConstant(0, dl, InstrExpVT);
14258 Exp = DAG.getNode(ISD::SELECT, dl, InstrExpVT, IsFinite, Exp, Zero);
14259 Mant = DAG.getNode(ISD::SELECT, dl, VT, IsFinite, Mant, Val);
14260 }
14261
14262 SDValue CastExp = DAG.getSExtOrTrunc(Exp, dl, ResultExpVT);
14263 return DAG.getMergeValues({Mant, CastExp}, dl);
14264}
14265
14266SDValue SITargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const {
14267 SDLoc DL(Op);
14268 StoreSDNode *Store = cast<StoreSDNode>(Op);
14269 EVT VT = Store->getMemoryVT();
14270
14271 if (VT == MVT::i1) {
14272 return DAG.getTruncStore(
14273 Store->getChain(), DL,
14274 DAG.getSExtOrTrunc(Store->getValue(), DL, MVT::i32),
14275 Store->getBasePtr(), MVT::i1, Store->getMemOperand());
14276 }
14277
14278 assert(VT.isVector() &&
14279 Store->getValue().getValueType().getScalarType() == MVT::i32);
14280
14281 unsigned AS = Store->getAddressSpace();
14282 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14283 AS == AMDGPUAS::FLAT_ADDRESS &&
14284 Store->getAlign().value() < VT.getStoreSize() &&
14285 VT.getSizeInBits() > 32) {
14286 return SplitVectorStore(Op, DAG);
14287 }
14288
14290 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
14291 // If there is a possibility that flat instruction access scratch memory
14292 // then we need to use the same legalization rules we use for private.
14293 if (AS == AMDGPUAS::FLAT_ADDRESS &&
14294 !Subtarget->hasMultiDwordFlatScratchAddressing())
14295 AS = addressMayBeAccessedAsPrivate(Store->getMemOperand(), *MFI)
14298
14299 unsigned NumElements = VT.getVectorNumElements();
14301 if (NumElements > 4)
14302 return SplitVectorStore(Op, DAG);
14303 // v3 stores not supported on SI.
14304 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14305 return SplitVectorStore(Op, DAG);
14306
14308 VT, *Store->getMemOperand()))
14309 return expandUnalignedStore(Store, DAG);
14310
14311 return SDValue();
14312 }
14313 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
14314 switch (Subtarget->getMaxPrivateElementSize()) {
14315 case 4:
14316 return scalarizeVectorStore(Store, DAG);
14317 case 8:
14318 if (NumElements > 2)
14319 return SplitVectorStore(Op, DAG);
14320 return SDValue();
14321 case 16:
14322 if (NumElements > 4 ||
14323 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14324 return SplitVectorStore(Op, DAG);
14325 return SDValue();
14326 default:
14327 llvm_unreachable("unsupported private_element_size");
14328 }
14329 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
14330 unsigned Fast = 0;
14331 auto Flags = Store->getMemOperand()->getFlags();
14333 Store->getAlign(), Flags, &Fast) &&
14334 Fast > 1)
14335 return SDValue();
14336
14337 if (VT.isVector())
14338 return SplitVectorStore(Op, DAG);
14339
14340 return expandUnalignedStore(Store, DAG);
14341 }
14342
14343 // Probably an invalid store. If so we'll end up emitting a selection error.
14344 return SDValue();
14345}
14346
14347// Avoid the full correct expansion for f32 sqrt when promoting from f16.
14348SDValue SITargetLowering::lowerFSQRTF16(SDValue Op, SelectionDAG &DAG) const {
14349 SDLoc SL(Op);
14350 assert(!Subtarget->has16BitInsts());
14351 SDNodeFlags Flags = Op->getFlags();
14352 SDValue Ext =
14353 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op.getOperand(0), Flags);
14354
14355 SDValue SqrtID = DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, SL, MVT::i32);
14356 SDValue Sqrt =
14357 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::f32, SqrtID, Ext, Flags);
14358
14359 return DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Sqrt,
14360 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
14361}
14362
14363SDValue SITargetLowering::lowerFSQRTF32(SDValue Op, SelectionDAG &DAG) const {
14364 SDLoc DL(Op);
14365 SDNodeFlags Flags = Op->getFlags();
14366 MVT VT = Op.getValueType().getSimpleVT();
14367 const SDValue X = Op.getOperand(0);
14368
14369 if (allowApproxFunc(DAG, Flags)) {
14370 // Instruction is 1ulp but ignores denormals.
14371 return DAG.getNode(
14373 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32), X, Flags);
14374 }
14375
14376 SDValue ScaleThreshold = DAG.getConstantFP(0x1.0p-96f, DL, VT);
14377 SDValue NeedScale = DAG.getSetCC(DL, MVT::i1, X, ScaleThreshold, ISD::SETOLT);
14378
14379 SDValue ScaleUpFactor = DAG.getConstantFP(0x1.0p+32f, DL, VT);
14380
14381 SDValue ScaledX = DAG.getNode(ISD::FMUL, DL, VT, X, ScaleUpFactor, Flags);
14382
14383 SDValue SqrtX =
14384 DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledX, X, Flags);
14385
14386 SDValue SqrtS;
14387 if (needsDenormHandlingF32(DAG, X, Flags)) {
14388 SDValue SqrtID =
14389 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32);
14390 SqrtS = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, SqrtID, SqrtX, Flags);
14391
14392 SDValue SqrtSAsInt = DAG.getNode(ISD::BITCAST, DL, MVT::i32, SqrtS);
14393 SDValue SqrtSNextDownInt =
14394 DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14395 DAG.getAllOnesConstant(DL, MVT::i32));
14396 SDValue SqrtSNextDown = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextDownInt);
14397
14398 SDValue NegSqrtSNextDown =
14399 DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextDown, Flags);
14400
14401 SDValue SqrtVP =
14402 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
14403
14404 SDValue SqrtSNextUpInt = DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14405 DAG.getConstant(1, DL, MVT::i32));
14406 SDValue SqrtSNextUp = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextUpInt);
14407
14408 SDValue NegSqrtSNextUp = DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextUp, Flags);
14409 SDValue SqrtVS =
14410 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
14411
14412 SDValue Zero = DAG.getConstantFP(0.0f, DL, VT);
14413 SDValue SqrtVPLE0 = DAG.getSetCC(DL, MVT::i1, SqrtVP, Zero, ISD::SETOLE);
14414
14415 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPLE0, SqrtSNextDown, SqrtS,
14416 Flags);
14417
14418 SDValue SqrtVPVSGT0 = DAG.getSetCC(DL, MVT::i1, SqrtVS, Zero, ISD::SETOGT);
14419 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPVSGT0, SqrtSNextUp, SqrtS,
14420 Flags);
14421 } else {
14422 SDValue SqrtR = DAG.getNode(AMDGPUISD::RSQ, DL, VT, SqrtX, Flags);
14423
14424 SqrtS = DAG.getNode(ISD::FMUL, DL, VT, SqrtX, SqrtR, Flags);
14425
14426 SDValue Half = DAG.getConstantFP(0.5f, DL, VT);
14427 SDValue SqrtH = DAG.getNode(ISD::FMUL, DL, VT, SqrtR, Half, Flags);
14428 SDValue NegSqrtH = DAG.getNode(ISD::FNEG, DL, VT, SqrtH, Flags);
14429
14430 SDValue SqrtE = DAG.getNode(ISD::FMA, DL, VT, NegSqrtH, SqrtS, Half, Flags);
14431 SqrtH = DAG.getNode(ISD::FMA, DL, VT, SqrtH, SqrtE, SqrtH, Flags);
14432 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtS, SqrtE, SqrtS, Flags);
14433
14434 SDValue NegSqrtS = DAG.getNode(ISD::FNEG, DL, VT, SqrtS, Flags);
14435 SDValue SqrtD =
14436 DAG.getNode(ISD::FMA, DL, VT, NegSqrtS, SqrtS, SqrtX, Flags);
14437 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtD, SqrtH, SqrtS, Flags);
14438 }
14439
14440 SDValue ScaleDownFactor = DAG.getConstantFP(0x1.0p-16f, DL, VT);
14441
14442 SDValue ScaledDown =
14443 DAG.getNode(ISD::FMUL, DL, VT, SqrtS, ScaleDownFactor, Flags);
14444
14445 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledDown, SqrtS, Flags);
14446 SDValue IsZeroOrInf =
14447 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14448 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14449
14450 return DAG.getNode(ISD::SELECT, DL, VT, IsZeroOrInf, SqrtX, SqrtS, Flags);
14451}
14452
14453SDValue SITargetLowering::lowerFSQRTF64(SDValue Op, SelectionDAG &DAG) const {
14454 // For double type, the SQRT and RSQ instructions don't have required
14455 // precision, we apply Goldschmidt's algorithm to improve the result:
14456 //
14457 // y0 = rsq(x)
14458 // g0 = x * y0
14459 // h0 = 0.5 * y0
14460 //
14461 // r0 = 0.5 - h0 * g0
14462 // g1 = g0 * r0 + g0
14463 // h1 = h0 * r0 + h0
14464 //
14465 // r1 = 0.5 - h1 * g1 => d0 = x - g1 * g1
14466 // g2 = g1 * r1 + g1 g2 = d0 * h1 + g1
14467 // h2 = h1 * r1 + h1
14468 //
14469 // r2 = 0.5 - h2 * g2 => d1 = x - g2 * g2
14470 // g3 = g2 * r2 + g2 g3 = d1 * h1 + g2
14471 //
14472 // sqrt(x) = g3
14473
14474 SDNodeFlags Flags = Op->getFlags();
14475
14476 SDLoc DL(Op);
14477
14478 SDValue X = Op.getOperand(0);
14479 SDValue ZeroInt = DAG.getConstant(0, DL, MVT::i32);
14480
14481 SDValue SqrtX = X;
14482 SDValue Scaling;
14483 if (!Flags.hasApproximateFuncs()) {
14484 SDValue ScaleConstant = DAG.getConstantFP(0x1.0p-767, DL, MVT::f64);
14485 Scaling = DAG.getSetCC(DL, MVT::i1, X, ScaleConstant, ISD::SETOLT);
14486
14487 // Scale up input if it is too small.
14488 SDValue ScaleUpFactor = DAG.getConstant(256, DL, MVT::i32);
14489 SDValue ScaleUp =
14490 DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling, ScaleUpFactor, ZeroInt);
14491 SqrtX = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, X, ScaleUp, Flags);
14492 }
14493
14494 SDValue SqrtY = DAG.getNode(AMDGPUISD::RSQ, DL, MVT::f64, SqrtX);
14495
14496 SDValue SqrtS0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtX, SqrtY);
14497
14498 SDValue Half = DAG.getConstantFP(0.5, DL, MVT::f64);
14499 SDValue SqrtH0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtY, Half);
14500
14501 SDValue NegSqrtH0 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtH0);
14502 SDValue SqrtR0 = DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtH0, SqrtS0, Half);
14503
14504 SDValue SqrtH1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtH0, SqrtR0, SqrtH0);
14505
14506 SDValue SqrtS1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtS0, SqrtR0, SqrtS0);
14507
14508 SDValue NegSqrtS1 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS1);
14509 SDValue SqrtD0 =
14510 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS1, SqrtS1, SqrtX);
14511
14512 SDValue SqrtS2 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD0, SqrtH1, SqrtS1);
14513
14514 SDValue SqrtRet = SqrtS2;
14515 if (!Flags.hasApproximateFuncs()) {
14516 SDValue NegSqrtS2 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS2);
14517 SDValue SqrtD1 =
14518 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS2, SqrtS2, SqrtX);
14519
14520 SqrtRet = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD1, SqrtH1, SqrtS2);
14521
14522 SDValue ScaleDownFactor = DAG.getSignedConstant(-128, DL, MVT::i32);
14523 SDValue ScaleDown = DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling,
14524 ScaleDownFactor, ZeroInt);
14525 SqrtRet = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, SqrtRet, ScaleDown, Flags);
14526 }
14527
14528 // TODO: Check for DAZ and expand to subnormals
14529
14530 SDValue IsZeroOrInf;
14531 if (Flags.hasNoInfs()) {
14532 SDValue Zero = DAG.getConstantFP(0.0, DL, MVT::f64);
14533 IsZeroOrInf = DAG.getSetCC(DL, MVT::i1, SqrtX, Zero, ISD::SETOEQ);
14534 } else {
14535 IsZeroOrInf =
14536 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14537 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14538 }
14539
14540 // If x is +INF, +0, or -0, use its original value
14541 return DAG.getNode(ISD::SELECT, DL, MVT::f64, IsZeroOrInf, SqrtX, SqrtRet,
14542 Flags);
14543}
14544
14545SDValue SITargetLowering::LowerTrig(SDValue Op, SelectionDAG &DAG) const {
14546 SDLoc DL(Op);
14547 EVT VT = Op.getValueType();
14548 SDValue Arg = Op.getOperand(0);
14549 SDValue TrigVal;
14550
14551 // Propagate fast-math flags so that the multiply we introduce can be folded
14552 // if Arg is already the result of a multiply by constant.
14553 auto Flags = Op->getFlags();
14554
14555 // AMDGPUISD nodes of vector type must be unrolled here since
14556 // they will not be expanded elsewhere.
14557 auto UnrollIfVec = [&DAG](SDValue V) -> SDValue {
14558 if (!V.getValueType().isVector())
14559 return V;
14560
14561 return DAG.UnrollVectorOp(cast<SDNode>(V));
14562 };
14563
14564 SDValue OneOver2Pi = DAG.getConstantFP(0.5 * numbers::inv_pi, DL, VT);
14565
14566 if (Subtarget->hasTrigReducedRange()) {
14567 SDValue MulVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14568 TrigVal = UnrollIfVec(DAG.getNode(AMDGPUISD::FRACT, DL, VT, MulVal, Flags));
14569 } else {
14570 TrigVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14571 }
14572
14573 switch (Op.getOpcode()) {
14574 case ISD::FCOS:
14575 TrigVal = DAG.getNode(AMDGPUISD::COS_HW, SDLoc(Op), VT, TrigVal, Flags);
14576 break;
14577 case ISD::FSIN:
14578 TrigVal = DAG.getNode(AMDGPUISD::SIN_HW, SDLoc(Op), VT, TrigVal, Flags);
14579 break;
14580 default:
14581 llvm_unreachable("Wrong trig opcode");
14582 }
14583
14584 return UnrollIfVec(TrigVal);
14585}
14586
14587SDValue SITargetLowering::LowerATOMIC_CMP_SWAP(SDValue Op,
14588 SelectionDAG &DAG) const {
14589 AtomicSDNode *AtomicNode = cast<AtomicSDNode>(Op);
14590 assert(AtomicNode->isCompareAndSwap());
14591 unsigned AS = AtomicNode->getAddressSpace();
14592
14593 // No custom lowering required for local address space
14595 return Op;
14596
14597 // Non-local address space requires custom lowering for atomic compare
14598 // and swap; cmp and swap should be in a v2i32 or v2i64 in case of _X2
14599 SDLoc DL(Op);
14600 SDValue ChainIn = Op.getOperand(0);
14601 SDValue Addr = Op.getOperand(1);
14602 SDValue Old = Op.getOperand(2);
14603 SDValue New = Op.getOperand(3);
14604 EVT VT = Op.getValueType();
14605 MVT SimpleVT = VT.getSimpleVT();
14606 MVT VecType = MVT::getVectorVT(SimpleVT, 2);
14607
14608 SDValue NewOld = DAG.getBuildVector(VecType, DL, {New, Old});
14609 SDValue Ops[] = {ChainIn, Addr, NewOld};
14610
14611 return DAG.getMemIntrinsicNode(AMDGPUISD::ATOMIC_CMP_SWAP, DL,
14612 Op->getVTList(), Ops, VT,
14613 AtomicNode->getMemOperand());
14614}
14615
14616//===----------------------------------------------------------------------===//
14617// Custom DAG optimizations
14618//===----------------------------------------------------------------------===//
14619
14620SDValue
14621SITargetLowering::performUCharToFloatCombine(SDNode *N,
14622 DAGCombinerInfo &DCI) const {
14623 EVT VT = N->getValueType(0);
14624 EVT ScalarVT = VT.getScalarType();
14625 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14626 return SDValue();
14627
14628 SelectionDAG &DAG = DCI.DAG;
14629 SDLoc DL(N);
14630
14631 SDValue Src = N->getOperand(0);
14632 EVT SrcVT = Src.getValueType();
14633
14634 // TODO: We could try to match extracting the higher bytes, which would be
14635 // easier if i8 vectors weren't promoted to i32 vectors, particularly after
14636 // types are legalized. v4i8 -> v4f32 is probably the only case to worry
14637 // about in practice.
14638 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14639 if (DAG.MaskedValueIsZero(Src, APInt::getHighBitsSet(32, 24))) {
14640 SDValue Cvt = DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0, DL, MVT::f32, Src);
14641 DCI.AddToWorklist(Cvt.getNode());
14642
14643 // For the f16 case, fold to a cast to f32 and then cast back to f16.
14644 if (ScalarVT != MVT::f32) {
14645 Cvt = DAG.getNode(ISD::FP_ROUND, DL, VT, Cvt,
14646 DAG.getTargetConstant(0, DL, MVT::i32));
14647 }
14648 return Cvt;
14649 }
14650 }
14651
14652 return SDValue();
14653}
14654
14655SDValue SITargetLowering::performFCopySignCombine(SDNode *N,
14656 DAGCombinerInfo &DCI) const {
14657 SDValue MagnitudeOp = N->getOperand(0);
14658 SDValue SignOp = N->getOperand(1);
14659
14660 // The generic combine for fcopysign + fp cast is too conservative with
14661 // vectors, and also gets confused by the splitting we will perform here, so
14662 // peek through FP casts.
14663 if (SignOp.getOpcode() == ISD::FP_EXTEND ||
14664 SignOp.getOpcode() == ISD::FP_ROUND)
14665 SignOp = SignOp.getOperand(0);
14666
14667 SelectionDAG &DAG = DCI.DAG;
14668 SDLoc DL(N);
14669 EVT SignVT = SignOp.getValueType();
14670
14671 // f64 fcopysign is really an f32 copysign on the high bits, so replace the
14672 // lower half with a copy.
14673 // fcopysign f64:x, _:y -> x.lo32, (fcopysign (f32 x.hi32), _:y)
14674 EVT MagVT = MagnitudeOp.getValueType();
14675
14676 unsigned NumElts = MagVT.isVector() ? MagVT.getVectorNumElements() : 1;
14677
14678 if (MagVT.getScalarType() == MVT::f64) {
14679 EVT F32VT = MagVT.isVector()
14680 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14681 : MVT::v2f32;
14682
14683 SDValue MagAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, MagnitudeOp);
14684
14686 for (unsigned I = 0; I != NumElts; ++I) {
14687 SDValue MagLo =
14688 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14689 DAG.getConstant(2 * I, DL, MVT::i32));
14690 SDValue MagHi =
14691 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14692 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14693
14694 SDValue SignOpElt =
14695 MagVT.isVector()
14697 SignOp, DAG.getConstant(I, DL, MVT::i32))
14698 : SignOp;
14699
14700 SDValue HiOp =
14701 DAG.getNode(ISD::FCOPYSIGN, DL, MVT::f32, MagHi, SignOpElt);
14702
14703 SDValue Vector =
14704 DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v2f32, MagLo, HiOp);
14705
14706 SDValue NewElt = DAG.getNode(ISD::BITCAST, DL, MVT::f64, Vector);
14707 NewElts.push_back(NewElt);
14708 }
14709
14710 if (NewElts.size() == 1)
14711 return NewElts[0];
14712
14713 return DAG.getNode(ISD::BUILD_VECTOR, DL, MagVT, NewElts);
14714 }
14715
14716 if (SignVT.getScalarType() != MVT::f64)
14717 return SDValue();
14718
14719 // Reduce width of sign operand, we only need the highest bit.
14720 //
14721 // fcopysign f64:x, f64:y ->
14722 // fcopysign f64:x, (extract_vector_elt (bitcast f64:y to v2f32), 1)
14723 // TODO: In some cases it might make sense to go all the way to f16.
14724
14725 EVT F32VT = MagVT.isVector()
14726 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14727 : MVT::v2f32;
14728
14729 SDValue SignAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, SignOp);
14730
14731 SmallVector<SDValue, 8> F32Signs;
14732 for (unsigned I = 0; I != NumElts; ++I) {
14733 // Take sign from odd elements of cast vector
14734 SDValue SignAsF32 =
14735 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, SignAsVector,
14736 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14737 F32Signs.push_back(SignAsF32);
14738 }
14739
14740 SDValue NewSign =
14741 NumElts == 1
14742 ? F32Signs.back()
14744 EVT::getVectorVT(*DAG.getContext(), MVT::f32, NumElts),
14745 F32Signs);
14746
14747 return DAG.getNode(ISD::FCOPYSIGN, DL, N->getValueType(0), N->getOperand(0),
14748 NewSign);
14749}
14750
14751// (shl (add x, c1), c2) -> add (shl x, c2), (shl c1, c2)
14752// (shl (or x, c1), c2) -> add (shl x, c2), (shl c1, c2) iff x and c1 share no
14753// bits
14754
14755// This is a variant of
14756// (mul (add x, c1), c2) -> add (mul x, c2), (mul c1, c2),
14757//
14758// The normal DAG combiner will do this, but only if the add has one use since
14759// that would increase the number of instructions.
14760//
14761// This prevents us from seeing a constant offset that can be folded into a
14762// memory instruction's addressing mode. If we know the resulting add offset of
14763// a pointer can be folded into an addressing offset, we can replace the pointer
14764// operand with the add of new constant offset. This eliminates one of the uses,
14765// and may allow the remaining use to also be simplified.
14766//
14767SDValue SITargetLowering::performSHLPtrCombine(SDNode *N, unsigned AddrSpace,
14768 EVT MemVT,
14769 DAGCombinerInfo &DCI) const {
14770 SDValue N0 = N->getOperand(0);
14771 SDValue N1 = N->getOperand(1);
14772
14773 // We only do this to handle cases where it's profitable when there are
14774 // multiple uses of the add, so defer to the standard combine.
14775 if ((!N0->isAnyAdd() && N0.getOpcode() != ISD::OR) || N0->hasOneUse())
14776 return SDValue();
14777
14778 const ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(N1);
14779 if (!CN1)
14780 return SDValue();
14781
14782 const ConstantSDNode *CAdd = dyn_cast<ConstantSDNode>(N0.getOperand(1));
14783 if (!CAdd)
14784 return SDValue();
14785
14786 SelectionDAG &DAG = DCI.DAG;
14787
14788 if (N0->getOpcode() == ISD::OR &&
14789 !DAG.haveNoCommonBitsSet(N0.getOperand(0), N0.getOperand(1)))
14790 return SDValue();
14791
14792 // If the resulting offset is too large, we can't fold it into the
14793 // addressing mode offset.
14794 APInt Offset = CAdd->getAPIntValue() << CN1->getAPIntValue();
14795 Type *Ty = MemVT.getTypeForEVT(*DCI.DAG.getContext());
14796
14797 AddrMode AM;
14798 AM.HasBaseReg = true;
14799 AM.BaseOffs = Offset.getSExtValue();
14800 if (!isLegalAddressingMode(DCI.DAG.getDataLayout(), AM, Ty, AddrSpace))
14801 return SDValue();
14802
14803 SDLoc SL(N);
14804 EVT VT = N->getValueType(0);
14805
14806 SDValue ShlX = DAG.getNode(ISD::SHL, SL, VT, N0.getOperand(0), N1);
14807 SDValue COffset = DAG.getConstant(Offset, SL, VT);
14808
14809 SDNodeFlags Flags;
14810 Flags.setNoUnsignedWrap(
14811 N->getFlags().hasNoUnsignedWrap() &&
14812 (N0.getOpcode() == ISD::OR || N0->getFlags().hasNoUnsignedWrap()));
14813
14814 // Use ISD::ADD even if the original operation was ISD::PTRADD, since we can't
14815 // be sure that the new left operand is a proper base pointer.
14816 return DAG.getNode(ISD::ADD, SL, VT, ShlX, COffset, Flags);
14817}
14818
14819/// MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset
14820/// by the chain and intrinsic ID. Theoretically we would also need to check the
14821/// specific intrinsic, but they all place the pointer operand first.
14822static unsigned getBasePtrIndex(const MemSDNode *N) {
14823 switch (N->getOpcode()) {
14824 case ISD::STORE:
14827 return 2;
14828 default:
14829 return 1;
14830 }
14831}
14832
14833SDValue SITargetLowering::performMemSDNodeCombine(MemSDNode *N,
14834 DAGCombinerInfo &DCI) const {
14835 SelectionDAG &DAG = DCI.DAG;
14836
14837 unsigned PtrIdx = getBasePtrIndex(N);
14838 SDValue Ptr = N->getOperand(PtrIdx);
14839
14840 // TODO: We could also do this for multiplies.
14841 if (Ptr.getOpcode() == ISD::SHL) {
14842 SDValue NewPtr = performSHLPtrCombine(Ptr.getNode(), N->getAddressSpace(),
14843 N->getMemoryVT(), DCI);
14844 if (NewPtr) {
14845 SmallVector<SDValue, 8> NewOps(N->ops());
14846
14847 NewOps[PtrIdx] = NewPtr;
14848 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
14849 }
14850 }
14851
14852 return SDValue();
14853}
14854
14855static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val) {
14856 return (Opc == ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14857 (Opc == ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14858 (Opc == ISD::XOR && Val == 0);
14859}
14860
14861// Break up 64-bit bit operation of a constant into two 32-bit and/or/xor. This
14862// will typically happen anyway for a VALU 64-bit and. This exposes other 32-bit
14863// integer combine opportunities since most 64-bit operations are decomposed
14864// this way. TODO: We won't want this for SALU especially if it is an inline
14865// immediate.
14866SDValue SITargetLowering::splitBinaryBitConstantOp(
14867 DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS,
14868 const ConstantSDNode *CRHS) const {
14869 uint64_t Val = CRHS->getZExtValue();
14870 uint32_t ValLo = Lo_32(Val);
14871 uint32_t ValHi = Hi_32(Val);
14872 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
14873
14874 if ((bitOpWithConstantIsReducible(Opc, ValLo) ||
14876 (CRHS->hasOneUse() && !TII->isInlineConstant(CRHS->getAPIntValue()))) {
14877 // We have 64-bit scalar and/or/xor, but do not have vector forms.
14878 if (Subtarget->has64BitLiterals() && CRHS->hasOneUse() &&
14879 !CRHS->user_begin()->isDivergent())
14880 return SDValue();
14881
14882 // If we need to materialize a 64-bit immediate, it will be split up later
14883 // anyway. Avoid creating the harder to understand 64-bit immediate
14884 // materialization.
14885 return splitBinaryBitConstantOpImpl(DCI, SL, Opc, LHS, ValLo, ValHi);
14886 }
14887
14888 return SDValue();
14889}
14890
14892 if (V.getValueType() != MVT::i1)
14893 return false;
14894 switch (V.getOpcode()) {
14895 default:
14896 break;
14897 case ISD::SETCC:
14898 case ISD::IS_FPCLASS:
14899 case AMDGPUISD::FP_CLASS:
14900 return true;
14901 case ISD::AND:
14902 case ISD::OR:
14903 case ISD::XOR:
14904 return isBoolSGPR(V.getOperand(0)) && isBoolSGPR(V.getOperand(1));
14905 case ISD::SADDO:
14906 case ISD::UADDO:
14907 case ISD::SSUBO:
14908 case ISD::USUBO:
14909 case ISD::SMULO:
14910 case ISD::UMULO:
14911 return V.getResNo() == 1;
14913 unsigned IntrinsicID = V.getConstantOperandVal(0);
14914 switch (IntrinsicID) {
14915 case Intrinsic::amdgcn_is_shared:
14916 case Intrinsic::amdgcn_is_private:
14917 return true;
14918 default:
14919 return false;
14920 }
14921
14922 return false;
14923 }
14924 }
14925 return false;
14926}
14927
14928// If a constant has all zeroes or all ones within each byte return it.
14929// Otherwise return 0.
14931 // 0xff for any zero byte in the mask
14932 uint32_t ZeroByteMask = 0;
14933 if (!(C & 0x000000ff))
14934 ZeroByteMask |= 0x000000ff;
14935 if (!(C & 0x0000ff00))
14936 ZeroByteMask |= 0x0000ff00;
14937 if (!(C & 0x00ff0000))
14938 ZeroByteMask |= 0x00ff0000;
14939 if (!(C & 0xff000000))
14940 ZeroByteMask |= 0xff000000;
14941 uint32_t NonZeroByteMask = ~ZeroByteMask; // 0xff for any non-zero byte
14942 if ((NonZeroByteMask & C) != NonZeroByteMask)
14943 return 0; // Partial bytes selected.
14944 return C;
14945}
14946
14947// Check if a node selects whole bytes from its operand 0 starting at a byte
14948// boundary while masking the rest. Returns select mask as in the v_perm_b32
14949// or -1 if not succeeded.
14950// Note byte select encoding:
14951// value 0-3 selects corresponding source byte;
14952// value 0xc selects zero;
14953// value 0xff selects 0xff.
14955 assert(V.getValueSizeInBits() == 32);
14956
14957 if (V.getNumOperands() != 2)
14958 return ~0;
14959
14960 ConstantSDNode *N1 = dyn_cast<ConstantSDNode>(V.getOperand(1));
14961 if (!N1)
14962 return ~0;
14963
14964 uint32_t C = N1->getZExtValue();
14965
14966 switch (V.getOpcode()) {
14967 default:
14968 break;
14969 case ISD::AND:
14970 if (uint32_t ConstMask = getConstantPermuteMask(C))
14971 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
14972 break;
14973
14974 case ISD::OR:
14975 if (uint32_t ConstMask = getConstantPermuteMask(C))
14976 return (0x03020100 & ~ConstMask) | ConstMask;
14977 break;
14978
14979 case ISD::SHL:
14980 if (C % 8)
14981 return ~0;
14982
14983 return uint32_t((0x030201000c0c0c0cull << C) >> 32);
14984
14985 case ISD::SRL:
14986 if (C % 8)
14987 return ~0;
14988
14989 return uint32_t(0x0c0c0c0c03020100ull >> C);
14990 }
14991
14992 return ~0;
14993}
14994
14995SDValue SITargetLowering::performAndCombine(SDNode *N,
14996 DAGCombinerInfo &DCI) const {
14997 if (DCI.isBeforeLegalize())
14998 return SDValue();
14999
15000 SelectionDAG &DAG = DCI.DAG;
15001 EVT VT = N->getValueType(0);
15002 SDValue LHS = N->getOperand(0);
15003 SDValue RHS = N->getOperand(1);
15004
15005 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS);
15006 if (VT == MVT::i64 && CRHS) {
15007 if (SDValue Split =
15008 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::AND, LHS, CRHS))
15009 return Split;
15010 }
15011
15012 if (CRHS && VT == MVT::i32) {
15013 // and (srl x, c), mask => shl (bfe x, nb + c, mask >> nb), nb
15014 // nb = number of trailing zeroes in mask
15015 // It can be optimized out using SDWA for GFX8+ in the SDWA peephole pass,
15016 // given that we are selecting 8 or 16 bit fields starting at byte boundary.
15017 uint64_t Mask = CRHS->getZExtValue();
15018 unsigned Bits = llvm::popcount(Mask);
15019 if (getSubtarget()->hasSDWA() && LHS->getOpcode() == ISD::SRL &&
15020 (Bits == 8 || Bits == 16) && isShiftedMask_64(Mask) && !(Mask & 1)) {
15021 if (auto *CShift = dyn_cast<ConstantSDNode>(LHS->getOperand(1))) {
15022 unsigned Shift = CShift->getZExtValue();
15023 unsigned NB = CRHS->getAPIntValue().countr_zero();
15024 unsigned Offset = NB + Shift;
15025 if ((Offset & (Bits - 1)) == 0) { // Starts at a byte or word boundary.
15026 SDLoc SL(N);
15027 SDValue BFE =
15028 DAG.getNode(AMDGPUISD::BFE_U32, SL, MVT::i32, LHS->getOperand(0),
15029 DAG.getConstant(Offset, SL, MVT::i32),
15030 DAG.getConstant(Bits, SL, MVT::i32));
15031 EVT NarrowVT = EVT::getIntegerVT(*DAG.getContext(), Bits);
15032 SDValue Ext = DAG.getNode(ISD::AssertZext, SL, VT, BFE,
15033 DAG.getValueType(NarrowVT));
15034 SDValue Shl = DAG.getNode(ISD::SHL, SDLoc(LHS), VT, Ext,
15035 DAG.getConstant(NB, SDLoc(CRHS), MVT::i32));
15036 return Shl;
15037 }
15038 }
15039 }
15040
15041 // and (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
15042 if (LHS.hasOneUse() && LHS.getOpcode() == AMDGPUISD::PERM &&
15043 isa<ConstantSDNode>(LHS.getOperand(2))) {
15044 uint32_t Sel = getConstantPermuteMask(Mask);
15045 if (!Sel)
15046 return SDValue();
15047
15048 // Select 0xc for all zero bytes
15049 Sel = (LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
15050 SDLoc DL(N);
15051 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15052 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
15053 }
15054 }
15055
15056 // (and (fcmp ord x, x), (fcmp une (fabs x), inf)) ->
15057 // fp_class x, ~(s_nan | q_nan | n_infinity | p_infinity)
15058 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == ISD::SETCC) {
15059 ISD::CondCode LCC = cast<CondCodeSDNode>(LHS.getOperand(2))->get();
15060 ISD::CondCode RCC = cast<CondCodeSDNode>(RHS.getOperand(2))->get();
15061
15062 SDValue X = LHS.getOperand(0);
15063 SDValue Y = RHS.getOperand(0);
15064 if (Y.getOpcode() != ISD::FABS || Y.getOperand(0) != X ||
15065 !isTypeLegal(X.getValueType()))
15066 return SDValue();
15067
15068 if (LCC == ISD::SETO) {
15069 if (X != LHS.getOperand(1))
15070 return SDValue();
15071
15072 if (RCC == ISD::SETUNE) {
15073 const ConstantFPSDNode *C1 =
15074 dyn_cast<ConstantFPSDNode>(RHS.getOperand(1));
15075 if (!C1 || !C1->isInfinity() || C1->isNegative())
15076 return SDValue();
15077
15078 const uint32_t Mask = SIInstrFlags::N_NORMAL |
15082
15083 static_assert(
15086 0x3ff) == Mask,
15087 "mask not equal");
15088
15089 SDLoc DL(N);
15090 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, X,
15091 DAG.getConstant(Mask, DL, MVT::i32));
15092 }
15093 }
15094 }
15095
15096 if (RHS.getOpcode() == ISD::SETCC && LHS.getOpcode() == AMDGPUISD::FP_CLASS)
15097 std::swap(LHS, RHS);
15098
15099 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15100 RHS.hasOneUse()) {
15101 ISD::CondCode LCC = cast<CondCodeSDNode>(LHS.getOperand(2))->get();
15102 // and (fcmp seto), (fp_class x, mask) -> fp_class x, mask & ~(p_nan |
15103 // n_nan) and (fcmp setuo), (fp_class x, mask) -> fp_class x, mask & (p_nan
15104 // | n_nan)
15105 const ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
15106 if ((LCC == ISD::SETO || LCC == ISD::SETUO) && Mask &&
15107 (RHS.getOperand(0) == LHS.getOperand(0) &&
15108 LHS.getOperand(0) == LHS.getOperand(1))) {
15109 const unsigned OrdMask = SIInstrFlags::S_NAN | SIInstrFlags::Q_NAN;
15110 unsigned NewMask = LCC == ISD::SETO ? Mask->getZExtValue() & ~OrdMask
15111 : Mask->getZExtValue() & OrdMask;
15112
15113 SDLoc DL(N);
15114 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, RHS.getOperand(0),
15115 DAG.getConstant(NewMask, DL, MVT::i32));
15116 }
15117 }
15118
15119 if (VT == MVT::i32 && (RHS.getOpcode() == ISD::SIGN_EXTEND ||
15120 LHS.getOpcode() == ISD::SIGN_EXTEND)) {
15121 // and x, (sext cc from i1) => select cc, x, 0
15122 if (RHS.getOpcode() != ISD::SIGN_EXTEND)
15123 std::swap(LHS, RHS);
15124 if (isBoolSGPR(RHS.getOperand(0)))
15125 return DAG.getSelect(SDLoc(N), MVT::i32, RHS.getOperand(0), LHS,
15126 DAG.getConstant(0, SDLoc(N), MVT::i32));
15127 }
15128
15129 // and (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
15130 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
15131 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
15132 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15133 uint32_t LHSMask = getPermuteMask(LHS);
15134 uint32_t RHSMask = getPermuteMask(RHS);
15135 if (LHSMask != ~0u && RHSMask != ~0u) {
15136 // Canonicalize the expression in an attempt to have fewer unique masks
15137 // and therefore fewer registers used to hold the masks.
15138 if (LHSMask > RHSMask) {
15139 std::swap(LHSMask, RHSMask);
15140 std::swap(LHS, RHS);
15141 }
15142
15143 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15144 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15145 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15146 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15147
15148 // Check of we need to combine values from two sources within a byte.
15149 if (!(LHSUsedLanes & RHSUsedLanes) &&
15150 // If we select high and lower word keep it for SDWA.
15151 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15152 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15153 // Each byte in each mask is either selector mask 0-3, or has higher
15154 // bits set in either of masks, which can be 0xff for 0xff or 0x0c for
15155 // zero. If 0x0c is in either mask it shall always be 0x0c. Otherwise
15156 // mask which is not 0xff wins. By anding both masks we have a correct
15157 // result except that 0x0c shall be corrected to give 0x0c only.
15158 uint32_t Mask = LHSMask & RHSMask;
15159 for (unsigned I = 0; I < 32; I += 8) {
15160 uint32_t ByteSel = 0xff << I;
15161 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15162 Mask &= (0x0c << I) & 0xffffffff;
15163 }
15164
15165 // Add 4 to each active LHS lane. It will not affect any existing 0xff
15166 // or 0x0c.
15167 uint32_t Sel = Mask | (LHSUsedLanes & 0x04040404);
15168 SDLoc DL(N);
15169
15170 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15171 RHS.getOperand(0),
15172 DAG.getConstant(Sel, DL, MVT::i32));
15173 }
15174 }
15175 }
15176
15177 return SDValue();
15178}
15179
15180// A key component of v_perm is a mapping between byte position of the src
15181// operands, and the byte position of the dest. To provide such, we need: 1. the
15182// node that provides x byte of the dest of the OR, and 2. the byte of the node
15183// used to provide that x byte. calculateByteProvider finds which node provides
15184// a certain byte of the dest of the OR, and calculateSrcByte takes that node,
15185// and finds an ultimate src and byte position For example: The supported
15186// LoadCombine pattern for vector loads is as follows
15187// t1
15188// or
15189// / \
15190// t2 t3
15191// zext shl
15192// | | \
15193// t4 t5 16
15194// or anyext
15195// / \ |
15196// t6 t7 t8
15197// srl shl or
15198// / | / \ / \
15199// t9 t10 t11 t12 t13 t14
15200// trunc* 8 trunc* 8 and and
15201// | | / | | \
15202// t15 t16 t17 t18 t19 t20
15203// trunc* 255 srl -256
15204// | / \
15205// t15 t15 16
15206//
15207// *In this example, the truncs are from i32->i16
15208//
15209// calculateByteProvider would find t6, t7, t13, and t14 for bytes 0-3
15210// respectively. calculateSrcByte would find (given node) -> ultimate src &
15211// byteposition: t6 -> t15 & 1, t7 -> t16 & 0, t13 -> t15 & 0, t14 -> t15 & 3.
15212// After finding the mapping, we can combine the tree into vperm t15, t16,
15213// 0x05000407
15214
15215// Find the source and byte position from a node.
15216// \p DestByte is the byte position of the dest of the or that the src
15217// ultimately provides. \p SrcIndex is the byte of the src that maps to this
15218// dest of the or byte. \p Depth tracks how many recursive iterations we have
15219// performed.
15220static const std::optional<ByteProvider<SDValue>>
15221calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex = 0,
15222 unsigned Depth = 0) {
15223 // We may need to recursively traverse a series of SRLs
15224 if (Depth >= 6)
15225 return std::nullopt;
15226
15227 if (Op.getValueSizeInBits() < 8)
15228 return std::nullopt;
15229
15230 if (Op.getValueType().isVector())
15231 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15232
15233 switch (Op->getOpcode()) {
15234 case ISD::TRUNCATE: {
15235 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15236 }
15237
15238 case ISD::ANY_EXTEND:
15239 case ISD::SIGN_EXTEND:
15240 case ISD::ZERO_EXTEND:
15242 SDValue NarrowOp = Op->getOperand(0);
15243 auto NarrowVT = NarrowOp.getValueType();
15244 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG) {
15245 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15246 NarrowVT = VTSign->getVT();
15247 }
15248 if (!NarrowVT.isByteSized())
15249 return std::nullopt;
15250 uint64_t NarrowByteWidth = NarrowVT.getStoreSize();
15251
15252 if (SrcIndex >= NarrowByteWidth)
15253 return std::nullopt;
15254 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15255 }
15256
15257 case ISD::SRA:
15258 case ISD::SRL: {
15259 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15260 if (!ShiftOp)
15261 return std::nullopt;
15262
15263 uint64_t BitShift = ShiftOp->getZExtValue();
15264
15265 if (BitShift % 8 != 0)
15266 return std::nullopt;
15267
15268 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15269 if (NewSrcIndex >= Op.getScalarValueSizeInBits() / 8)
15270 return std::nullopt;
15271
15272 return calculateSrcByte(Op->getOperand(0), DestByte, NewSrcIndex,
15273 Depth + 1);
15274 }
15275
15276 default: {
15277 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15278 }
15279 }
15280 llvm_unreachable("fully handled switch");
15281}
15282
15283// For a byte position in the result of an Or, traverse the tree and find the
15284// node (and the byte of the node) which ultimately provides this {Or,
15285// BytePosition}. \p Op is the operand we are currently examining. \p Index is
15286// the byte position of the Op that corresponds with the originally requested
15287// byte of the Or \p Depth tracks how many recursive iterations we have
15288// performed. \p StartingIndex is the originally requested byte of the Or
15289static const std::optional<ByteProvider<SDValue>>
15290calculateByteProvider(const SDValue &Op, unsigned Index, unsigned Depth,
15291 unsigned StartingIndex = 0) {
15292 // Finding Src tree of RHS of or typically requires at least 1 additional
15293 // depth
15294 if (Depth > 6)
15295 return std::nullopt;
15296
15297 unsigned BitWidth = Op.getScalarValueSizeInBits();
15298 if (BitWidth % 8 != 0)
15299 return std::nullopt;
15300 if (Index > BitWidth / 8 - 1)
15301 return std::nullopt;
15302
15303 bool IsVec = Op.getValueType().isVector();
15304 switch (Op.getOpcode()) {
15305 case ISD::OR: {
15306 if (IsVec)
15307 return std::nullopt;
15308
15309 auto RHS = calculateByteProvider(Op.getOperand(1), Index, Depth + 1,
15310 StartingIndex);
15311 if (!RHS)
15312 return std::nullopt;
15313 auto LHS = calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15314 StartingIndex);
15315 if (!LHS)
15316 return std::nullopt;
15317 // A well formed Or will have two ByteProviders for each byte, one of which
15318 // is constant zero
15319 if (!LHS->isConstantZero() && !RHS->isConstantZero())
15320 return std::nullopt;
15321 if (!LHS || LHS->isConstantZero())
15322 return RHS;
15323 if (!RHS || RHS->isConstantZero())
15324 return LHS;
15325 return std::nullopt;
15326 }
15327
15328 case ISD::AND: {
15329 if (IsVec)
15330 return std::nullopt;
15331
15332 auto *BitMaskOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15333 if (!BitMaskOp)
15334 return std::nullopt;
15335
15336 uint32_t BitMask = BitMaskOp->getZExtValue();
15337 // Bits we expect for our StartingIndex
15338 uint32_t IndexMask = 0xFF << (Index * 8);
15339
15340 if ((IndexMask & BitMask) != IndexMask) {
15341 // If the result of the and partially provides the byte, then it
15342 // is not well formatted
15343 if (IndexMask & BitMask)
15344 return std::nullopt;
15346 }
15347
15348 return calculateSrcByte(Op->getOperand(0), StartingIndex, Index);
15349 }
15350
15351 case ISD::FSHR: {
15352 if (IsVec)
15353 return std::nullopt;
15354
15355 // fshr(X,Y,Z): (X << (BW - (Z % BW))) | (Y >> (Z % BW))
15356 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15357 if (!ShiftOp || Op.getValueType().isVector())
15358 return std::nullopt;
15359
15360 uint64_t BitsProvided = Op.getValueSizeInBits();
15361 if (BitsProvided % 8 != 0)
15362 return std::nullopt;
15363
15364 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15365 if (BitShift % 8)
15366 return std::nullopt;
15367
15368 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15369 uint64_t ByteShift = BitShift / 8;
15370
15371 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15372 uint64_t BytesProvided = BitsProvided / 8;
15373 SDValue NextOp = Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15374 NewIndex %= BytesProvided;
15375 return calculateByteProvider(NextOp, NewIndex, Depth + 1, StartingIndex);
15376 }
15377
15378 case ISD::SRA:
15379 case ISD::SRL: {
15380 if (IsVec)
15381 return std::nullopt;
15382
15383 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15384 if (!ShiftOp)
15385 return std::nullopt;
15386
15387 uint64_t BitShift = ShiftOp->getZExtValue();
15388 if (BitShift % 8)
15389 return std::nullopt;
15390
15391 auto BitsProvided = Op.getScalarValueSizeInBits();
15392 if (BitsProvided % 8 != 0)
15393 return std::nullopt;
15394
15395 uint64_t BytesProvided = BitsProvided / 8;
15396 uint64_t ByteShift = BitShift / 8;
15397 if (Index + ByteShift < BytesProvided)
15398 return calculateSrcByte(Op->getOperand(0), StartingIndex,
15399 Index + ByteShift);
15400 // SRA's out-of-range bytes are sign bits, not constant zero.
15401 if (Op.getOpcode() == ISD::SRA)
15402 return std::nullopt;
15404 }
15405
15406 case ISD::SHL: {
15407 if (IsVec)
15408 return std::nullopt;
15409
15410 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15411 if (!ShiftOp)
15412 return std::nullopt;
15413
15414 uint64_t BitShift = ShiftOp->getZExtValue();
15415 if (BitShift % 8 != 0)
15416 return std::nullopt;
15417 uint64_t ByteShift = BitShift / 8;
15418
15419 // If we are shifting by an amount greater than (or equal to)
15420 // the index we are trying to provide, then it provides 0s. If not,
15421 // then this bytes are not definitively 0s, and the corresponding byte
15422 // of interest is Index - ByteShift of the src
15423 return Index < ByteShift
15425 : calculateByteProvider(Op.getOperand(0), Index - ByteShift,
15426 Depth + 1, StartingIndex);
15427 }
15428 case ISD::ANY_EXTEND:
15429 case ISD::SIGN_EXTEND:
15430 case ISD::ZERO_EXTEND:
15432 case ISD::AssertZext:
15433 case ISD::AssertSext: {
15434 if (IsVec)
15435 return std::nullopt;
15436
15437 SDValue NarrowOp = Op->getOperand(0);
15438 unsigned NarrowBitWidth = NarrowOp.getValueSizeInBits();
15439 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG ||
15440 Op->getOpcode() == ISD::AssertZext ||
15441 Op->getOpcode() == ISD::AssertSext) {
15442 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15443 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15444 }
15445 if (NarrowBitWidth % 8 != 0)
15446 return std::nullopt;
15447 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15448
15449 if (Index >= NarrowByteWidth)
15450 return Op.getOpcode() == ISD::ZERO_EXTEND
15451 ? std::optional<ByteProvider<SDValue>>(
15453 : std::nullopt;
15454 return calculateByteProvider(NarrowOp, Index, Depth + 1, StartingIndex);
15455 }
15456
15457 case ISD::TRUNCATE: {
15458 if (IsVec)
15459 return std::nullopt;
15460
15461 uint64_t NarrowByteWidth = BitWidth / 8;
15462
15463 if (NarrowByteWidth >= Index) {
15464 return calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15465 StartingIndex);
15466 }
15467
15468 return std::nullopt;
15469 }
15470
15471 case ISD::CopyFromReg: {
15472 if (BitWidth / 8 > Index)
15473 return calculateSrcByte(Op, StartingIndex, Index);
15474
15475 return std::nullopt;
15476 }
15477
15478 case ISD::LOAD: {
15479 auto *L = cast<LoadSDNode>(Op.getNode());
15480
15481 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15482 if (NarrowBitWidth % 8 != 0)
15483 return std::nullopt;
15484 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15485
15486 // If the width of the load does not reach byte we are trying to provide for
15487 // and it is not a ZEXTLOAD, then the load does not provide for the byte in
15488 // question
15489 if (Index >= NarrowByteWidth) {
15490 return L->getExtensionType() == ISD::ZEXTLOAD
15491 ? std::optional<ByteProvider<SDValue>>(
15493 : std::nullopt;
15494 }
15495
15496 if (NarrowByteWidth > Index) {
15497 return calculateSrcByte(Op, StartingIndex, Index);
15498 }
15499
15500 return std::nullopt;
15501 }
15502
15503 case ISD::BSWAP: {
15504 if (IsVec)
15505 return std::nullopt;
15506
15507 return calculateByteProvider(Op->getOperand(0), BitWidth / 8 - Index - 1,
15508 Depth + 1, StartingIndex);
15509 }
15510
15512 auto *IdxOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15513 if (!IdxOp)
15514 return std::nullopt;
15515 auto VecIdx = IdxOp->getZExtValue();
15516 auto ScalarSize = Op.getScalarValueSizeInBits();
15517 if (ScalarSize < 32)
15518 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15519 return calculateSrcByte(ScalarSize >= 32 ? Op : Op.getOperand(0),
15520 StartingIndex, Index);
15521 }
15522
15523 case AMDGPUISD::PERM: {
15524 if (IsVec)
15525 return std::nullopt;
15526
15527 auto *PermMask = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15528 if (!PermMask)
15529 return std::nullopt;
15530
15531 auto IdxMask =
15532 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15533 if (IdxMask > 0x07 && IdxMask != 0x0c)
15534 return std::nullopt;
15535
15536 auto NextOp = Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15537 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15538
15539 return IdxMask != 0x0c ? calculateSrcByte(NextOp, StartingIndex, NextIndex)
15542 }
15543
15544 default: {
15545 return std::nullopt;
15546 }
15547 }
15548
15549 llvm_unreachable("fully handled switch");
15550}
15551
15552// Returns true if the Operand is a scalar and is 16 bits
15553static bool isExtendedFrom16Bits(SDValue &Operand) {
15554
15555 switch (Operand.getOpcode()) {
15556 case ISD::ANY_EXTEND:
15557 case ISD::SIGN_EXTEND:
15558 case ISD::ZERO_EXTEND: {
15559 auto OpVT = Operand.getOperand(0).getValueType();
15560 return !OpVT.isVector() && OpVT.getSizeInBits() == 16;
15561 }
15562 case ISD::LOAD: {
15563 LoadSDNode *L = cast<LoadSDNode>(Operand.getNode());
15564 auto ExtType = cast<LoadSDNode>(L)->getExtensionType();
15565 if (ExtType == ISD::ZEXTLOAD || ExtType == ISD::SEXTLOAD ||
15566 ExtType == ISD::EXTLOAD) {
15567 auto MemVT = L->getMemoryVT();
15568 return !MemVT.isVector() && MemVT.getSizeInBits() == 16;
15569 }
15570 return L->getMemoryVT().getSizeInBits() == 16;
15571 }
15572 default:
15573 return false;
15574 }
15575}
15576
15577// Returns true if the mask matches consecutive bytes, and the first byte
15578// begins at a power of 2 byte offset from 0th byte
15579static bool addresses16Bits(int Mask) {
15580 int Low8 = Mask & 0xff;
15581 int Hi8 = (Mask & 0xff00) >> 8;
15582
15583 assert(Low8 < 8 && Hi8 < 8);
15584 // Are the bytes contiguous in the order of increasing addresses.
15585 bool IsConsecutive = (Hi8 - Low8 == 1);
15586 // Is the first byte at location that is aligned for 16 bit instructions.
15587 // A counter example is taking 2 consecutive bytes starting at the 8th bit.
15588 // In this case, we still need code to extract the 16 bit operand, so it
15589 // is better to use i8 v_perm
15590 bool Is16Aligned = !(Low8 % 2);
15591
15592 return IsConsecutive && Is16Aligned;
15593}
15594
15595// Do not lower into v_perm if the operands are actually 16 bit
15596// and the selected bits (based on PermMask) correspond with two
15597// easily addressable 16 bit operands.
15599 SDValue &OtherOp) {
15600 int Low16 = PermMask & 0xffff;
15601 int Hi16 = (PermMask & 0xffff0000) >> 16;
15602
15603 auto TempOp = peekThroughBitcasts(Op);
15604 auto TempOtherOp = peekThroughBitcasts(OtherOp);
15605
15606 auto OpIs16Bit =
15607 TempOp.getValueSizeInBits() == 16 || isExtendedFrom16Bits(TempOp);
15608 if (!OpIs16Bit)
15609 return true;
15610
15611 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15612 isExtendedFrom16Bits(TempOtherOp);
15613 if (!OtherOpIs16Bit)
15614 return true;
15615
15616 // Do we cleanly address both
15617 return !addresses16Bits(Low16) || !addresses16Bits(Hi16);
15618}
15619
15621 unsigned DWordOffset) {
15622 SDValue Ret;
15623
15624 auto TypeSize = Src.getValueSizeInBits().getFixedValue();
15625 // ByteProvider must be at least 8 bits
15626 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15627
15628 if (TypeSize <= 32)
15629 return DAG.getBitcastedAnyExtOrTrunc(Src, SL, MVT::i32);
15630
15631 if (Src.getValueType().isVector()) {
15632 auto ScalarTySize = Src.getScalarValueSizeInBits();
15633 auto ScalarTy = Src.getValueType().getScalarType();
15634 if (ScalarTySize == 32) {
15635 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Src,
15636 DAG.getConstant(DWordOffset, SL, MVT::i32));
15637 }
15638 if (ScalarTySize > 32) {
15639 Ret = DAG.getNode(
15640 ISD::EXTRACT_VECTOR_ELT, SL, ScalarTy, Src,
15641 DAG.getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15642 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15643 if (ShiftVal)
15644 Ret = DAG.getNode(ISD::SRL, SL, Ret.getValueType(), Ret,
15645 DAG.getConstant(ShiftVal, SL, MVT::i32));
15646 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15647 }
15648
15649 assert(ScalarTySize < 32);
15650 if (TypeSize % 32 == 0) {
15651 assert(DWordOffset < TypeSize / 32);
15652 SDValue Cast = DAG.getBitcast(
15653 EVT::getVectorVT(*DAG.getContext(), MVT::i32, TypeSize / 32), Src);
15654 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Cast,
15655 DAG.getConstant(DWordOffset, SL, MVT::i32));
15656 }
15657
15658 auto NumElements = TypeSize / ScalarTySize;
15659 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15660 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15661 auto NumElementsIn32 = 32 / ScalarTySize;
15662 auto NumAvailElements = DWordOffset < Trunc32Elements
15663 ? NumElementsIn32
15664 : NumElements - NormalizedTrunc;
15665
15667 DAG.ExtractVectorElements(Src, VecSrcs, DWordOffset * NumElementsIn32,
15668 NumAvailElements);
15669
15670 Ret = DAG.getBuildVector(
15671 MVT::getVectorVT(MVT::getIntegerVT(ScalarTySize), NumAvailElements), SL,
15672 VecSrcs);
15673 return Ret = DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15674 }
15675
15676 /// Scalar Type
15677 auto ShiftVal = 32 * DWordOffset;
15678 Ret = DAG.getNode(ISD::SRL, SL, Src.getValueType(), Src,
15679 DAG.getConstant(ShiftVal, SL, MVT::i32));
15680 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15681}
15682
15684 SelectionDAG &DAG = DCI.DAG;
15685 [[maybe_unused]] EVT VT = N->getValueType(0);
15687
15688 // VT is known to be MVT::i32, so we need to provide 4 bytes.
15689 assert(VT == MVT::i32);
15690 for (int i = 0; i < 4; i++) {
15691 // Find the ByteProvider that provides the ith byte of the result of OR
15692 std::optional<ByteProvider<SDValue>> P =
15693 calculateByteProvider(SDValue(N, 0), i, 0, /*StartingIndex = */ i);
15694 // TODO support constantZero
15695 if (!P || P->isConstantZero())
15696 return SDValue();
15697
15698 PermNodes.push_back(*P);
15699 }
15700 if (PermNodes.size() != 4)
15701 return SDValue();
15702
15703 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15704 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15705 uint64_t PermMask = 0x00000000;
15706 for (size_t i = 0; i < PermNodes.size(); i++) {
15707 auto PermOp = PermNodes[i];
15708 // Since the mask is applied to Src1:Src2, Src1 bytes must be offset
15709 // by sizeof(Src2) = 4
15710 int SrcByteAdjust = 4;
15711
15712 // If the Src uses a byte from a different DWORD, then it corresponds
15713 // with a difference source
15714 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15715 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15716 if (SecondSrc)
15717 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15718 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15719 return SDValue();
15720
15721 // Set the index of the second distinct Src node
15722 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15723 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15724 SrcByteAdjust = 0;
15725 }
15726 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15728 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15729 }
15730 SDLoc DL(N);
15731 SDValue Op = *PermNodes[FirstSrc.first].Src;
15732 Op = getDWordFromOffset(DAG, DL, Op, FirstSrc.second);
15733 assert(Op.getValueSizeInBits() == 32);
15734
15735 // Check that we are not just extracting the bytes in order from an op
15736 if (!SecondSrc) {
15737 int Low16 = PermMask & 0xffff;
15738 int Hi16 = (PermMask & 0xffff0000) >> 16;
15739
15740 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15741 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15742
15743 // The perm op would really just produce Op. So combine into Op
15744 if (WellFormedLow && WellFormedHi)
15745 return DAG.getBitcast(MVT::getIntegerVT(32), Op);
15746 }
15747
15748 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src : Op;
15749
15750 if (SecondSrc) {
15751 OtherOp = getDWordFromOffset(DAG, DL, OtherOp, SecondSrc->second);
15752 assert(OtherOp.getValueSizeInBits() == 32);
15753 }
15754
15755 // Check that we haven't just recreated the same FSHR node.
15756 if (N->getOpcode() == ISD::FSHR &&
15757 (N->getOperand(0) == Op || N->getOperand(0) == OtherOp) &&
15758 (N->getOperand(1) == Op || N->getOperand(1) == OtherOp))
15759 return SDValue();
15760
15761 if (hasNon16BitAccesses(PermMask, Op, OtherOp)) {
15762
15763 assert(Op.getValueType().isByteSized() &&
15764 OtherOp.getValueType().isByteSized());
15765
15766 // If the ultimate src is less than 32 bits, then we will only be
15767 // using bytes 0: Op.getValueSizeInBytes() - 1 in the or.
15768 // CalculateByteProvider would not have returned Op as source if we
15769 // used a byte that is outside its ValueType. Thus, we are free to
15770 // ANY_EXTEND as the extended bits are dont-cares.
15771 Op = DAG.getBitcastedAnyExtOrTrunc(Op, DL, MVT::i32);
15772 OtherOp = DAG.getBitcastedAnyExtOrTrunc(OtherOp, DL, MVT::i32);
15773
15774 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op, OtherOp,
15775 DAG.getConstant(PermMask, DL, MVT::i32));
15776 }
15777 return SDValue();
15778}
15779
15780SDValue SITargetLowering::performOrCombine(SDNode *N,
15781 DAGCombinerInfo &DCI) const {
15782 SelectionDAG &DAG = DCI.DAG;
15783 SDValue LHS = N->getOperand(0);
15784 SDValue RHS = N->getOperand(1);
15785
15786 EVT VT = N->getValueType(0);
15787 if (VT == MVT::i1) {
15788 // or (fp_class x, c1), (fp_class x, c2) -> fp_class x, (c1 | c2)
15789 if (LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15790 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15791 SDValue Src = LHS.getOperand(0);
15792 if (Src != RHS.getOperand(0))
15793 return SDValue();
15794
15795 const ConstantSDNode *CLHS = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
15796 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
15797 if (!CLHS || !CRHS)
15798 return SDValue();
15799
15800 // Only 10 bits are used.
15801 static const uint32_t MaxMask = 0x3ff;
15802
15803 uint32_t NewMask =
15804 (CLHS->getZExtValue() | CRHS->getZExtValue()) & MaxMask;
15805 SDLoc DL(N);
15806 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, Src,
15807 DAG.getConstant(NewMask, DL, MVT::i32));
15808 }
15809
15810 return SDValue();
15811 }
15812
15813 // or (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
15815 LHS.getOpcode() == AMDGPUISD::PERM &&
15816 isa<ConstantSDNode>(LHS.getOperand(2))) {
15817 uint32_t Sel = getConstantPermuteMask(N->getConstantOperandVal(1));
15818 if (!Sel)
15819 return SDValue();
15820
15821 Sel |= LHS.getConstantOperandVal(2);
15822 SDLoc DL(N);
15823 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15824 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
15825 }
15826
15827 // or (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
15828 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
15829 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
15830 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15831
15832 // If all the uses of an or need to extract the individual elements, do not
15833 // attempt to lower into v_perm
15834 auto usesCombinedOperand = [](SDNode *OrUse) {
15835 // If we have any non-vectorized use, then it is a candidate for v_perm
15836 if (OrUse->getOpcode() != ISD::BITCAST ||
15837 !OrUse->getValueType(0).isVector())
15838 return true;
15839
15840 // If we have any non-vectorized use, then it is a candidate for v_perm
15841 for (auto *VUser : OrUse->users()) {
15842 if (!VUser->getValueType(0).isVector())
15843 return true;
15844
15845 // If the use of a vector is a store, then combining via a v_perm
15846 // is beneficial.
15847 // TODO -- whitelist more uses
15848 for (auto VectorwiseOp : {ISD::STORE, ISD::CopyToReg, ISD::CopyFromReg})
15849 if (VUser->getOpcode() == VectorwiseOp)
15850 return true;
15851 }
15852 return false;
15853 };
15854
15855 if (!any_of(N->users(), usesCombinedOperand))
15856 return SDValue();
15857
15858 uint32_t LHSMask = getPermuteMask(LHS);
15859 uint32_t RHSMask = getPermuteMask(RHS);
15860
15861 if (LHSMask != ~0u && RHSMask != ~0u) {
15862 // Canonicalize the expression in an attempt to have fewer unique masks
15863 // and therefore fewer registers used to hold the masks.
15864 if (LHSMask > RHSMask) {
15865 std::swap(LHSMask, RHSMask);
15866 std::swap(LHS, RHS);
15867 }
15868
15869 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15870 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15871 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15872 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15873
15874 // Check of we need to combine values from two sources within a byte.
15875 if (!(LHSUsedLanes & RHSUsedLanes) &&
15876 // If we select high and lower word keep it for SDWA.
15877 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15878 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15879 // Kill zero bytes selected by other mask. Zero value is 0xc.
15880 LHSMask &= ~RHSUsedLanes;
15881 RHSMask &= ~LHSUsedLanes;
15882 // Add 4 to each active LHS lane
15883 LHSMask |= LHSUsedLanes & 0x04040404;
15884 // Combine masks
15885 uint32_t Sel = LHSMask | RHSMask;
15886 SDLoc DL(N);
15887
15888 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15889 RHS.getOperand(0),
15890 DAG.getConstant(Sel, DL, MVT::i32));
15891 }
15892 }
15893 if (LHSMask == ~0u || RHSMask == ~0u) {
15894 if (SDValue Perm = matchPERM(N, DCI))
15895 return Perm;
15896 }
15897 }
15898
15899 // Detect identity v2i32 OR and replace with identity source node.
15900 // Specifically an Or that has operands constructed from the same source node
15901 // via extract_vector_elt and build_vector. I.E.
15902 // v2i32 or(
15903 // v2i32 build_vector(
15904 // i32 extract_elt(%IdentitySrc, 0),
15905 // i32 0
15906 // ),
15907 // v2i32 build_vector(
15908 // i32 0,
15909 // i32 extract_elt(%IdentitySrc, 1)
15910 // ) )
15911 // =>
15912 // v2i32 %IdentitySrc
15913
15914 if (VT == MVT::v2i32 && LHS->getOpcode() == ISD::BUILD_VECTOR &&
15915 RHS->getOpcode() == ISD::BUILD_VECTOR) {
15916
15917 ConstantSDNode *LC = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
15918 ConstantSDNode *RC = dyn_cast<ConstantSDNode>(RHS->getOperand(0));
15919
15920 // Test for and normalise build vectors.
15921 if (LC && RC && LC->getZExtValue() == 0 && RC->getZExtValue() == 0) {
15922
15923 // Get the extract_vector_element operands.
15924 SDValue LEVE = LHS->getOperand(0);
15925 SDValue REVE = RHS->getOperand(1);
15926
15927 if (LEVE->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15929 // Check that different elements from the same vector are
15930 // extracted.
15931 if (LEVE->getOperand(0) == REVE->getOperand(0) &&
15932 LEVE->getOperand(1) != REVE->getOperand(1)) {
15933 SDValue IdentitySrc = LEVE.getOperand(0);
15934 return IdentitySrc;
15935 }
15936 }
15937 }
15938 }
15939
15940 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
15941 return SDValue();
15942
15943 // TODO: This could be a generic combine with a predicate for extracting the
15944 // high half of an integer being free.
15945
15946 // (or i64:x, (zero_extend i32:y)) ->
15947 // i64 (bitcast (v2i32 build_vector (or i32:y, lo_32(x)), hi_32(x)))
15948 if (LHS.getOpcode() == ISD::ZERO_EXTEND &&
15949 RHS.getOpcode() != ISD::ZERO_EXTEND)
15950 std::swap(LHS, RHS);
15951
15952 if (RHS.getOpcode() == ISD::ZERO_EXTEND) {
15953 SDValue ExtSrc = RHS.getOperand(0);
15954 EVT SrcVT = ExtSrc.getValueType();
15955 if (SrcVT == MVT::i32) {
15956 SDLoc SL(N);
15957 auto [LowLHS, HiBits] = split64BitValue(LHS, DAG);
15958 SDValue LowOr = DAG.getNode(ISD::OR, SL, MVT::i32, LowLHS, ExtSrc);
15959
15960 DCI.AddToWorklist(LowOr.getNode());
15961 DCI.AddToWorklist(HiBits.getNode());
15962
15963 SDValue Vec =
15964 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, LowOr, HiBits);
15965 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
15966 }
15967 }
15968
15969 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
15970 if (CRHS) {
15971 if (SDValue Split = splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::OR,
15972 N->getOperand(0), CRHS))
15973 return Split;
15974 }
15975
15976 return SDValue();
15977}
15978
15979SDValue SITargetLowering::performXorCombine(SDNode *N,
15980 DAGCombinerInfo &DCI) const {
15981 if (SDValue RV = reassociateScalarOps(N, DCI.DAG))
15982 return RV;
15983
15984 SDValue LHS = N->getOperand(0);
15985 SDValue RHS = N->getOperand(1);
15986
15987 const ConstantSDNode *CRHS = isConstOrConstSplat(RHS);
15988 SelectionDAG &DAG = DCI.DAG;
15989
15990 EVT VT = N->getValueType(0);
15991 if (CRHS && VT == MVT::i64) {
15992 if (SDValue Split =
15993 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::XOR, LHS, CRHS))
15994 return Split;
15995 }
15996
15997 // v2i32 (xor (vselect cc, x, y), K) ->
15998 // (v2i32 svelect cc, (xor x, K), (xor y, K)) This enables the xor to be
15999 // replaced with source modifiers when the select is lowered to CNDMASK.
16000 unsigned Opc = LHS.getOpcode();
16001 if (((Opc == ISD::VSELECT && VT == MVT::v2i32) ||
16002 (Opc == ISD::SELECT && VT == MVT::i64)) &&
16003 CRHS && CRHS->getAPIntValue().isSignMask()) {
16004 SDValue CC = LHS->getOperand(0);
16005 SDValue TRUE = LHS->getOperand(1);
16006 SDValue FALSE = LHS->getOperand(2);
16007 SDValue XTrue = DAG.getNode(ISD::XOR, SDLoc(N), VT, TRUE, RHS);
16008 SDValue XFalse = DAG.getNode(ISD::XOR, SDLoc(N), VT, FALSE, RHS);
16009 SDValue XSelect =
16010 DAG.getNode(ISD::VSELECT, SDLoc(N), VT, CC, XTrue, XFalse);
16011 return XSelect;
16012 }
16013
16014 // Make sure to apply the 64-bit constant splitting fold before trying to fold
16015 // fneg-like xors into 64-bit select.
16016 if (LHS.getOpcode() == ISD::SELECT && VT == MVT::i32) {
16017 // This looks like an fneg, try to fold as a source modifier.
16018 if (CRHS && CRHS->getAPIntValue().isSignMask() &&
16020 // xor (select c, a, b), 0x80000000 ->
16021 // bitcast (select c, (fneg (bitcast a)), (fneg (bitcast b)))
16022 SDLoc DL(N);
16023 SDValue CastLHS =
16024 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(1));
16025 SDValue CastRHS =
16026 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(2));
16027 SDValue FNegLHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastLHS);
16028 SDValue FNegRHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastRHS);
16029 SDValue NewSelect = DAG.getNode(ISD::SELECT, DL, MVT::f32,
16030 LHS->getOperand(0), FNegLHS, FNegRHS);
16031 return DAG.getNode(ISD::BITCAST, DL, VT, NewSelect);
16032 }
16033 }
16034
16035 return SDValue();
16036}
16037
16038SDValue
16039SITargetLowering::performZeroOrAnyExtendCombine(SDNode *N,
16040 DAGCombinerInfo &DCI) const {
16041 if (!Subtarget->has16BitInsts() ||
16042 DCI.getDAGCombineLevel() < AfterLegalizeTypes)
16043 return SDValue();
16044
16045 EVT VT = N->getValueType(0);
16046 if (VT != MVT::i32)
16047 return SDValue();
16048
16049 SDValue Src = N->getOperand(0);
16050 if (Src.getValueType() != MVT::i16)
16051 return SDValue();
16052
16053 if (!Src->hasOneUse())
16054 return SDValue();
16055
16056 // TODO: We bail out below if SrcOffset is not in the first dword (>= 4). It's
16057 // possible we're missing out on some combine opportunities, but we'd need to
16058 // weigh the cost of extracting the byte from the upper dwords.
16059
16060 std::optional<ByteProvider<SDValue>> BP0 =
16061 calculateByteProvider(SDValue(N, 0), 0, 0, 0);
16062 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
16063 return SDValue();
16064 SDValue V0 = *BP0->Src;
16065
16066 std::optional<ByteProvider<SDValue>> BP1 =
16067 calculateByteProvider(SDValue(N, 0), 1, 0, 1);
16068 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
16069 return SDValue();
16070
16071 SDValue V1 = *BP1->Src;
16072
16073 if (V0 == V1)
16074 return SDValue();
16075
16076 SelectionDAG &DAG = DCI.DAG;
16077 SDLoc DL(N);
16078 uint32_t PermMask = 0x0c0c0c0c;
16079 if (V0) {
16080 V0 = DAG.getBitcastedAnyExtOrTrunc(V0, DL, MVT::i32);
16081 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
16082 }
16083
16084 if (V1) {
16085 V1 = DAG.getBitcastedAnyExtOrTrunc(V1, DL, MVT::i32);
16086 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
16087 }
16088
16089 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, V0, V1,
16090 DAG.getConstant(PermMask, DL, MVT::i32));
16091}
16092
16093SDValue
16094SITargetLowering::performSignExtendInRegCombine(SDNode *N,
16095 DAGCombinerInfo &DCI) const {
16096 SDValue Src = N->getOperand(0);
16097 auto *VTSign = cast<VTSDNode>(N->getOperand(1));
16098
16099 // Combine s_buffer_load_u8 or s_buffer_load_u16 with sext and replace them
16100 // with s_buffer_load_i8 and s_buffer_load_i16 respectively.
16101 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
16102 VTSign->getVT() == MVT::i8) ||
16103 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
16104 VTSign->getVT() == MVT::i16))) {
16105 assert(Subtarget->hasScalarSubwordLoads() &&
16106 "s_buffer_load_{u8, i8} are supported "
16107 "in GFX12 (or newer) architectures.");
16108 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
16109 ? AMDGPUISD::SBUFFER_LOAD_BYTE
16110 : AMDGPUISD::SBUFFER_LOAD_SHORT;
16111 SDLoc DL(N);
16112 SDVTList ResList =
16113 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16114 SDValue Ops[] = {
16115 Src.getOperand(0), // Chain
16116 Src.getOperand(1), // source register
16117 Src.getOperand(2), // offset
16118 Src.getOperand(3) // cachePolicy
16119 };
16120 auto *M = cast<MemSDNode>(Src);
16121 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
16122 Opc, DL, ResList, Ops, M->getMemoryVT(), M->getMemOperand());
16123 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.getValue(1)}, DL);
16124 }
16125 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
16126 VTSign->getVT() == MVT::i8) ||
16127 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
16128 VTSign->getVT() == MVT::i16)) &&
16129 Src.hasOneUse()) {
16130 auto *M = cast<MemSDNode>(Src);
16131 SDValue Ops[] = {Src.getOperand(0), // Chain
16132 Src.getOperand(1), // rsrc
16133 Src.getOperand(2), // vindex
16134 Src.getOperand(3), // voffset
16135 Src.getOperand(4), // soffset
16136 Src.getOperand(5), // offset
16137 Src.getOperand(6), Src.getOperand(7)};
16138 // replace with BUFFER_LOAD_BYTE/SHORT
16139 SDVTList ResList =
16140 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16141 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
16142 ? AMDGPUISD::BUFFER_LOAD_BYTE
16143 : AMDGPUISD::BUFFER_LOAD_SHORT;
16144 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
16145 Opc, SDLoc(N), ResList, Ops, M->getMemoryVT(), M->getMemOperand());
16146 return DCI.DAG.getMergeValues(
16147 {BufferLoadSignExt, BufferLoadSignExt.getValue(1)}, SDLoc(N));
16148 }
16149 return SDValue();
16150}
16151
16152SDValue SITargetLowering::performClassCombine(SDNode *N,
16153 DAGCombinerInfo &DCI) const {
16154 SelectionDAG &DAG = DCI.DAG;
16155 SDValue Mask = N->getOperand(1);
16156
16157 // fp_class x, 0 -> false
16158 if (isNullConstant(Mask))
16159 return DAG.getConstant(0, SDLoc(N), MVT::i1);
16160
16161 if (N->getOperand(0).isUndef())
16162 return DAG.getUNDEF(MVT::i1);
16163
16164 return SDValue();
16165}
16166
16167SDValue SITargetLowering::performRcpCombine(SDNode *N,
16168 DAGCombinerInfo &DCI) const {
16169 EVT VT = N->getValueType(0);
16170 SDValue N0 = N->getOperand(0);
16171
16172 if (N0.isUndef()) {
16173 return DCI.DAG.getConstantFP(APFloat::getQNaN(VT.getFltSemantics()),
16174 SDLoc(N), VT);
16175 }
16176
16177 // TODO: Could handle f32 + amdgcn.sqrt but probably never reaches here.
16178 if ((VT == MVT::f16 && N0.getOpcode() == ISD::FSQRT) &&
16179 N->getFlags().hasAllowContract() && N0->getFlags().hasAllowContract()) {
16180 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(N), VT, N0.getOperand(0),
16181 N->getFlags());
16182 }
16183
16185}
16186
16188 SDNodeFlags UserFlags,
16189 unsigned MaxDepth) const {
16190 EVT VT = Op.getValueType();
16191 assert(VT.isFloatingPoint() &&
16192 "expected a floating-point value to query canonicality of");
16193 return isCanonicalized(DAG, Op, VT.getScalarType(), UserFlags, MaxDepth);
16194}
16195
16197 EVT QueryVT, SDNodeFlags UserFlags,
16198 unsigned MaxDepth) const {
16199 assert(QueryVT.isFloatingPoint() && !QueryVT.isVector() &&
16200 "QueryVT must be a floating-point scalar type");
16201 EVT VT = Op.getValueType();
16202 if (VT.isFloatingPoint() && VT.getScalarType() != QueryVT)
16203 return false;
16204
16205 unsigned Opcode = Op.getOpcode();
16206 if (Opcode == ISD::FCANONICALIZE)
16207 return true;
16208
16209 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16210 const auto &F = CFP->getValueAPF();
16211 if (F.isNaN() && F.isSignaling())
16212 return false;
16213 if (!F.isDenormal())
16214 return true;
16215
16216 DenormalMode Mode =
16217 DAG.getMachineFunction().getDenormalMode(F.getSemantics());
16218 return Mode == DenormalMode::getIEEE();
16219 }
16220
16221 // If source is a result of another standard FP operation it is already in
16222 // canonical form.
16223 if (MaxDepth == 0)
16224 return false;
16225
16226 switch (Opcode) {
16227 // These will flush denorms if required.
16228 case ISD::FADD:
16229 case ISD::FSUB:
16230 case ISD::FMUL:
16231 case ISD::FCEIL:
16232 case ISD::FFLOOR:
16233 case ISD::FMA:
16234 case ISD::FMAD:
16235 case ISD::FSQRT:
16236 case ISD::FDIV:
16237 case ISD::FREM:
16238 case ISD::FP_ROUND:
16239 case ISD::FP_EXTEND:
16240 case ISD::FP16_TO_FP:
16241 case ISD::FP_TO_FP16:
16242 case ISD::BF16_TO_FP:
16243 case ISD::FP_TO_BF16:
16244 case ISD::FLDEXP:
16245 case AMDGPUISD::FMUL_LEGACY:
16246 case AMDGPUISD::FMAD_FTZ:
16247 case AMDGPUISD::RCP:
16248 case AMDGPUISD::RSQ:
16249 case AMDGPUISD::RSQ_CLAMP:
16250 case AMDGPUISD::RCP_LEGACY:
16251 case AMDGPUISD::RCP_IFLAG:
16252 case AMDGPUISD::LOG:
16253 case AMDGPUISD::EXP:
16254 case AMDGPUISD::DIV_SCALE:
16255 case AMDGPUISD::DIV_FMAS:
16256 case AMDGPUISD::DIV_FIXUP:
16257 case AMDGPUISD::FRACT:
16258 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16259 case AMDGPUISD::CVT_F32_UBYTE0:
16260 case AMDGPUISD::CVT_F32_UBYTE1:
16261 case AMDGPUISD::CVT_F32_UBYTE2:
16262 case AMDGPUISD::CVT_F32_UBYTE3:
16263 case AMDGPUISD::FP_TO_FP16:
16264 case AMDGPUISD::SIN_HW:
16265 case AMDGPUISD::COS_HW:
16266 return true;
16267
16268 // It can/will be lowered or combined as a bit operation.
16269 // Need to check their input recursively to handle.
16270 case ISD::FNEG:
16271 case ISD::FABS:
16272 case ISD::FCOPYSIGN:
16273 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16274 MaxDepth - 1);
16275
16276 case ISD::AND:
16277 if (Op.getValueType() == MVT::i32) {
16278 // Be careful as we only know it is a bitcast floating point type. It
16279 // could be f32, v2f16, we have no way of knowing. Luckily the constant
16280 // value that we optimize for, which comes up in fp32 to bf16 conversions,
16281 // is valid to optimize for all types.
16282 if (auto *RHS = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
16283 if (RHS->getZExtValue() == 0xffff0000) {
16284 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16285 MaxDepth - 1);
16286 }
16287 }
16288 }
16289 break;
16290
16291 case ISD::FSIN:
16292 case ISD::FCOS:
16293 case ISD::FSINCOS:
16294 return Op.getValueType().getScalarType() != MVT::f16;
16295
16296 case ISD::FMINNUM:
16297 case ISD::FMAXNUM:
16298 case ISD::FMINNUM_IEEE:
16299 case ISD::FMAXNUM_IEEE:
16300 case ISD::FMINIMUM:
16301 case ISD::FMAXIMUM:
16302 case ISD::FMINIMUMNUM:
16303 case ISD::FMAXIMUMNUM:
16304 case AMDGPUISD::CLAMP:
16305 case AMDGPUISD::FMED3:
16306 case AMDGPUISD::FMAX3:
16307 case AMDGPUISD::FMIN3:
16308 case AMDGPUISD::FMAXIMUM3:
16309 case AMDGPUISD::FMINIMUM3: {
16310 // FIXME: Shouldn't treat the generic operations different based these.
16311 // However, we aren't really required to flush the result from
16312 // minnum/maxnum..
16313
16314 // snans will be quieted, so we only need to worry about denormals.
16315 if (Subtarget->supportsMinMaxDenormModes() ||
16316 // FIXME: denormalsEnabledForType is broken for dynamic
16317 denormalsEnabledForType(DAG, Op.getValueType()))
16318 return true;
16319
16320 // Flushing may be required.
16321 // In pre-GFX9 targets V_MIN_F32 and others do not flush denorms. For such
16322 // targets need to check their input recursively.
16323
16324 // FIXME: Does this apply with clamp? It's implemented with max.
16325 for (unsigned I = 0, E = Op.getNumOperands(); I != E; ++I) {
16326 if (!isCanonicalized(DAG, Op.getOperand(I), QueryVT, UserFlags,
16327 MaxDepth - 1))
16328 return false;
16329 }
16330
16331 return true;
16332 }
16333 case ISD::SELECT: {
16334 return isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16335 MaxDepth - 1) &&
16336 isCanonicalized(DAG, Op.getOperand(2), QueryVT, UserFlags,
16337 MaxDepth - 1);
16338 }
16339 case ISD::BUILD_VECTOR: {
16340 for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
16341 SDValue SrcOp = Op.getOperand(i);
16342 if (!isCanonicalized(DAG, SrcOp, QueryVT, UserFlags, MaxDepth - 1))
16343 return false;
16344 }
16345
16346 return true;
16347 }
16350 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16351 MaxDepth - 1);
16352 }
16354 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16355 MaxDepth - 1) &&
16356 isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16357 MaxDepth - 1);
16358 }
16359 case ISD::POISON:
16360 return true;
16361 case ISD::UNDEF:
16362 // Could be anything.
16363 return false;
16364
16365 case ISD::BITCAST: {
16366 // Carry QueryVT through the bitcast unchanged. The top-of-function guard
16367 // rejects a source whose FP format differs from the consumed type, so a
16368 // value canonical in one FP format is not assumed canonical in another.
16369 SDValue Src = peekThroughBitcasts(Op.getOperand(0));
16370 return isCanonicalized(DAG, Src, QueryVT, UserFlags, MaxDepth - 1);
16371 }
16372 case ISD::TRUNCATE: {
16373 // Hack round the mess we make when legalizing extract_vector_elt
16374 if (Op.getValueType() == MVT::i16) {
16375 SDValue TruncSrc = Op.getOperand(0);
16376 if (TruncSrc.getValueType() == MVT::i32 &&
16377 TruncSrc.getOpcode() == ISD::BITCAST &&
16378 TruncSrc.getOperand(0).getValueType() == MVT::v2f16) {
16379 return isCanonicalized(DAG, TruncSrc.getOperand(0), QueryVT, UserFlags,
16380 MaxDepth - 1);
16381 }
16382 }
16383 return false;
16384 }
16386 unsigned IntrinsicID = Op.getConstantOperandVal(0);
16387 // TODO: Handle more intrinsics
16388 switch (IntrinsicID) {
16389 case Intrinsic::amdgcn_cvt_pkrtz:
16390 case Intrinsic::amdgcn_cubeid:
16391 case Intrinsic::amdgcn_frexp_mant:
16392 case Intrinsic::amdgcn_fdot2:
16393 case Intrinsic::amdgcn_rcp:
16394 case Intrinsic::amdgcn_rsq:
16395 case Intrinsic::amdgcn_rsq_clamp:
16396 case Intrinsic::amdgcn_rcp_legacy:
16397 case Intrinsic::amdgcn_rsq_legacy:
16398 case Intrinsic::amdgcn_trig_preop:
16399 case Intrinsic::amdgcn_tanh:
16400 case Intrinsic::amdgcn_log:
16401 case Intrinsic::amdgcn_exp2:
16402 case Intrinsic::amdgcn_sqrt:
16403 return true;
16404 default:
16405 break;
16406 }
16407
16408 break;
16409 }
16410 default:
16411 break;
16412 }
16413
16414 // FIXME: denormalsEnabledForType is broken for dynamic
16415 return denormalsEnabledForType(DAG, Op.getValueType()) &&
16416 (UserFlags.hasNoNaNs() || DAG.isKnownNeverSNaN(Op));
16417}
16418
16420 unsigned MaxDepth) const {
16421 const MachineRegisterInfo &MRI = MF.getRegInfo();
16422 MachineInstr *MI = MRI.getVRegDef(Reg);
16423 unsigned Opcode = MI->getOpcode();
16424
16425 if (Opcode == AMDGPU::G_FCANONICALIZE)
16426 return true;
16427
16428 std::optional<FPValueAndVReg> FCR;
16429 // Constant splat (can be padded with undef) or scalar constant.
16430 if (mi_match(Reg, MRI, MIPatternMatch::m_GFCstOrSplat(FCR))) {
16431 if (FCR->Value.isSignaling())
16432 return false;
16433 if (!FCR->Value.isDenormal())
16434 return true;
16435
16436 DenormalMode Mode = MF.getDenormalMode(FCR->Value.getSemantics());
16437 return Mode == DenormalMode::getIEEE();
16438 }
16439
16440 if (MaxDepth == 0)
16441 return false;
16442
16443 switch (Opcode) {
16444 case AMDGPU::G_FADD:
16445 case AMDGPU::G_FSUB:
16446 case AMDGPU::G_FMUL:
16447 case AMDGPU::G_FCEIL:
16448 case AMDGPU::G_FFLOOR:
16449 case AMDGPU::G_FRINT:
16450 case AMDGPU::G_FNEARBYINT:
16451 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16452 case AMDGPU::G_INTRINSIC_TRUNC:
16453 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16454 case AMDGPU::G_FMA:
16455 case AMDGPU::G_FMAD:
16456 case AMDGPU::G_FSQRT:
16457 case AMDGPU::G_FDIV:
16458 case AMDGPU::G_FREM:
16459 case AMDGPU::G_FPOW:
16460 case AMDGPU::G_FPEXT:
16461 case AMDGPU::G_FLOG:
16462 case AMDGPU::G_FLOG2:
16463 case AMDGPU::G_FLOG10:
16464 case AMDGPU::G_FPTRUNC:
16465 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16466 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16467 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16468 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16469 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16470 return true;
16471 case AMDGPU::G_FNEG:
16472 case AMDGPU::G_FABS:
16473 case AMDGPU::G_FCOPYSIGN:
16474 return isCanonicalized(MI->getOperand(1).getReg(), MF, MaxDepth - 1);
16475 case AMDGPU::G_FMINNUM:
16476 case AMDGPU::G_FMAXNUM:
16477 case AMDGPU::G_FMINNUM_IEEE:
16478 case AMDGPU::G_FMAXNUM_IEEE:
16479 case AMDGPU::G_FMINIMUM:
16480 case AMDGPU::G_FMAXIMUM:
16481 case AMDGPU::G_FMINIMUMNUM:
16482 case AMDGPU::G_FMAXIMUMNUM: {
16483 if (Subtarget->supportsMinMaxDenormModes() ||
16484 // FIXME: denormalsEnabledForType is broken for dynamic
16485 denormalsEnabledForType(MRI.getType(Reg), MF))
16486 return true;
16487
16488 [[fallthrough]];
16489 }
16490 case AMDGPU::G_BUILD_VECTOR:
16491 for (const MachineOperand &MO : llvm::drop_begin(MI->operands()))
16492 if (!isCanonicalized(MO.getReg(), MF, MaxDepth - 1))
16493 return false;
16494 return true;
16495 case AMDGPU::G_INTRINSIC:
16496 case AMDGPU::G_INTRINSIC_CONVERGENT:
16497 switch (cast<GIntrinsic>(MI)->getIntrinsicID()) {
16498 case Intrinsic::amdgcn_fmul_legacy:
16499 case Intrinsic::amdgcn_fmad_ftz:
16500 case Intrinsic::amdgcn_sqrt:
16501 case Intrinsic::amdgcn_fmed3:
16502 case Intrinsic::amdgcn_sin:
16503 case Intrinsic::amdgcn_cos:
16504 case Intrinsic::amdgcn_log:
16505 case Intrinsic::amdgcn_exp2:
16506 case Intrinsic::amdgcn_log_clamp:
16507 case Intrinsic::amdgcn_rcp:
16508 case Intrinsic::amdgcn_rcp_legacy:
16509 case Intrinsic::amdgcn_rsq:
16510 case Intrinsic::amdgcn_rsq_clamp:
16511 case Intrinsic::amdgcn_rsq_legacy:
16512 case Intrinsic::amdgcn_div_scale:
16513 case Intrinsic::amdgcn_div_fmas:
16514 case Intrinsic::amdgcn_div_fixup:
16515 case Intrinsic::amdgcn_fract:
16516 case Intrinsic::amdgcn_cvt_pkrtz:
16517 case Intrinsic::amdgcn_cubeid:
16518 case Intrinsic::amdgcn_cubema:
16519 case Intrinsic::amdgcn_cubesc:
16520 case Intrinsic::amdgcn_cubetc:
16521 case Intrinsic::amdgcn_frexp_mant:
16522 case Intrinsic::amdgcn_fdot2:
16523 case Intrinsic::amdgcn_trig_preop:
16524 case Intrinsic::amdgcn_tanh:
16525 return true;
16526 default:
16527 break;
16528 }
16529
16530 [[fallthrough]];
16531 default:
16532 return false;
16533 }
16534
16535 llvm_unreachable("invalid operation");
16536}
16537
16538// Constant fold canonicalize.
16539SDValue SITargetLowering::getCanonicalConstantFP(SelectionDAG &DAG,
16540 const SDLoc &SL, EVT VT,
16541 const APFloat &C) const {
16542 // Flush denormals to 0 if not enabled.
16543 if (C.isDenormal()) {
16544 DenormalMode Mode =
16545 DAG.getMachineFunction().getDenormalMode(C.getSemantics());
16546 if (Mode == DenormalMode::getPreserveSign()) {
16547 return DAG.getConstantFP(
16548 APFloat::getZero(C.getSemantics(), C.isNegative()), SL, VT);
16549 }
16550
16551 if (Mode != DenormalMode::getIEEE())
16552 return SDValue();
16553 }
16554
16555 if (C.isNaN()) {
16556 if (C.isSignaling()) {
16557 // Quiet a signaling NaN.
16558 return DAG.getConstantFP(C.makeQuiet(), SL, VT);
16559 }
16560 }
16561
16562 // Already canonical.
16563 return DAG.getConstantFP(C, SL, VT);
16564}
16565
16567 return Op.isUndef() || isa<ConstantFPSDNode>(Op);
16568}
16569
16570SDValue
16571SITargetLowering::performFCanonicalizeCombine(SDNode *N,
16572 DAGCombinerInfo &DCI) const {
16573 SelectionDAG &DAG = DCI.DAG;
16574 SDValue N0 = N->getOperand(0);
16575 EVT VT = N->getValueType(0);
16576
16577 // fcanonicalize undef -> qnan
16578 if (N0.isUndef()) {
16580 return DAG.getConstantFP(QNaN, SDLoc(N), VT);
16581 }
16582
16583 if (ConstantFPSDNode *CFP = isConstOrConstSplatFP(N0))
16584 return getCanonicalConstantFP(DAG, SDLoc(N), VT, CFP->getValueAPF());
16585
16586 // fcanonicalize (build_vector x, k) -> build_vector (fcanonicalize x),
16587 // (fcanonicalize k)
16588 //
16589 // fcanonicalize (build_vector x, undef) -> build_vector (fcanonicalize x), 0
16590
16591 // TODO: This could be better with wider vectors that will be split to v2f16,
16592 // and to consider uses since there aren't that many packed operations.
16593 if (N0.getOpcode() == ISD::BUILD_VECTOR && N0.getNumOperands() == 2 &&
16594 isTypeLegal(VT)) {
16595 SDLoc SL(N);
16596 SDValue NewElts[2];
16597 SDValue Lo = N0.getOperand(0);
16598 SDValue Hi = N0.getOperand(1);
16599 EVT EltVT = Lo.getValueType();
16600
16601 // Only apply this optimization if scalar canonicalize is legal for the
16602 // element type. Otherwise, scalarizing may require widening the scalar back
16603 // to a vector, adding overhead (e.g., bf16 has no scalar instructions).
16605 return SDValue();
16606
16608 for (unsigned I = 0; I != 2; ++I) {
16609 SDValue Op = N0.getOperand(I);
16610 if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16611 NewElts[I] =
16612 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16613 } else if (Op.isUndef()) {
16614 // Handled below based on what the other operand is.
16615 NewElts[I] = Op;
16616 } else {
16617 NewElts[I] = DAG.getNode(ISD::FCANONICALIZE, SL, EltVT, Op);
16618 }
16619 }
16620
16621 // If one half is undef, and one is constant, prefer a splat vector.
16622 // Otherwise, convert the undef to 0.0 since that's cheaper to use and may
16623 // be free with a packed operation.
16624 if (NewElts[0].isUndef()) {
16625 NewElts[0] = isa<ConstantFPSDNode>(NewElts[1])
16626 ? NewElts[1]
16627 : DAG.getConstantFP(0.0f, SL, EltVT);
16628 }
16629
16630 if (NewElts[1].isUndef()) {
16631 NewElts[1] = isa<ConstantFPSDNode>(NewElts[0])
16632 ? NewElts[0]
16633 : DAG.getConstantFP(0.0f, SL, EltVT);
16634 }
16635
16636 return DAG.getBuildVector(VT, SL, NewElts);
16637 }
16638 }
16639
16640 return SDValue();
16641}
16642
16643static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc) {
16644 switch (Opc) {
16645 case ISD::FMAXNUM:
16646 case ISD::FMAXNUM_IEEE:
16647 case ISD::FMAXIMUMNUM:
16648 return AMDGPUISD::FMAX3;
16649 case ISD::FMAXIMUM:
16650 return AMDGPUISD::FMAXIMUM3;
16651 case ISD::SMAX:
16652 return AMDGPUISD::SMAX3;
16653 case ISD::UMAX:
16654 return AMDGPUISD::UMAX3;
16655 case ISD::FMINNUM:
16656 case ISD::FMINNUM_IEEE:
16657 case ISD::FMINIMUMNUM:
16658 return AMDGPUISD::FMIN3;
16659 case ISD::FMINIMUM:
16660 return AMDGPUISD::FMINIMUM3;
16661 case ISD::SMIN:
16662 return AMDGPUISD::SMIN3;
16663 case ISD::UMIN:
16664 return AMDGPUISD::UMIN3;
16665 default:
16666 llvm_unreachable("Not a min/max opcode");
16667 }
16668}
16669
16670SDValue SITargetLowering::performIntMed3ImmCombine(SelectionDAG &DAG,
16671 const SDLoc &SL, SDValue Src,
16672 SDValue MinVal,
16673 SDValue MaxVal,
16674 bool Signed) const {
16675
16676 // med3 comes from
16677 // min(max(x, K0), K1), K0 < K1
16678 // max(min(x, K0), K1), K1 < K0
16679 //
16680 // "MinVal" and "MaxVal" respectively refer to the rhs of the
16681 // min/max op.
16682 ConstantSDNode *MinK = dyn_cast<ConstantSDNode>(MinVal);
16683 ConstantSDNode *MaxK = dyn_cast<ConstantSDNode>(MaxVal);
16684
16685 if (!MinK || !MaxK)
16686 return SDValue();
16687
16688 if (Signed) {
16689 if (MaxK->getAPIntValue().sge(MinK->getAPIntValue()))
16690 return SDValue();
16691 } else {
16692 if (MaxK->getAPIntValue().uge(MinK->getAPIntValue()))
16693 return SDValue();
16694 }
16695
16696 EVT VT = MinK->getValueType(0);
16697 unsigned Med3Opc = Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16698 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16699 return DAG.getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16700
16701 // Note: we could also extend to i32 and use i32 med3 if i16 med3 is
16702 // not available, but this is unlikely to be profitable as constants
16703 // will often need to be materialized & extended, especially on
16704 // pre-GFX10 where VOP3 instructions couldn't take literal operands.
16705 return SDValue();
16706}
16707
16710 return C;
16711
16713 if (ConstantFPSDNode *C = BV->getConstantFPSplatNode())
16714 return C;
16715 }
16716
16717 return nullptr;
16718}
16719
16720SDValue SITargetLowering::performFPMed3ImmCombine(SelectionDAG &DAG,
16721 const SDLoc &SL, SDValue Op0,
16722 SDValue Op1,
16723 bool IsKnownNoNaNs) const {
16724 ConstantFPSDNode *K1 = getSplatConstantFP(Op1);
16725 if (!K1)
16726 return SDValue();
16727
16728 ConstantFPSDNode *K0 = getSplatConstantFP(Op0.getOperand(1));
16729 if (!K0)
16730 return SDValue();
16731
16732 // Ordered >= (although NaN inputs should have folded away by now).
16733 if (K0->getValueAPF() > K1->getValueAPF())
16734 return SDValue();
16735
16736 // med3 with a nan input acts like
16737 // v_min_f32(v_min_f32(S0.f32, S1.f32), S2.f32)
16738 //
16739 // So the result depends on whether the IEEE mode bit is enabled or not with a
16740 // signaling nan input.
16741 // ieee=1
16742 // s0 snan: yields s2
16743 // s1 snan: yields s2
16744 // s2 snan: qnan
16745
16746 // s0 qnan: min(s1, s2)
16747 // s1 qnan: min(s0, s2)
16748 // s2 qnan: min(s0, s1)
16749
16750 // ieee=0
16751 // s0 snan: min(s1, s2)
16752 // s1 snan: min(s0, s2)
16753 // s2 snan: qnan
16754
16755 // s0 qnan: min(s1, s2)
16756 // s1 qnan: min(s0, s2)
16757 // s2 qnan: min(s0, s1)
16758 const MachineFunction &MF = DAG.getMachineFunction();
16759 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
16760
16761 // TODO: Check IEEE bit enabled. We can form fmed3 with IEEE=0 regardless of
16762 // whether the input is a signaling nan if op0 is fmaximum or fmaximumnum. We
16763 // can only form if op0 is fmaxnum_ieee if IEEE=1.
16764 EVT VT = Op0.getValueType();
16765 if (Info->getMode().DX10Clamp) {
16766 // If dx10_clamp is enabled, NaNs clamp to 0.0. This is the same as the
16767 // hardware fmed3 behavior converting to a min.
16768 // FIXME: Should this be allowing -0.0?
16769 if (K1->isOne() && K0->isPosZero())
16770 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Op0.getOperand(0));
16771 }
16772
16773 // med3 for f16 is only available on gfx9+, and not available for v2f16.
16774 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16775 // This isn't safe with signaling NaNs because in IEEE mode, min/max on a
16776 // signaling NaN gives a quiet NaN. The quiet NaN input to the min would
16777 // then give the other result, which is different from med3 with a NaN
16778 // input.
16779 SDValue Var = Op0.getOperand(0);
16780 if (!IsKnownNoNaNs && !DAG.isKnownNeverSNaN(Var))
16781 return SDValue();
16782
16783 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
16784
16785 if ((!K0->hasOneUse() || TII->isInlineConstant(K0->getValueAPF())) &&
16786 (!K1->hasOneUse() || TII->isInlineConstant(K1->getValueAPF()))) {
16787 return DAG.getNode(AMDGPUISD::FMED3, SL, K0->getValueType(0), Var,
16788 SDValue(K0, 0), SDValue(K1, 0));
16789 }
16790 }
16791
16792 return SDValue();
16793}
16794
16795/// \return true if the subtarget supports minimum3 and maximum3 with the given
16796/// base min/max opcode \p Opc for type \p VT.
16797static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc,
16798 EVT VT) {
16799 switch (Opc) {
16800 case ISD::FMINNUM:
16801 case ISD::FMAXNUM:
16802 case ISD::FMINNUM_IEEE:
16803 case ISD::FMAXNUM_IEEE:
16804 case ISD::FMINIMUMNUM:
16805 case ISD::FMAXIMUMNUM:
16806 case AMDGPUISD::FMIN_LEGACY:
16807 case AMDGPUISD::FMAX_LEGACY:
16808 return (VT == MVT::f32) || (VT == MVT::f16 && Subtarget.hasMin3Max3_16()) ||
16809 (VT == MVT::v2f16 && Subtarget.hasMin3Max3PKF16());
16810 case ISD::FMINIMUM:
16811 case ISD::FMAXIMUM:
16812 return (VT == MVT::f32 && Subtarget.hasMinimum3Maximum3F32()) ||
16813 (VT == MVT::f16 && Subtarget.hasMinimum3Maximum3F16()) ||
16814 (VT == MVT::v2f16 && Subtarget.hasMinimum3Maximum3PKF16());
16815 case ISD::SMAX:
16816 case ISD::SMIN:
16817 case ISD::UMAX:
16818 case ISD::UMIN:
16819 return (VT == MVT::i32) || (VT == MVT::i16 && Subtarget.hasMin3Max3_16());
16820 default:
16821 return false;
16822 }
16823
16824 llvm_unreachable("not a min/max opcode");
16825}
16826
16827SDValue SITargetLowering::performMinMaxCombine(SDNode *N,
16828 DAGCombinerInfo &DCI) const {
16829 SelectionDAG &DAG = DCI.DAG;
16830
16831 EVT VT = N->getValueType(0);
16832 unsigned Opc = N->getOpcode();
16833 SDValue Op0 = N->getOperand(0);
16834 SDValue Op1 = N->getOperand(1);
16835
16836 // Only do this if the inner op has one use since this will just increases
16837 // register pressure for no benefit.
16838
16839 if (supportsMin3Max3(*Subtarget, Opc, VT)) {
16840 auto IsTreeWithCombinableChildren = [Opc](SDValue Op) {
16841 return (Op.getOperand(0).getOpcode() == Opc &&
16842 Op.getOperand(0).hasOneUse()) ||
16843 (Op.getOperand(1).getOpcode() == Opc &&
16844 Op.getOperand(1).hasOneUse());
16845 };
16846
16847 bool CanTreeCombineApply = Op0.getOpcode() == Opc && Op0.hasOneUse() &&
16848 Op1.getOpcode() == Opc && Op1.hasOneUse();
16849 bool HasCombinableTreeChild =
16850 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
16851 IsTreeWithCombinableChildren(Op1));
16852
16853 // Tree reduction: when both operands are the same min/max op, restructure
16854 // to keep a 2-op node on top so higher tree levels can still combine.
16855 //
16856 // max(max(a, b), max(c, d)) -> max(max3(a, b, c), d)
16857 // min(min(a, b), min(c, d)) -> min(min3(a, b, c), d)
16858 //
16859 // Defer when either inner op is a tree node with combinable children.
16860 if (CanTreeCombineApply && !HasCombinableTreeChild) {
16861 SDLoc DL(N);
16862 SDValue Inner =
16864 Op0.getOperand(1), Op1.getOperand(0));
16865 return DAG.getNode(Opc, DL, VT, Inner, Op1.getOperand(1));
16866 }
16867
16868 // max(max(a, b), c) -> max3(a, b, c)
16869 // min(min(a, b), c) -> min3(a, b, c)
16870 // Deferred when Op0 is a tree node with combinable children.
16871 if (Op0.getOpcode() == Opc && Op0.hasOneUse() && !HasCombinableTreeChild) {
16872 SDLoc DL(N);
16873 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
16874 Op0.getOperand(0), Op0.getOperand(1), Op1);
16875 }
16876
16877 // Try commuted.
16878 // max(a, max(b, c)) -> max3(a, b, c)
16879 // min(a, min(b, c)) -> min3(a, b, c)
16880 // Deferred when Op1 is a tree node with combinable children.
16881 if (Op1.getOpcode() == Opc && Op1.hasOneUse() && !HasCombinableTreeChild) {
16882 SDLoc DL(N);
16883 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
16884 Op0, Op1.getOperand(0), Op1.getOperand(1));
16885 }
16886 }
16887
16888 // umin(sffbh(x), bitwidth) -> sffbh(x) if x is known to be not 0 or -1.
16889 SDValue FfbhSrc;
16890 uint64_t Clamp = 0;
16891 if (Opc == ISD::UMIN &&
16892 sd_match(Op0,
16894 sd_match(Op1, m_ConstInt(Clamp))) {
16895 unsigned BitWidth = FfbhSrc.getValueType().getScalarSizeInBits();
16896 if (Clamp >= BitWidth) {
16897 KnownBits Known = DAG.computeKnownBits(FfbhSrc);
16898 if (Known.isNonZero() && Known.Zero.getBoolValue())
16899 return Op0;
16900 }
16901 }
16902
16903 // min(max(x, K0), K1), K0 < K1 -> med3(x, K0, K1)
16904 // max(min(x, K0), K1), K1 < K0 -> med3(x, K1, K0)
16905 if (Opc == ISD::SMIN && Op0.getOpcode() == ISD::SMAX && Op0.hasOneUse()) {
16906 if (SDValue Med3 = performIntMed3ImmCombine(
16907 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), true))
16908 return Med3;
16909 }
16910 if (Opc == ISD::SMAX && Op0.getOpcode() == ISD::SMIN && Op0.hasOneUse()) {
16911 if (SDValue Med3 = performIntMed3ImmCombine(
16912 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, true))
16913 return Med3;
16914 }
16915
16916 if (Opc == ISD::UMIN && Op0.getOpcode() == ISD::UMAX && Op0.hasOneUse()) {
16917 if (SDValue Med3 = performIntMed3ImmCombine(
16918 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), false))
16919 return Med3;
16920 }
16921 if (Opc == ISD::UMAX && Op0.getOpcode() == ISD::UMIN && Op0.hasOneUse()) {
16922 if (SDValue Med3 = performIntMed3ImmCombine(
16923 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, false))
16924 return Med3;
16925 }
16926
16927 // if !is_snan(x):
16928 // fminnum(fmaxnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16929 // fminnum_ieee(fmaxnum_ieee(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16930 // fminnumnum(fmaxnumnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16931 // fmin_legacy(fmax_legacy(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16932 if (((Opc == ISD::FMINNUM && Op0.getOpcode() == ISD::FMAXNUM) ||
16935 (Opc == AMDGPUISD::FMIN_LEGACY &&
16936 Op0.getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
16937 (VT == MVT::f32 || VT == MVT::f64 ||
16938 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
16939 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
16940 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
16941 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
16942 Op0.hasOneUse()) {
16943 if (SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(N), Op0, Op1,
16944 N->getFlags().hasNoNaNs()))
16945 return Res;
16946 }
16947
16948 // Prefer fminnum_ieee over fminimum. For gfx950, minimum/maximum are legal
16949 // for some types, but at a higher cost since it's implemented with a 3
16950 // operand form.
16951 const SDNodeFlags Flags = N->getFlags();
16952 if ((Opc == ISD::FMINIMUM || Opc == ISD::FMAXIMUM) && Flags.hasNoNaNs() &&
16953 !Subtarget->hasIEEEMinimumMaximumInsts() &&
16955 unsigned NewOpc =
16957 return DAG.getNode(NewOpc, SDLoc(N), VT, Op0, Op1, Flags);
16958 }
16959
16960 return SDValue();
16961}
16962
16966 // FIXME: Should this be allowing -0.0?
16967 return (CA->isPosZero() && CB->isOne()) ||
16968 (CA->isOne() && CB->isPosZero());
16969 }
16970 }
16971
16972 return false;
16973}
16974
16975// FIXME: Should only worry about snans for version with chain.
16976SDValue SITargetLowering::performFMed3Combine(SDNode *N,
16977 DAGCombinerInfo &DCI) const {
16978 EVT VT = N->getValueType(0);
16979 // v_med3_f32 and v_max_f32 behave identically wrt denorms, exceptions and
16980 // NaNs. With a NaN input, the order of the operands may change the result.
16981
16982 SelectionDAG &DAG = DCI.DAG;
16983 SDLoc SL(N);
16984
16985 SDValue Src0 = N->getOperand(0);
16986 SDValue Src1 = N->getOperand(1);
16987 SDValue Src2 = N->getOperand(2);
16988
16989 if (isClampZeroToOne(Src0, Src1)) {
16990 // const_a, const_b, x -> clamp is safe in all cases including signaling
16991 // nans.
16992 // FIXME: Should this be allowing -0.0?
16993 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
16994 }
16995
16996 const MachineFunction &MF = DAG.getMachineFunction();
16997 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
16998
16999 // FIXME: dx10_clamp behavior assumed in instcombine. Should we really bother
17000 // handling no dx10-clamp?
17001 if (Info->getMode().DX10Clamp) {
17002 // If NaNs is clamped to 0, we are free to reorder the inputs.
17003
17004 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
17005 std::swap(Src0, Src1);
17006
17007 if (isa<ConstantFPSDNode>(Src1) && !isa<ConstantFPSDNode>(Src2))
17008 std::swap(Src1, Src2);
17009
17010 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
17011 std::swap(Src0, Src1);
17012
17013 if (isClampZeroToOne(Src1, Src2))
17014 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
17015 }
17016
17017 return SDValue();
17018}
17019
17020SDValue SITargetLowering::performCvtPkRTZCombine(SDNode *N,
17021 DAGCombinerInfo &DCI) const {
17022 SDValue Src0 = N->getOperand(0);
17023 SDValue Src1 = N->getOperand(1);
17024 if (Src0.isUndef() && Src1.isUndef())
17025 return DCI.DAG.getUNDEF(N->getValueType(0));
17026 return SDValue();
17027}
17028
17029// Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be
17030// expanded into a set of cmp/select instructions.
17032 unsigned NumElem,
17033 bool IsDivergentIdx,
17034 const GCNSubtarget *Subtarget) {
17036 return false;
17037
17038 unsigned VecSize = EltSize * NumElem;
17039
17040 // Sub-dword vectors of size 2 dword or less have better implementation.
17041 if (VecSize <= 64 && EltSize < 32)
17042 return false;
17043
17044 // Always expand the rest of sub-dword instructions, otherwise it will be
17045 // lowered via memory.
17046 if (EltSize < 32)
17047 return true;
17048
17049 // Always do this if var-idx is divergent, otherwise it will become a loop.
17050 if (IsDivergentIdx)
17051 return true;
17052
17053 // Large vectors would yield too many compares and v_cndmask_b32 instructions.
17054 unsigned NumInsts = NumElem /* Number of compares */ +
17055 ((EltSize + 31) / 32) * NumElem /* Number of cndmasks */;
17056
17057 // On some architectures (GFX9) movrel is not available and it's better
17058 // to expand.
17059 if (Subtarget->useVGPRIndexMode())
17060 return NumInsts <= 16;
17061
17062 // If movrel is available, use it instead of expanding for vector of 8
17063 // elements.
17064 if (Subtarget->hasMovrel())
17065 return NumInsts <= 15;
17066
17067 return true;
17068}
17069
17071 SDValue Idx = N->getOperand(N->getNumOperands() - 1);
17072 if (isa<ConstantSDNode>(Idx))
17073 return false;
17074
17075 SDValue Vec = N->getOperand(0);
17076 EVT VecVT = Vec.getValueType();
17077 EVT EltVT = VecVT.getVectorElementType();
17078 unsigned EltSize = EltVT.getSizeInBits();
17079 unsigned NumElem = VecVT.getVectorNumElements();
17080
17082 EltSize, NumElem, Idx->isDivergent(), getSubtarget());
17083}
17084
17085SDValue
17086SITargetLowering::performExtractVectorEltCombine(SDNode *N,
17087 DAGCombinerInfo &DCI) const {
17088 SDValue Vec = N->getOperand(0);
17089 SelectionDAG &DAG = DCI.DAG;
17090
17091 EVT VecVT = Vec.getValueType();
17092 EVT VecEltVT = VecVT.getVectorElementType();
17093 EVT ResVT = N->getValueType(0);
17094
17095 unsigned VecSize = VecVT.getSizeInBits();
17096 unsigned VecEltSize = VecEltVT.getSizeInBits();
17097
17098 if ((Vec.getOpcode() == ISD::FNEG || Vec.getOpcode() == ISD::FABS) &&
17100 SDLoc SL(N);
17101 SDValue Idx = N->getOperand(1);
17102 SDValue Elt =
17103 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec.getOperand(0), Idx);
17104 return DAG.getNode(Vec.getOpcode(), SL, ResVT, Elt);
17105 }
17106
17107 // (extract_vector_element (and {y0, y1}, (build_vector 0x1f, 0x1f)), index)
17108 // -> (and (extract_vector_element {y0, y1}, index), 0x1f)
17109 // There are optimisations to transform 64-bit shifts into 32-bit shifts
17110 // depending on the shift operand. See e.g. performSraCombine().
17111 // This combine ensures that the optimisation is compatible with v2i32
17112 // legalised AND.
17113 if (VecVT == MVT::v2i32 && Vec->getOpcode() == ISD::AND &&
17114 Vec->getOperand(1)->getOpcode() == ISD::BUILD_VECTOR) {
17115
17117 if (!C || C->getZExtValue() != 0x1f)
17118 return SDValue();
17119
17120 SDLoc SL(N);
17121 SDValue AndMask = DAG.getConstant(0x1f, SL, MVT::i32);
17122 SDValue EVE = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32,
17123 Vec->getOperand(0), N->getOperand(1));
17124 SDValue A = DAG.getNode(ISD::AND, SL, MVT::i32, EVE, AndMask);
17125 DAG.ReplaceAllUsesWith(N, A.getNode());
17126 }
17127
17128 // ScalarRes = EXTRACT_VECTOR_ELT ((vector-BINOP Vec1, Vec2), Idx)
17129 // =>
17130 // Vec1Elt = EXTRACT_VECTOR_ELT(Vec1, Idx)
17131 // Vec2Elt = EXTRACT_VECTOR_ELT(Vec2, Idx)
17132 // ScalarRes = scalar-BINOP Vec1Elt, Vec2Elt
17133 if (Vec.hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17134 SDLoc SL(N);
17135 SDValue Idx = N->getOperand(1);
17136 unsigned Opc = Vec.getOpcode();
17137
17138 switch (Opc) {
17139 default:
17140 break;
17141 // TODO: Support other binary operations.
17142 case ISD::FADD:
17143 case ISD::FSUB:
17144 case ISD::FMUL:
17145 case ISD::ADD:
17146 case ISD::UMIN:
17147 case ISD::UMAX:
17148 case ISD::SMIN:
17149 case ISD::SMAX:
17150 case ISD::FMAXNUM:
17151 case ISD::FMINNUM:
17152 case ISD::FMAXNUM_IEEE:
17153 case ISD::FMINNUM_IEEE:
17154 case ISD::FMAXIMUM:
17155 case ISD::FMINIMUM: {
17156 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17157 Vec.getOperand(0), Idx);
17158 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17159 Vec.getOperand(1), Idx);
17160
17161 DCI.AddToWorklist(Elt0.getNode());
17162 DCI.AddToWorklist(Elt1.getNode());
17163 return DAG.getNode(Opc, SL, ResVT, Elt0, Elt1, Vec->getFlags());
17164 }
17165 }
17166 }
17167
17168 // EXTRACT_VECTOR_ELT (<n x e>, var-idx) => n x select (e, const-idx)
17170 SDLoc SL(N);
17171 SDValue Idx = N->getOperand(1);
17172 SDValue V;
17173 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17174 SDValue IC = DAG.getVectorIdxConstant(I, SL);
17175 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec, IC);
17176 if (I == 0)
17177 V = Elt;
17178 else
17179 V = DAG.getSelectCC(SL, Idx, IC, Elt, V, ISD::SETEQ);
17180 }
17181 return V;
17182 }
17183
17184 // EXTRACT_VECTOR_ELT (v2i32 bitcast (i64/f64:k), Idx)
17185 // =>
17186 // i32:Lo(k) if Idx == 0, or
17187 // i32:Hi(k) if Idx == 1
17188 auto *Idx = dyn_cast<ConstantSDNode>(N->getOperand(1));
17189 if (Vec.getOpcode() == ISD::BITCAST && VecVT == MVT::v2i32 && Idx) {
17190 SDLoc SL(N);
17191 SDValue PeekThrough = Vec.getOperand(0);
17192 auto *KImm = dyn_cast<ConstantSDNode>(PeekThrough);
17193 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17194 uint64_t KImmValue = KImm->getZExtValue();
17195 return DAG.getConstant(
17196 (KImmValue >> (32 * Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17197 }
17198 auto *KFPImm = dyn_cast<ConstantFPSDNode>(PeekThrough);
17199 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17200 uint64_t KFPImmValue =
17201 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17202 return DAG.getConstant((KFPImmValue >> (32 * Idx->getZExtValue())) &
17203 0xffffffff,
17204 SL, MVT::i32);
17205 }
17206 }
17207
17208 if (!DCI.isBeforeLegalize())
17209 return SDValue();
17210
17211 // Try to turn sub-dword accesses of vectors into accesses of the same 32-bit
17212 // elements. This exposes more load reduction opportunities by replacing
17213 // multiple small extract_vector_elements with a single 32-bit extract.
17214 if (isa<MemSDNode>(Vec) && VecEltSize <= 16 && VecEltVT.isByteSized() &&
17215 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17216 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VecVT);
17217
17218 unsigned BitIndex = Idx->getZExtValue() * VecEltSize;
17219 unsigned EltIdx = BitIndex / 32;
17220 unsigned LeftoverBitIdx = BitIndex % 32;
17221 SDLoc SL(N);
17222
17223 SDValue Cast = DAG.getNode(ISD::BITCAST, SL, NewVT, Vec);
17224 DCI.AddToWorklist(Cast.getNode());
17225
17226 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Cast,
17227 DAG.getConstant(EltIdx, SL, MVT::i32));
17228 DCI.AddToWorklist(Elt.getNode());
17229 SDValue Srl = DAG.getNode(ISD::SRL, SL, MVT::i32, Elt,
17230 DAG.getConstant(LeftoverBitIdx, SL, MVT::i32));
17231 DCI.AddToWorklist(Srl.getNode());
17232
17233 EVT VecEltAsIntVT = VecEltVT.changeTypeToInteger();
17234 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SL, VecEltAsIntVT, Srl);
17235 DCI.AddToWorklist(Trunc.getNode());
17236
17237 if (VecEltVT == ResVT) {
17238 return DAG.getNode(ISD::BITCAST, SL, VecEltVT, Trunc);
17239 }
17240
17241 assert(ResVT.isScalarInteger());
17242 return DAG.getAnyExtOrTrunc(Trunc, SL, ResVT);
17243 }
17244
17245 return SDValue();
17246}
17247
17248SDValue
17249SITargetLowering::performInsertVectorEltCombine(SDNode *N,
17250 DAGCombinerInfo &DCI) const {
17251 SDValue Vec = N->getOperand(0);
17252 SDValue Idx = N->getOperand(2);
17253 EVT VecVT = Vec.getValueType();
17254 EVT EltVT = VecVT.getVectorElementType();
17255
17256 // INSERT_VECTOR_ELT (<n x e>, var-idx)
17257 // => BUILD_VECTOR n x select (e, const-idx)
17259 return SDValue();
17260
17261 SelectionDAG &DAG = DCI.DAG;
17262 SDLoc SL(N);
17263 SDValue Ins = N->getOperand(1);
17264 EVT IdxVT = Idx.getValueType();
17265
17267 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17268 SDValue IC = DAG.getConstant(I, SL, IdxVT);
17269 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec, IC);
17270 SDValue V = DAG.getSelectCC(SL, Idx, IC, Ins, Elt, ISD::SETEQ);
17271 Ops.push_back(V);
17272 }
17273
17274 return DAG.getBuildVector(VecVT, SL, Ops);
17275}
17276
17277/// Return the source of an fp_extend from f16 to f32, or a converted FP
17278/// constant.
17280 if (Src.getOpcode() == ISD::FP_EXTEND &&
17281 Src.getOperand(0).getValueType() == MVT::f16) {
17282 return Src.getOperand(0);
17283 }
17284
17285 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Src)) {
17286 APFloat Val = CFP->getValueAPF();
17287 bool LosesInfo = true;
17289 if (!LosesInfo)
17290 return DAG.getConstantFP(Val, SDLoc(Src), MVT::f16);
17291 }
17292
17293 return SDValue();
17294}
17295
17296SDValue SITargetLowering::performFPRoundCombine(SDNode *N,
17297 DAGCombinerInfo &DCI) const {
17298 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17299 "combine only useful on gfx8");
17300
17301 SDValue TruncSrc = N->getOperand(0);
17302 EVT VT = N->getValueType(0);
17303 if (VT != MVT::f16)
17304 return SDValue();
17305
17306 if (TruncSrc.getOpcode() != AMDGPUISD::FMED3 ||
17307 TruncSrc.getValueType() != MVT::f32 || !TruncSrc.hasOneUse())
17308 return SDValue();
17309
17310 SelectionDAG &DAG = DCI.DAG;
17311 SDLoc SL(N);
17312
17313 // Optimize f16 fmed3 pattern performed on f32. On gfx8 there is no f16 fmed3,
17314 // and expanding it with min/max saves 1 instruction vs. casting to f32 and
17315 // casting back.
17316
17317 // fptrunc (f32 (fmed3 (fpext f16:a, fpext f16:b, fpext f16:c))) =>
17318 // fmin(fmax(a, b), fmax(fmin(a, b), c))
17319 SDValue A = strictFPExtFromF16(DAG, TruncSrc.getOperand(0));
17320 if (!A)
17321 return SDValue();
17322
17323 SDValue B = strictFPExtFromF16(DAG, TruncSrc.getOperand(1));
17324 if (!B)
17325 return SDValue();
17326
17327 SDValue C = strictFPExtFromF16(DAG, TruncSrc.getOperand(2));
17328 if (!C)
17329 return SDValue();
17330
17331 // This changes signaling nan behavior. If an input is a signaling nan, it
17332 // would have been quieted by the fpext originally. We don't care because
17333 // these are unconstrained ops. If we needed to insert quieting canonicalizes
17334 // we would be worse off than just doing the promotion.
17335 SDValue A1 = DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, A, B);
17336 SDValue B1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A, B);
17337 SDValue C1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A1, C);
17338 return DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, B1, C1);
17339}
17340
17341unsigned SITargetLowering::getFusedOpcode(const SelectionDAG &DAG,
17342 const SDNode *N0,
17343 const SDNode *N1) const {
17344 EVT VT = N0->getValueType(0);
17345
17346 // Only do this if we are not trying to support denormals. v_mad_f32 does not
17347 // support denormals ever.
17348 if (((VT == MVT::f32 &&
17350 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17353 return ISD::FMAD;
17354
17355 if (N0->getFlags().hasAllowContract() && N1->getFlags().hasAllowContract() &&
17357 return ISD::FMA;
17358 }
17359
17360 return 0;
17361}
17362
17363// For a reassociatable opcode perform:
17364// op x, (op y, z) -> op (op x, z), y, if x and z are uniform
17365SDValue SITargetLowering::reassociateScalarOps(SDNode *N,
17366 SelectionDAG &DAG) const {
17367 EVT VT = N->getValueType(0);
17368 if (VT != MVT::i32 && VT != MVT::i64)
17369 return SDValue();
17370
17371 if (DAG.isBaseWithConstantOffset(SDValue(N, 0)))
17372 return SDValue();
17373
17374 unsigned Opc = N->getOpcode();
17375 SDValue Op0 = N->getOperand(0);
17376 SDValue Op1 = N->getOperand(1);
17377
17378 if (!(Op0->isDivergent() ^ Op1->isDivergent()))
17379 return SDValue();
17380
17381 if (Op0->isDivergent())
17382 std::swap(Op0, Op1);
17383
17384 if (Op1.getOpcode() != Opc || !Op1.hasOneUse())
17385 return SDValue();
17386
17387 SDValue Op2 = Op1.getOperand(1);
17388 Op1 = Op1.getOperand(0);
17389 if (!(Op1->isDivergent() ^ Op2->isDivergent()))
17390 return SDValue();
17391
17392 if (Op1->isDivergent())
17393 std::swap(Op1, Op2);
17394
17395 SDLoc SL(N);
17396 SDValue Add1 = DAG.getNode(Opc, SL, VT, Op0, Op1);
17397 return DAG.getNode(Opc, SL, VT, Add1, Op2);
17398}
17399
17400static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT,
17401 SDValue N0, SDValue N1, SDValue N2, bool Signed) {
17403 SDVTList VTs = DAG.getVTList(MVT::i64, MVT::i1);
17404 SDValue Mad = DAG.getNode(MadOpc, SL, VTs, N0, N1, N2);
17405 return DAG.getNode(ISD::TRUNCATE, SL, VT, Mad);
17406}
17407
17408// Fold
17409// y = lshr i64 x, 32
17410// res = add (mul i64 y, Const), x where "Const" is a 64-bit constant
17411// with Const.hi == -1
17412// To
17413// res = mad_u64_u32 y.lo ,Const.lo, x.lo
17415 SDValue MulLHS, SDValue MulRHS,
17416 SDValue AddRHS) {
17417 if (MulRHS.getOpcode() == ISD::SRL)
17418 std::swap(MulLHS, MulRHS);
17419
17420 if (MulLHS.getValueType() != MVT::i64 || MulLHS.getOpcode() != ISD::SRL)
17421 return SDValue();
17422
17423 ConstantSDNode *ShiftVal = dyn_cast<ConstantSDNode>(MulLHS.getOperand(1));
17424 if (!ShiftVal || ShiftVal->getAsZExtVal() != 32 ||
17425 MulLHS.getOperand(0) != AddRHS)
17426 return SDValue();
17427
17429 if (!Const || Hi_32(Const->getZExtValue()) != uint32_t(-1))
17430 return SDValue();
17431
17432 SDValue ConstMul =
17433 DAG.getConstant(Lo_32(Const->getZExtValue()), SL, MVT::i32);
17434 return getMad64_32(DAG, SL, MVT::i64,
17435 DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS), ConstMul,
17436 DAG.getZeroExtendInReg(AddRHS, SL, MVT::i32), false);
17437}
17438
17439// Fold (add (mul x, y), z) --> (mad_[iu]64_[iu]32 x, y, z) plus high
17440// multiplies, if any.
17441//
17442// Full 64-bit multiplies that feed into an addition are lowered here instead
17443// of using the generic expansion. The generic expansion ends up with
17444// a tree of ADD nodes that prevents us from using the "add" part of the
17445// MAD instruction. The expansion produced here results in a chain of ADDs
17446// instead of a tree.
17447SDValue SITargetLowering::tryFoldToMad64_32(SDNode *N,
17448 DAGCombinerInfo &DCI) const {
17449 assert(N->isAnyAdd());
17450
17451 SelectionDAG &DAG = DCI.DAG;
17452 EVT VT = N->getValueType(0);
17453 SDLoc SL(N);
17454 SDValue LHS = N->getOperand(0);
17455 SDValue RHS = N->getOperand(1);
17456
17457 if (VT.isVector())
17458 return SDValue();
17459
17460 // S_MUL_HI_[IU]32 was added in gfx9, which allows us to keep the overall
17461 // result in scalar registers for uniform values.
17462 if (!N->isDivergent() && Subtarget->hasSMulHi())
17463 return SDValue();
17464
17465 unsigned NumBits = VT.getScalarSizeInBits();
17466 if (NumBits <= 32 || NumBits > 64)
17467 return SDValue();
17468
17469 if (LHS.getOpcode() != ISD::MUL) {
17470 assert(RHS.getOpcode() == ISD::MUL);
17471 std::swap(LHS, RHS);
17472 }
17473
17474 // Avoid the fold if it would unduly increase the number of multiplies due to
17475 // multiple uses, except on hardware with full-rate multiply-add (which is
17476 // part of full-rate 64-bit ops).
17477 if (!Subtarget->hasFullRate64Ops()) {
17478 unsigned NumUsers = 0;
17479 for (SDNode *User : LHS->users()) {
17480 // There is a use that does not feed into addition, so the multiply can't
17481 // be removed. We prefer MUL + ADD + ADDC over MAD + MUL.
17482 if (!User->isAnyAdd())
17483 return SDValue();
17484
17485 // We prefer 2xMAD over MUL + 2xADD + 2xADDC (code density), and prefer
17486 // MUL + 3xADD + 3xADDC over 3xMAD.
17487 ++NumUsers;
17488 if (NumUsers >= 3)
17489 return SDValue();
17490 }
17491 }
17492
17493 SDValue MulLHS = LHS.getOperand(0);
17494 SDValue MulRHS = LHS.getOperand(1);
17495 SDValue AddRHS = RHS;
17496
17497 if (SDValue FoldedMAD = tryFoldMADwithSRL(DAG, SL, MulLHS, MulRHS, AddRHS))
17498 return FoldedMAD;
17499
17500 // Always check whether operands are small unsigned values, since that
17501 // knowledge is useful in more cases. Check for small signed values only if
17502 // doing so can unlock a shorter code sequence.
17503 bool MulLHSUnsigned32 = numBitsUnsigned(MulLHS, DAG) <= 32;
17504 bool MulRHSUnsigned32 = numBitsUnsigned(MulRHS, DAG) <= 32;
17505
17506 bool MulSignedLo = false;
17507 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17508 MulSignedLo =
17509 numBitsSigned(MulLHS, DAG) <= 32 && numBitsSigned(MulRHS, DAG) <= 32;
17510 }
17511
17512 // The operands and final result all have the same number of bits. If
17513 // operands need to be extended, they can be extended with garbage. The
17514 // resulting garbage in the high bits of the mad_[iu]64_[iu]32 result is
17515 // truncated away in the end.
17516 if (VT != MVT::i64) {
17517 MulLHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulLHS);
17518 MulRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulRHS);
17519 AddRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, AddRHS);
17520 }
17521
17522 // The basic code generated is conceptually straightforward. Pseudo code:
17523 //
17524 // accum = mad_64_32 lhs.lo, rhs.lo, accum
17525 // accum.hi = add (mul lhs.hi, rhs.lo), accum.hi
17526 // accum.hi = add (mul lhs.lo, rhs.hi), accum.hi
17527 //
17528 // The second and third lines are optional, depending on whether the factors
17529 // are {sign,zero}-extended or not.
17530 //
17531 // The actual DAG is noisier than the pseudo code, but only due to
17532 // instructions that disassemble values into low and high parts, and
17533 // assemble the final result.
17534 SDValue One = DAG.getConstant(1, SL, MVT::i32);
17535
17536 auto MulLHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS);
17537 auto MulRHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulRHS);
17538 SDValue Accum =
17539 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17540
17541 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17542 auto [AccumLo, AccumHi] = DAG.SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17543
17544 if (!MulLHSUnsigned32) {
17545 auto MulLHSHi =
17546 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulLHS, One);
17547 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSHi, MulRHSLo);
17548 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17549 }
17550
17551 if (!MulRHSUnsigned32) {
17552 auto MulRHSHi =
17553 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulRHS, One);
17554 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSLo, MulRHSHi);
17555 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17556 }
17557
17558 Accum = DAG.getBuildVector(MVT::v2i32, SL, {AccumLo, AccumHi});
17559 Accum = DAG.getBitcast(MVT::i64, Accum);
17560 }
17561
17562 if (VT != MVT::i64)
17563 Accum = DAG.getNode(ISD::TRUNCATE, SL, VT, Accum);
17564 return Accum;
17565}
17566
17567SDValue
17568SITargetLowering::foldAddSub64WithZeroLowBitsTo32(SDNode *N,
17569 DAGCombinerInfo &DCI) const {
17570 SDValue RHS = N->getOperand(1);
17571 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
17572 if (!CRHS)
17573 return SDValue();
17574
17575 // TODO: Worth using computeKnownBits? Maybe expensive since it's so
17576 // common.
17577 uint64_t Val = CRHS->getZExtValue();
17578 if (countr_zero(Val) >= 32) {
17579 SelectionDAG &DAG = DCI.DAG;
17580 SDLoc SL(N);
17581 SDValue LHS = N->getOperand(0);
17582
17583 // Avoid carry machinery if we know the low half of the add does not
17584 // contribute to the final result.
17585 //
17586 // add i64:x, K if computeTrailingZeros(K) >= 32
17587 // => build_pair (add x.hi, K.hi), x.lo
17588
17589 // Breaking the 64-bit add here with this strange constant is unlikely
17590 // to interfere with addressing mode patterns.
17591
17592 SDValue Hi = getHiHalf64(LHS, DAG);
17593 SDValue ConstHi32 = DAG.getConstant(Hi_32(Val), SL, MVT::i32);
17594 unsigned Opcode = N->getOpcode();
17595 if (Opcode == ISD::PTRADD)
17596 Opcode = ISD::ADD;
17597 SDValue AddHi =
17598 DAG.getNode(Opcode, SL, MVT::i32, Hi, ConstHi32, N->getFlags());
17599
17600 SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
17601 return DAG.getNode(ISD::BUILD_PAIR, SL, MVT::i64, Lo, AddHi);
17602 }
17603
17604 return SDValue();
17605}
17606
17607// Collect the ultimate src of each of the mul node's operands, and confirm
17608// each operand is 8 bytes.
17609static std::optional<ByteProvider<SDValue>>
17610handleMulOperand(const SDValue &MulOperand) {
17611 auto Byte0 = calculateByteProvider(MulOperand, 0, 0);
17612 if (!Byte0 || Byte0->isConstantZero()) {
17613 return std::nullopt;
17614 }
17615 auto Byte1 = calculateByteProvider(MulOperand, 1, 0);
17616 if (Byte1 && !Byte1->isConstantZero()) {
17617 return std::nullopt;
17618 }
17619 return Byte0;
17620}
17621
17622static unsigned addPermMasks(unsigned First, unsigned Second) {
17623 unsigned FirstCs = First & 0x0c0c0c0c;
17624 unsigned SecondCs = Second & 0x0c0c0c0c;
17625 unsigned FirstNoCs = First & ~0x0c0c0c0c;
17626 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17627
17628 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17629 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17630 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17631 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17632
17633 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17634}
17635
17636struct DotSrc {
17638 int64_t PermMask;
17640};
17641
17645 SmallVectorImpl<DotSrc> &Src1s, int Step) {
17646
17647 assert(Src0.Src.has_value() && Src1.Src.has_value());
17648 // Src0s and Src1s are empty, just place arbitrarily.
17649 if (Step == 0) {
17650 Src0s.push_back({*Src0.Src, ((Src0.SrcOffset % 4) << 24) + 0x0c0c0c,
17651 Src0.SrcOffset / 4});
17652 Src1s.push_back({*Src1.Src, ((Src1.SrcOffset % 4) << 24) + 0x0c0c0c,
17653 Src1.SrcOffset / 4});
17654 return;
17655 }
17656
17657 for (int BPI = 0; BPI < 2; BPI++) {
17658 std::pair<ByteProvider<SDValue>, ByteProvider<SDValue>> BPP = {Src0, Src1};
17659 if (BPI == 1) {
17660 BPP = {Src1, Src0};
17661 }
17662 unsigned ZeroMask = 0x0c0c0c0c;
17663 unsigned FMask = 0xFF << (8 * (3 - Step));
17664
17665 unsigned FirstMask =
17666 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17667 unsigned SecondMask =
17668 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17669 // Attempt to find Src vector which contains our SDValue, if so, add our
17670 // perm mask to the existing one. If we are unable to find a match for the
17671 // first SDValue, attempt to find match for the second.
17672 int FirstGroup = -1;
17673 for (int I = 0; I < 2; I++) {
17674 SmallVectorImpl<DotSrc> &Srcs = I == 0 ? Src0s : Src1s;
17675 auto MatchesFirst = [&BPP](DotSrc &IterElt) {
17676 return IterElt.SrcOp == *BPP.first.Src &&
17677 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17678 };
17679
17680 auto *Match = llvm::find_if(Srcs, MatchesFirst);
17681 if (Match != Srcs.end()) {
17682 Match->PermMask = addPermMasks(FirstMask, Match->PermMask);
17683 FirstGroup = I;
17684 break;
17685 }
17686 }
17687 if (FirstGroup != -1) {
17688 SmallVectorImpl<DotSrc> &Srcs = FirstGroup == 1 ? Src0s : Src1s;
17689 auto MatchesSecond = [&BPP](DotSrc &IterElt) {
17690 return IterElt.SrcOp == *BPP.second.Src &&
17691 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17692 };
17693 auto *Match = llvm::find_if(Srcs, MatchesSecond);
17694 if (Match != Srcs.end()) {
17695 Match->PermMask = addPermMasks(SecondMask, Match->PermMask);
17696 } else
17697 Srcs.push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17698 return;
17699 }
17700 }
17701
17702 // If we have made it here, then we could not find a match in Src0s or Src1s
17703 // for either Src0 or Src1, so just place them arbitrarily.
17704
17705 unsigned ZeroMask = 0x0c0c0c0c;
17706 unsigned FMask = 0xFF << (8 * (3 - Step));
17707
17708 Src0s.push_back(
17709 {*Src0.Src,
17710 ((Src0.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17711 Src0.SrcOffset / 4});
17712 Src1s.push_back(
17713 {*Src1.Src,
17714 ((Src1.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17715 Src1.SrcOffset / 4});
17716}
17717
17719 SmallVectorImpl<DotSrc> &Srcs, bool IsSigned,
17720 bool IsAny) {
17721
17722 // If we just have one source, just permute it accordingly.
17723 if (Srcs.size() == 1) {
17724 auto *Elt = Srcs.begin();
17725 auto EltOp = getDWordFromOffset(DAG, SL, Elt->SrcOp, Elt->DWordOffset);
17726
17727 // v_perm will produce the original value
17728 if (Elt->PermMask == 0x3020100)
17729 return EltOp;
17730
17731 return DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17732 DAG.getConstant(Elt->PermMask, SL, MVT::i32));
17733 }
17734
17735 auto *FirstElt = Srcs.begin();
17736 auto *SecondElt = std::next(FirstElt);
17737
17739
17740 // If we have multiple sources in the chain, combine them via perms (using
17741 // calculated perm mask) and Ors.
17742 while (true) {
17743 auto FirstMask = FirstElt->PermMask;
17744 auto SecondMask = SecondElt->PermMask;
17745
17746 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17747 unsigned FirstPlusFour = FirstMask | 0x04040404;
17748 // 0x0c + 0x04 = 0x10, so anding with 0x0F will produced 0x00 for any
17749 // original 0x0C.
17750 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17751
17752 auto PermMask = addPermMasks(FirstMask, SecondMask);
17753 auto FirstVal =
17754 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17755 auto SecondVal =
17756 getDWordFromOffset(DAG, SL, SecondElt->SrcOp, SecondElt->DWordOffset);
17757
17758 Perms.push_back(DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, FirstVal,
17759 SecondVal,
17760 DAG.getConstant(PermMask, SL, MVT::i32)));
17761
17762 FirstElt = std::next(SecondElt);
17763 if (FirstElt == Srcs.end())
17764 break;
17765
17766 SecondElt = std::next(FirstElt);
17767 // If we only have a FirstElt, then just combine that into the cumulative
17768 // source node.
17769 if (SecondElt == Srcs.end()) {
17770 auto EltOp =
17771 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17772
17773 Perms.push_back(
17774 DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17775 DAG.getConstant(FirstElt->PermMask, SL, MVT::i32)));
17776 break;
17777 }
17778 }
17779
17780 assert(Perms.size() == 1 || Perms.size() == 2);
17781 return Perms.size() == 2
17782 ? DAG.getNode(ISD::OR, SL, MVT::i32, Perms[0], Perms[1])
17783 : Perms[0];
17784}
17785
17786static void fixMasks(SmallVectorImpl<DotSrc> &Srcs, unsigned ChainLength) {
17787 for (auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17788 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17789 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17790 EntryMask += ZeroMask;
17791 }
17792}
17793
17794static bool isMul(const SDValue Op) {
17795 auto Opcode = Op.getOpcode();
17796
17797 return (Opcode == ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17798 Opcode == AMDGPUISD::MUL_I24);
17799}
17800
17801static std::optional<bool>
17803 ByteProvider<SDValue> &Src1, const SDValue &S0Op,
17804 const SDValue &S1Op, const SelectionDAG &DAG) {
17805 // If we both ops are i8s (pre legalize-dag), then the signedness semantics
17806 // of the dot4 is irrelevant.
17807 if (S0Op.getValueSizeInBits() == 8 && S1Op.getValueSizeInBits() == 8)
17808 return false;
17809
17810 auto Known0 = DAG.computeKnownBits(S0Op, 0);
17811 bool S0IsUnsigned = Known0.countMinLeadingZeros() > 0;
17812 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17813 auto Known1 = DAG.computeKnownBits(S1Op, 0);
17814 bool S1IsUnsigned = Known1.countMinLeadingZeros() > 0;
17815 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
17816
17817 assert(!(S0IsUnsigned && S0IsSigned));
17818 assert(!(S1IsUnsigned && S1IsSigned));
17819
17820 // There are 9 possible permutations of
17821 // {S0IsUnsigned, S0IsSigned, S1IsUnsigned, S1IsSigned}
17822
17823 // In two permutations, the sign bits are known to be the same for both Ops,
17824 // so simply return Signed / Unsigned corresponding to the MSB
17825
17826 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
17827 return S0IsSigned;
17828
17829 // In another two permutations, the sign bits are known to be opposite. In
17830 // this case return std::nullopt to indicate a bad match.
17831
17832 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
17833 return std::nullopt;
17834
17835 // In the remaining five permutations, we don't know the value of the sign
17836 // bit for at least one Op. Since we have a valid ByteProvider, we know that
17837 // the upper bits must be extension bits. Thus, the only ways for the sign
17838 // bit to be unknown is if it was sign extended from unknown value, or if it
17839 // was any extended. In either case, it is correct to use the signed
17840 // version of the signedness semantics of dot4
17841
17842 // In two of such permutations, we known the sign bit is set for
17843 // one op, and the other is unknown. It is okay to used signed version of
17844 // dot4.
17845 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
17846 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
17847 return true;
17848
17849 // In one such permutation, we don't know either of the sign bits. It is okay
17850 // to used the signed version of dot4.
17851 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
17852 return true;
17853
17854 // In two of such permutations, we known the sign bit is unset for
17855 // one op, and the other is unknown. Return std::nullopt to indicate a
17856 // bad match.
17857 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
17858 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
17859 return std::nullopt;
17860
17861 llvm_unreachable("Fully covered condition");
17862}
17863
17864SDValue SITargetLowering::performAddCombine(SDNode *N,
17865 DAGCombinerInfo &DCI) const {
17866 SelectionDAG &DAG = DCI.DAG;
17867 EVT VT = N->getValueType(0);
17868 SDLoc SL(N);
17869 SDValue LHS = N->getOperand(0);
17870 SDValue RHS = N->getOperand(1);
17871
17872 if (LHS.getOpcode() == ISD::MUL || RHS.getOpcode() == ISD::MUL) {
17873 if (Subtarget->hasMad64_32()) {
17874 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
17875 return Folded;
17876 }
17877 }
17878
17879 if (SDValue V = reassociateScalarOps(N, DAG)) {
17880 return V;
17881 }
17882
17883 if (VT == MVT::i64) {
17884 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
17885 return Folded;
17886 }
17887
17888 // dot4 produces a 32-bit result, so a wider VT can't be folded.
17889 if (!VT.isVector() && VT.getSizeInBits() <= 32 &&
17890 (isMul(LHS) || isMul(RHS)) && Subtarget->hasDot7Insts() &&
17891 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
17892 SDValue TempNode(N, 0);
17893 std::optional<bool> IsSigned;
17897
17898 // Match the v_dot4 tree, while collecting src nodes.
17899 int ChainLength = 0;
17900 for (int I = 0; I < 4; I++) {
17901 auto MulIdx = isMul(LHS) ? 0 : isMul(RHS) ? 1 : -1;
17902 if (MulIdx == -1)
17903 break;
17904 auto Src0 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(0));
17905 if (!Src0)
17906 break;
17907 auto Src1 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(1));
17908 if (!Src1)
17909 break;
17910
17911 auto IterIsSigned = checkDot4MulSignedness(
17912 TempNode->getOperand(MulIdx), *Src0, *Src1,
17913 TempNode->getOperand(MulIdx)->getOperand(0),
17914 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
17915 if (!IterIsSigned)
17916 break;
17917 if (!IsSigned)
17918 IsSigned = *IterIsSigned;
17919 if (*IterIsSigned != *IsSigned)
17920 break;
17921 placeSources(*Src0, *Src1, Src0s, Src1s, I);
17922 auto AddIdx = 1 - MulIdx;
17923 // Allow the special case where add (add (mul24, 0), mul24) became ->
17924 // add (mul24, mul24).
17925 if (I == 2 && isMul(TempNode->getOperand(AddIdx))) {
17926 Src2s.push_back(TempNode->getOperand(AddIdx));
17927 auto Src0 =
17928 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(0));
17929 if (!Src0)
17930 break;
17931 auto Src1 =
17932 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(1));
17933 if (!Src1)
17934 break;
17935 auto IterIsSigned = checkDot4MulSignedness(
17936 TempNode->getOperand(AddIdx), *Src0, *Src1,
17937 TempNode->getOperand(AddIdx)->getOperand(0),
17938 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
17939 if (!IterIsSigned)
17940 break;
17941 assert(IsSigned);
17942 if (*IterIsSigned != *IsSigned)
17943 break;
17944 placeSources(*Src0, *Src1, Src0s, Src1s, I + 1);
17945 Src2s.push_back(DAG.getConstant(0, SL, MVT::i32));
17946 ChainLength = I + 2;
17947 break;
17948 }
17949
17950 TempNode = TempNode->getOperand(AddIdx);
17951 Src2s.push_back(TempNode);
17952 ChainLength = I + 1;
17953 // The loop body treats TempNode's operands as addends.
17954 if (TempNode.getOpcode() != ISD::ADD)
17955 break;
17956 LHS = TempNode->getOperand(0);
17957 RHS = TempNode->getOperand(1);
17958 }
17959
17960 if (ChainLength < 2)
17961 return SDValue();
17962
17963 // Masks were constructed with assumption that we would find a chain of
17964 // length 4. If not, then we need to 0 out the MSB bits (via perm mask of
17965 // 0x0c) so they do not affect dot calculation.
17966 if (ChainLength < 4) {
17967 fixMasks(Src0s, ChainLength);
17968 fixMasks(Src1s, ChainLength);
17969 }
17970
17971 SDValue Src0, Src1;
17972
17973 // If we are just using a single source for both, and have permuted the
17974 // bytes consistently, we can just use the sources without permuting
17975 // (commutation).
17976 bool UseOriginalSrc = false;
17977 if (ChainLength == 4 && Src0s.size() == 1 && Src1s.size() == 1 &&
17978 Src0s.begin()->PermMask == Src1s.begin()->PermMask &&
17979 Src0s.begin()->SrcOp.getValueSizeInBits() >= 32 &&
17980 Src1s.begin()->SrcOp.getValueSizeInBits() >= 32) {
17981 SmallVector<unsigned, 4> SrcBytes;
17982 auto Src0Mask = Src0s.begin()->PermMask;
17983 SrcBytes.push_back(Src0Mask & 0xFF000000);
17984 bool UniqueEntries = true;
17985 for (auto I = 1; I < 4; I++) {
17986 auto NextByte = Src0Mask & (0xFF << ((3 - I) * 8));
17987
17988 if (is_contained(SrcBytes, NextByte)) {
17989 UniqueEntries = false;
17990 break;
17991 }
17992 SrcBytes.push_back(NextByte);
17993 }
17994
17995 if (UniqueEntries) {
17996 UseOriginalSrc = true;
17997
17998 auto *FirstElt = Src0s.begin();
17999 auto FirstEltOp =
18000 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
18001
18002 auto *SecondElt = Src1s.begin();
18003 auto SecondEltOp = getDWordFromOffset(DAG, SL, SecondElt->SrcOp,
18004 SecondElt->DWordOffset);
18005
18006 Src0 = DAG.getBitcastedAnyExtOrTrunc(FirstEltOp, SL,
18007 MVT::getIntegerVT(32));
18008 Src1 = DAG.getBitcastedAnyExtOrTrunc(SecondEltOp, SL,
18009 MVT::getIntegerVT(32));
18010 }
18011 }
18012
18013 if (!UseOriginalSrc) {
18014 Src0 = resolveSources(DAG, SL, Src0s, false, true);
18015 Src1 = resolveSources(DAG, SL, Src1s, false, true);
18016 }
18017
18018 assert(IsSigned);
18019 SDValue Src2 =
18020 DAG.getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
18021
18022 SDValue IID = DAG.getTargetConstant(*IsSigned ? Intrinsic::amdgcn_sdot4
18023 : Intrinsic::amdgcn_udot4,
18024 SL, MVT::i64);
18025
18026 assert(!VT.isVector());
18027 auto Dot = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32, IID, Src0,
18028 Src1, Src2, DAG.getTargetConstant(0, SL, MVT::i1));
18029
18030 return DAG.getExtOrTrunc(*IsSigned, Dot, SL, VT);
18031 }
18032
18033 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
18034 return SDValue();
18035
18036 // add x, zext (setcc) => uaddo_carry x, 0, setcc
18037 // add x, sext (setcc) => usubo_carry x, 0, setcc
18038 unsigned Opc = LHS.getOpcode();
18041 std::swap(RHS, LHS);
18042
18043 Opc = RHS.getOpcode();
18044 switch (Opc) {
18045 default:
18046 break;
18047 case ISD::ZERO_EXTEND:
18048 case ISD::SIGN_EXTEND:
18049 case ISD::ANY_EXTEND: {
18050 auto Cond = RHS.getOperand(0);
18051 // If this won't be a real VOPC output, we would still need to insert an
18052 // extra instruction anyway.
18053 if (!isBoolSGPR(Cond))
18054 break;
18055 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
18056 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
18058 return DAG.getNode(Opc, SL, VTList, Args);
18059 }
18060 case ISD::UADDO_CARRY: {
18061 // add x, (uaddo_carry y, 0, cc) => uaddo_carry x, y, cc
18062 if (!isNullConstant(RHS.getOperand(1)))
18063 break;
18064 SDValue Args[] = {LHS, RHS.getOperand(0), RHS.getOperand(2)};
18065 return DAG.getNode(ISD::UADDO_CARRY, SDLoc(N), RHS->getVTList(), Args);
18066 }
18067 }
18068 return SDValue();
18069}
18070
18071SDValue SITargetLowering::performPtrAddCombine(SDNode *N,
18072 DAGCombinerInfo &DCI) const {
18073 SelectionDAG &DAG = DCI.DAG;
18074 SDLoc DL(N);
18075 EVT VT = N->getValueType(0);
18076 SDValue N0 = N->getOperand(0);
18077 SDValue N1 = N->getOperand(1);
18078
18079 // The following folds transform PTRADDs into regular arithmetic in cases
18080 // where the PTRADD wouldn't be folded as an immediate offset into memory
18081 // instructions anyway. They are target-specific in that other targets might
18082 // prefer to not lose information about the pointer arithmetic.
18083
18084 // Fold (ptradd x, shl(0 - v, k)) -> sub(x, shl(v, k)).
18085 // Adapted from DAGCombiner::visitADDLikeCommutative.
18086 SDValue V, K;
18087 if (sd_match(N1, m_Shl(m_Neg(m_Value(V)), m_Value(K)))) {
18088 SDNodeFlags ShlFlags = N1->getFlags();
18089 // If the original shl is NUW and NSW, the first k+1 bits of 0-v are all 0,
18090 // so v is either 0 or the first k+1 bits of v are all 1 -> NSW can be
18091 // preserved.
18092 SDNodeFlags NewShlFlags =
18093 ShlFlags.hasNoUnsignedWrap() && ShlFlags.hasNoSignedWrap()
18095 : SDNodeFlags();
18096 SDValue Inner = DAG.getNode(ISD::SHL, DL, VT, V, K, NewShlFlags);
18097 DCI.AddToWorklist(Inner.getNode());
18098 return DAG.getNode(ISD::SUB, DL, VT, N0, Inner);
18099 }
18100
18101 // Fold into Mad64 if the right-hand side is a MUL. Analogous to a fold in
18102 // performAddCombine.
18103 if (N1.getOpcode() == ISD::MUL) {
18104 if (Subtarget->hasMad64_32()) {
18105 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
18106 return Folded;
18107 }
18108 }
18109
18110 // If the 32 low bits of the constant are all zero, there is nothing to fold
18111 // into an immediate offset, so it's better to eliminate the unnecessary
18112 // addition for the lower 32 bits than to preserve the PTRADD.
18113 // Analogous to a fold in performAddCombine.
18114 if (VT == MVT::i64) {
18115 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18116 return Folded;
18117 }
18118
18119 if (N1.getOpcode() != ISD::ADD || !N1.hasOneUse())
18120 return SDValue();
18121
18122 SDValue X = N0;
18123 SDValue Y = N1.getOperand(0);
18124 SDValue Z = N1.getOperand(1);
18125 bool YIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Y);
18126 bool ZIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Z);
18127
18128 if (!YIsConstant && !ZIsConstant && !X->isDivergent() &&
18129 Y->isDivergent() != Z->isDivergent()) {
18130 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, y), z) if x and
18131 // y are uniform and z isn't.
18132 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, z), y) if x and
18133 // z are uniform and y isn't.
18134 // The goal is to push uniform operands up in the computation, so that they
18135 // can be handled with scalar operations. We can't use reassociateScalarOps
18136 // for this since it requires two identical commutative operations to
18137 // reassociate.
18138 if (Y->isDivergent())
18139 std::swap(Y, Z);
18140 // If both additions in the original were NUW, reassociation preserves that.
18141 SDNodeFlags ReassocFlags =
18142 (N->getFlags() & N1->getFlags()) & SDNodeFlags::NoUnsignedWrap;
18143 SDValue UniformInner = DAG.getMemBasePlusOffset(X, Y, DL, ReassocFlags);
18144 DCI.AddToWorklist(UniformInner.getNode());
18145 return DAG.getMemBasePlusOffset(UniformInner, Z, DL, ReassocFlags);
18146 }
18147
18148 return SDValue();
18149}
18150
18151static bool isCtlzOpc(unsigned Opc) {
18152 return Opc == ISD::CTLZ || Opc == ISD::CTLZ_ZERO_POISON;
18153}
18154
18155SDValue SITargetLowering::performSubCombine(SDNode *N,
18156 DAGCombinerInfo &DCI) const {
18157 SelectionDAG &DAG = DCI.DAG;
18158 EVT VT = N->getValueType(0);
18159
18160 if (VT == MVT::i64) {
18161 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18162 return Folded;
18163 }
18164
18165 if (VT != MVT::i32)
18166 return SDValue();
18167
18168 SDLoc SL(N);
18169 SDValue LHS = N->getOperand(0);
18170 SDValue RHS = N->getOperand(1);
18171
18172 // sub x, zext (setcc) => usubo_carry x, 0, setcc
18173 // sub x, sext (setcc) => uaddo_carry x, 0, setcc
18174 unsigned Opc = RHS.getOpcode();
18175 switch (Opc) {
18176 default:
18177 break;
18178 case ISD::ZERO_EXTEND:
18179 case ISD::SIGN_EXTEND:
18180 case ISD::ANY_EXTEND: {
18181 auto Cond = RHS.getOperand(0);
18182 // If this won't be a real VOPC output, we would still need to insert an
18183 // extra instruction anyway.
18184 if (!isBoolSGPR(Cond))
18185 break;
18186 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
18187 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
18189 return DAG.getNode(Opc, SL, VTList, Args);
18190 }
18191 }
18192
18193 if (LHS.getOpcode() == ISD::USUBO_CARRY) {
18194 // sub (usubo_carry x, 0, cc), y => usubo_carry x, y, cc
18195 if (!isNullConstant(LHS.getOperand(1)))
18196 return SDValue();
18197 SDValue Args[] = {LHS.getOperand(0), RHS, LHS.getOperand(2)};
18198 return DAG.getNode(ISD::USUBO_CARRY, SDLoc(N), LHS->getVTList(), Args);
18199 }
18200
18201 // sub (ctlz (xor x, (sra x, 31))), 1 -> ctls x.
18202 if (isOneConstant(RHS) && isCtlzOpc(LHS.getOpcode())) {
18203 SDValue CtlzSrc = LHS.getOperand(0);
18204 // Check for xor x, (sra x, 31) pattern.
18205 if (CtlzSrc.getOpcode() == ISD::XOR) {
18206 SDValue X = CtlzSrc.getOperand(0);
18207 SDValue SignExt = CtlzSrc.getOperand(1);
18208 // Try both ordering of XOR operands.
18209 if (SignExt.getOpcode() != ISD::SRA)
18210 std::swap(X, SignExt);
18211 if (SignExt.getOpcode() == ISD::SRA && SignExt.getOperand(0) == X) {
18212 ConstantSDNode *ShiftAmt =
18214 unsigned BitWidth = X.getValueType().getScalarSizeInBits();
18215 if (ShiftAmt && ShiftAmt->getZExtValue() == BitWidth - 1)
18216 return DAG.getNode(ISD::CTLS, SL, VT, X);
18217 }
18218 }
18219 }
18220
18221 return SDValue();
18222}
18223
18224SDValue SITargetLowering::performFAddCombine(SDNode *N,
18225 DAGCombinerInfo &DCI) const {
18226 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18227 return SDValue();
18228
18229 SelectionDAG &DAG = DCI.DAG;
18230 EVT VT = N->getValueType(0);
18231
18232 SDLoc SL(N);
18233 SDValue LHS = N->getOperand(0);
18234 SDValue RHS = N->getOperand(1);
18235
18236 // These should really be instruction patterns, but writing patterns with
18237 // source modifiers is a pain.
18238
18239 // fadd (fadd (a, a), b) -> mad 2.0, a, b
18240 if (LHS.getOpcode() == ISD::FADD) {
18241 SDValue A = LHS.getOperand(0);
18242 if (A == LHS.getOperand(1)) {
18243 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18244 if (FusedOp != 0) {
18245 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18246 return DAG.getNode(FusedOp, SL, VT, A, Two, RHS);
18247 }
18248 }
18249 }
18250
18251 // fadd (b, fadd (a, a)) -> mad 2.0, a, b
18252 if (RHS.getOpcode() == ISD::FADD) {
18253 SDValue A = RHS.getOperand(0);
18254 if (A == RHS.getOperand(1)) {
18255 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18256 if (FusedOp != 0) {
18257 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18258 return DAG.getNode(FusedOp, SL, VT, A, Two, LHS);
18259 }
18260 }
18261 }
18262
18263 return SDValue();
18264}
18265
18266SDValue SITargetLowering::performFSubCombine(SDNode *N,
18267 DAGCombinerInfo &DCI) const {
18268 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18269 return SDValue();
18270
18271 SelectionDAG &DAG = DCI.DAG;
18272 SDLoc SL(N);
18273 EVT VT = N->getValueType(0);
18274 assert(!VT.isVector());
18275
18276 // Try to get the fneg to fold into the source modifier. This undoes generic
18277 // DAG combines and folds them into the mad.
18278 //
18279 // Only do this if we are not trying to support denormals. v_mad_f32 does
18280 // not support denormals ever.
18281 SDValue LHS = N->getOperand(0);
18282 SDValue RHS = N->getOperand(1);
18283 if (LHS.getOpcode() == ISD::FADD) {
18284 // (fsub (fadd a, a), c) -> mad 2.0, a, (fneg c)
18285 SDValue A = LHS.getOperand(0);
18286 if (A == LHS.getOperand(1)) {
18287 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18288 if (FusedOp != 0) {
18289 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18290 SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
18291
18292 return DAG.getNode(FusedOp, SL, VT, A, Two, NegRHS);
18293 }
18294 }
18295 }
18296
18297 if (RHS.getOpcode() == ISD::FADD) {
18298 // (fsub c, (fadd a, a)) -> mad -2.0, a, c
18299
18300 SDValue A = RHS.getOperand(0);
18301 if (A == RHS.getOperand(1)) {
18302 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18303 if (FusedOp != 0) {
18304 const SDValue NegTwo = DAG.getConstantFP(-2.0, SL, VT);
18305 return DAG.getNode(FusedOp, SL, VT, A, NegTwo, LHS);
18306 }
18307 }
18308 }
18309
18310 return SDValue();
18311}
18312
18313SDValue SITargetLowering::performFDivCombine(SDNode *N,
18314 DAGCombinerInfo &DCI) const {
18315 SelectionDAG &DAG = DCI.DAG;
18316 SDLoc SL(N);
18317 EVT VT = N->getValueType(0);
18318
18319 if (VT != MVT::f16 && VT != MVT::bf16)
18320 return SDValue();
18321
18322 SDValue LHS = N->getOperand(0);
18323 SDValue RHS = N->getOperand(1);
18324
18325 SDNodeFlags Flags = N->getFlags();
18326 SDNodeFlags RHSFlags = RHS->getFlags();
18327 if (!Flags.hasAllowContract() || !RHSFlags.hasAllowContract() ||
18328 !RHS->hasOneUse())
18329 return SDValue();
18330
18331 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
18332 bool IsNegative = false;
18333 if (CLHS->isOne() || (IsNegative = CLHS->isMinusOne())) {
18334 // fdiv contract 1.0, (sqrt contract x) -> rsq
18335 // fdiv contract -1.0, (sqrt contract x) -> fneg(rsq)
18336 if (RHS.getOpcode() == ISD::FSQRT) {
18337 // TODO: Or in RHS flags, somehow missing from SDNodeFlags
18338 SDValue SqrtOp = RHS.getOperand(0);
18339 SDValue Rsq;
18340 if (isOperationLegal(ISD::FSQRT, VT)) {
18341 // fsqrt legality correlates to rsq availability of the same type.
18342 Rsq = DAG.getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18343 } else if (VT == MVT::f16) {
18344 // Targets without 16-bit instructions (gfx6/gfx7) have no f16 rsq,
18345 // but v_rsq_f32 is more than accurate enough for f16. Unlike bf16,
18346 // every f16 value (including denormals) extends to a normal f32, and
18347 // an f16 rsq result is never denormal, so the f32 reciprocal square
18348 // root needs no denormal handling. Compute it in f32 and round back.
18349 SDValue Ext =
18350 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, SqrtOp, Flags);
18351 SDValue F32Rsq =
18352 DAG.getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18353 Rsq = DAG.getNode(ISD::FP_ROUND, SL, VT, F32Rsq,
18354 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
18355 } else {
18356 // bf16 shares f32's exponent range, so bf16 denormals would extend to
18357 // f32 denormals that v_rsq_f32 does not handle. Leave it expanded.
18358 return SDValue();
18359 }
18360 return IsNegative ? DAG.getNode(ISD::FNEG, SL, VT, Rsq, Flags) : Rsq;
18361 }
18362 }
18363 }
18364
18365 return SDValue();
18366}
18367
18368SDValue SITargetLowering::performFMulCombine(SDNode *N,
18369 DAGCombinerInfo &DCI) const {
18370 SelectionDAG &DAG = DCI.DAG;
18371 EVT VT = N->getValueType(0);
18372 EVT ScalarVT = VT.getScalarType();
18373 EVT IntVT = VT.changeElementType(*DAG.getContext(), MVT::i32);
18374
18375 if (!N->isDivergent() && getSubtarget()->hasSALUFloatInsts() &&
18376 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18377 // Prefer to use s_mul_f16/f32 instead of v_ldexp_f16/f32.
18378 return SDValue();
18379 }
18380
18381 SDValue LHS = N->getOperand(0);
18382 SDValue RHS = N->getOperand(1);
18383
18384 // It is cheaper to realize i32 inline constants as compared against
18385 // materializing f16 or f64 (or even non-inline f32) values,
18386 // possible via ldexp usage, as shown below :
18387 //
18388 // Given : A = 2^a & B = 2^b ; where a and b are integers.
18389 // fmul x, (select y, A, B) -> ldexp( x, (select i32 y, a, b) )
18390 // fmul x, (select y, -A, -B) -> ldexp( (fneg x), (select i32 y, a, b) )
18391 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18392 (RHS.hasOneUse() && RHS.getOpcode() == ISD::SELECT)) {
18393 const ConstantFPSDNode *TrueNode = isConstOrConstSplatFP(RHS.getOperand(1));
18394 if (!TrueNode)
18395 return SDValue();
18396 const ConstantFPSDNode *FalseNode =
18397 isConstOrConstSplatFP(RHS.getOperand(2));
18398 if (!FalseNode)
18399 return SDValue();
18400
18401 if (TrueNode->isNegative() != FalseNode->isNegative())
18402 return SDValue();
18403
18404 // For f32, only non-inline constants should be transformed.
18405 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
18406 if (ScalarVT == MVT::f32 &&
18407 TII->isInlineConstant(TrueNode->getValueAPF()) &&
18408 TII->isInlineConstant(FalseNode->getValueAPF()))
18409 return SDValue();
18410
18411 int TrueNodeExpVal = TrueNode->getValueAPF().getExactLog2Abs();
18412 if (TrueNodeExpVal == INT_MIN)
18413 return SDValue();
18414 int FalseNodeExpVal = FalseNode->getValueAPF().getExactLog2Abs();
18415 if (FalseNodeExpVal == INT_MIN)
18416 return SDValue();
18417
18418 SDLoc SL(N);
18419 SDValue SelectNode =
18420 DAG.getNode(ISD::SELECT, SL, IntVT, RHS.getOperand(0),
18421 DAG.getSignedConstant(TrueNodeExpVal, SL, IntVT),
18422 DAG.getSignedConstant(FalseNodeExpVal, SL, IntVT));
18423
18424 LHS = TrueNode->isNegative()
18425 ? DAG.getNode(ISD::FNEG, SL, VT, LHS, LHS->getFlags())
18426 : LHS;
18427
18428 return DAG.getNode(ISD::FLDEXP, SL, VT, LHS, SelectNode, N->getFlags());
18429 }
18430
18431 return SDValue();
18432}
18433
18434SDValue SITargetLowering::performFMACombine(SDNode *N,
18435 DAGCombinerInfo &DCI) const {
18436 SelectionDAG &DAG = DCI.DAG;
18437 EVT VT = N->getValueType(0);
18438 SDLoc SL(N);
18439
18440 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18441 return SDValue();
18442
18443 // FMA((F32)S0.x, (F32)S1. x, FMA((F32)S0.y, (F32)S1.y, (F32)z)) ->
18444 // FDOT2((V2F16)S0, (V2F16)S1, (F32)z))
18445 SDValue Op1 = N->getOperand(0);
18446 SDValue Op2 = N->getOperand(1);
18447 SDValue FMA = N->getOperand(2);
18448
18449 if (FMA.getOpcode() != ISD::FMA || Op1.getOpcode() != ISD::FP_EXTEND ||
18450 Op2.getOpcode() != ISD::FP_EXTEND)
18451 return SDValue();
18452
18453 // The fdot2 fold (fma_mix -> dot2) is only safe when both instructions agree
18454 // on how f16 subnormal inputs are handled. However, if both FMAs carry afn
18455 // the caller accepts approximate results, so any subnormal flushing
18456 // introduced by dot2 is acceptable regardless of mode.
18457 //
18458 // gfx90a (CDNA2) is the sole exception (dot2UnconditionalFlush): v_dot2c
18459 // unconditionally flushes f16 subnormal inputs to zero regardless of MODE,
18460 // while v_fma_mix_f32 preserves them when ieee=1 (the default compute kernel
18461 // mode). The fold is safe only when f32 denorm = PreserveSign, which implies
18462 // ieee=0 so both flush.
18463 //
18464 // All other GPUs: v_dot2 does NOT flush f16 subnormal inputs. v_fma_mix_f32
18465 // flushes them only when f32 denorm = PreserveSign. The fold is safe only
18466 // when f32 denorm is IEEE (both preserve the subnormal). Dynamic mode is
18467 // also rejected since the runtime value is unknown.
18468 bool AllowInaccuracy = N->getFlags().hasApproximateFuncs() &&
18469 FMA->getFlags().hasApproximateFuncs();
18470 if (!AllowInaccuracy) {
18471 const MachineFunction &MF = DAG.getMachineFunction();
18472 DenormalMode Mode = MF.getDenormalMode(APFloat::IEEEsingle());
18473 if (Subtarget->dot2UnconditionalFlush()) {
18474 // gfx90a: fold safe only when f32 denorm flushes.
18476 return SDValue();
18477 } else {
18478 // All other GPUs: fold safe only when f32 denorm is IEEE.
18479 if (Mode != DenormalMode::getIEEE())
18480 return SDValue();
18481 }
18482 }
18483
18484 // fp-contract allows reassociating the fma tree into a dot product.
18485 if (N->getFlags().hasAllowContract() && FMA->getFlags().hasAllowContract()) {
18486 Op1 = Op1.getOperand(0);
18487 Op2 = Op2.getOperand(0);
18488 if (Op1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18490 return SDValue();
18491
18492 SDValue Vec1 = Op1.getOperand(0);
18493 SDValue Idx1 = Op1.getOperand(1);
18494 SDValue Vec2 = Op2.getOperand(0);
18495
18496 SDValue FMAOp1 = FMA.getOperand(0);
18497 SDValue FMAOp2 = FMA.getOperand(1);
18498 SDValue FMAAcc = FMA.getOperand(2);
18499
18500 if (FMAOp1.getOpcode() != ISD::FP_EXTEND ||
18501 FMAOp2.getOpcode() != ISD::FP_EXTEND)
18502 return SDValue();
18503
18504 FMAOp1 = FMAOp1.getOperand(0);
18505 FMAOp2 = FMAOp2.getOperand(0);
18506 if (FMAOp1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18508 return SDValue();
18509
18510 SDValue Vec3 = FMAOp1.getOperand(0);
18511 SDValue Vec4 = FMAOp2.getOperand(0);
18512 SDValue Idx2 = FMAOp1.getOperand(1);
18513
18514 if (Idx1 != Op2.getOperand(1) || Idx2 != FMAOp2.getOperand(1))
18515 return SDValue();
18516
18517 if (!isa<ConstantSDNode>(Idx1) || !isa<ConstantSDNode>(Idx2) ||
18518 Idx1 == Idx2)
18519 return SDValue();
18520
18521 if (Vec1 == Vec2 || Vec3 == Vec4)
18522 return SDValue();
18523
18524 if (Vec1.getValueType() != MVT::v2f16 || Vec2.getValueType() != MVT::v2f16)
18525 return SDValue();
18526
18527 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18528 return DAG.getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18529 DAG.getTargetConstant(0, SL, MVT::i1));
18530 }
18531 }
18532 return SDValue();
18533}
18534
18535// Given a double-precision ordered or unordered comparison, return the
18536// condition code for an equivalent integral comparison of the operands' upper
18537// 32 bits, or `SETCC_INVALID` if not possible.
18538// For simplicity, no simplification occurs if the operands are not both known
18539// to have sign bit zero.
18540//
18541// EQ/NE:
18542// If LHS.lo32 == RHS.lo32:
18543// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18544// If LHS.lo32 != RHS.lo32:
18545// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18546// The reduction is not possible if operands may be +0 and -0.
18547// For ordered eq / unordered ne, at most one operand may be NaN.
18548// For unordered eq / ordered ne, neither operand can be NaN.
18549//
18550// LT/GE:
18551// If LHS.lo32 >= RHS.lo32 (unsigned):
18552// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18553// If LHS.lo32 < RHS.lo32 (unsigned):
18554// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18555// The reduction is only supported if both operands are nonnegative.
18556// For ordered lt / unordered ge, the RHS cannot be NaN.
18557// For unordered lt / ordered ge, neither operand can be NaN.
18558//
18559// LE/GT:
18560// If LHS.lo32 > RHS.lo32 (unsigned):
18561// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18562// If LHS.lo32 <= RHS.lo32 (unsigned):
18563// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18564// The reduction is only supported if both operands are nonnegative.
18565// For unordered le / ordered gt, the LHS cannot be NaN.
18566// For ordered le / unordered gt, neither operand can be NaN.
18568 const SDValue LHS,
18569 const SDValue RHS,
18570 const SelectionDAG &DAG) {
18571 EVT VT = LHS.getValueType();
18572 assert(VT == MVT::f64 && "Incorrect operand type!");
18573
18574 const KnownBits RHSBits = DAG.computeKnownBits(RHS);
18575 // Bail if RHS sign bit is not known to be zero.
18576 if (!RHSBits.Zero.isSignBitSet())
18577 return ISD::SETCC_INVALID;
18578
18579 const KnownBits RHSKnownLo32 = RHSBits.trunc(32);
18580 const KnownFPClass RHSFPClass =
18582 const bool RHSMaybeNaN = !RHSFPClass.isKnownNeverNaN();
18583
18584 const KnownBits LHSBits = DAG.computeKnownBits(LHS);
18585 const KnownBits LHSKnownLo32 = LHSBits.trunc(32);
18586 const KnownFPClass LHSFPClass =
18588 const bool LHSMaybeNaN = !LHSFPClass.isKnownNeverNaN();
18589
18590 // Bail if LHS sign bit is not known to be zero.
18591 if (!LHSBits.Zero.isSignBitSet())
18592 return ISD::SETCC_INVALID;
18593
18594 switch (CC) {
18595 default:
18596 break;
18597 case ISD::SETEQ:
18598 case ISD::SETOEQ:
18599 case ISD::SETUEQ:
18600 case ISD::SETONE:
18601 case ISD::SETUNE: {
18602 // OEQ should be false if either operand is NaN, so it suffices that at
18603 // least one operand is not NaN.
18604 if (CC == ISD::SETOEQ && LHSMaybeNaN && RHSMaybeNaN)
18605 break;
18606 // UEQ should be true if either operand is NaN, but this cannot be checked
18607 // on underlying bits.
18608 if (CC == ISD::SETUEQ && (LHSMaybeNaN || RHSMaybeNaN))
18609 break;
18610 // ONE should be false if either operand is NaN, but this cannot be
18611 // checked on underlying bits.
18612 if (CC == ISD::SETONE && (LHSMaybeNaN || RHSMaybeNaN))
18613 break;
18614 // UNE should be true if either operand is NaN, so it suffices that they
18615 // are not both NaN.
18616 if (CC == ISD::SETUNE && LHSMaybeNaN && RHSMaybeNaN)
18617 break;
18618
18619 const std::optional<bool> KnownEq =
18620 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18621
18622 if (!KnownEq)
18623 break;
18624
18625 if (*KnownEq)
18626 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18627 ? ISD::SETEQ
18628 : ISD::SETNE;
18629
18630 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18632 : ISD::SETTRUE;
18633 }
18634 case ISD::SETLT:
18635 case ISD::SETOLT:
18636 case ISD::SETULT:
18637 case ISD::SETGE:
18638 case ISD::SETOGE:
18639 case ISD::SETUGE: {
18640 // OLT should be false if either operand is NaN.
18641 // Since NaNs have maximum exponent and nonzero mantissa, false positives
18642 // are only possible if the RHS is NaN. (No issue with RHS == +inf since
18643 // the inequality is strict)
18644 if (CC == ISD::SETOLT && RHSMaybeNaN)
18645 break;
18646 // ULT should be true if either operand is NaN, but this cannot be ensured
18647 // with a truncated comparison.
18648 if (CC == ISD::SETULT && (LHSMaybeNaN || RHSMaybeNaN))
18649 break;
18650 // OGE should be false if either operand is NaN, but this cannot be
18651 // ensured with a truncated comparison.
18652 if (CC == ISD::SETOGE && (LHSMaybeNaN || RHSMaybeNaN))
18653 break;
18654 // UGE should be true if either operand is NaN.
18655 // False negatives are only possible if the RHS is NaN.
18656 // (No issue with RHS == +inf since the inequality is inclusive)
18657 if (CC == ISD::SETUGE && RHSMaybeNaN)
18658 break;
18659
18660 const std::optional<bool> KnownUge =
18661 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
18662
18663 if (!KnownUge)
18664 break;
18665
18666 if (*KnownUge) {
18667 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
18668 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18669 ? ISD::SETLT
18670 : ISD::SETGE;
18671 }
18672 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
18673 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18674 ? ISD::SETLE
18675 : ISD::SETGT;
18676 }
18677 case ISD::SETLE:
18678 case ISD::SETOLE:
18679 case ISD::SETULE:
18680 case ISD::SETGT:
18681 case ISD::SETOGT:
18682 case ISD::SETUGT: {
18683 // OLE should be false if either operand is NaN, but this cannot be
18684 // ensured with a truncated comparison.
18685 if (CC == ISD::SETOLE && (LHSMaybeNaN || RHSMaybeNaN))
18686 break;
18687 // ULE should be true if either operand is NaN.
18688 // False negatives are only possible if the LHS is NaN.
18689 // (No issue with LHS == +inf since the inequality is inclusive)
18690 if (CC == ISD::SETULE && LHSMaybeNaN)
18691 break;
18692 // OGT should be false if either operand is NaN.
18693 // False positives are only possible if the LHS is NaN.
18694 // (No issue with LHS == +inf since the inequality is strict)
18695 if (CC == ISD::SETOGT && LHSMaybeNaN)
18696 break;
18697 // UGT should be true if either operand is NaN, but this cannot be ensured
18698 // with a truncated comparison.
18699 if (CC == ISD::SETUGT && (LHSMaybeNaN || RHSMaybeNaN))
18700 break;
18701
18702 const std::optional<bool> KnownUle =
18703 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
18704
18705 if (!KnownUle)
18706 break;
18707
18708 if (*KnownUle) {
18709 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
18710 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18711 ? ISD::SETLE
18712 : ISD::SETGT;
18713 }
18714 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
18715 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18716 ? ISD::SETLT
18717 : ISD::SETGE;
18718 }
18719 }
18720
18721 return ISD::SETCC_INVALID;
18722}
18723
18724SDValue SITargetLowering::performSetCCCombine(SDNode *N,
18725 DAGCombinerInfo &DCI) const {
18726 SelectionDAG &DAG = DCI.DAG;
18727 SDLoc SL(N);
18728
18729 SDValue LHS = N->getOperand(0);
18730 SDValue RHS = N->getOperand(1);
18731 EVT VT = LHS.getValueType();
18732 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
18733
18734 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
18735 if (!CRHS) {
18737 if (CRHS) {
18738 std::swap(LHS, RHS);
18739 CC = getSetCCSwappedOperands(CC);
18740 }
18741 }
18742
18743 if (CRHS) {
18744 if (VT == MVT::i32 && LHS.getOpcode() == ISD::SIGN_EXTEND &&
18745 isBoolSGPR(LHS.getOperand(0))) {
18746 // setcc (sext from i1 cc), -1, ne|sgt|ult) => not cc => xor cc, -1
18747 // setcc (sext from i1 cc), -1, eq|sle|uge) => cc
18748 // setcc (sext from i1 cc), 0, eq|sge|ule) => not cc => xor cc, -1
18749 // setcc (sext from i1 cc), 0, ne|ugt|slt) => cc
18750 if ((CRHS->isAllOnes() &&
18751 (CC == ISD::SETNE || CC == ISD::SETGT || CC == ISD::SETULT)) ||
18752 (CRHS->isZero() &&
18753 (CC == ISD::SETEQ || CC == ISD::SETGE || CC == ISD::SETULE)))
18754 return DAG.getNode(ISD::XOR, SL, MVT::i1, LHS.getOperand(0),
18755 DAG.getAllOnesConstant(SL, MVT::i1));
18756 if ((CRHS->isAllOnes() &&
18757 (CC == ISD::SETEQ || CC == ISD::SETLE || CC == ISD::SETUGE)) ||
18758 (CRHS->isZero() &&
18759 (CC == ISD::SETNE || CC == ISD::SETUGT || CC == ISD::SETLT)))
18760 return LHS.getOperand(0);
18761 }
18762
18763 const APInt &CRHSVal = CRHS->getAPIntValue();
18764 if ((CC == ISD::SETEQ || CC == ISD::SETNE) &&
18765 LHS.getOpcode() == ISD::SELECT &&
18766 isa<ConstantSDNode>(LHS.getOperand(1)) &&
18767 isa<ConstantSDNode>(LHS.getOperand(2)) &&
18768 isBoolSGPR(LHS.getOperand(0))) {
18769 // Given CT != FT:
18770 // setcc (select cc, CT, CF), CF, eq => xor cc, -1
18771 // setcc (select cc, CT, CF), CF, ne => cc
18772 // setcc (select cc, CT, CF), CT, ne => xor cc, -1
18773 // setcc (select cc, CT, CF), CT, eq => cc
18774 const APInt &CT = LHS.getConstantOperandAPInt(1);
18775 const APInt &CF = LHS.getConstantOperandAPInt(2);
18776
18777 if (CT != CF) {
18778 if ((CF == CRHSVal && CC == ISD::SETEQ) ||
18779 (CT == CRHSVal && CC == ISD::SETNE))
18780 return DAG.getNOT(SL, LHS.getOperand(0), MVT::i1);
18781 if ((CF == CRHSVal && CC == ISD::SETNE) ||
18782 (CT == CRHSVal && CC == ISD::SETEQ))
18783 return LHS.getOperand(0);
18784 }
18785 }
18786 }
18787
18788 // Truncate 64-bit setcc to test only upper 32-bits of its operands in the
18789 // following cases where information about the lower 32-bits of its operands
18790 // is known:
18791 //
18792 // If LHS.lo32 == RHS.lo32:
18793 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18794 // If LHS.lo32 != RHS.lo32:
18795 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18796 // If LHS.lo32 >= RHS.lo32 (unsigned):
18797 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18798 // If LHS.lo32 > RHS.lo32 (unsigned):
18799 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18800 // If LHS.lo32 <= RHS.lo32 (unsigned):
18801 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18802 // If LHS.lo32 < RHS.lo32 (unsigned):
18803 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18804 if (VT == MVT::i64) {
18805 const KnownBits LHSKnownLo32 = DAG.computeKnownBits(LHS).trunc(32);
18806 const KnownBits RHSKnownLo32 = DAG.computeKnownBits(RHS).trunc(32);
18807
18808 // NewCC is valid iff we can truncate the setcc to only test the upper 32
18809 // bits
18811
18812 switch (CC) {
18813 default:
18814 break;
18815 case ISD::SETEQ: {
18816 const std::optional<bool> KnownEq =
18817 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18818 if (KnownEq)
18819 NewCC = *KnownEq ? ISD::SETEQ : ISD::SETFALSE;
18820
18821 break;
18822 }
18823 case ISD::SETNE: {
18824 const std::optional<bool> KnownEq =
18825 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18826 if (KnownEq)
18827 NewCC = *KnownEq ? ISD::SETNE : ISD::SETTRUE;
18828
18829 break;
18830 }
18831 case ISD::SETULT:
18832 case ISD::SETUGE:
18833 case ISD::SETLT:
18834 case ISD::SETGE: {
18835 const std::optional<bool> KnownUge =
18836 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
18837 if (KnownUge) {
18838 if (*KnownUge) {
18839 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
18840 NewCC = CC;
18841 } else {
18842 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
18843 NewCC = CC == ISD::SETULT ? ISD::SETULE
18844 : CC == ISD::SETUGE ? ISD::SETUGT
18845 : CC == ISD::SETLT ? ISD::SETLE
18846 : ISD::SETGT;
18847 }
18848 }
18849 break;
18850 }
18851 case ISD::SETULE:
18852 case ISD::SETUGT:
18853 case ISD::SETLE:
18854 case ISD::SETGT: {
18855 const std::optional<bool> KnownUle =
18856 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
18857 if (KnownUle) {
18858 if (*KnownUle) {
18859 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
18860 NewCC = CC;
18861 } else {
18862 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
18863 NewCC = CC == ISD::SETULE ? ISD::SETULT
18864 : CC == ISD::SETUGT ? ISD::SETUGE
18865 : CC == ISD::SETLE ? ISD::SETLT
18866 : ISD::SETGE;
18867 }
18868 }
18869 break;
18870 }
18871 }
18872
18873 if (NewCC != ISD::SETCC_INVALID)
18874 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
18875 getHiHalf64(RHS, DAG), NewCC);
18876 }
18877
18878 // Eliminate setcc by using carryout from add/sub instruction
18879
18880 // LHS = ADD i64 RHS, Z LHSlo = UADDO i32 RHSlo, Zlo
18881 // setcc LHS ult RHS -> LHSHi = UADDO_CARRY i32 RHShi, Zhi
18882 // similarly for subtraction
18883
18884 // LHS = ADD i64 Y, 1 LHSlo = UADDO i32 Ylo, 1
18885 // setcc LHS eq 0 -> LHSHi = UADDO_CARRY i32 Yhi, 0
18886
18887 if (VT == MVT::i64 && ((CC == ISD::SETULT &&
18889 (CC == ISD::SETUGT &&
18891 (CC == ISD::SETEQ && CRHS && CRHS->isZero() &&
18892 sd_match(LHS, m_Add(m_Value(), m_One()))))) {
18893 bool IsAdd = LHS.getOpcode() == ISD::ADD;
18894
18895 SDValue Op0 = LHS.getOperand(0);
18896 SDValue Op1 = LHS.getOperand(1);
18897
18898 SDValue Op0Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op0);
18899 SDValue Op1Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op1);
18900
18901 SDValue Op0Hi = getHiHalf64(Op0, DAG);
18902 SDValue Op1Hi = getHiHalf64(Op1, DAG);
18903
18904 SDValue NodeLo =
18905 DAG.getNode(IsAdd ? ISD::UADDO : ISD::USUBO, SL,
18906 DAG.getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
18907
18908 SDValue CarryInHi = NodeLo.getValue(1);
18909 SDValue NodeHi = DAG.getNode(IsAdd ? ISD::UADDO_CARRY : ISD::USUBO_CARRY,
18910 SL, DAG.getVTList(MVT::i32, MVT::i1),
18911 {Op0Hi, Op1Hi, CarryInHi});
18912
18913 SDValue ResultLo = NodeLo.getValue(0);
18914 SDValue ResultHi = NodeHi.getValue(0);
18915
18916 SDValue JoinedResult =
18917 DAG.getBuildVector(MVT::v2i32, SL, {ResultLo, ResultHi});
18918
18919 SDValue Result = DAG.getNode(ISD::BITCAST, SL, VT, JoinedResult);
18920 SDValue Overflow = NodeHi.getValue(1);
18921 DCI.CombineTo(LHS.getNode(), Result);
18922 return Overflow;
18923 }
18924
18925 if (VT != MVT::f32 && VT != MVT::f64 &&
18926 (!Subtarget->has16BitInsts() || VT != MVT::f16))
18927 return SDValue();
18928
18929 // Match isinf/isfinite pattern
18930 // (fcmp oeq (fabs x), inf) -> (fp_class x, (p_infinity | n_infinity))
18931 // (fcmp one (fabs x), inf) -> (fp_class x,
18932 // (p_normal | n_normal | p_subnormal | n_subnormal | p_zero | n_zero)
18933 if ((CC == ISD::SETOEQ || CC == ISD::SETONE) &&
18934 LHS.getOpcode() == ISD::FABS) {
18935 const ConstantFPSDNode *CRHS = dyn_cast<ConstantFPSDNode>(RHS);
18936 if (!CRHS)
18937 return SDValue();
18938
18939 const APFloat &APF = CRHS->getValueAPF();
18940 if (APF.isInfinity() && !APF.isNegative()) {
18941 const unsigned IsInfMask =
18943 const unsigned IsFiniteMask =
18947 unsigned Mask = CC == ISD::SETOEQ ? IsInfMask : IsFiniteMask;
18948 return DAG.getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1, LHS.getOperand(0),
18949 DAG.getConstant(Mask, SL, MVT::i32));
18950 }
18951 }
18952
18953 if (VT == MVT::f64) {
18954 ISD::CondCode HiHalfCC = tryReduceF64CompareToHiHalf(CC, LHS, RHS, DAG);
18955 if (HiHalfCC != ISD::SETCC_INVALID)
18956 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
18957 getHiHalf64(RHS, DAG), HiHalfCC);
18958 }
18959
18960 return SDValue();
18961}
18962
18963SDValue
18964SITargetLowering::performCvtF32UByteNCombine(SDNode *N,
18965 DAGCombinerInfo &DCI) const {
18966 SelectionDAG &DAG = DCI.DAG;
18967 SDLoc SL(N);
18968 unsigned Offset = N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
18969
18970 SDValue Src = N->getOperand(0);
18971 SDValue Shift = N->getOperand(0);
18972
18973 // TODO: Extend type shouldn't matter (assuming legal types).
18974 if (Shift.getOpcode() == ISD::ZERO_EXTEND)
18975 Shift = Shift.getOperand(0);
18976
18977 if (Shift.getOpcode() == ISD::SRL || Shift.getOpcode() == ISD::SHL) {
18978 // cvt_f32_ubyte1 (shl x, 8) -> cvt_f32_ubyte0 x
18979 // cvt_f32_ubyte3 (shl x, 16) -> cvt_f32_ubyte1 x
18980 // cvt_f32_ubyte0 (srl x, 16) -> cvt_f32_ubyte2 x
18981 // cvt_f32_ubyte1 (srl x, 16) -> cvt_f32_ubyte3 x
18982 // cvt_f32_ubyte0 (srl x, 8) -> cvt_f32_ubyte1 x
18983 if (auto *C = dyn_cast<ConstantSDNode>(Shift.getOperand(1))) {
18984 SDValue Shifted = DAG.getZExtOrTrunc(
18985 Shift.getOperand(0), SDLoc(Shift.getOperand(0)), MVT::i32);
18986
18987 unsigned ShiftOffset = 8 * Offset;
18988 if (Shift.getOpcode() == ISD::SHL)
18989 ShiftOffset -= C->getZExtValue();
18990 else
18991 ShiftOffset += C->getZExtValue();
18992
18993 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
18994 return DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
18995 MVT::f32, Shifted);
18996 }
18997 }
18998 }
18999
19000 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
19001 APInt DemandedBits = APInt::getBitsSet(32, 8 * Offset, 8 * Offset + 8);
19002 if (TLI.SimplifyDemandedBits(Src, DemandedBits, DCI)) {
19003 // We simplified Src. If this node is not dead, visit it again so it is
19004 // folded properly.
19005 if (N->getOpcode() != ISD::DELETED_NODE)
19006 DCI.AddToWorklist(N);
19007 return SDValue(N, 0);
19008 }
19009
19010 // Handle (or x, (srl y, 8)) pattern when known bits are zero.
19011 if (SDValue DemandedSrc =
19012 TLI.SimplifyMultipleUseDemandedBits(Src, DemandedBits, DAG))
19013 return DAG.getNode(N->getOpcode(), SL, MVT::f32, DemandedSrc);
19014
19015 return SDValue();
19016}
19017
19018SDValue SITargetLowering::performClampCombine(SDNode *N,
19019 DAGCombinerInfo &DCI) const {
19020 ConstantFPSDNode *CSrc = dyn_cast<ConstantFPSDNode>(N->getOperand(0));
19021 if (!CSrc)
19022 return SDValue();
19023
19024 const MachineFunction &MF = DCI.DAG.getMachineFunction();
19025 const APFloat &F = CSrc->getValueAPF();
19026 APFloat Zero = APFloat::getZero(F.getSemantics());
19027 if (F < Zero ||
19028 (F.isNaN() && MF.getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
19029 return DCI.DAG.getConstantFP(Zero, SDLoc(N), N->getValueType(0));
19030 }
19031
19032 APFloat One = APFloat::getOne(F.getSemantics());
19033 if (F > One)
19034 return DCI.DAG.getConstantFP(One, SDLoc(N), N->getValueType(0));
19035
19036 return getCanonicalConstantFP(DCI.DAG, SDLoc(N), N->getValueType(0), F);
19037}
19038
19039// Check if V is the exponent result of a frexp operation. Returns the frexp
19040// input via FrexpInput if matched. We only match the exponent (not mantissa)
19041// because V_FREXP_MANT returns its input for Inf/NaN, not zero.
19042static bool isFrexpExp(SDValue V, SDValue &FrexpInput) {
19043 // ISD::FFREXP returns {mant, exp} - only match if using the exp result
19044 // (result number 1).
19045 if (V.getOpcode() == ISD::FFREXP && V.getResNo() == 1) {
19046 FrexpInput = V.getOperand(0);
19047 return true;
19048 }
19050 m_Value(FrexpInput))))
19051 return true;
19052 return false;
19053}
19054
19055SDValue
19056SITargetLowering::performFrexpSelectCombine(SDNode *N,
19057 DAGCombinerInfo &DCI) const {
19058 // This optimization only applies when the hardware handles inf/nan correctly.
19059 if (Subtarget->hasFractBug())
19060 return SDValue();
19061
19062 SDValue Cond = N->getOperand(0);
19063 SDValue TrueVal = N->getOperand(1);
19064 SDValue FalseVal = N->getOperand(2);
19065
19066 // Identify which operand is the frexp result and which is the zero constant.
19067 // Pattern 1: select cond, 0, frexp_result (cond true -> return 0)
19068 // Pattern 2: select cond, frexp_result, 0 (cond false -> return 0)
19069 SDValue FrexpVal;
19070 SDValue ZeroVal;
19071 bool CondSelectsZero; // If true, condition=true selects zero
19072
19073 // Check if FrexpVal comes from ISD::FFREXP (exponent result only) or
19074 // amdgcn_frexp_exp intrinsic.
19075 SDValue FrexpInput;
19076 if (isFrexpExp(FalseVal, FrexpInput)) {
19077 FrexpVal = FalseVal;
19078 ZeroVal = TrueVal;
19079 CondSelectsZero = true;
19080 } else if (isFrexpExp(TrueVal, FrexpInput)) {
19081 FrexpVal = TrueVal;
19082 ZeroVal = FalseVal;
19083 CondSelectsZero = false;
19084 } else {
19085 return SDValue();
19086 }
19087
19088 // frexp_exp returns integer, so check for integer zero.
19089 if (!isNullConstant(ZeroVal))
19090 return SDValue();
19091
19092 // The frexp intrinsics ignore sign, so we can strip sign ops when comparing.
19093 SDValue FrexpInputStripped = peekFPSignOps(FrexpInput);
19094
19095 bool IsNonFiniteTest = false;
19096
19097 // Handle SETCC conditions for inf/nan tests.
19098 // The canonical form of these checks is fcmp + fabs.
19099 if (Cond.getOpcode() == ISD::SETCC) {
19100 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
19101 SDValue CondLHS = Cond.getOperand(0);
19102 SDValue CondRHS = Cond.getOperand(1);
19103
19104 // Check if LHS is fabs(FrexpInput) - required for infinity comparisons.
19105 SDValue FAbsInput;
19106 bool LHSIsFabs = sd_match(CondLHS, m_FAbs(m_Value(FAbsInput)));
19107 bool LHSMatchesFrexp =
19108 (CondLHS == FrexpInput) ||
19109 (LHSIsFabs && peekFPSignOps(FAbsInput) == FrexpInputStripped) ||
19110 (peekFPSignOps(CondLHS) == FrexpInputStripped);
19111 bool RHSMatchesFrexp = (CondRHS == FrexpInput) ||
19112 (peekFPSignOps(CondRHS) == FrexpInputStripped);
19113
19114 if (CC == ISD::SETUO) {
19115 // fcmp uno x, y - true if either x or y is NaN
19116 // We can only fold if the non-frexp operand is known to never be NaN,
19117 // otherwise the comparison could be true due to the other operand.
19118 // Special case: fcmp uno x, x (same operand) is a valid NaN test.
19119 SelectionDAG &DAG = DCI.DAG;
19120 if (LHSMatchesFrexp &&
19121 (CondLHS == CondRHS || DAG.isKnownNeverNaN(CondRHS)))
19122 IsNonFiniteTest = CondSelectsZero;
19123 else if (RHSMatchesFrexp && DAG.isKnownNeverNaN(CondLHS))
19124 IsNonFiniteTest = CondSelectsZero;
19125 } else if ((CC == ISD::SETOEQ || CC == ISD::SETUEQ) && LHSMatchesFrexp &&
19126 LHSIsFabs &&
19127 sd_match(CondRHS,
19129 CondRHS.getValueType().getFltSemantics())))) {
19130 // fcmp oeq/ueq fabs(x), +inf - true if x is inf (or inf/nan for ueq)
19131 IsNonFiniteTest = CondSelectsZero;
19132 } else if ((CC == ISD::SETONE || CC == ISD::SETUNE) && LHSMatchesFrexp &&
19133 LHSIsFabs &&
19134 sd_match(CondRHS,
19136 CondRHS.getValueType().getFltSemantics())))) {
19137 // fcmp one/une fabs(x), +inf - true if x is NOT inf
19138 IsNonFiniteTest = !CondSelectsZero;
19139 } else if (CC == ISD::SETO) {
19140 // fcmp ord x, y - true if both are NOT NaN
19141 // We can only fold if the non-frexp operand is known to never be NaN,
19142 // otherwise the comparison could be false due to the other operand.
19143 // Special case: fcmp ord x, x (same operand) is a valid not-NaN test.
19144 SelectionDAG &DAG = DCI.DAG;
19145 if (LHSMatchesFrexp &&
19146 (CondLHS == CondRHS || DAG.isKnownNeverNaN(CondRHS)))
19147 IsNonFiniteTest = !CondSelectsZero;
19148 else if (RHSMatchesFrexp && DAG.isKnownNeverNaN(CondLHS))
19149 IsNonFiniteTest = !CondSelectsZero;
19150 }
19151 }
19152
19153 if (!IsNonFiniteTest)
19154 return SDValue();
19155
19156 // The select can be eliminated - just return the frexp result directly.
19157 return FrexpVal;
19158}
19159
19160SDValue SITargetLowering::performSelectCombine(SDNode *N,
19161 DAGCombinerInfo &DCI) const {
19162
19163 // Try to fold CMP + SELECT patterns with shared constants (both FP and
19164 // integer).
19165 // Detect when CMP and SELECT use the same constant and fold them to avoid
19166 // loading the constant twice. Specifically handles patterns like:
19167 // %cmp = icmp eq i32 %val, 4242
19168 // %sel = select i1 %cmp, i32 4242, i32 %other
19169 // It can be optimized to reuse %val instead of 4242 in select.
19170 SDValue Cond = N->getOperand(0);
19171 SDValue TrueVal = N->getOperand(1);
19172 SDValue FalseVal = N->getOperand(2);
19173
19174 // Check if condition is a comparison.
19175 if (Cond.getOpcode() != ISD::SETCC)
19176 return SDValue();
19177
19178 SDValue LHS = Cond.getOperand(0);
19179 SDValue RHS = Cond.getOperand(1);
19180 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
19181
19182 bool isFloatingPoint = LHS.getValueType().isFloatingPoint();
19183 bool isInteger = LHS.getValueType().isInteger();
19184
19185 // Handle simple floating-point and integer types only.
19186 if (!isFloatingPoint && !isInteger)
19187 return SDValue();
19188
19189 // Bare SETEQ/SETNE is the builder's NaN-impossible downgrade.
19190 bool isEquality = CC == ISD::SETEQ || (isFloatingPoint && CC == ISD::SETOEQ);
19191 bool isNonEquality =
19192 CC == ISD::SETNE || (isFloatingPoint && CC == ISD::SETONE);
19193 if (!isEquality && !isNonEquality)
19194 return SDValue();
19195
19196 SDValue ArgVal, ConstVal;
19197 if ((isFloatingPoint && isa<ConstantFPSDNode>(RHS)) ||
19198 (isInteger && isa<ConstantSDNode>(RHS))) {
19199 ConstVal = RHS;
19200 ArgVal = LHS;
19201 } else if ((isFloatingPoint && isa<ConstantFPSDNode>(LHS)) ||
19202 (isInteger && isa<ConstantSDNode>(LHS))) {
19203 ConstVal = LHS;
19204 ArgVal = RHS;
19205 } else {
19206 return SDValue();
19207 }
19208
19209 // Skip optimization for inlinable immediates.
19210 if (isFloatingPoint) {
19211 const APFloat &Val = cast<ConstantFPSDNode>(ConstVal)->getValueAPF();
19212 if (!Val.isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
19213 return SDValue();
19214 } else {
19215 const std::optional<int64_t> Val =
19216 cast<ConstantSDNode>(ConstVal)->getAPIntValue().trySExtValue();
19217 if (Val && AMDGPU::isInlinableIntLiteral(*Val))
19218 return SDValue();
19219 }
19220
19221 // For equality and non-equality comparisons, patterns:
19222 // select (setcc x, const), const, y -> select (setcc x, const), x, y
19223 // select (setccinv x, const), y, const -> select (setccinv x, const), y, x
19224 if (!(isEquality && TrueVal == ConstVal) &&
19225 !(isNonEquality && FalseVal == ConstVal))
19226 return SDValue();
19227
19228 // SETONE's false arm is also taken for NaN ArgVal, so require NaN excluded.
19229 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
19230 !Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
19231 return SDValue();
19232
19233 SDValue SelectLHS = (isEquality && TrueVal == ConstVal) ? ArgVal : TrueVal;
19234 SDValue SelectRHS =
19235 (isNonEquality && FalseVal == ConstVal) ? ArgVal : FalseVal;
19236 return DCI.DAG.getNode(ISD::SELECT, SDLoc(N), N->getValueType(0), Cond,
19237 SelectLHS, SelectRHS);
19238}
19239
19241 DAGCombinerInfo &DCI) const {
19242 switch (N->getOpcode()) {
19243 case ISD::ABS:
19244 if (SDValue Res = promoteUniformUnaryOpToI32(SDValue(N, 0), DCI))
19245 return Res;
19246 break;
19247 case ISD::ADD:
19248 case ISD::SUB:
19249 case ISD::SHL:
19250 case ISD::SRL:
19251 case ISD::SRA:
19252 case ISD::AND:
19253 case ISD::OR:
19254 case ISD::XOR:
19255 case ISD::MUL:
19256 case ISD::SETCC:
19257 case ISD::SELECT:
19258 case ISD::SMIN:
19259 case ISD::SMAX:
19260 case ISD::UMIN:
19261 case ISD::UMAX:
19262 case ISD::USUBSAT:
19263 case ISD::UADDSAT:
19264 if (auto Res = promoteUniformOpToI32(SDValue(N, 0), DCI))
19265 return Res;
19266 break;
19267 default:
19268 break;
19269 }
19270
19271 if (getTargetMachine().getOptLevel() == CodeGenOptLevel::None)
19272 return SDValue();
19273
19274 switch (N->getOpcode()) {
19275 case ISD::ADD:
19276 return performAddCombine(N, DCI);
19277 case ISD::PTRADD:
19278 return performPtrAddCombine(N, DCI);
19279 case ISD::SUB:
19280 return performSubCombine(N, DCI);
19281 case ISD::FADD:
19282 return performFAddCombine(N, DCI);
19283 case ISD::FSUB:
19284 return performFSubCombine(N, DCI);
19285 case ISD::FDIV:
19286 return performFDivCombine(N, DCI);
19287 case ISD::FMUL:
19288 return performFMulCombine(N, DCI);
19289 case ISD::SETCC:
19290 return performSetCCCombine(N, DCI);
19291 case ISD::SELECT:
19292 if (auto Res = performFrexpSelectCombine(N, DCI))
19293 return Res;
19294 if (auto Res = performSelectCombine(N, DCI))
19295 return Res;
19296 break;
19297 case ISD::FMAXNUM:
19298 case ISD::FMINNUM:
19299 case ISD::FMAXNUM_IEEE:
19300 case ISD::FMINNUM_IEEE:
19301 case ISD::FMAXIMUM:
19302 case ISD::FMINIMUM:
19303 case ISD::FMAXIMUMNUM:
19304 case ISD::FMINIMUMNUM:
19305 case ISD::SMAX:
19306 case ISD::SMIN:
19307 case ISD::UMAX:
19308 case ISD::UMIN:
19309 case AMDGPUISD::FMIN_LEGACY:
19310 case AMDGPUISD::FMAX_LEGACY:
19311 return performMinMaxCombine(N, DCI);
19312 case ISD::FMA:
19313 return performFMACombine(N, DCI);
19314 case ISD::AND:
19315 return performAndCombine(N, DCI);
19316 case ISD::OR:
19317 return performOrCombine(N, DCI);
19318 case ISD::FSHR: {
19320 if (N->getValueType(0) == MVT::i32 && N->isDivergent() &&
19321 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19322 return matchPERM(N, DCI);
19323 }
19324 break;
19325 }
19326 case ISD::XOR:
19327 return performXorCombine(N, DCI);
19328 case ISD::ANY_EXTEND:
19329 case ISD::ZERO_EXTEND:
19330 return performZeroOrAnyExtendCombine(N, DCI);
19332 return performSignExtendInRegCombine(N, DCI);
19333 case AMDGPUISD::FP_CLASS:
19334 return performClassCombine(N, DCI);
19335 case ISD::FCANONICALIZE:
19336 return performFCanonicalizeCombine(N, DCI);
19337 case AMDGPUISD::RCP:
19338 return performRcpCombine(N, DCI);
19339 case ISD::FLDEXP:
19340 case AMDGPUISD::FRACT:
19341 case AMDGPUISD::RSQ:
19342 case AMDGPUISD::RCP_LEGACY:
19343 case AMDGPUISD::RCP_IFLAG:
19344 case AMDGPUISD::RSQ_CLAMP: {
19345 // FIXME: This is probably wrong. If src is an sNaN, it won't be quieted
19346 SDValue Src = N->getOperand(0);
19347 if (Src.isUndef())
19348 return Src;
19349 break;
19350 }
19351 case ISD::SINT_TO_FP:
19352 case ISD::UINT_TO_FP:
19353 return performUCharToFloatCombine(N, DCI);
19354 case ISD::FCOPYSIGN:
19355 return performFCopySignCombine(N, DCI);
19356 case AMDGPUISD::CVT_F32_UBYTE0:
19357 case AMDGPUISD::CVT_F32_UBYTE1:
19358 case AMDGPUISD::CVT_F32_UBYTE2:
19359 case AMDGPUISD::CVT_F32_UBYTE3:
19360 return performCvtF32UByteNCombine(N, DCI);
19361 case AMDGPUISD::FMED3:
19362 return performFMed3Combine(N, DCI);
19363 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19364 return performCvtPkRTZCombine(N, DCI);
19365 case AMDGPUISD::CLAMP:
19366 return performClampCombine(N, DCI);
19367 case ISD::SCALAR_TO_VECTOR: {
19368 SelectionDAG &DAG = DCI.DAG;
19369 EVT VT = N->getValueType(0);
19370
19371 // v2i16 (scalar_to_vector i16:x) -> v2i16 (bitcast (any_extend i16:x))
19372 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19373 SDLoc SL(N);
19374 SDValue Src = N->getOperand(0);
19375 EVT EltVT = Src.getValueType();
19376 if (EltVT != MVT::i16)
19377 Src = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
19378
19379 SDValue Ext = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Src);
19380 return DAG.getNode(ISD::BITCAST, SL, VT, Ext);
19381 }
19382
19383 break;
19384 }
19386 return performExtractVectorEltCombine(N, DCI);
19388 return performInsertVectorEltCombine(N, DCI);
19389 case ISD::FP_ROUND:
19390 return performFPRoundCombine(N, DCI);
19391 case ISD::LOAD: {
19392 if (SDValue Widened = widenLoad(cast<LoadSDNode>(N), DCI))
19393 return Widened;
19394 [[fallthrough]];
19395 }
19396 default: {
19397 if (!DCI.isBeforeLegalize()) {
19398 if (MemSDNode *MemNode = dyn_cast<MemSDNode>(N))
19399 return performMemSDNodeCombine(MemNode, DCI);
19400 }
19401
19402 break;
19403 }
19404 }
19405
19407}
19408
19409/// Helper function for adjustWritemask
19410static unsigned SubIdx2Lane(unsigned Idx) {
19411 switch (Idx) {
19412 default:
19413 return ~0u;
19414 case AMDGPU::sub0:
19415 return 0;
19416 case AMDGPU::sub1:
19417 return 1;
19418 case AMDGPU::sub2:
19419 return 2;
19420 case AMDGPU::sub3:
19421 return 3;
19422 case AMDGPU::sub4:
19423 return 4; // Possible with TFE/LWE
19424 }
19425}
19426
19427/// Adjust the writemask of MIMG, VIMAGE or VSAMPLE instructions
19428SDNode *SITargetLowering::adjustWritemask(MachineSDNode *&Node,
19429 SelectionDAG &DAG) const {
19430 unsigned Opcode = Node->getMachineOpcode();
19431
19432 // Subtract 1 because the vdata output is not a MachineSDNode operand.
19433 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19434 if (D16Idx >= 0 && Node->getConstantOperandVal(D16Idx))
19435 return Node; // not implemented for D16
19436
19437 SDNode *Users[5] = {nullptr};
19438 unsigned Lane = 0;
19439 unsigned DmaskIdx =
19440 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19441 unsigned OldDmask = Node->getConstantOperandVal(DmaskIdx);
19442 unsigned NewDmask = 0;
19443 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19444 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19445 bool UsesTFC = (int(TFEIdx) >= 0 && Node->getConstantOperandVal(TFEIdx)) ||
19446 (int(LWEIdx) >= 0 && Node->getConstantOperandVal(LWEIdx));
19447 unsigned TFCLane = 0;
19448 bool HasChain = Node->getNumValues() > 1;
19449
19450 if (OldDmask == 0) {
19451 // These are folded out, but on the chance it happens don't assert.
19452 return Node;
19453 }
19454
19455 unsigned OldBitsSet = llvm::popcount(OldDmask);
19456 // Work out which is the TFE/LWE lane if that is enabled.
19457 if (UsesTFC) {
19458 TFCLane = OldBitsSet;
19459 }
19460
19461 // Try to figure out the used register components
19462 for (SDUse &Use : Node->uses()) {
19463
19464 // Don't look at users of the chain.
19465 if (Use.getResNo() != 0)
19466 continue;
19467
19468 SDNode *User = Use.getUser();
19469
19470 // Abort if we can't understand the usage
19471 if (!User->isMachineOpcode() ||
19472 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19473 return Node;
19474
19475 // Lane means which subreg of %vgpra_vgprb_vgprc_vgprd is used.
19476 // Note that subregs are packed, i.e. Lane==0 is the first bit set
19477 // in OldDmask, so it can be any of X,Y,Z,W; Lane==1 is the second bit
19478 // set, etc.
19479 Lane = SubIdx2Lane(User->getConstantOperandVal(1));
19480 if (Lane == ~0u)
19481 return Node;
19482
19483 // Check if the use is for the TFE/LWE generated result at VGPRn+1.
19484 if (UsesTFC && Lane == TFCLane) {
19485 Users[Lane] = User;
19486 } else {
19487 // Set which texture component corresponds to the lane.
19488 unsigned Comp;
19489 for (unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19490 Comp = llvm::countr_zero(Dmask);
19491 Dmask &= ~(1 << Comp);
19492 }
19493
19494 // Abort if we have more than one user per component.
19495 if (Users[Lane])
19496 return Node;
19497
19498 Users[Lane] = User;
19499 NewDmask |= 1 << Comp;
19500 }
19501 }
19502
19503 // Don't allow 0 dmask, as hardware assumes one channel enabled.
19504 bool NoChannels = !NewDmask;
19505 if (NoChannels) {
19506 if (!UsesTFC) {
19507 // No uses of the result and not using TFC. Then do nothing.
19508 return Node;
19509 }
19510 // If the original dmask has one channel - then nothing to do
19511 if (OldBitsSet == 1)
19512 return Node;
19513 // Use an arbitrary dmask - required for the instruction to work
19514 NewDmask = 1;
19515 }
19516 // Abort if there's no change
19517 if (NewDmask == OldDmask)
19518 return Node;
19519
19520 unsigned BitsSet = llvm::popcount(NewDmask);
19521
19522 // Check for TFE or LWE - increase the number of channels by one to account
19523 // for the extra return value
19524 // This will need adjustment for D16 if this is also included in
19525 // adjustWriteMask (this function) but at present D16 are excluded.
19526 unsigned NewChannels = BitsSet + UsesTFC;
19527
19528 int NewOpcode =
19529 AMDGPU::getMaskedMIMGOp(Node->getMachineOpcode(), NewChannels);
19530 assert(NewOpcode != -1 &&
19531 NewOpcode != static_cast<int>(Node->getMachineOpcode()) &&
19532 "failed to find equivalent MIMG op");
19533
19534 // Adjust the writemask in the node
19536 llvm::append_range(Ops, Node->ops().take_front(DmaskIdx));
19537 Ops.push_back(DAG.getTargetConstant(NewDmask, SDLoc(Node), MVT::i32));
19538 llvm::append_range(Ops, Node->ops().drop_front(DmaskIdx + 1));
19539
19540 MVT SVT = Node->getValueType(0).getVectorElementType().getSimpleVT();
19541
19542 MVT ResultVT = NewChannels == 1
19543 ? SVT
19544 : MVT::getVectorVT(SVT, NewChannels == 3 ? 4
19545 : NewChannels == 5 ? 8
19546 : NewChannels);
19547 SDVTList NewVTList =
19548 HasChain ? DAG.getVTList(ResultVT, MVT::Other) : DAG.getVTList(ResultVT);
19549
19550 MachineSDNode *NewNode =
19551 DAG.getMachineNode(NewOpcode, SDLoc(Node), NewVTList, Ops);
19552
19553 if (HasChain) {
19554 // Update chain.
19555 DAG.setNodeMemRefs(NewNode, Node->memoperands());
19556 DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), SDValue(NewNode, 1));
19557 }
19558
19559 if (NewChannels == 1) {
19560 assert(Node->hasNUsesOfValue(1, 0));
19561 SDNode *Copy =
19562 DAG.getMachineNode(TargetOpcode::COPY, SDLoc(Node),
19563 Users[Lane]->getValueType(0), SDValue(NewNode, 0));
19564 DAG.ReplaceAllUsesWith(Users[Lane], Copy);
19565 return nullptr;
19566 }
19567
19568 // Update the users of the node with the new indices
19569 for (unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19570 SDNode *User = Users[i];
19571 if (!User) {
19572 // Handle the special case of NoChannels. We set NewDmask to 1 above, but
19573 // Users[0] is still nullptr because channel 0 doesn't really have a use.
19574 if (i || !NoChannels)
19575 continue;
19576 } else {
19577 SDValue Op = DAG.getTargetConstant(Idx, SDLoc(User), MVT::i32);
19578 SDNode *NewUser = DAG.UpdateNodeOperands(User, SDValue(NewNode, 0), Op);
19579 if (NewUser != User) {
19580 DAG.ReplaceAllUsesWith(SDValue(User, 0), SDValue(NewUser, 0));
19581 DAG.RemoveDeadNode(User);
19582 }
19583 }
19584
19585 switch (Idx) {
19586 default:
19587 break;
19588 case AMDGPU::sub0:
19589 Idx = AMDGPU::sub1;
19590 break;
19591 case AMDGPU::sub1:
19592 Idx = AMDGPU::sub2;
19593 break;
19594 case AMDGPU::sub2:
19595 Idx = AMDGPU::sub3;
19596 break;
19597 case AMDGPU::sub3:
19598 Idx = AMDGPU::sub4;
19599 break;
19600 }
19601 }
19602
19603 DAG.RemoveDeadNode(Node);
19604 return nullptr;
19605}
19606
19608 if (Op.getOpcode() == ISD::AssertZext)
19609 Op = Op.getOperand(0);
19610
19611 return isa<FrameIndexSDNode>(Op);
19612}
19613
19614/// Legalize target independent instructions (e.g. INSERT_SUBREG)
19615/// with frame index operands.
19616/// LLVM assumes that inputs are to these instructions are registers.
19617SDNode *
19619 SelectionDAG &DAG) const {
19620 if (Node->getOpcode() == ISD::CopyToReg) {
19621 RegisterSDNode *DestReg = cast<RegisterSDNode>(Node->getOperand(1));
19622 SDValue SrcVal = Node->getOperand(2);
19623
19624 // Insert a copy to a VReg_1 virtual register so LowerI1Copies doesn't have
19625 // to try understanding copies to physical registers.
19626 if (SrcVal.getValueType() == MVT::i1 && DestReg->getReg().isPhysical()) {
19627 SDLoc SL(Node);
19629 SDValue VReg = DAG.getRegister(
19630 MRI.createVirtualRegister(&AMDGPU::VReg_1RegClass), MVT::i1);
19631
19632 SDNode *Glued = Node->getGluedNode();
19633 SDValue ToVReg = DAG.getCopyToReg(
19634 Node->getOperand(0), SL, VReg, SrcVal,
19635 SDValue(Glued, Glued ? Glued->getNumValues() - 1 : 0));
19636 SDValue ToResultReg = DAG.getCopyToReg(ToVReg, SL, SDValue(DestReg, 0),
19637 VReg, ToVReg.getValue(1));
19638 DAG.ReplaceAllUsesWith(Node, ToResultReg.getNode());
19639 DAG.RemoveDeadNode(Node);
19640 return ToResultReg.getNode();
19641 }
19642 }
19643
19645 for (unsigned i = 0; i < Node->getNumOperands(); ++i) {
19646 if (!isFrameIndexOp(Node->getOperand(i))) {
19647 Ops.push_back(Node->getOperand(i));
19648 continue;
19649 }
19650
19651 SDLoc DL(Node);
19652 Ops.push_back(SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL,
19653 Node->getOperand(i).getValueType(),
19654 Node->getOperand(i)),
19655 0));
19656 }
19657
19658 return DAG.UpdateNodeOperands(Node, Ops);
19659}
19660
19661/// Fold the instructions after selecting them.
19662/// Returns null if users were already updated.
19664 SelectionDAG &DAG) const {
19666 unsigned Opcode = Node->getMachineOpcode();
19667
19668 if (TII->isImage(Opcode) && !TII->get(Opcode).mayStore() &&
19669 !TII->isGather4(Opcode) &&
19670 AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::dmask)) {
19671 return adjustWritemask(Node, DAG);
19672 }
19673
19674 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19676 return Node;
19677 }
19678
19679 switch (Opcode) {
19680 case AMDGPU::V_DIV_SCALE_F32_e64:
19681 case AMDGPU::V_DIV_SCALE_F64_e64: {
19682 // Satisfy the operand register constraint when one of the inputs is
19683 // undefined. Ordinarily each undef value will have its own implicit_def of
19684 // a vreg, so force these to use a single register.
19685 SDValue Src0 = Node->getOperand(1);
19686 SDValue Src1 = Node->getOperand(3);
19687 SDValue Src2 = Node->getOperand(5);
19688
19689 if ((Src0.isMachineOpcode() &&
19690 Src0.getMachineOpcode() != AMDGPU::IMPLICIT_DEF) &&
19691 (Src0 == Src1 || Src0 == Src2))
19692 break;
19693
19694 MVT VT = Src0.getValueType().getSimpleVT();
19695 const TargetRegisterClass *RC =
19696 getRegClassFor(VT, Src0.getNode()->isDivergent());
19697
19699 SDValue UndefReg = DAG.getRegister(MRI.createVirtualRegister(RC), VT);
19700
19701 SDValue ImpDef = DAG.getCopyToReg(DAG.getEntryNode(), SDLoc(Node), UndefReg,
19702 Src0, SDValue());
19703
19704 // src0 must be the same register as src1 or src2, even if the value is
19705 // undefined, so make sure we don't violate this constraint.
19706 if (Src0.isMachineOpcode() &&
19707 Src0.getMachineOpcode() == AMDGPU::IMPLICIT_DEF) {
19708 if (Src1.isMachineOpcode() &&
19709 Src1.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19710 Src0 = Src1;
19711 else if (Src2.isMachineOpcode() &&
19712 Src2.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19713 Src0 = Src2;
19714 else {
19715 assert(Src1.getMachineOpcode() == AMDGPU::IMPLICIT_DEF);
19716 Src0 = UndefReg;
19717 Src1 = UndefReg;
19718 }
19719 } else
19720 break;
19721
19723 Ops[1] = Src0;
19724 Ops[3] = Src1;
19725 Ops[5] = Src2;
19726 Ops.push_back(ImpDef.getValue(1));
19727 return DAG.getMachineNode(Opcode, SDLoc(Node), Node->getVTList(), Ops);
19728 }
19729 default:
19730 break;
19731 }
19732
19733 return Node;
19734}
19735
19736// Any MIMG instructions that use tfe or lwe require an initialization of the
19737// result register that will be written in the case of a memory access failure.
19738// The required code is also added to tie this init code to the result of the
19739// img instruction.
19742 const SIRegisterInfo &TRI = TII->getRegisterInfo();
19743 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
19744 MachineBasicBlock &MBB = *MI.getParent();
19745
19746 int DstIdx =
19747 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
19748 unsigned InitIdx = 0;
19749
19750 if (TII->isImage(MI)) {
19751 MachineOperand *TFE = TII->getNamedOperand(MI, AMDGPU::OpName::tfe);
19752 MachineOperand *LWE = TII->getNamedOperand(MI, AMDGPU::OpName::lwe);
19753 MachineOperand *D16 = TII->getNamedOperand(MI, AMDGPU::OpName::d16);
19754
19755 if (!TFE && !LWE) // intersect_ray
19756 return;
19757
19758 unsigned TFEVal = TFE ? TFE->getImm() : 0;
19759 unsigned LWEVal = LWE ? LWE->getImm() : 0;
19760 unsigned D16Val = D16 ? D16->getImm() : 0;
19761
19762 if (!TFEVal && !LWEVal)
19763 return;
19764
19765 // At least one of TFE or LWE are non-zero
19766 // We have to insert a suitable initialization of the result value and
19767 // tie this to the dest of the image instruction.
19768
19769 // Calculate which dword we have to initialize to 0.
19770 MachineOperand *MO_Dmask = TII->getNamedOperand(MI, AMDGPU::OpName::dmask);
19771
19772 // check that dmask operand is found.
19773 assert(MO_Dmask && "Expected dmask operand in instruction");
19774
19775 unsigned dmask = MO_Dmask->getImm();
19776 // Determine the number of active lanes taking into account the
19777 // Gather4 special case
19778 unsigned ActiveLanes = TII->isGather4(MI) ? 4 : llvm::popcount(dmask);
19779
19780 bool Packed = !Subtarget->hasUnpackedD16VMem();
19781
19782 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19783
19784 // Abandon attempt if the dst size isn't large enough
19785 // - this is in fact an error but this is picked up elsewhere and
19786 // reported correctly.
19787 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
19788
19789 uint32_t DstSize = TRI.getRegSizeInBits(*DstRC) / 32;
19790 if (DstSize < InitIdx)
19791 return;
19792 } else if (TII->isMUBUF(MI) && AMDGPU::getMUBUFTfe(MI.getOpcode())) {
19793 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
19794 InitIdx = TRI.getRegSizeInBits(*DstRC) / 32;
19795 } else {
19796 return;
19797 }
19798
19799 const DebugLoc &DL = MI.getDebugLoc();
19800
19801 // Create a register for the initialization value.
19802 Register PrevDst = MRI.cloneVirtualRegister(MI.getOperand(DstIdx).getReg());
19803 unsigned NewDst = 0; // Final initialized value will be in here
19804
19805 // If PRTStrictNull feature is enabled (the default) then initialize
19806 // all the result registers to 0, otherwise just the error indication
19807 // register (VGPRn+1)
19808 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
19809 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
19810
19811 BuildMI(MBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), PrevDst);
19812 for (; SizeLeft; SizeLeft--, CurrIdx++) {
19813 NewDst = MRI.createVirtualRegister(TII->getOpRegClass(MI, DstIdx));
19814 // Initialize dword
19815 Register SubReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
19816 // clang-format off
19817 BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), SubReg)
19818 .addImm(0);
19819 // clang-format on
19820 // Insert into the super-reg
19821 BuildMI(MBB, MI, DL, TII->get(TargetOpcode::INSERT_SUBREG), NewDst)
19822 .addReg(PrevDst)
19823 .addReg(SubReg)
19825
19826 PrevDst = NewDst;
19827 }
19828
19829 // Add as an implicit operand
19830 MI.addOperand(MachineOperand::CreateReg(NewDst, false, true));
19831
19832 // Tie the just added implicit operand to the dst
19833 MI.tieOperands(DstIdx, MI.getNumOperands() - 1);
19834}
19835
19836/// Assign the register class depending on the number of
19837/// bits set in the writemask
19839 SDNode *Node) const {
19841
19842 MachineFunction *MF = MI.getMF();
19843 MachineRegisterInfo &MRI = MF->getRegInfo();
19844
19845 if (TII->isVOP3(MI.getOpcode())) {
19846 // Make sure constant bus requirements are respected.
19847 TII->legalizeOperandsVOP3(MRI, MI);
19848
19849 if (TII->isMAI(MI)) {
19850 // The ordinary src0, src1, src2 were legalized above.
19851 //
19852 // We have to also legalize the appended v_mfma_ld_scale_b32 operands,
19853 // as a separate instruction.
19854 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
19855 AMDGPU::OpName::scale_src0);
19856 if (Src0Idx != -1) {
19857 int Src1Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
19858 AMDGPU::OpName::scale_src1);
19859 if (TII->usesConstantBus(MRI, MI, Src0Idx) &&
19860 TII->usesConstantBus(MRI, MI, Src1Idx))
19861 TII->legalizeOpWithMove(MI, Src1Idx);
19862 }
19863 }
19864
19865 return;
19866 }
19867
19868 if (TII->isImage(MI))
19869 TII->enforceOperandRCAlignment(MI, AMDGPU::OpName::vaddr);
19870}
19871
19873 uint64_t Val) {
19874 SDValue K = DAG.getTargetConstant(Val, DL, MVT::i32);
19875 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, K), 0);
19876}
19877
19879 const SDLoc &DL,
19880 SDValue Ptr) const {
19882
19883 // Build the half of the subregister with the constants before building the
19884 // full 128-bit register. If we are building multiple resource descriptors,
19885 // this will allow CSEing of the 2-component register.
19886 const SDValue Ops0[] = {
19887 DAG.getTargetConstant(AMDGPU::SGPR_64RegClassID, DL, MVT::i32),
19888 buildSMovImm32(DAG, DL, 0),
19889 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
19890 buildSMovImm32(DAG, DL, TII->getDefaultRsrcDataFormat() >> 32),
19891 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32)};
19892
19893 SDValue SubRegHi = SDValue(
19894 DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v2i32, Ops0), 0);
19895
19896 // Combine the constants and the pointer.
19897 const SDValue Ops1[] = {
19898 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32), Ptr,
19899 DAG.getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32), SubRegHi,
19900 DAG.getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32)};
19901
19902 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops1);
19903}
19904
19905/// Return a resource descriptor with the 'Add TID' bit enabled
19906/// The TID (Thread ID) is multiplied by the stride value (bits [61:48]
19907/// of the resource descriptor) to create an offset, which is added to
19908/// the resource pointer.
19910 SDValue Ptr, uint32_t RsrcDword1,
19911 uint64_t RsrcDword2And3) const {
19912 SDValue PtrLo = DAG.getTargetExtractSubreg(AMDGPU::sub0, DL, MVT::i32, Ptr);
19913 SDValue PtrHi = DAG.getTargetExtractSubreg(AMDGPU::sub1, DL, MVT::i32, Ptr);
19914 if (RsrcDword1) {
19915 PtrHi = DAG.getNode(ISD::OR, DL, MVT::i32, PtrHi,
19916 DAG.getConstant(RsrcDword1, DL, MVT::i32));
19917 }
19918
19919 SDValue DataLo =
19920 buildSMovImm32(DAG, DL, RsrcDword2And3 & UINT64_C(0xFFFFFFFF));
19921 SDValue DataHi = buildSMovImm32(DAG, DL, RsrcDword2And3 >> 32);
19922
19923 const SDValue Ops[] = {
19924 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32),
19925 PtrLo,
19926 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
19927 PtrHi,
19928 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32),
19929 DataLo,
19930 DAG.getTargetConstant(AMDGPU::sub2, DL, MVT::i32),
19931 DataHi,
19932 DAG.getTargetConstant(AMDGPU::sub3, DL, MVT::i32)};
19933
19934 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops);
19935}
19936
19937//===----------------------------------------------------------------------===//
19938// SI Inline Assembly Support
19939//===----------------------------------------------------------------------===//
19940
19941std::pair<unsigned, const TargetRegisterClass *>
19943 StringRef Constraint,
19944 MVT VT) const {
19945 const SIRegisterInfo *TRI = static_cast<const SIRegisterInfo *>(TRI_);
19946
19947 const TargetRegisterClass *RC = nullptr;
19948 if (Constraint.size() == 1) {
19949 // Check if we cannot determine the bit size of the given value type. This
19950 // can happen, for example, in this situation where we have an empty struct
19951 // (size 0): `call void asm "", "v"({} poison)`-
19952 if (VT == MVT::Other)
19953 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
19954 const unsigned BitWidth = VT.getSizeInBits();
19955 switch (Constraint[0]) {
19956 default:
19957 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
19958 case 's':
19959 case 'r':
19960 switch (BitWidth) {
19961 case 16:
19962 RC = &AMDGPU::SReg_32RegClass;
19963 break;
19964 case 64:
19965 RC = &AMDGPU::SGPR_64RegClass;
19966 break;
19967 default:
19969 if (!RC)
19970 return std::pair(0U, nullptr);
19971 break;
19972 }
19973 break;
19974 case 'v':
19975 switch (BitWidth) {
19976 case 1:
19977 return std::pair(0U, nullptr);
19978 case 16:
19979 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
19980 : &AMDGPU::VGPR_32_Lo256RegClass;
19981 break;
19982 default:
19983 RC = Subtarget->has1024AddressableVGPRs()
19984 ? TRI->getAlignedLo256VGPRClassForBitWidth(BitWidth)
19985 : TRI->getVGPRClassForBitWidth(BitWidth);
19986 if (!RC)
19987 return std::pair(0U, nullptr);
19988 break;
19989 }
19990 break;
19991 case 'a':
19992 if (!Subtarget->hasMAIInsts())
19993 break;
19994 switch (BitWidth) {
19995 case 1:
19996 return std::pair(0U, nullptr);
19997 case 16:
19998 RC = &AMDGPU::AGPR_32RegClass;
19999 break;
20000 default:
20001 RC = TRI->getAGPRClassForBitWidth(BitWidth);
20002 if (!RC)
20003 return std::pair(0U, nullptr);
20004 break;
20005 }
20006 break;
20007 }
20008 } else if (Constraint == "VA" && Subtarget->hasGFX90AInsts()) {
20009 const unsigned BitWidth = VT.getSizeInBits();
20010 switch (BitWidth) {
20011 case 16:
20012 RC = &AMDGPU::AV_32RegClass;
20013 break;
20014 default:
20015 RC = TRI->getVectorSuperClassForBitWidth(BitWidth);
20016 if (!RC)
20017 return std::pair(0U, nullptr);
20018 break;
20019 }
20020 }
20021
20022 // We actually support i128, i16 and f16 as inline parameters
20023 // even if they are not reported as legal
20024 if (RC && (isTypeLegal(VT) || VT.SimpleTy == MVT::i128 ||
20025 VT.SimpleTy == MVT::i16 || VT.SimpleTy == MVT::f16))
20026 return std::pair(0U, RC);
20027
20028 auto [Kind, Idx, NumRegs] = AMDGPU::parseAsmConstraintPhysReg(Constraint);
20029 if (Kind != '\0') {
20030 if (Kind == 'v') {
20031 RC = &AMDGPU::VGPR_32_Lo256RegClass;
20032 } else if (Kind == 's') {
20033 RC = &AMDGPU::SGPR_32RegClass;
20034 } else if (Kind == 'a') {
20035 RC = &AMDGPU::AGPR_32RegClass;
20036 }
20037
20038 if (RC) {
20039 if (NumRegs > 1) {
20040 if (Idx >= RC->getNumRegs() || Idx + NumRegs - 1 >= RC->getNumRegs())
20041 return std::pair(0U, nullptr);
20042
20043 uint32_t Width = NumRegs * 32;
20044 // Prohibit constraints for register ranges with a width that does not
20045 // match the required type.
20046 if (VT.SimpleTy != MVT::Other && Width != VT.getSizeInBits())
20047 return std::pair(0U, nullptr);
20048
20049 MCRegister Reg = RC->getRegister(Idx);
20051 RC = TRI->getVGPRClassForBitWidth(Width);
20052 else if (SIRegisterInfo::isSGPRClass(RC))
20053 RC = TRI->getSGPRClassForBitWidth(Width);
20054 else if (SIRegisterInfo::isAGPRClass(RC))
20055 RC = TRI->getAGPRClassForBitWidth(Width);
20056 if (RC) {
20057 Reg = TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
20058 if (!Reg) {
20059 // The register class does not contain the requested register,
20060 // e.g., because it is an SGPR pair that would violate alignment
20061 // requirements.
20062 return std::pair(0U, nullptr);
20063 }
20064 return std::pair(Reg, RC);
20065 }
20066 }
20067
20068 // Reject types that do not fit a single 32-bit register: any scalar wider
20069 // than 32 bits, or a vector that is not exactly 32 bits.
20070 if (VT.SimpleTy != MVT::Other &&
20071 (VT.getSizeInBits() > 32 ||
20072 (VT.isVector() && VT.getSizeInBits() != 32)))
20073 return std::pair(0U, nullptr);
20074 if (RC && Idx < RC->getNumRegs())
20075 return std::pair(RC->getRegister(Idx), RC);
20076 return std::pair(0U, nullptr);
20077 }
20078 }
20079
20080 auto Ret = TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20081 if (Ret.first)
20082 Ret.second = TRI->getPhysRegBaseClass(Ret.first);
20083
20084 return Ret;
20085}
20086
20087static bool isImmConstraint(StringRef Constraint) {
20088 if (Constraint.size() == 1) {
20089 switch (Constraint[0]) {
20090 default:
20091 break;
20092 case 'I':
20093 case 'J':
20094 case 'A':
20095 case 'B':
20096 case 'C':
20097 return true;
20098 }
20099 } else if (Constraint == "DA" || Constraint == "DB") {
20100 return true;
20101 }
20102 return false;
20103}
20104
20107 if (Constraint.size() == 1) {
20108 switch (Constraint[0]) {
20109 default:
20110 break;
20111 case 's':
20112 case 'v':
20113 case 'a':
20114 return C_RegisterClass;
20115 }
20116 } else if (Constraint.size() == 2) {
20117 if (Constraint == "VA")
20118 return C_RegisterClass;
20119 }
20120 if (isImmConstraint(Constraint)) {
20121 return C_Other;
20122 }
20123 return TargetLowering::getConstraintType(Constraint);
20124}
20125
20126static uint64_t clearUnusedBits(uint64_t Val, unsigned Size) {
20128 Val = Val & maskTrailingOnes<uint64_t>(Size);
20129 }
20130 return Val;
20131}
20132
20134 StringRef Constraint,
20135 std::vector<SDValue> &Ops,
20136 SelectionDAG &DAG) const {
20137 if (isImmConstraint(Constraint)) {
20138 uint64_t Val;
20139 if (getAsmOperandConstVal(Op, Val) &&
20140 checkAsmConstraintVal(Op, Constraint, Val)) {
20141 Val = clearUnusedBits(Val, Op.getScalarValueSizeInBits());
20142 Ops.push_back(DAG.getTargetConstant(Val, SDLoc(Op), MVT::i64));
20143 }
20144 } else {
20146 }
20147}
20148
20150 unsigned Size = Op.getScalarValueSizeInBits();
20151 if (Size > 64)
20152 return false;
20153
20154 if (Size == 16 && !Subtarget->has16BitInsts())
20155 return false;
20156
20158 Val = C->getSExtValue();
20159 return true;
20160 }
20162 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
20163 return true;
20164 }
20166 if (Size != 16 || Op.getNumOperands() != 2)
20167 return false;
20168 if (Op.getOperand(0).isUndef() || Op.getOperand(1).isUndef())
20169 return false;
20170 if (ConstantSDNode *C = V->getConstantSplatNode()) {
20171 Val = C->getSExtValue();
20172 return true;
20173 }
20174 if (ConstantFPSDNode *C = V->getConstantFPSplatNode()) {
20175 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
20176 return true;
20177 }
20178 }
20179
20180 return false;
20181}
20182
20184 uint64_t Val) const {
20185 if (Constraint.size() == 1) {
20186 switch (Constraint[0]) {
20187 case 'I':
20189 case 'J':
20190 return isInt<16>(Val);
20191 case 'A':
20192 return checkAsmConstraintValA(Op, Val);
20193 case 'B':
20194 return isInt<32>(Val);
20195 case 'C':
20196 return isUInt<32>(clearUnusedBits(Val, Op.getScalarValueSizeInBits())) ||
20198 default:
20199 break;
20200 }
20201 } else if (Constraint.size() == 2) {
20202 if (Constraint == "DA") {
20203 int64_t HiBits = static_cast<int32_t>(Val >> 32);
20204 int64_t LoBits = static_cast<int32_t>(Val);
20205 return checkAsmConstraintValA(Op, HiBits, 32) &&
20206 checkAsmConstraintValA(Op, LoBits, 32);
20207 }
20208 if (Constraint == "DB") {
20209 return true;
20210 }
20211 }
20212 llvm_unreachable("Invalid asm constraint");
20213}
20214
20216 unsigned MaxSize) const {
20217 unsigned Size = std::min<unsigned>(Op.getScalarValueSizeInBits(), MaxSize);
20218 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
20219 if (Size == 16) {
20220 MVT VT = Op.getSimpleValueType();
20221 switch (VT.SimpleTy) {
20222 default:
20223 return false;
20224 case MVT::i16:
20225 return AMDGPU::isInlinableLiteralI16(Val, HasInv2Pi);
20226 case MVT::f16:
20227 return AMDGPU::isInlinableLiteralFP16(Val, HasInv2Pi);
20228 case MVT::bf16:
20229 return AMDGPU::isInlinableLiteralBF16(Val, HasInv2Pi);
20230 case MVT::v2i16:
20231 return AMDGPU::getInlineEncodingV2I16(Val).has_value();
20232 case MVT::v2f16:
20233 return AMDGPU::getInlineEncodingV2F16(Val).has_value();
20234 case MVT::v2bf16:
20235 return AMDGPU::getInlineEncodingV2BF16(Val).has_value();
20236 }
20237 }
20238 if ((Size == 32 && AMDGPU::isInlinableLiteral32(Val, HasInv2Pi)) ||
20239 (Size == 64 && AMDGPU::isInlinableLiteral64(Val, HasInv2Pi)))
20240 return true;
20241 return false;
20242}
20243
20244static int getAlignedAGPRClassID(unsigned UnalignedClassID) {
20245 switch (UnalignedClassID) {
20246 case AMDGPU::VReg_64RegClassID:
20247 return AMDGPU::VReg_64_Align2RegClassID;
20248 case AMDGPU::VReg_96RegClassID:
20249 return AMDGPU::VReg_96_Align2RegClassID;
20250 case AMDGPU::VReg_128RegClassID:
20251 return AMDGPU::VReg_128_Align2RegClassID;
20252 case AMDGPU::VReg_160RegClassID:
20253 return AMDGPU::VReg_160_Align2RegClassID;
20254 case AMDGPU::VReg_192RegClassID:
20255 return AMDGPU::VReg_192_Align2RegClassID;
20256 case AMDGPU::VReg_224RegClassID:
20257 return AMDGPU::VReg_224_Align2RegClassID;
20258 case AMDGPU::VReg_256RegClassID:
20259 return AMDGPU::VReg_256_Align2RegClassID;
20260 case AMDGPU::VReg_288RegClassID:
20261 return AMDGPU::VReg_288_Align2RegClassID;
20262 case AMDGPU::VReg_320RegClassID:
20263 return AMDGPU::VReg_320_Align2RegClassID;
20264 case AMDGPU::VReg_352RegClassID:
20265 return AMDGPU::VReg_352_Align2RegClassID;
20266 case AMDGPU::VReg_384RegClassID:
20267 return AMDGPU::VReg_384_Align2RegClassID;
20268 case AMDGPU::VReg_512RegClassID:
20269 return AMDGPU::VReg_512_Align2RegClassID;
20270 case AMDGPU::VReg_1024RegClassID:
20271 return AMDGPU::VReg_1024_Align2RegClassID;
20272 case AMDGPU::AReg_64RegClassID:
20273 return AMDGPU::AReg_64_Align2RegClassID;
20274 case AMDGPU::AReg_96RegClassID:
20275 return AMDGPU::AReg_96_Align2RegClassID;
20276 case AMDGPU::AReg_128RegClassID:
20277 return AMDGPU::AReg_128_Align2RegClassID;
20278 case AMDGPU::AReg_160RegClassID:
20279 return AMDGPU::AReg_160_Align2RegClassID;
20280 case AMDGPU::AReg_192RegClassID:
20281 return AMDGPU::AReg_192_Align2RegClassID;
20282 case AMDGPU::AReg_256RegClassID:
20283 return AMDGPU::AReg_256_Align2RegClassID;
20284 case AMDGPU::AReg_512RegClassID:
20285 return AMDGPU::AReg_512_Align2RegClassID;
20286 case AMDGPU::AReg_1024RegClassID:
20287 return AMDGPU::AReg_1024_Align2RegClassID;
20288 default:
20289 return -1;
20290 }
20291}
20292
20293// Figure out which registers should be reserved for stack access. Only after
20294// the function is legalized do we know all of the non-spill stack objects or if
20295// calls are present.
20297 MachineRegisterInfo &MRI = MF.getRegInfo();
20299 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
20300 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20301 const SIInstrInfo *TII = ST.getInstrInfo();
20302
20303 if (Info->isEntryFunction()) {
20304 // Callable functions have fixed registers used for stack access.
20306 }
20307
20308 // TODO: Move this logic to getReservedRegs()
20309 // Reserve the SGPR(s) to save/restore EXEC for WWM spill/copy handling.
20310 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20311 Register SReg = ST.isWave32()
20312 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20313 : TRI->getAlignedHighSGPRForRC(MF, /*Align=*/2,
20314 &AMDGPU::SGPR_64RegClass);
20315 Info->setSGPRForEXECCopy(SReg);
20316
20317 assert(!TRI->isSubRegister(Info->getScratchRSrcReg(),
20318 Info->getStackPtrOffsetReg()));
20319 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20320 MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20321
20322 // We need to worry about replacing the default register with itself in case
20323 // of MIR testcases missing the MFI.
20324 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20325 MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20326
20327 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20328 MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());
20329
20330 Info->limitOccupancy(MF);
20331
20332 if (ST.isWave32() && !MF.empty()) {
20333 for (auto &MBB : MF) {
20334 for (auto &MI : MBB) {
20335 TII->fixImplicitOperands(MI);
20336 }
20337 }
20338 }
20339
20340 // FIXME: This is a hack to fixup AGPR classes to use the properly aligned
20341 // classes if required. Ideally the register class constraints would differ
20342 // per-subtarget, but there's no easy way to achieve that right now. This is
20343 // not a problem for VGPRs because the correctly aligned VGPR class is implied
20344 // from using them as the register class for legal types.
20345 if (ST.needsAlignedVGPRs()) {
20346 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
20347 const Register Reg = Register::index2VirtReg(I);
20348 const TargetRegisterClass *RC = MRI.getRegClassOrNull(Reg);
20349 if (!RC)
20350 continue;
20351 int NewClassID = getAlignedAGPRClassID(RC->getID());
20352 if (NewClassID != -1)
20353 MRI.setRegClass(Reg, TRI->getRegClass(NewClassID));
20354 }
20355 }
20356
20358}
20359
20362 const APInt &DemandedElts,
20363 const SelectionDAG &DAG,
20364 unsigned Depth) const {
20365 Known.resetAll();
20366 unsigned Opc = Op.getOpcode();
20367 switch (Opc) {
20369 unsigned IID = Op.getConstantOperandVal(0);
20370 switch (IID) {
20371 case Intrinsic::amdgcn_mbcnt_lo:
20372 case Intrinsic::amdgcn_mbcnt_hi: {
20373 const GCNSubtarget &ST =
20375 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20376 // most 31 + src1.
20377 Known.Zero.setBitsFrom(
20378 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20379 KnownBits Known2 = DAG.computeKnownBits(Op.getOperand(2), Depth + 1);
20380 Known = KnownBits::add(Known, Known2);
20381 return;
20382 }
20383 }
20384 break;
20385 }
20386 }
20388 Op, Known, DemandedElts, DAG, Depth);
20389}
20390
20392 KnownBits &Known, const MachineFunction &MF, Align Alignment) const {
20394
20395 // Set the high bits to zero based on the maximum allowed scratch size per
20396 // wave. We can't use vaddr in MUBUF instructions if we don't know the address
20397 // calculation won't overflow, so assume the sign bit is never set.
20398 Known.Zero.setHighBits(getSubtarget()->getKnownHighZeroBitsForFrameIndex());
20399}
20400
20403 unsigned Dim) {
20404 unsigned MaxValue =
20405 ST.getMaxWorkitemID(VT.getMachineFunction().getFunction(), Dim);
20406 Known.Zero.setHighBits(llvm::countl_zero(MaxValue));
20407}
20408
20410 KnownBits &Known, const APInt &DemandedElts,
20411 unsigned BFEWidth, bool SExt, unsigned Depth) {
20413 const MachineOperand &Src1 = MI.getOperand(2);
20414
20415 unsigned Src1Cst = 0;
20416 if (Src1.isImm()) {
20417 Src1Cst = Src1.getImm();
20418 } else if (Src1.isReg()) {
20419 auto Cst = getIConstantVRegValWithLookThrough(Src1.getReg(), MRI);
20420 if (!Cst)
20421 return;
20422 Src1Cst = Cst->Value.getZExtValue();
20423 } else {
20424 return;
20425 }
20426
20427 // Offset is at bits [4:0] for 32 bit, [5:0] for 64 bit.
20428 // Width is always [22:16].
20429 const unsigned Offset =
20430 Src1Cst & maskTrailingOnes<unsigned>((BFEWidth == 32) ? 5 : 6);
20431 const unsigned Width = (Src1Cst >> 16) & maskTrailingOnes<unsigned>(6);
20432
20433 if (Width >= BFEWidth) // Ill-formed.
20434 return;
20435
20436 VT.computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
20437 Depth + 1);
20438
20439 Known = Known.extractBits(Width, Offset);
20440
20441 if (SExt)
20442 Known = Known.sext(BFEWidth);
20443 else
20444 Known = Known.zext(BFEWidth);
20445}
20446
20449 const APInt &DemandedElts, const MachineRegisterInfo &MRI,
20450 unsigned Depth) const {
20451 Known.resetAll();
20452 const MachineInstr *MI = MRI.getVRegDef(R);
20453 switch (MI->getOpcode()) {
20454 case AMDGPU::S_BFE_I32:
20455 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20456 /*SExt=*/true, Depth);
20457 case AMDGPU::S_BFE_U32:
20458 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20459 /*SExt=*/false, Depth);
20460 case AMDGPU::S_BFE_I64:
20461 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20462 /*SExt=*/true, Depth);
20463 case AMDGPU::S_BFE_U64:
20464 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20465 /*SExt=*/false, Depth);
20466 case AMDGPU::G_INTRINSIC:
20467 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20468 Intrinsic::ID IID = cast<GIntrinsic>(MI)->getIntrinsicID();
20469 switch (IID) {
20470 case Intrinsic::amdgcn_workitem_id_x:
20472 break;
20473 case Intrinsic::amdgcn_workitem_id_y:
20475 break;
20476 case Intrinsic::amdgcn_workitem_id_z:
20478 break;
20479 case Intrinsic::amdgcn_mbcnt_lo:
20480 case Intrinsic::amdgcn_mbcnt_hi: {
20481 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20482 // most 31 + src1.
20483 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20484 ? getSubtarget()->getWavefrontSizeLog2()
20485 : 5);
20486 KnownBits Known2;
20487 VT.computeKnownBitsImpl(MI->getOperand(3).getReg(), Known2, DemandedElts,
20488 Depth + 1);
20489 Known = KnownBits::add(Known, Known2);
20490 break;
20491 }
20492 case Intrinsic::amdgcn_groupstaticsize: {
20493 // We can report everything over the maximum size as 0. We can't report
20494 // based on the actual size because we don't know if it's accurate or not
20495 // at any given point.
20496 Known.Zero.setHighBits(
20497 llvm::countl_zero(getSubtarget()->getAddressableLocalMemorySize()));
20498 break;
20499 }
20500 case Intrinsic::amdgcn_readfirstlane:
20501 case Intrinsic::amdgcn_readlane: {
20502 // Result is the data operand's value from some lane.
20503 VT.computeKnownBitsImpl(MI->getOperand(2).getReg(), Known, DemandedElts,
20504 Depth + 1);
20505 break;
20506 }
20507 }
20508 break;
20509 }
20510 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20511 Known.Zero.setHighBits(24);
20512 break;
20513 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20514 Known.Zero.setHighBits(16);
20515 break;
20516 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20517 // G_AMDGPU_COPY_SCC_VCC converts a uniform boolean in VCC to SGPR s32,
20518 // producing exactly 0 or 1.
20519 Known.Zero.setHighBits(Known.getBitWidth() - 1);
20520 break;
20521 case AMDGPU::G_AMDGPU_SMED3:
20522 case AMDGPU::G_AMDGPU_UMED3: {
20523 auto [Dst, Src0, Src1, Src2] = MI->getFirst4Regs();
20524
20525 KnownBits Known2;
20526 VT.computeKnownBitsImpl(Src2, Known2, DemandedElts, Depth + 1);
20527 if (Known2.isUnknown())
20528 break;
20529
20530 KnownBits Known1;
20531 VT.computeKnownBitsImpl(Src1, Known1, DemandedElts, Depth + 1);
20532 if (Known1.isUnknown())
20533 break;
20534
20535 KnownBits Known0;
20536 VT.computeKnownBitsImpl(Src0, Known0, DemandedElts, Depth + 1);
20537 if (Known0.isUnknown())
20538 break;
20539
20540 // TODO: Handle LeadZero/LeadOne from UMIN/UMAX handling.
20541 Known.Zero = Known0.Zero & Known1.Zero & Known2.Zero;
20542 Known.One = Known0.One & Known1.One & Known2.One;
20543 break;
20544 }
20545 }
20546}
20547
20550 unsigned Depth) const {
20551 const MachineInstr *MI = MRI.getVRegDef(R);
20552 if (auto *GI = dyn_cast<GIntrinsic>(MI)) {
20553 // FIXME: Can this move to generic code? What about the case where the call
20554 // site specifies a lower alignment?
20555 Intrinsic::ID IID = GI->getIntrinsicID();
20557 AttributeList Attrs =
20558 Intrinsic::getAttributes(Ctx, IID, Intrinsic::getType(Ctx, IID));
20559 if (MaybeAlign RetAlign = Attrs.getRetAlignment())
20560 return *RetAlign;
20561 }
20562 return Align(1);
20563}
20564
20567 const Align CacheLineAlign = Align(64);
20568
20569 // GFX950: Prevent an 8-byte instruction at loop header from being split by
20570 // the 32-byte instruction fetch window boundary. This avoids a significant
20571 // fetch delay after backward branch. We use 32-byte alignment with max
20572 // padding of 4 bytes (one s_nop), see getMaxPermittedBytesForAlignment().
20573 if (ML && !DisableLoopAlignment &&
20574 getSubtarget()->hasLoopHeadInstSplitSensitivity()) {
20575 const MachineBasicBlock *Header = ML->getHeader();
20576 // Respect user-specified or previously set alignment.
20577 if (Header->getAlignment() != PrefAlign)
20578 return Header->getAlignment();
20579 if (needsFetchWindowAlignment(*Header))
20580 return Align(32);
20581 }
20582
20583 // Pre-GFX10 target did not benefit from loop alignment
20584 if (!ML || DisableLoopAlignment || !getSubtarget()->hasInstPrefetch() ||
20585 getSubtarget()->hasInstFwdPrefetchBug())
20586 return PrefAlign;
20587
20588 // On GFX10 I$ is 4 x 64 bytes cache lines.
20589 // By default prefetcher keeps one cache line behind and reads two ahead.
20590 // We can modify it with S_INST_PREFETCH for larger loops to have two lines
20591 // behind and one ahead.
20592 // Therefor we can benefit from aligning loop headers if loop fits 192 bytes.
20593 // If loop fits 64 bytes it always spans no more than two cache lines and
20594 // does not need an alignment.
20595 // Else if loop is less or equal 128 bytes we do not need to modify prefetch,
20596 // Else if loop is less or equal 192 bytes we need two lines behind.
20597
20599 const MachineBasicBlock *Header = ML->getHeader();
20600 if (Header->getAlignment() != PrefAlign)
20601 return Header->getAlignment(); // Already processed.
20602
20603 unsigned LoopSize = 0;
20604 for (const MachineBasicBlock *MBB : ML->blocks()) {
20605 // If inner loop block is aligned assume in average half of the alignment
20606 // size to be added as nops.
20607 if (MBB != Header)
20608 LoopSize += MBB->getAlignment().value() / 2;
20609
20610 for (const MachineInstr &MI : *MBB) {
20611 LoopSize += TII->getInstSizeInBytes(MI);
20612 if (LoopSize > 192)
20613 return PrefAlign;
20614 }
20615 }
20616
20617 if (LoopSize <= 64)
20618 return PrefAlign;
20619
20620 if (LoopSize <= 128)
20621 return CacheLineAlign;
20622
20623 // If any of parent loops is surrounded by prefetch instructions do not
20624 // insert new for inner loop, which would reset parent's settings.
20625 for (MachineLoop *P = ML->getParentLoop(); P; P = P->getParentLoop()) {
20626 if (MachineBasicBlock *Exit = P->getExitBlock()) {
20627 auto I = Exit->getFirstNonDebugInstr();
20628 if (I != Exit->end() && I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20629 return CacheLineAlign;
20630 }
20631 }
20632
20633 MachineBasicBlock *Pre = ML->getLoopPreheader();
20634 MachineBasicBlock *Exit = ML->getExitBlock();
20635
20636 if (Pre && Exit) {
20637 auto PreTerm = Pre->getFirstTerminator();
20638 if (PreTerm == Pre->begin() ||
20639 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20640 BuildMI(*Pre, PreTerm, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20641 .addImm(1); // prefetch 2 lines behind PC
20642
20643 auto ExitHead = Exit->getFirstNonDebugInstr();
20644 if (ExitHead == Exit->end() ||
20645 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20646 BuildMI(*Exit, ExitHead, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20647 .addImm(2); // prefetch 1 line behind PC
20648 }
20649
20650 return CacheLineAlign;
20651}
20652
20654 MachineBasicBlock *MBB) const {
20655 // GFX950: Limit padding to 4 bytes (one s_nop) for blocks where an 8-byte
20656 // instruction could be split by the 32-byte fetch window boundary.
20657 // See getPrefLoopAlignment() for context.
20658 if (needsFetchWindowAlignment(*MBB))
20659 return 4;
20661}
20662
20663bool SITargetLowering::needsFetchWindowAlignment(
20664 const MachineBasicBlock &MBB) const {
20665 if (!getSubtarget()->hasLoopHeadInstSplitSensitivity())
20666 return false;
20668 for (const MachineInstr &MI : MBB) {
20669 if (MI.isMetaInstruction())
20670 continue;
20671 // Instructions larger than 4 bytes can be split by a 32-byte boundary.
20672 return TII->getInstSizeInBytes(MI) > 4;
20673 }
20674 return false;
20675}
20676
20677[[maybe_unused]]
20678static bool isCopyFromRegOfInlineAsm(const SDNode *N) {
20679 assert(N->getOpcode() == ISD::CopyFromReg);
20680 do {
20681 // Follow the chain until we find an INLINEASM node.
20682 N = N->getOperand(0).getNode();
20683 if (N->getOpcode() == ISD::INLINEASM || N->getOpcode() == ISD::INLINEASM_BR)
20684 return true;
20685 } while (N->getOpcode() == ISD::CopyFromReg);
20686 return false;
20687}
20688
20691 UniformityInfo *UA) const {
20692 switch (N->getOpcode()) {
20693 case ISD::CopyFromReg: {
20694 const RegisterSDNode *R = cast<RegisterSDNode>(N->getOperand(1));
20695 const MachineRegisterInfo &MRI = FLI->MF->getRegInfo();
20696 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20697 Register Reg = R->getReg();
20698
20699 // FIXME: Why does this need to consider isLiveIn?
20700 if (Reg.isPhysical() || MRI.isLiveIn(Reg))
20701 return !TRI->isSGPRReg(MRI, Reg);
20702
20703 if (const Value *V = FLI->getValueFromVirtualReg(R->getReg()))
20704 return UA->isDivergentAtDef(V);
20705
20707 return !TRI->isSGPRReg(MRI, Reg);
20708 }
20709 case ISD::LOAD: {
20710 const LoadSDNode *L = cast<LoadSDNode>(N);
20711 unsigned AS = L->getAddressSpace();
20712 // A flat load may access private memory.
20714 }
20715 case ISD::CALLSEQ_END:
20716 return true;
20718 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(0));
20720 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(1));
20721 case AMDGPUISD::ATOMIC_CMP_SWAP:
20722 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20723 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20724 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20725 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20726 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20727 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20728 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20729 case AMDGPUISD::BUFFER_ATOMIC_AND:
20730 case AMDGPUISD::BUFFER_ATOMIC_OR:
20731 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20732 case AMDGPUISD::BUFFER_ATOMIC_INC:
20733 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20734 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20735 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20736 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20737 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20738 // Target-specific read-modify-write atomics are sources of divergence.
20739 return true;
20740 default:
20741 if (auto *A = dyn_cast<AtomicSDNode>(N)) {
20742 // Generic read-modify-write atomics are sources of divergence.
20743 return A->readMem() && A->writeMem();
20744 }
20745 return false;
20746 }
20747}
20748
20750 EVT VT) const {
20751 switch (VT.getScalarType().getSimpleVT().SimpleTy) {
20752 case MVT::f32:
20754 case MVT::f64:
20755 case MVT::f16:
20757 default:
20758 return false;
20759 }
20760}
20761
20763 LLT Ty, const MachineFunction &MF) const {
20764 switch (Ty.getScalarSizeInBits()) {
20765 case 32:
20766 return !denormalModeIsFlushAllF32(MF);
20767 case 64:
20768 case 16:
20769 return !denormalModeIsFlushAllF64F16(MF);
20770 default:
20771 return false;
20772 }
20773}
20774
20776 const APInt &DemandedElts,
20777 const SelectionDAG &DAG,
20778 bool SNaN,
20779 unsigned Depth) const {
20780 if (Op.getOpcode() == AMDGPUISD::CLAMP) {
20781 const MachineFunction &MF = DAG.getMachineFunction();
20783
20784 if (Info->getMode().DX10Clamp)
20785 return true; // Clamped to 0.
20786 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);
20787 }
20788
20790 DAG, SNaN, Depth);
20791}
20792
20793// On older subtargets, global FP atomic instructions have a hardcoded FP mode
20794// and do not support FP32 denormals, and only support v2f16/f64 denormals.
20796 if (RMW->hasMetadata(LLVMContext::MD_atomic_ignore_denormal_mode))
20797 return true;
20798
20799 const fltSemantics &Flt = RMW->getType()->getScalarType()->getFltSemantics();
20800 auto DenormMode = RMW->getFunction()->getDenormalMode(Flt);
20801 if (DenormMode == DenormalMode::getPreserveSign())
20802 return true;
20803
20804 // TODO: Remove this.
20805 return RMW->getFunction()
20806 ->getFnAttribute("amdgpu-unsafe-fp-atomics")
20807 .getValueAsBool();
20808}
20809
20811 LLVMContext &Ctx = RMW->getContext();
20812 StringRef MemScope =
20813 Ctx.getSyncScopeName(RMW->getSyncScopeID()).value_or("system");
20814
20815 return OptimizationRemark(DEBUG_TYPE, "Passed", RMW)
20816 << "Hardware instruction generated for atomic "
20817 << RMW->getOperationName(RMW->getOperation())
20818 << " operation at memory scope " << MemScope;
20819}
20820
20821static bool isV2F16OrV2BF16(Type *Ty) {
20822 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
20823 Type *EltTy = VT->getElementType();
20824 return VT->getNumElements() == 2 &&
20825 (EltTy->isHalfTy() || EltTy->isBFloatTy());
20826 }
20827
20828 return false;
20829}
20830
20831static bool isV2F16(Type *Ty) {
20833 return VT && VT->getNumElements() == 2 && VT->getElementType()->isHalfTy();
20834}
20835
20836static bool isV2BF16(Type *Ty) {
20838 return VT && VT->getNumElements() == 2 && VT->getElementType()->isBFloatTy();
20839}
20840
20841/// \return true if atomicrmw integer ops work for the type.
20842static bool isAtomicRMWLegalIntTy(Type *Ty) {
20843 if (auto *IT = dyn_cast<IntegerType>(Ty)) {
20844 unsigned BW = IT->getBitWidth();
20845 return BW == 32 || BW == 64;
20846 }
20847
20848 return false;
20849}
20850
20851/// \return true if this atomicrmw xchg type can be selected.
20852static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW) {
20853 Type *Ty = RMW->getType();
20854 if (isAtomicRMWLegalIntTy(Ty))
20855 return true;
20856
20857 if (PointerType *PT = dyn_cast<PointerType>(Ty)) {
20858 const DataLayout &DL = RMW->getFunction()->getParent()->getDataLayout();
20859 unsigned BW = DL.getPointerSizeInBits(PT->getAddressSpace());
20860 return BW == 32 || BW == 64;
20861 }
20862
20863 if (Ty->isFloatTy() || Ty->isDoubleTy())
20864 return true;
20865
20867 return VT->getNumElements() == 2 &&
20868 VT->getElementType()->getPrimitiveSizeInBits() == 16;
20869 }
20870
20871 return false;
20872}
20873
20874/// \returns true if it's valid to emit a native instruction for \p RMW, based
20875/// on the properties of the target memory.
20876static bool globalMemoryFPAtomicIsLegal(const GCNSubtarget &Subtarget,
20877 const AtomicRMWInst *RMW,
20878 bool HasSystemScope) {
20879 // The remote/fine-grained access logic is different from the integer
20880 // atomics. Without AgentScopeFineGrainedRemoteMemoryAtomics support,
20881 // fine-grained access does not work, even for a device local allocation.
20882 //
20883 // With AgentScopeFineGrainedRemoteMemoryAtomics, system scoped device local
20884 // allocations work.
20885 if (HasSystemScope) {
20886 if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
20887 RMW->hasMetadata("amdgpu.no.remote.memory"))
20888 return true;
20889 if (Subtarget.hasEmulatedSystemScopeAtomics())
20890 return true;
20891 } else if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
20892 return true;
20893
20894 return RMW->hasMetadata("amdgpu.no.fine.grained.memory");
20895}
20896
20897/// \return Action to perform on AtomicRMWInsts for integer operations.
20904
20905/// Return if a flat address space atomicrmw can access private memory.
20907 const MDNode *MD = I->getMetadata(LLVMContext::MD_noalias_addrspace);
20908 return !MD ||
20910}
20911
20914 // For GAS, lower to flat atomic.
20915 return STI.hasGloballyAddressableScratch()
20918}
20919
20922 unsigned AS = RMW->getPointerAddressSpace();
20923 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
20925
20926 // 64-bit flat atomics that dynamically reside in private memory will silently
20927 // be dropped.
20928 //
20929 // Note that we will emit a new copy of the original atomic in the expansion,
20930 // which will be incrementally relegalized.
20931 const DataLayout &DL = RMW->getFunction()->getDataLayout();
20932 if (AS == AMDGPUAS::FLAT_ADDRESS &&
20933 DL.getTypeSizeInBits(RMW->getType()) == 64 &&
20936
20937 auto ReportUnsafeHWInst = [=](TargetLowering::AtomicExpansionKind Kind) {
20939 ORE.emit([=]() {
20940 return emitAtomicRMWLegalRemark(RMW) << " due to an unsafe request.";
20941 });
20942 return Kind;
20943 };
20944
20945 auto SSID = RMW->getSyncScopeID();
20946 bool HasSystemScope =
20947 SSID == SyncScope::System ||
20949 getTargetMachine().getTargetTriple(), AtomicScope::System,
20950 /*OneAddressSpace=*/true));
20951
20952 auto Op = RMW->getOperation();
20953 switch (Op) {
20955 // PCIe supports add and xchg for system atomics.
20956 return isAtomicRMWLegalXChgTy(RMW)
20959 case AtomicRMWInst::Add:
20960 // PCIe supports add and xchg for system atomics.
20962 case AtomicRMWInst::Sub:
20963 case AtomicRMWInst::And:
20964 case AtomicRMWInst::Or:
20965 case AtomicRMWInst::Xor:
20966 case AtomicRMWInst::Max:
20967 case AtomicRMWInst::Min:
20974 if (Op == AtomicRMWInst::USubCond && !Subtarget->hasCondSubInsts())
20976 if (Op == AtomicRMWInst::USubSat && !Subtarget->hasSubClampInsts())
20979 auto *IT = dyn_cast<IntegerType>(RMW->getType());
20980 if (!IT || IT->getBitWidth() != 32)
20982 }
20983
20986 if (Subtarget->hasEmulatedSystemScopeAtomics())
20988
20989 // On most subtargets, for atomicrmw operations other than add/xchg,
20990 // whether or not the instructions will behave correctly depends on where
20991 // the address physically resides and what interconnect is used in the
20992 // system configuration. On some some targets the instruction will nop,
20993 // and in others synchronization will only occur at degraded device scope.
20994 //
20995 // If the allocation is known local to the device, the instructions should
20996 // work correctly.
20997 if (RMW->hasMetadata("amdgpu.no.remote.memory"))
20999
21000 // If fine-grained remote memory works at device scope, we don't need to
21001 // do anything.
21002 if (!HasSystemScope &&
21003 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
21005
21006 // If we are targeting a remote allocated address, it depends what kind of
21007 // allocation the address belongs to.
21008 //
21009 // If the allocation is fine-grained (in host memory, or in PCIe peer
21010 // device memory), the operation will fail depending on the target.
21011 //
21012 // Note fine-grained host memory access does work on APUs or if XGMI is
21013 // used, but we do not know if we are targeting an APU or the system
21014 // configuration from the ISA version/target-cpu.
21015 if (RMW->hasMetadata("amdgpu.no.fine.grained.memory"))
21017
21020 // Atomic sub/or/xor do not work over PCI express, but atomic add
21021 // does. InstCombine transforms these with 0 to or, so undo that.
21022 // Sub-word types are not selectable and take the cmpxchg expansion.
21023 if (const Constant *ConstVal = dyn_cast<Constant>(RMW->getValOperand());
21024 ConstVal && ConstVal->isNullValue() &&
21027 }
21028
21029 // If the allocation could be in remote, fine-grained memory, the rmw
21030 // instructions may fail. cmpxchg should work, so emit that. On some
21031 // system configurations, PCIe atomics aren't supported so cmpxchg won't
21032 // even work, so you're out of luck anyway.
21033
21034 // In summary:
21035 //
21036 // Cases that may fail:
21037 // - fine-grained pinned host memory
21038 // - fine-grained migratable host memory
21039 // - fine-grained PCIe peer device
21040 //
21041 // Cases that should work, but may be treated overly conservatively.
21042 // - fine-grained host memory on an APU
21043 // - fine-grained XGMI peer device
21045 }
21046
21048 }
21049 case AtomicRMWInst::FAdd: {
21050 Type *Ty = RMW->getType();
21051
21052 // TODO: Handle REGION_ADDRESS
21053 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
21054 // DS F32 FP atomics do respect the denormal mode, but the rounding mode
21055 // is fixed to round-to-nearest-even.
21056 //
21057 // F64 / PK_F16 / PK_BF16 never flush and are also fixed to
21058 // round-to-nearest-even.
21059 //
21060 // We ignore the rounding mode problem, even in strictfp. The C++ standard
21061 // suggests it is OK if the floating-point mode may not match the calling
21062 // thread.
21063 if (Ty->isFloatTy()) {
21064 return Subtarget->hasLDSFPAtomicAddF32() ? AtomicExpansionKind::None
21066 }
21067
21068 if (Ty->isDoubleTy()) {
21069 // Ignores denormal mode, but we don't consider flushing mandatory.
21070 return Subtarget->hasLDSFPAtomicAddF64() ? AtomicExpansionKind::None
21072 }
21073
21074 if (Subtarget->hasAtomicDsPkAdd16Insts() && isV2F16OrV2BF16(Ty))
21076
21078 }
21079
21080 // LDS atomics respect the denormal mode from the mode register.
21081 //
21082 // Traditionally f32 global/buffer memory atomics would unconditionally
21083 // flush denormals, but newer targets do not flush. f64/f16/bf16 cases never
21084 // flush.
21085 //
21086 // On targets with flat atomic fadd, denormals would flush depending on
21087 // whether the target address resides in LDS or global memory. We consider
21088 // this flat-maybe-flush as will-flush.
21089 if (Ty->isFloatTy() &&
21090 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport() &&
21093
21094 // FIXME: These ReportUnsafeHWInsts are imprecise. Some of these cases are
21095 // safe. The message phrasing also should be better.
21096 if (globalMemoryFPAtomicIsLegal(*Subtarget, RMW, HasSystemScope)) {
21097 if (AS == AMDGPUAS::FLAT_ADDRESS) {
21098 // gfx942, gfx12
21099 if (Subtarget->hasAtomicFlatPkAdd16Insts() && isV2F16OrV2BF16(Ty))
21100 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21101 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS)) {
21102 // gfx90a, gfx942, gfx12
21103 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
21104 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21105
21106 // gfx942, gfx12
21107 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() && isV2BF16(Ty))
21108 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21109 } else if (AS == AMDGPUAS::BUFFER_FAT_POINTER) {
21110 // gfx90a, gfx942, gfx12
21111 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
21112 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21113
21114 // While gfx90a/gfx942 supports v2bf16 for global/flat, it does not for
21115 // buffer. gfx12 does have the buffer version.
21116 if (Subtarget->hasAtomicBufferPkAddBF16Inst() && isV2BF16(Ty))
21117 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21118 }
21119
21120 // global and flat atomic fadd f64: gfx90a, gfx942.
21121 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
21122 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21123
21124 if (AS != AMDGPUAS::FLAT_ADDRESS) {
21125 if (Ty->isFloatTy()) {
21126 // global/buffer atomic fadd f32 no-rtn: gfx908, gfx90a, gfx942,
21127 // gfx11+.
21128 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21129 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21130 // global/buffer atomic fadd f32 rtn: gfx90a, gfx942, gfx11+.
21131 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21132 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21133 } else {
21134 // gfx908
21135 if (RMW->use_empty() &&
21136 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
21137 isV2F16(Ty))
21138 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21139 }
21140 }
21141
21142 // flat atomic fadd f32: gfx942, gfx11+.
21143 if (AS == AMDGPUAS::FLAT_ADDRESS && Ty->isFloatTy()) {
21144 if (Subtarget->hasFlatAtomicFaddF32Inst())
21145 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21146
21147 // If it is in flat address space, and the type is float, we will try to
21148 // expand it, if the target supports global and lds atomic fadd. The
21149 // reason we need that is, in the expansion, we emit the check of
21150 // address space. If it is in global address space, we emit the global
21151 // atomic fadd; if it is in shared address space, we emit the LDS atomic
21152 // fadd.
21153 if (Subtarget->hasLDSFPAtomicAddF32()) {
21154 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21156 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21158 }
21159 }
21160 }
21161
21163 }
21165 case AtomicRMWInst::FMax: {
21166 Type *Ty = RMW->getType();
21167
21168 // LDS float and double fmin/fmax were always supported.
21169 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
21170 return Ty->isFloatTy() || Ty->isDoubleTy() ? AtomicExpansionKind::None
21172 }
21173
21174 if (globalMemoryFPAtomicIsLegal(*Subtarget, RMW, HasSystemScope)) {
21175 // For flat and global cases:
21176 // float, double in gfx7. Manual claims denormal support.
21177 // Removed in gfx8.
21178 // float, double restored in gfx10.
21179 // double removed again in gfx11, so only f32 for gfx11/gfx12.
21180 //
21181 // For gfx9, gfx90a and gfx942 support f64 for global (same as fadd), but
21182 // no f32.
21183 if (AS == AMDGPUAS::FLAT_ADDRESS) {
21184 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
21185 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21186 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
21187 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21188 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS) ||
21190 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
21191 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21192 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
21193 return ReportUnsafeHWInst(AtomicExpansionKind::None);
21194 }
21195 }
21196
21198 }
21201 default:
21203 }
21204
21205 llvm_unreachable("covered atomicrmw op switch");
21206}
21207
21214
21221
21224 const AtomicCmpXchgInst *CmpX) const {
21225 unsigned AddrSpace = CmpX->getPointerAddressSpace();
21226 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS)
21228
21229 if (AddrSpace != AMDGPUAS::FLAT_ADDRESS || !flatInstrMayAccessPrivate(CmpX))
21231
21232 const DataLayout &DL = CmpX->getDataLayout();
21233
21234 Type *ValTy = CmpX->getNewValOperand()->getType();
21235
21236 // If a 64-bit flat atomic may alias private, we need to avoid using the
21237 // atomic in the private case.
21238 return DL.getTypeSizeInBits(ValTy) == 64 ? AtomicExpansionKind::CustomExpand
21240}
21241
21242const TargetRegisterClass *
21243SITargetLowering::getRegClassFor(MVT VT, bool isDivergent) const {
21245 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
21246 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
21247 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
21248 : &AMDGPU::SReg_32RegClass;
21249 if (!TRI->isSGPRClass(RC) && !isDivergent)
21250 return TRI->getEquivalentSGPRClass(RC);
21251 if (TRI->isSGPRClass(RC) && isDivergent) {
21252 if (Subtarget->hasGFX90AInsts())
21253 return TRI->getEquivalentAVClass(RC);
21254 return TRI->getEquivalentVGPRClass(RC);
21255 }
21256
21257 return RC;
21258}
21259
21260// FIXME: This is a workaround for DivergenceAnalysis not understanding always
21261// uniform values (as produced by the mask results of control flow intrinsics)
21262// used outside of divergent blocks. The phi users need to also be treated as
21263// always uniform.
21264//
21265// FIXME: DA is no longer in-use. Does this still apply to UniformityAnalysis?
21266static bool hasCFUser(const Value *V, SmallPtrSet<const Value *, 16> &Visited,
21267 unsigned WaveSize) {
21268 // FIXME: We assume we never cast the mask results of a control flow
21269 // intrinsic.
21270 // Early exit if the type won't be consistent as a compile time hack.
21271 IntegerType *IT = dyn_cast<IntegerType>(V->getType());
21272 if (!IT || IT->getBitWidth() != WaveSize)
21273 return false;
21274
21275 if (!isa<Instruction>(V))
21276 return false;
21277 if (!Visited.insert(V).second)
21278 return false;
21279 bool Result = false;
21280 for (const auto *U : V->users()) {
21282 if (V == U->getOperand(1)) {
21283 switch (Intrinsic->getIntrinsicID()) {
21284 default:
21285 Result = false;
21286 break;
21287 case Intrinsic::amdgcn_if_break:
21288 case Intrinsic::amdgcn_if:
21289 case Intrinsic::amdgcn_else:
21290 Result = true;
21291 break;
21292 }
21293 }
21294 if (V == U->getOperand(0)) {
21295 switch (Intrinsic->getIntrinsicID()) {
21296 default:
21297 Result = false;
21298 break;
21299 case Intrinsic::amdgcn_end_cf:
21300 case Intrinsic::amdgcn_loop:
21301 Result = true;
21302 break;
21303 }
21304 }
21305 } else {
21306 Result = hasCFUser(U, Visited, WaveSize);
21307 }
21308 if (Result)
21309 break;
21310 }
21311 return Result;
21312}
21313
21315 const Value *V) const {
21316 if (const CallInst *CI = dyn_cast<CallInst>(V)) {
21317 if (CI->isInlineAsm()) {
21318 // FIXME: This cannot give a correct answer. This should only trigger in
21319 // the case where inline asm returns mixed SGPR and VGPR results, used
21320 // outside the defining block. We don't have a specific result to
21321 // consider, so this assumes if any value is SGPR, the overall register
21322 // also needs to be SGPR.
21323 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
21325 MF.getDataLayout(), Subtarget->getRegisterInfo(), *CI);
21326 for (auto &TC : TargetConstraints) {
21327 if (TC.Type == InlineAsm::isOutput) {
21329 const TargetRegisterClass *RC =
21330 getRegForInlineAsmConstraint(SIRI, TC.ConstraintCode,
21331 TC.ConstraintVT)
21332 .second;
21333 if (RC && SIRI->isSGPRClass(RC))
21334 return true;
21335 }
21336 }
21337 }
21338 }
21340 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21341}
21342
21344 for (SDUse &Use : N->uses()) {
21346 if (getBasePtrIndex(M) == Use.getOperandNo())
21347 return true;
21348 }
21349 }
21350 return false;
21351}
21352
21354 SDValue N1) const {
21355 if (!N0.hasOneUse())
21356 return false;
21357 // Take care of the opportunity to keep N0 uniform
21358 if (N0->isDivergent() || !N1->isDivergent())
21359 return true;
21360 // Check if we have a good chance to form the memory access pattern with the
21361 // base and offset
21362 return (DAG.isBaseWithConstantOffset(N0) &&
21364}
21365
21367 Register N0, Register N1) const {
21368 return MRI.hasOneNonDBGUse(N0); // FIXME: handle regbanks
21369}
21370
21373 // Propagate metadata set by AMDGPUAnnotateUniformValues to the MMO of a load.
21375 if (I.getMetadata("amdgpu.noclobber"))
21376 Flags |= MONoClobber;
21377 if (I.getMetadata("amdgpu.last.use"))
21378 Flags |= MOLastUse;
21379 return Flags;
21380}
21381
21383 Instruction *AI) const {
21384 // Given: atomicrmw fadd ptr %addr, float %val ordering
21385 //
21386 // With this expansion we produce the following code:
21387 // [...]
21388 // %is.shared = call i1 @llvm.amdgcn.is.shared(ptr %addr)
21389 // br i1 %is.shared, label %atomicrmw.shared, label %atomicrmw.check.private
21390 //
21391 // atomicrmw.shared:
21392 // %cast.shared = addrspacecast ptr %addr to ptr addrspace(3)
21393 // %loaded.shared = atomicrmw fadd ptr addrspace(3) %cast.shared,
21394 // float %val ordering
21395 // br label %atomicrmw.phi
21396 //
21397 // atomicrmw.check.private:
21398 // %is.private = call i1 @llvm.amdgcn.is.private(ptr %int8ptr)
21399 // br i1 %is.private, label %atomicrmw.private, label %atomicrmw.global
21400 //
21401 // atomicrmw.private:
21402 // %cast.private = addrspacecast ptr %addr to ptr addrspace(5)
21403 // %loaded.private = load float, ptr addrspace(5) %cast.private
21404 // %val.new = fadd float %loaded.private, %val
21405 // store float %val.new, ptr addrspace(5) %cast.private
21406 // br label %atomicrmw.phi
21407 //
21408 // atomicrmw.global:
21409 // %cast.global = addrspacecast ptr %addr to ptr addrspace(1)
21410 // %loaded.global = atomicrmw fadd ptr addrspace(1) %cast.global,
21411 // float %val ordering
21412 // br label %atomicrmw.phi
21413 //
21414 // atomicrmw.phi:
21415 // %loaded.phi = phi float [ %loaded.shared, %atomicrmw.shared ],
21416 // [ %loaded.private, %atomicrmw.private ],
21417 // [ %loaded.global, %atomicrmw.global ]
21418 // br label %atomicrmw.end
21419 //
21420 // atomicrmw.end:
21421 // [...]
21422 //
21423 //
21424 // For 64-bit atomics which may reside in private memory, we perform a simpler
21425 // version that only inserts the private check, and uses the flat operation.
21426
21427 IRBuilder<> Builder(AI);
21428 LLVMContext &Ctx = Builder.getContext();
21429
21430 auto *RMW = dyn_cast<AtomicRMWInst>(AI);
21431 const unsigned PtrOpIdx = RMW ? AtomicRMWInst::getPointerOperandIndex()
21433 Value *Addr = AI->getOperand(PtrOpIdx);
21434
21435 /// TODO: Only need to check private, then emit flat-known-not private (no
21436 /// need for shared block, or cast to global).
21438
21439 Align Alignment;
21440 if (RMW)
21441 Alignment = RMW->getAlign();
21442 else if (CX)
21443 Alignment = CX->getAlign();
21444 else
21445 llvm_unreachable("unhandled atomic operation");
21446
21447 // FullFlatEmulation is true if we need to issue the private, shared, and
21448 // global cases.
21449 //
21450 // If this is false, we are only dealing with the flat-targeting-private case,
21451 // where we only insert a check for private and still use the flat instruction
21452 // for global and shared.
21453
21454 bool FullFlatEmulation =
21455 RMW && RMW->getOperation() == AtomicRMWInst::FAdd &&
21456 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21457 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21458 RMW->getType()->isDoubleTy()));
21459
21460 // If the return value isn't used, do not introduce a false use in the phi.
21461 bool ReturnValueIsUsed = !AI->use_empty();
21462
21463 BasicBlock *BB = Builder.GetInsertBlock();
21464 Function *F = BB->getParent();
21465 BasicBlock *ExitBB =
21466 BB->splitBasicBlock(Builder.GetInsertPoint(), "atomicrmw.end");
21467 BasicBlock *SharedBB = nullptr;
21468
21469 BasicBlock *CheckPrivateBB = BB;
21470 if (FullFlatEmulation) {
21471 SharedBB = BasicBlock::Create(Ctx, "atomicrmw.shared", F, ExitBB);
21472 CheckPrivateBB =
21473 BasicBlock::Create(Ctx, "atomicrmw.check.private", F, ExitBB);
21474 }
21475
21476 BasicBlock *PrivateBB =
21477 BasicBlock::Create(Ctx, "atomicrmw.private", F, ExitBB);
21478 BasicBlock *GlobalBB = BasicBlock::Create(Ctx, "atomicrmw.global", F, ExitBB);
21479 BasicBlock *PhiBB = BasicBlock::Create(Ctx, "atomicrmw.phi", F, ExitBB);
21480
21481 std::prev(BB->end())->eraseFromParent();
21482 Builder.SetInsertPoint(BB);
21483
21484 Value *LoadedShared = nullptr;
21485 if (FullFlatEmulation) {
21486 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21487 {Addr}, nullptr, "is.shared");
21488 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21489 Builder.SetInsertPoint(SharedBB);
21490 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21492
21493 Instruction *Clone = AI->clone();
21494 Clone->insertInto(SharedBB, SharedBB->end());
21495 Clone->getOperandUse(PtrOpIdx).set(CastToLocal);
21496 LoadedShared = Clone;
21497
21498 Builder.CreateBr(PhiBB);
21499 Builder.SetInsertPoint(CheckPrivateBB);
21500 }
21501
21502 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21503 {Addr}, nullptr, "is.private");
21504 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21505
21506 Builder.SetInsertPoint(PrivateBB);
21507
21508 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21510
21511 Value *LoadedPrivate;
21512 if (RMW) {
21513 LoadedPrivate = Builder.CreateAlignedLoad(
21514 RMW->getType(), CastToPrivate, RMW->getAlign(), RMW->isVolatile(),
21515 "loaded.private");
21516
21517 Value *NewVal = buildAtomicRMWValue(RMW->getOperation(), Builder,
21518 LoadedPrivate, RMW->getValOperand());
21519
21520 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign(),
21521 RMW->isVolatile());
21522 } else {
21523 auto [ResultLoad, Equal] = buildCmpXchgValue(
21524 Builder, CastToPrivate, CX->getCompareOperand(), CX->getNewValOperand(),
21525 CX->getAlign(), CX->isVolatile());
21526
21527 Value *Insert = Builder.CreateInsertValue(PoisonValue::get(CX->getType()),
21528 ResultLoad, 0);
21529 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21530 }
21531
21532 Builder.CreateBr(PhiBB);
21533
21534 Builder.SetInsertPoint(GlobalBB);
21535
21536 // Continue using a flat instruction if we only emitted the check for private.
21537 Instruction *LoadedGlobal = AI;
21538 if (FullFlatEmulation) {
21539 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21541 AI->getOperandUse(PtrOpIdx).set(CastToGlobal);
21542 }
21543
21544 AI->removeFromParent();
21545 AI->insertInto(GlobalBB, GlobalBB->end());
21546
21547 // The new atomicrmw may go through another round of legalization later.
21548 if (!FullFlatEmulation) {
21549 // We inserted the runtime check already, make sure we do not try to
21550 // re-expand this.
21551 // TODO: Should union with any existing metadata.
21552 MDBuilder MDB(F->getContext());
21553 MDNode *RangeNotPrivate =
21556 LoadedGlobal->setMetadata(LLVMContext::MD_noalias_addrspace,
21557 RangeNotPrivate);
21558 }
21559
21560 Builder.CreateBr(PhiBB);
21561
21562 Builder.SetInsertPoint(PhiBB);
21563
21564 if (ReturnValueIsUsed) {
21565 PHINode *Loaded = Builder.CreatePHI(AI->getType(), 3);
21566 AI->replaceAllUsesWith(Loaded);
21567 if (FullFlatEmulation)
21568 Loaded->addIncoming(LoadedShared, SharedBB);
21569 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21570 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21571 Loaded->takeName(AI);
21572 }
21573
21574 Builder.CreateBr(ExitBB);
21575}
21576
21578 unsigned PtrOpIdx) {
21579 Value *PtrOp = I->getOperand(PtrOpIdx);
21582
21583 Type *FlatPtr = PointerType::get(I->getContext(), AMDGPUAS::FLAT_ADDRESS);
21584 Value *ASCast = CastInst::CreatePointerCast(PtrOp, FlatPtr, "scratch.ascast",
21585 I->getIterator());
21586 I->setOperand(PtrOpIdx, ASCast);
21587}
21588
21591
21594
21597 if (const auto *ConstVal = dyn_cast<Constant>(AI->getValOperand());
21598 ConstVal && ConstVal->isNullValue() &&
21600 // atomicrmw or %ptr, 0 -> atomicrmw add %ptr, 0
21602
21603 // We may still need the private-alias-flat handling below.
21604
21605 // TODO: Skip this for cases where we cannot access remote memory.
21606 }
21607 }
21608
21609 // The non-flat expansions should only perform the de-canonicalization of
21610 // identity values.
21612 return;
21613
21615}
21616
21623
21627
21629 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21630}
21631
21633 if (SI->getPointerAddressSpace() == AMDGPUAS::PRIVATE_ADDRESS)
21634 return convertScratchAtomicToFlatAtomic(SI, SI->getPointerOperandIndex());
21635
21637 "Expand Atomic Store only handles SCRATCH -> FLAT conversion");
21638}
static bool isMul(MachineInstr *MI)
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
static constexpr std::pair< ImplicitArgumentMask, StringLiteral > ImplicitAttrs[]
static bool allUsesHaveSourceMods(MachineInstr &MI, MachineRegisterInfo &MRI, unsigned CostThreshold=4)
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.
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
Function Alias Analysis Results
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
@ DEFAULT
Default weight is used in cases when there is no dedicated execution weight set.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< SDByteProvider > calculateByteProvider(SDValue Op, unsigned Index, unsigned Depth, std::optional< uint64_t > VectorIndex, unsigned StartingIndex=0, MutableArrayRef< uint8_t > ByteMask={})
dxil translate DXIL Translate Metadata
static bool isSigned(unsigned Opcode)
Utilities for dealing with flags related to floating point properties and mode controls.
AMD GCN specific subclass of TargetSubtarget.
Provides analysis for querying information about KnownBits during GISel passes.
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
iv Induction Variable Users
Definition IVUsers.cpp:48
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RegName(no)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Contains matchers for matching SSA Machine Instructions.
static bool isUndef(const MachineInstr &MI)
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
uint64_t IntrinsicInst * II
#define P(N)
if(PassOpts->AAPipeline)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
Contains matchers for matching SelectionDAG nodes and values.
static void r0(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:39
static void r3(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:57
static void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:51
static void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:45
#define FP_DENORM_FLUSH_NONE
Definition SIDefines.h:1507
#define FP_DENORM_FLUSH_IN_FLUSH_OUT
Definition SIDefines.h:1504
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::pair< SDValue, SDValue > splitTFEValueAndStatus(SDValue Op, EVT VT, const SDLoc &DL, SelectionDAG &DAG)
static std::optional< ByteProvider< SDValue > > handleMulOperand(const SDValue &MulOperand)
static ISD::CondCode tryReduceF64CompareToHiHalf(const ISD::CondCode CC, const SDValue LHS, const SDValue RHS, const SelectionDAG &DAG)
static Register getIndirectSGPRIdx(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static SDValue emitNonHSAIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static EVT memVTFromLoadIntrData(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc)
static unsigned getExtOpcodeForPromotedOp(SDValue Op)
static void expand64BitV_CNDMASK(MachineInstr &MI, MachineBasicBlock *BB)
static 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
static const LaneMaskConstants & get(const GCNSubtarget &ST)
static const fltSemantics & IEEEsingle()
Definition APFloat.h:304
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:361
static const fltSemantics & IEEEhalf()
Definition APFloat.h:302
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
Definition APFloat.h:1224
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:6034
LLVM_READONLY int getExactLog2Abs() const
Definition APFloat.h:1639
bool isNegative() const
Definition APFloat.h:1583
bool isNormal() const
Definition APFloat.h:1587
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
Definition APFloat.h:1192
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
Definition APFloat.h:1242
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition APFloat.h:1202
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition APFloat.h:1183
bool isInfinity() const
Definition APFloat.h:1580
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1057
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
Definition APInt.h:202
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
Definition APInt.h:254
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:376
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
Definition APInt.h:462
unsigned countr_zero() const
Count the number of trailing zero bits.
Definition APInt.h:1659
bool isOneBitSet(unsigned BitNo) const
Determine if this APInt Value only has the specified bit set.
Definition APInt.h:362
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
Definition APInt.h:337
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition APInt.h:292
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
Definition APInt.h:1241
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
Definition APInt.h:1225
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Check if an argument has a given attribute.
Definition Function.cpp:336
const Function * getParent() const
Definition Argument.h:44
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
An instruction that atomically checks whether a specified value is in a memory location,...
bool isVolatile() const
Return true if this is a cmpxchg from a volatile memory location.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
static unsigned getPointerOperandIndex()
an instruction that atomically reads a memory location, combines it with another value,...
static unsigned getPointerOperandIndex()
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ Add
*p = old + v
@ FAdd
*p = old + v
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ Sub
*p = old - v
@ And
*p = old & v
@ Xor
*p = old ^ v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ FSub
*p = old - v
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
@ Nand
*p = ~(old & v)
void setOperation(BinOp Operation)
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
static LLVM_ABI StringRef getOperationName(BinOp Op)
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
bool isCompareAndSwap() const
Returns true if this SDNode represents cmpxchg atomic operation, false otherwise.
This class holds the attributes for a particular argument, parameter, function, or return value.
Definition Attributes.h:410
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM_ABI bool getValueAsBool() const
Return the attribute's value as a boolean.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator end()
Definition BasicBlock.h:459
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
A "pseudo-class" with methods for operating on BUILD_VECTORs.
Represents known origin of an individual byte in combine pattern.
static ByteProvider getConstantZero()
static ByteProvider getSrc(std::optional< ISelOp > Val, int64_t ByteOffset, int64_t VectorOffset)
std::optional< ISelOp > Src
CCState - This class holds information needed while lowering arguments and return values.
MachineFunction & getMachineFunction() const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
LLVM_ABI void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
bool isAllocated(MCRegister Reg) const
isAllocated - Return true if the specified register (or an alias) is allocated.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
bool isTailCall() const
static LLVM_ABI CastInst * CreatePointerCast(Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction.
const APFloat & getValueAPF() const
bool isPosZero() const
Return true if the value is positive zero.
bool isOne() const
Returns true if this value is exactly +1.0.
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isNegative() const
Return true if the value is negative.
bool isInfinity() const
Return true if the value is an infinity.
This is the shared class of boolean and integer constants.
Definition Constants.h:87
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition Constants.h:219
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
Definition Constant.h:43
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
bool isBigEndian() const
Definition DataLayout.h:218
A debug info location.
Definition DebugLoc.h:126
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:305
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Register DemoteRegister
DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg allocated to hold a pointer to ...
LLVM_ABI const Value * getValueFromVirtualReg(Register Vreg)
This method is called from TargetLowerinInfo::isSDNodeSourceOfDivergence to get the Value correspondi...
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:212
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Definition Function.cpp:360
iterator_range< arg_iterator > args()
Definition Function.h:877
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:765
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:273
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:356
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
Definition Function.cpp:806
size_t arg_size() const
Definition Function.h:886
Argument * getArg(unsigned i) const
Definition Function.h:871
const SIInstrInfo * getInstrInfo() const override
bool hasMadF16() const
unsigned getInstCacheLineSize() const
Instruction cache line size in bytes (64 for pre-GFX11, 128 for GFX11+).
const SIRegisterInfo * getRegisterInfo() const override
bool hasMin3Max3_16() const
bool supportsWaveWideBPermute() const
unsigned getMaxPrivateElementSize(bool ForBufferRSrc=false) const
bool isWave64() const
bool hasPrivateSegmentBuffer() const
const MachineFunction & getMachineFunction() const
void computeKnownBitsImpl(Register R, KnownBits &Known, const APInt &DemandedElts, unsigned Depth=0)
bool isDivergentAtDef(ConstValueRefT V) const
Whether V is divergent at its definition.
LLVM_ABI unsigned getAddressSpace() const
const GlobalValue * getGlobal() const
bool hasExternalLinkage() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Definition Globals.cpp:205
Type * getValueType() const
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2917
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
constexpr unsigned getScalarSizeInBits() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
static LLT integer(unsigned SizeInBits)
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI SyncScope::ID getOrInsertSyncScopeID(StringRef SSN)
getOrInsertSyncScopeID - Maps synchronization scope name to synchronization scope ID.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
static unsigned getPointerOperandIndex()
This class is used to represent ISD::LOAD nodes.
Describe properties that are true of each instruction in the target description file.
unsigned getID() const
getID() - Return the register class ID number.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
iterator begin() const
begin/end - Return all of the registers in this class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
LLVM_ABI MDNode * createRange(const APInt &Lo, const APInt &Hi)
Return metadata describing the range [Lo, Hi).
Definition MDBuilder.cpp:96
Metadata node.
Definition Metadata.h:1081
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1437
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
Machine Value Type.
SimpleValueType SimpleTy
uint64_t getScalarSizeInBits() const
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto all_valuetypes()
SimpleValueType Iteration.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
bool hasCalls() const
Return true if the current function has any function calls.
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
bool hasStackObjects() const
Return true if there are any stack objects in this function.
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
Representation of each machine instruction.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static MachineOperand CreateImm(int64_t Val)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI bool isLiveIn(Register Reg) const
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register getLiveInVirtReg(MCRegister PReg) const
getLiveInVirtReg - If PReg is a live-in physical register, return the corresponding live-in virtual r...
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
EVT getMemoryVT() const
Return the type of the in-memory value.
bool onlyWritesMemory() const
Whether this function only (at most) writes memory.
Definition ModRef.h:252
bool doesNotAccessMemory() const
Whether this function accesses no memory.
Definition ModRef.h:246
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
Definition ModRef.h:249
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition Module.h:325
The optimization diagnostic interface.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Diagnostic information for applied optimization remarks.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
Definition Type.cpp:887
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition Register.h:72
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool isDivergent() const
bool hasOneUse() const
Return true if there is exactly one use of this node.
value_iterator value_end() const
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
op_iterator op_end() const
bool isAnyAdd() const
Returns true if the node type is ADD or PTRADD.
value_iterator value_begin() const
op_iterator op_begin() const
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isUndef() const
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
bool isMachineOpcode() const
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getMachineOpcode() const
unsigned getOpcode() const
unsigned getNumOperands() const
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
const AMDGPUGWSResourcePseudoSourceValue * getGWSPSV(const AMDGPUTargetMachine &TM)
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static bool isVGPRClass(const TargetRegisterClass *RC)
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
bool isTypeDesirableForOp(unsigned Op, EVT VT) const override
Return true if the target has native support for the specified value type and it is 'desirable' to us...
SDNode * PostISelFolding(MachineSDNode *N, SelectionDAG &DAG) const override
Fold the instructions after selecting them.
SDValue splitTernaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachineSDNode * wrapAddr64Rsrc(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr) const
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool requiresUniformRegister(MachineFunction &MF, const Value *V) const override
Allows target to decide about the register class of the specific value that is live outside the defin...
bool isFMADLegal(const SelectionDAG &DAG, const SDNode *N) const override
Returns true if be combined with to form an ISD::FMAD.
AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void bundleInstWithWaitcnt(MachineInstr &MI) const
Insert MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
SDValue lowerROTR(SDValue Op, SelectionDAG &DAG) const
MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override
Return the type to use for a scalar shift opcode, given the shifted amount type.
SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
MVT getPointerTy(const DataLayout &DL, unsigned AS) const override
Map address space 7 to MVT::amdgpuBufferFatPointer because that's its in-memory representation.
bool denormalsEnabledForType(const SelectionDAG &DAG, EVT VT) const
void insertCopiesSplitCSR(MachineBasicBlock *Entry, const SmallVectorImpl< MachineBasicBlock * > &Exits) const override
Insert explicit copies in entry and exit blocks.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
SDNode * legalizeTargetIndependentNode(SDNode *Node, SelectionDAG &DAG) const
Legalize target independent instructions (e.g.
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
SDValue lowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const
const GCNSubtarget * getSubtarget() const
bool enableAggressiveFMAFusion(EVT VT) const override
Return true if target always benefits from combining into FMA for a given value type.
bool shouldEmitGOTReloc(const GlobalValue *GV) const
SDValue splitUnaryVectorOp(SDValue Op, SelectionDAG &DAG) const
SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool isCanonicalized(SelectionDAG &DAG, SDValue Op, SDNodeFlags UserFlags={}, unsigned MaxDepth=5) const
void allocateSpecialInputSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocateLDSKernelId(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const
bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const override
void allocateHSAUserSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent) const override
Return the register class that should be used for the specified value type.
void AddMemOpInit(MachineInstr &MI) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
bool isLegalGlobalAddressingMode(const AddrMode &AM) const
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
Align getPrefLoopAlignment(MachineLoop *ML) const override
Return the preferred loop alignment.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
void emitExpandAtomicStore(StoreInst *SI) const override
Perform a atomic store using a target-specific way.
AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
Align computeKnownAlignForTargetInstr(GISelValueTracking &Analysis, Register R, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine the known alignment for the pointer value R.
bool getAsmOperandConstVal(SDValue Op, uint64_t &Val) const
bool isShuffleMaskLegal(ArrayRef< int >, EVT) const override
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
void emitExpandAtomicLoad(LoadInst *LI) const override
Perform a atomic load using a target-specific way.
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const override
Determine known bits of a pointer to a known valid stack object.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
LLT getPreferredShiftAmountTy(LLT Ty) const override
Return the preferred type to use for a shift opcode, given the shifted amount type is ShiftValueTy.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const override
True if target has some particular form of dealing with pointer arithmetic semantics for pointers wit...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &, const CallBase &, MachineFunction &MF, unsigned IntrinsicID) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
void allocateSpecialInputVGPRsFixed(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments in fixed registers.
MachineBasicBlock * emitGWSMemViolTestLoop(MachineInstr &MI, MachineBasicBlock *BB) const
bool getAddrModeArguments(const IntrinsicInst *I, SmallVectorImpl< Value * > &Ops, Type *&AccessTy) const override
CodeGenPrepare sinks address calculations into the same BB as Load/Store instructions reading the add...
bool checkAsmConstraintValA(SDValue Op, uint64_t Val, unsigned MaxSize=64) const
bool shouldEmitFixup(const GlobalValue *GV) const
MachineBasicBlock * splitKillBlock(MachineInstr &MI, MachineBasicBlock *BB) const
void emitExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) const override
Perform a cmpxchg expansion using a target-specific method.
bool canTransformPtrArithOutOfBounds(const Function &F, EVT PtrVT) const override
True if the target allows transformations of in-bounds pointer arithmetic that cause out-of-bounds in...
bool hasMemSDNodeUser(SDNode *N) const
bool isSDNodeSourceOfDivergence(const SDNode *N, FunctionLoweringInfo *FLI, UniformityInfo *UA) const override
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
bool isEligibleForTailCallOptimization(SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SmallVectorImpl< ISD::InputArg > &Ins, SelectionDAG &DAG) const
bool isMemOpHasNoClobberedMemOperand(const SDNode *N) const
bool isLegalFlatAddressingMode(const AddrMode &AM, unsigned AddrSpace) const
SDValue LowerCallResult(SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals, bool isThisReturn, SDValue ThisVal) const
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode, EVT DestVT, EVT SrcVT) const override
Return true if an fpext operation input to an Opcode operation is free (for instance,...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
Assign the register class depending on the number of bits set in the writemask.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void allocateSpecialInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments at the end of allocated user arguments.
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
static bool isNonGlobalAddrSpace(unsigned AS)
void emitExpandAtomicAddrSpacePredicate(Instruction *AI) const
MachineSDNode * buildRSRC(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr, uint32_t RsrcDword1, uint64_t RsrcDword2And3) const
Return a resource descriptor with the 'Add TID' bit enabled The TID (Thread ID) is multiplied by the ...
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain targets require unusual breakdowns of certain types.
bool mayBeEmittedAsTailCall(const CallInst *) const override
Return true if the target may be able emit the call instruction as a tail call.
void passSpecialInputs(CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info, SmallVectorImpl< std::pair< unsigned, SDValue > > &RegsToPass, SmallVectorImpl< SDValue > &MemOpChains, SDValue Chain) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool checkAsmConstraintVal(SDValue Op, StringRef Constraint, uint64_t Val) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
static bool shouldExpandVectorDynExt(unsigned EltSize, unsigned NumElem, bool IsDivergentIdx, const GCNSubtarget *Subtarget)
Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be expanded into a set of cmp...
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool supportSplitCSR(MachineFunction *MF) const override
Return true if the target supports that a subset of CSRs for the given machine function is handled ex...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
bool allowsMisalignedMemoryAccesses(LLT Ty, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const override
LLT handling variant.
bool canMergeStoresTo(unsigned AS, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const
SITargetLowering(const TargetMachine &tm, const GCNSubtarget &STI)
void computeKnownBitsForTargetInstr(GISelValueTracking &Analysis, Register R, KnownBits &Known, const APInt &DemandedElts, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool isFreeAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g.
bool shouldEmitPCReloc(const GlobalValue *GV) const
AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
void initializeSplitCSR(MachineBasicBlock *Entry) const override
Perform necessary initialization to handle a subset of CSRs explicitly via copies.
void allocateSpecialEntryInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocatePreloadKernArgSGPRs(CCState &CCInfo, SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< ISD::InputArg > &Ins, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue copyToM0(SelectionDAG &DAG, SDValue Chain, const SDLoc &DL, SDValue V) const
SDValue splitBinaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
MVT getPointerMemTy(const DataLayout &DL, unsigned AS) const override
Similarly, the in-memory representation of a p7 is {p8, i32}, aka v8i32 when padding is added.
void allocateSystemSGPRs(CCState &CCInfo, MachineFunction &MF, SIMachineFunctionInfo &Info, CallingConv::ID CallConv, bool IsShader) const
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const override
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT, unsigned Opcode)
Convert Op, which must be of integer type, to the integer type VT, by either any/sign/zero-extending ...
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
bool isKnownNeverSNaN(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI bool isConstantIntBuildVectorOrConstantInt(SDValue N, bool AllowOpaques=true) const
Test whether the given value is a constant int or similar node.
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS, const SDNodeFlags Flags=SDNodeFlags())
Return an AddrSpaceCastSDNode.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI bool SignBitIsZeroFP(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero, for a floating-point value.
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO)
Gets a node for an atomic op, produces result (if relevant) and chain and takes 2 operands.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by first bitcasting (from potentia...
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
const TargetMachine & getTarget() const
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getErrorMergeValues(ArrayRef< EVT > ResultTypes, SDValue Chain, const SDLoc &dl)
Return poison values for each of ResultTypes, substituting Chain for any result of type MVT::Other,...
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
const SDValue & setRoot(SDValue N)
Set the current root tag of the SelectionDAG.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
int getMaskElt(unsigned Idx) const
ArrayRef< int > getMask() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition SmallSet.h:176
bool empty() const
Definition SmallSet.h:169
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Information about stack frame layout on the target.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
TargetInstrInfo - Interface to description of machine instruction set.
Type * Ty
Same as OrigTy, or partially legalized for soft float libcalls.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setHasExtractBitsInsn(bool hasExtractInsn=true)
Tells the code generator that the target has BitExtract instructions.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
virtual Align getPrefLoopAlignment(MachineLoop *ML=nullptr) const
Return the preferred loop alignment.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS=0) const
Return the in-memory pointer type for the given address space, defaults to the pointer type from the ...
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
std::vector< AsmOperandInfo > AsmOperandInfoVector
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminimumnum/fmaximumnum into multiple comparison with selects.
virtual bool isTypeDesirableForOp(unsigned, EVT VT) const
Return true if the target has native support for the specified value type and it is 'desirable' to us...
virtual void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const
Determine known bits of a pointer to a known valid stack object.
std::pair< SDValue, SDValue > scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Turn load of vector type into a load of the individual elements.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
TargetLowering(const TargetLowering &)=delete
virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
virtual AsmOperandInfoVector ParseConstraints(const DataLayout &DL, const TargetRegisterInfo *TRI, const CallBase &Call) const
Split up the constraint string from the inline assembly value into the specific constraints and their...
SDValue expandRoundInexactToOdd(EVT ResultVT, SDValue Op, const SDLoc &DL, SelectionDAG &DAG) const
Truncate Op to ResultVT.
virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, SelectionDAG *DAG=nullptr) const
Determines the constraint code and constraint type to use for the specific AsmOperandInfo,...
SDValue annotateStackObjectPointer(SDValue Ptr, SelectionDAG &DAG, const SDLoc &DL, Align Alignment) const
Annotate a stack object pointer with known-bits assertions.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs.
Primary interface to the complete machine description for the target machine.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
const Triple & getTargetTriple() const
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
TargetOptions Options
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
OSType getOS() const
Get the parsed operating system type of this triple.
Definition Triple.h:523
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:339
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition Type.h:147
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:363
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition Type.h:144
bool isFunctionTy() const
True if this is an instance of FunctionType.
Definition Type.h:268
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
LLVM_ABI const fltSemantics & getFltSemantics() const
Definition Type.cpp:96
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Definition Use.cpp:35
LLVM_ABI void set(Value *Val)
Definition Value.h:876
User * getUser() const
Returns the User that contains this Use.
Definition Use.h:61
const Use & getOperandUse(unsigned i) const
Definition User.h:220
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
bool hasOneUse() const
Return true if there is exactly one use of this value.
Definition Value.h:441
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:260
iterator_range< user_iterator > users()
Definition Value.h:428
bool use_empty() const
Definition Value.h:348
iterator_range< use_iterator > uses()
Definition Value.h:382
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
Definition TypeSize.h:176
self_iterator getIterator()
Definition ilist_node.h:123
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ STREAMOUT_REGISTER
Internal address spaces. Can be freely renumbered.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char NumVGPRs[]
Key for Kernel::CodeProps::Metadata::mNumVGPRs.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
LLVM_READONLY const MIMGG16MappingInfo * getMIMGG16MappingInfo(unsigned G)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isShader(CallingConv::ID CC)
bool shouldEmitConstantsToTextSection(const Triple &TT)
bool isFlatGlobalAddrSpace(unsigned AS)
const uint64_t FltRoundToHWConversionTable
bool isGFX12Plus(const MCSubtargetInfo &STI)
unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
bool isGFX13(const MCSubtargetInfo &STI)
bool hasValueInRangeLikeMetadata(const MDNode &MD, int64_t Val)
Checks if Val is inside MD, a !range-like metadata.
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READNONE constexpr bool mayTailCallThisCC(CallingConv::ID CC)
Return true if we might ever do TCO for calls with this calling convention.
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool getMUBUFTfe(unsigned Opc)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
bool isGFX11Plus(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
std::tuple< char, unsigned, unsigned > parseAsmConstraintPhysReg(StringRef Constraint)
Returns a valid charcode or 0 in the first entry if this is a valid physical register constraint.
bool isGFX10Plus(const MCSubtargetInfo &STI)
bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale, unsigned BFmt, unsigned BScale)
bool isUniformMMO(const MachineMemOperand *MMO)
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
uint32_t decodeFltRoundToHWConversionTable(uint32_t FltRounds)
Read the hardware rounding mode equivalent of a AMDGPUFltRounds value.
bool isExtendedGlobalAddrSpace(unsigned AS)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
unsigned getSyntheticApertureNumber(unsigned AS)
LLVM_READNONE constexpr bool isChainCC(CallingConv::ID CC)
int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels)
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool canGuaranteeTCO(CallingConv::ID CC)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
const RsrcIntrinsic * lookupRsrcIntrinsic(unsigned Intr)
const uint64_t FltRoundConversionTable
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ MaxID
The highest possible ID. Must be some 2^k - 1.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ AMDGPU_CS_ChainPreserve
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:835
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:261
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
Definition ISDOpcodes.h:45
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:236
@ SET_FPENV
Sets the current floating-point environment.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:275
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:603
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:795
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
Definition ISDOpcodes.h:525
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:869
@ ATOMIC_LOAD_USUB_COND
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:521
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition ISDOpcodes.h:220
@ GlobalAddress
Definition ISDOpcodes.h:88
@ ATOMIC_CMP_SWAP_WITH_SUCCESS
Val, Success, OUTCHAIN = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) N.b.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:896
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:587
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:418
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:755
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition ISDOpcodes.h:254
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ ATOMIC_LOAD_USUB_SAT
@ CTLZ_ZERO_POISON
Definition ISDOpcodes.h:804
@ SET_ROUNDING
Set rounding mode.
Definition ISDOpcodes.h:991
@ CONVERGENCECTRL_GLUE
This does not correspond to any convergence control intrinsic.
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:860
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:673
@ READSTEADYCOUNTER
READSTEADYCOUNTER - This corresponds to the readfixedcounter intrinsic.
@ BR
Control flow instructions. These all have token chains.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
Definition ISDOpcodes.h:353
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:544
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
Definition ISDOpcodes.h:551
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:375
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:812
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
Definition ISDOpcodes.h:247
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
Definition ISDOpcodes.h:230
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:349
@ CTLS
Count leading redundant sign bits.
Definition ISDOpcodes.h:808
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
Definition ISDOpcodes.h:986
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:712
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:777
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:657
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:617
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:579
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition ISDOpcodes.h:224
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:866
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:827
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:357
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:904
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:735
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:994
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:821
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:329
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ ATOMIC_LOAD_UDEC_WRAP
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:503
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:942
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:508
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:747
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:568
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
Definition ISDOpcodes.h:803
@ ExternalSymbol
Definition ISDOpcodes.h:93
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:975
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
Definition ISDOpcodes.h:122
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
Definition ISDOpcodes.h:961
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:872
@ BRCOND
BRCOND - Conditional branch.
@ CONVERT_TO_ARBITRARY_FP
CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary floating-point format,...
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
Definition ISDOpcodes.h:849
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ ATOMIC_LOAD_UINC_WRAP
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:537
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:366
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:213
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:559
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI AttributeSet getFnAttributes(LLVMContext &C, ID id)
Return the function attributes for an intrinsic.
LLVM_ABI StringRef getBaseName(ID id)
Return the LLVM name for an intrinsic, without encoded types for overloading, such as "llvm....
LLVM_ABI AttributeList getAttributes(LLVMContext &C, ID id, FunctionType *FT)
Return the attributes for an intrinsic.
LLVM_ABI FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > OverloadTys={})
Return the function type for an intrinsic.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
specific_fpval m_SpecificFP(double V)
Match a specific floating point value or vector with all elements equal to the value.
auto m_Value()
Match an arbitrary value and ignore it.
auto m_FAbs(const Opnd0 &Op0)
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
auto m_IntrinsicWOChain(const OpndPreds &...Opnds)
bool sd_match(SDValue N, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
Offsets
Offsets in bytes from the start of the input buffer.
@ System
Synchronized with respect to all concurrently executing threads.
Definition LLVMContext.h:58
initializer< Ty > init(const Ty &Val)
constexpr double inv_pi
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Offset
Definition DWP.cpp:577
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
Definition STLExtras.h:856
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Done
Definition Threading.h:60
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
Definition MathExtras.h:224
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:325
SDValue peekFPSignOps(SDValue Val)
Strip fabs/fneg/fcopysign from a value to get the underlying source.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:541
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
Definition ModRef.h:356
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
Definition MathExtras.h:380
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
Definition MathExtras.h:274
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
Definition MathExtras.h:352
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
Definition SIInstrInfo.h:46
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
AtomicOrderingCABI
Atomic ordering for C11 / C++11's memory models.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition bit.h:263
bool isBoolSGPR(SDValue V)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
Definition SIInstrInfo.h:54
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI Value * buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Val)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ AfterLegalizeDAG
Definition DAGCombine.h:19
@ AfterLegalizeVectorOps
Definition DAGCombine.h:18
@ AfterLegalizeTypes
Definition DAGCombine.h:17
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
@ Add
Sum of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ NearestTiesToEven
roundTiesToEven.
unsigned M0(unsigned Val)
Definition VE.h:376
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
Definition MathExtras.h:233
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI std::pair< Value *, Value * > buildCmpXchgValue(IRBuilderBase &Builder, Value *Ptr, Value *Cmp, Value *Val, Align Alignment, bool IsVolatile=false)
Emit IR to implement the given cmpxchg operation on values in registers, returning the new value.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition Utils.cpp:436
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
std::optional< StringRef > getAtomicScopeIRString(const Triple &T, AtomicScope S, bool IsSingleAddressSpace=false)
Returns the LLVM IR syncscope string that T uses to spell S.
Definition AtomicScope.h:34
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:50
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:201
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
constexpr RegState getUndefRegState(bool B)
@ Custom
The result value requires a custom uniformity check.
Definition Uniformity.h:31
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
int64_t DWordOffset
int64_t PermMask
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(PreloadedValue Value) const
static const AMDGPUFunctionArgInfo FixedABIFunctionInfo
static constexpr uint64_t encode(Fields... Values)
static std::tuple< typename Fields::ValueType... > decode(uint64_t Encoded)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
static ArgDescriptor createStack(unsigned Offset, unsigned Mask=~0u)
MCRegister getRegister() const
static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask)
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
Helper struct shared between Function Specialization and SCCP Solver.
Definition SCCPSolver.h:42
Represents the full denormal controls for a function, including the default mode and the f32 specific...
Represent subnormal handling kind for floating point instruction inputs and outputs.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
Extended Value Type.
Definition ValueTypes.h:35
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition ValueTypes.h:418
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:145
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:70
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
Definition ValueTypes.h:129
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
Definition ValueTypes.h:323
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:155
ElementCount getVectorElementCount() const
Definition ValueTypes.h:373
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:266
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:501
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
Definition ValueTypes.h:435
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition ValueTypes.h:61
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
Definition ValueTypes.h:404
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:346
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
Definition ValueTypes.h:121
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
Definition ValueTypes.h:181
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
Definition ValueTypes.h:165
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
unsigned getPointerAddrSpace() const
unsigned getByValSize() const
Align getNonZeroMemAlign() const
InputArg - This struct carries flags and type information about a single incoming (formal) argument o...
MVT VT
Legalized type of this argument part.
unsigned getOrigArgIndex() const
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
static LLVM_ABI std::optional< bool > eq(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_EQ result.
bool isUnknown() const
Returns true if we don't know any bits.
Definition KnownBits.h:64
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
Definition KnownBits.h:165
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
Definition KnownBits.h:361
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
Definition KnownBits.h:262
static LLVM_ABI std::optional< bool > ule(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_ULE result.
static LLVM_ABI std::optional< bool > uge(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_UGE result.
bool isKnownNeverNaN() const
Return true if it's known this can never be a nan.
static LLVM_ABI KnownFPClass bitcast(const fltSemantics &FltSemantics, const KnownBits &Bits)
Report known values for a bitcast into a float with provided semantics.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoUnsignedWrap() const
bool hasAllowContract() const
bool hasNoSignedWrap() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
unsigned int NumVTs
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
std::optional< unsigned > fallbackAddressSpace
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs