LLVM 24.0.0git
SIISelLowering.cpp
Go to the documentation of this file.
1//===-- SIISelLowering.cpp - SI DAG Lowering Implementation ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// Custom DAG lowering for SI
11//
12//===----------------------------------------------------------------------===//
13
14#include "SIISelLowering.h"
15#include "AMDGPU.h"
16#include "AMDGPUIGroupLP.h"
17#include "AMDGPUInstrInfo.h"
18#include "AMDGPULaneMaskUtils.h"
19#include "AMDGPUMemoryUtils.h"
21#include "AMDGPUTargetMachine.h"
22#include "GCNSubtarget.h"
25#include "SIRegisterInfo.h"
26#include "llvm/ADT/APFloat.h"
27#include "llvm/ADT/APInt.h"
29#include "llvm/ADT/Statistic.h"
45#include "llvm/IR/IRBuilder.h"
47#include "llvm/IR/IntrinsicsAMDGPU.h"
48#include "llvm/IR/IntrinsicsR600.h"
49#include "llvm/IR/MDBuilder.h"
53#include "llvm/Support/ModRef.h"
56#include <optional>
57
58using namespace llvm;
59using namespace llvm::SDPatternMatch;
60
61#define DEBUG_TYPE "si-lower"
62
63STATISTIC(NumTailCalls, "Number of tail calls");
64
65static cl::opt<bool>
66 DisableLoopAlignment("amdgpu-disable-loop-alignment",
67 cl::desc("Do not align and prefetch loops"),
68 cl::init(false));
69
71 "amdgpu-use-divergent-register-indexing", cl::Hidden,
72 cl::desc("Use indirect register addressing for divergent indexes"),
73 cl::init(false));
74
76 return MF.getInfo<SIMachineFunctionInfo>()->getMode().getDenormalFPEnv();
77}
78
83
88
89static unsigned findFirstFreeSGPR(CCState &CCInfo) {
90 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
91 for (unsigned Reg = 0; Reg < NumSGPRs; ++Reg) {
92 if (!CCInfo.isAllocated(AMDGPU::SGPR0 + Reg)) {
93 return AMDGPU::SGPR0 + Reg;
94 }
95 }
96 llvm_unreachable("Cannot allocate sgpr");
97}
98
100 const GCNSubtarget &STI)
101 : AMDGPUTargetLowering(TM, STI, STI), Subtarget(&STI) {
102 addRegisterClass(MVT::i1, &AMDGPU::VReg_1RegClass);
103 addRegisterClass(MVT::i64, &AMDGPU::SReg_64RegClass);
104
105 addRegisterClass(MVT::i32, &AMDGPU::SReg_32RegClass);
106
107 const SIRegisterInfo *TRI = STI.getRegisterInfo();
108 const TargetRegisterClass *V32RegClass =
109 TRI->getDefaultVectorSuperClassForBitWidth(32);
110 addRegisterClass(MVT::f32, V32RegClass);
111
112 addRegisterClass(MVT::v2i32, &AMDGPU::SReg_64RegClass);
113
114 const TargetRegisterClass *V64RegClass =
115 TRI->getDefaultVectorSuperClassForBitWidth(64);
116
117 addRegisterClass(MVT::f64, V64RegClass);
118 addRegisterClass(MVT::v2f32, V64RegClass);
119 addRegisterClass(MVT::Untyped, V64RegClass);
120
121 addRegisterClass(MVT::v3i32, &AMDGPU::SGPR_96RegClass);
122 addRegisterClass(MVT::v3f32, TRI->getDefaultVectorSuperClassForBitWidth(96));
123
124 addRegisterClass(MVT::v2i64, &AMDGPU::SGPR_128RegClass);
125 addRegisterClass(MVT::v2f64, &AMDGPU::SGPR_128RegClass);
126
127 addRegisterClass(MVT::v4i32, &AMDGPU::SGPR_128RegClass);
128 addRegisterClass(MVT::v4f32, TRI->getDefaultVectorSuperClassForBitWidth(128));
129
130 addRegisterClass(MVT::v5i32, &AMDGPU::SGPR_160RegClass);
131 addRegisterClass(MVT::v5f32, TRI->getDefaultVectorSuperClassForBitWidth(160));
132
133 addRegisterClass(MVT::v6i32, &AMDGPU::SGPR_192RegClass);
134 addRegisterClass(MVT::v6f32, TRI->getDefaultVectorSuperClassForBitWidth(192));
135
136 addRegisterClass(MVT::v3i64, &AMDGPU::SGPR_192RegClass);
137 addRegisterClass(MVT::v3f64, TRI->getDefaultVectorSuperClassForBitWidth(192));
138
139 addRegisterClass(MVT::v7i32, &AMDGPU::SGPR_224RegClass);
140 addRegisterClass(MVT::v7f32, TRI->getDefaultVectorSuperClassForBitWidth(224));
141
142 addRegisterClass(MVT::v8i32, &AMDGPU::SGPR_256RegClass);
143 addRegisterClass(MVT::v8f32, TRI->getDefaultVectorSuperClassForBitWidth(256));
144
145 addRegisterClass(MVT::v4i64, &AMDGPU::SGPR_256RegClass);
146 addRegisterClass(MVT::v4f64, TRI->getDefaultVectorSuperClassForBitWidth(256));
147
148 addRegisterClass(MVT::v9i32, &AMDGPU::SGPR_288RegClass);
149 addRegisterClass(MVT::v9f32, TRI->getDefaultVectorSuperClassForBitWidth(288));
150
151 addRegisterClass(MVT::v10i32, &AMDGPU::SGPR_320RegClass);
152 addRegisterClass(MVT::v10f32,
153 TRI->getDefaultVectorSuperClassForBitWidth(320));
154
155 addRegisterClass(MVT::v11i32, &AMDGPU::SGPR_352RegClass);
156 addRegisterClass(MVT::v11f32,
157 TRI->getDefaultVectorSuperClassForBitWidth(352));
158
159 addRegisterClass(MVT::v12i32, &AMDGPU::SGPR_384RegClass);
160 addRegisterClass(MVT::v12f32,
161 TRI->getDefaultVectorSuperClassForBitWidth(384));
162
163 addRegisterClass(MVT::v16i32, &AMDGPU::SGPR_512RegClass);
164 addRegisterClass(MVT::v16f32,
165 TRI->getDefaultVectorSuperClassForBitWidth(512));
166
167 addRegisterClass(MVT::v8i64, &AMDGPU::SGPR_512RegClass);
168 addRegisterClass(MVT::v8f64, TRI->getDefaultVectorSuperClassForBitWidth(512));
169
170 addRegisterClass(MVT::v16i64, &AMDGPU::SGPR_1024RegClass);
171 addRegisterClass(MVT::v16f64,
172 TRI->getDefaultVectorSuperClassForBitWidth(1024));
173
174 if (Subtarget->has16BitInsts()) {
175 if (Subtarget->useRealTrue16Insts()) {
176 addRegisterClass(MVT::i16, &AMDGPU::VGPR_16RegClass);
177 addRegisterClass(MVT::f16, &AMDGPU::VGPR_16RegClass);
178 addRegisterClass(MVT::bf16, &AMDGPU::VGPR_16RegClass);
179 } else {
180 addRegisterClass(MVT::i16, &AMDGPU::SReg_32RegClass);
181 addRegisterClass(MVT::f16, &AMDGPU::SReg_32RegClass);
182 addRegisterClass(MVT::bf16, &AMDGPU::SReg_32RegClass);
183 }
184
185 // Unless there are also VOP3P operations, not operations are really legal.
186 addRegisterClass(MVT::v2i16, &AMDGPU::SReg_32RegClass);
187 addRegisterClass(MVT::v2f16, &AMDGPU::SReg_32RegClass);
188 addRegisterClass(MVT::v2bf16, &AMDGPU::SReg_32RegClass);
189 addRegisterClass(MVT::v4i16, &AMDGPU::SReg_64RegClass);
190 addRegisterClass(MVT::v4f16, &AMDGPU::SReg_64RegClass);
191 addRegisterClass(MVT::v4bf16, &AMDGPU::SReg_64RegClass);
192 addRegisterClass(MVT::v8i16, &AMDGPU::SGPR_128RegClass);
193 addRegisterClass(MVT::v8f16, &AMDGPU::SGPR_128RegClass);
194 addRegisterClass(MVT::v8bf16, &AMDGPU::SGPR_128RegClass);
195 addRegisterClass(MVT::v16i16, &AMDGPU::SGPR_256RegClass);
196 addRegisterClass(MVT::v16f16, &AMDGPU::SGPR_256RegClass);
197 addRegisterClass(MVT::v16bf16, &AMDGPU::SGPR_256RegClass);
198 addRegisterClass(MVT::v32i16, &AMDGPU::SGPR_512RegClass);
199 addRegisterClass(MVT::v32f16, &AMDGPU::SGPR_512RegClass);
200 addRegisterClass(MVT::v32bf16, &AMDGPU::SGPR_512RegClass);
201 }
202
203 addRegisterClass(MVT::v32i32, &AMDGPU::VReg_1024RegClass);
204 addRegisterClass(MVT::v32f32,
205 TRI->getDefaultVectorSuperClassForBitWidth(1024));
206
207 computeRegisterProperties(Subtarget->getRegisterInfo());
208
211
212 // The boolean content concept here is too inflexible. Compares only ever
213 // really produce a 1-bit result. Any copy/extend from these will turn into a
214 // select, and zext/1 or sext/-1 are equally cheap. Arbitrarily choose 0/1, as
215 // it's what most targets use.
218
219 // We need to custom lower vector stores from local memory
221 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
222 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
223 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
224 MVT::i1, MVT::v32i32},
225 Custom);
226
228 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
229 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
230 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
231 MVT::i1, MVT::v32i32},
232 Custom);
233
234 if (isTypeLegal(MVT::bf16)) {
235 for (unsigned Opc :
244 ISD::SETCC}) {
245 setOperationAction(Opc, MVT::bf16, Promote);
246 }
247
248 // Only targets with packed bf16 instructions, e.g. gfx13.
249 if (Subtarget->hasBF16PackedInsts()) {
250 // Don't use Expand for fsub - the DAG combiner will undo fadd+fneg back
251 // to fsub, causing a libcall (which doesn't exist for bf16). Instead,
252 // directly expand to widened v2bf16 operations.
255 Promote);
256 // Promote scalar operations to a v2bf16 operation with an unused high
257 // lane.
258 for (unsigned Opc :
261 AddPromotedToType(Opc, MVT::bf16, MVT::v2bf16);
262 }
263
265
267 AddPromotedToType(ISD::SELECT, MVT::bf16, MVT::i16);
268
272
273 // We only need to custom lower because we can't specify an action for bf16
274 // sources.
277 }
278
279 setTruncStoreAction(MVT::v2i32, MVT::v2i16, Expand);
280 setTruncStoreAction(MVT::v3i32, MVT::v3i16, Expand);
281 setTruncStoreAction(MVT::v4i32, MVT::v4i16, Expand);
282 setTruncStoreAction(MVT::v8i32, MVT::v8i16, Expand);
283 setTruncStoreAction(MVT::v16i32, MVT::v16i16, Expand);
284 setTruncStoreAction(MVT::v32i32, MVT::v32i16, Expand);
285 setTruncStoreAction(MVT::v2i32, MVT::v2i8, Expand);
286 setTruncStoreAction(MVT::v4i32, MVT::v4i8, Expand);
287 setTruncStoreAction(MVT::v8i32, MVT::v8i8, Expand);
288 setTruncStoreAction(MVT::v16i32, MVT::v16i8, Expand);
289 setTruncStoreAction(MVT::v32i32, MVT::v32i8, Expand);
290 setTruncStoreAction(MVT::v2i16, MVT::v2i8, Expand);
291 setTruncStoreAction(MVT::v4i16, MVT::v4i8, Expand);
292 setTruncStoreAction(MVT::v8i16, MVT::v8i8, Expand);
293 setTruncStoreAction(MVT::v16i16, MVT::v16i8, Expand);
294 setTruncStoreAction(MVT::v32i16, MVT::v32i8, Expand);
295
296 setTruncStoreAction(MVT::v3i64, MVT::v3i16, Expand);
297 setTruncStoreAction(MVT::v3i64, MVT::v3i32, Expand);
298 setTruncStoreAction(MVT::v4i64, MVT::v4i8, Expand);
299 setTruncStoreAction(MVT::v8i64, MVT::v8i8, Expand);
300 setTruncStoreAction(MVT::v8i64, MVT::v8i16, Expand);
301 setTruncStoreAction(MVT::v8i64, MVT::v8i32, Expand);
302 setTruncStoreAction(MVT::v16i64, MVT::v16i32, Expand);
303
304 setOperationAction(ISD::GlobalAddress, {MVT::i32, MVT::i64}, Custom);
305 setOperationAction(ISD::BlockAddress, {MVT::i32, MVT::i64}, Custom);
306 setOperationAction(ISD::ExternalSymbol, {MVT::i32, MVT::i64}, Custom);
307
311 AddPromotedToType(ISD::SELECT, MVT::f64, MVT::i64);
312
313 setOperationAction(ISD::FSQRT, {MVT::f32, MVT::f64}, Custom);
314
316 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1}, Expand);
317
319 setOperationAction(ISD::SETCC, {MVT::v2i1, MVT::v4i1}, Expand);
320 AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32);
321
323 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
324 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
325 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
326 Expand);
328 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
329 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
330 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
331 Expand);
332
334 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
335 MVT::v3i16, MVT::v4i16, MVT::Other},
336 Custom);
337
340 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64}, Expand);
341
344
347
349 Expand);
350
352
353 // We only support LOAD/STORE and vector manipulation ops for vectors
354 // with > 4 elements.
355 for (MVT VT :
356 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
357 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
358 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
359 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
360 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
361 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
362 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
363 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
364 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
365 switch (Op) {
366 case ISD::LOAD:
367 case ISD::STORE:
368 case ISD::ATOMIC_LOAD:
371 case ISD::BITCAST:
372 case ISD::UNDEF:
373 case ISD::POISON:
377 case ISD::IS_FPCLASS:
378 break;
383 break;
384 default:
386 break;
387 }
388 }
389 }
390
392
393 // TODO: For dynamic 64-bit vector inserts/extracts, should emit a pseudo that
394 // is expanded to avoid having two separate loops in case the index is a VGPR.
395
396 // Most operations are naturally 32-bit vector operations. We only support
397 // load and store of i64 vectors, so promote v2i64 vector operations to v4i32.
398 for (MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
400 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v4i32);
401
403 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v4i32);
404
406 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v4i32);
407
409 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v4i32);
410 }
411
412 for (MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
414 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v6i32);
415
417 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v6i32);
418
420 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v6i32);
421
423 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v6i32);
424 }
425
426 for (MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
428 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v8i32);
429
431 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v8i32);
432
434 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v8i32);
435
437 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v8i32);
438 }
439
440 for (MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
442 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v16i32);
443
445 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v16i32);
446
448 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v16i32);
449
451 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v16i32);
452 }
453
454 for (MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
456 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v32i32);
457
459 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v32i32);
460
462 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v32i32);
463
465 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v32i32);
466 }
467
469 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
470 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
471 Custom);
472
473 if (Subtarget->hasPkMovB32()) {
474 // TODO: 16-bit element vectors should be legal with even aligned elements.
475 // TODO: Can be legal with wider source types than the result with
476 // subregister extracts.
477 setOperationAction(ISD::VECTOR_SHUFFLE, {MVT::v2i32, MVT::v2f32}, Legal);
478 }
479
481 // Prevent SELECT v2i32 from being implemented with the above bitwise ops and
482 // instead lower to cndmask in SITargetLowering::LowerSELECT().
484 // Enable MatchRotate to produce ISD::ROTR, which is later transformed to
485 // alignbit.
486 setOperationAction(ISD::ROTR, MVT::v2i32, Custom);
487
488 setOperationAction(ISD::BUILD_VECTOR, {MVT::v4f16, MVT::v4i16, MVT::v4bf16},
489 Custom);
490
491 // Avoid stack access for these.
492 // TODO: Generalize to wider i8 vectors.
494 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
495 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
496 Custom);
497
498 // Deal with vec3 vector operations when widened to vec4.
500 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32}, Custom);
501
502 // Deal with vec5/6/7 vector operations when widened to vec8.
504 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
505 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
506 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
507 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
508 Custom);
509
510 // BUFFER/FLAT_ATOMIC_CMP_SWAP on GCN GPUs needs input marshalling,
511 // and output demarshalling
512 setOperationAction(ISD::ATOMIC_CMP_SWAP, {MVT::i32, MVT::i64}, Custom);
513
514 // We can't return success/failure, only the old value,
515 // let LLVM add the comparison
517 Expand);
518
519 setOperationAction(ISD::ADDRSPACECAST, {MVT::i32, MVT::i64}, Custom);
520
521 setOperationAction(ISD::BITREVERSE, {MVT::i32, MVT::i64}, Legal);
522
523 // FIXME: This should be narrowed to i32, but that only happens if i64 is
524 // illegal.
525 // FIXME: Should lower sub-i32 bswaps to bit-ops without v_perm_b32.
526 setOperationAction(ISD::BSWAP, {MVT::i64, MVT::i32}, Legal);
527
528 // On SI this is s_memtime and s_memrealtime on VI.
530
531 if (Subtarget->hasSMemRealTime() ||
532 Subtarget->getGeneration() >= AMDGPUSubtarget::GFX11)
535
536 if (Subtarget->has16BitInsts()) {
539 setOperationAction(ISD::IS_FPCLASS, {MVT::f16, MVT::f32, MVT::f64}, Legal);
542 } else {
544 }
545
546 if (Subtarget->hasMadMacF32Insts())
548
552
553 // We only really have 32-bit BFE instructions (and 16-bit on VI).
554 //
555 // On SI+ there are 64-bit BFEs, but they are scalar only and there isn't any
556 // effort to match them now. We want this to be false for i64 cases when the
557 // extraction isn't restricted to the upper or lower half. Ideally we would
558 // have some pass reduce 64-bit extracts to 32-bit if possible. Extracts that
559 // span the midpoint are probably relatively rare, so don't worry about them
560 // for now.
562
563 // Clamp modifier on add/sub
564 if (Subtarget->hasIntClamp())
566
567 if (Subtarget->hasAddNoCarryInsts())
568 setOperationAction({ISD::SADDSAT, ISD::SSUBSAT}, {MVT::i16, MVT::i32},
569 Legal);
570
571 // Do not have s_{min|max}_*f64 instruction f64 will only be lowered to
572 // v_{min|max}_*f64
573 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
576 {MVT::f64, MVT::f32}, Legal);
577 } else {
580 {MVT::f64, MVT::f32}, Custom);
581 // These are really only legal for ieee_mode functions. We should be
582 // avoiding them for functions that don't have ieee_mode enabled, so just
583 // say they are legal.
585 {MVT::f64, MVT::f32}, Legal);
586 }
587
588 if (Subtarget->haveRoundOpsF64())
590 Legal);
591 else
593 MVT::f64, Custom);
594
596 setOperationAction({ISD::FLDEXP, ISD::STRICT_FLDEXP}, {MVT::f32, MVT::f64},
597 Legal);
598 setOperationAction(ISD::FFREXP, {MVT::f32, MVT::f64}, Custom);
599
602
603 setOperationAction(ISD::BF16_TO_FP, {MVT::i16, MVT::f32, MVT::f64}, Expand);
604 setOperationAction(ISD::FP_TO_BF16, {MVT::i16, MVT::f32, MVT::f64}, Expand);
605
607 Custom);
609 Custom);
611 Custom);
612
613 // Custom lower these because we can't specify a rule based on an illegal
614 // source bf16.
617
618 if (Subtarget->has16BitInsts()) {
621 MVT::i16, Legal);
622
623 AddPromotedToType(ISD::SIGN_EXTEND, MVT::i16, MVT::i32);
624
626 MVT::i16, Expand);
627
631 ISD::CTPOP},
632 MVT::i16, Promote);
633
635
636 setTruncStoreAction(MVT::i64, MVT::i16, Expand);
637
639 AddPromotedToType(ISD::FP16_TO_FP, MVT::i16, MVT::i32);
641 AddPromotedToType(ISD::FP_TO_FP16, MVT::i16, MVT::i32);
642
647
649
650 // F16 - Constant Actions.
653
654 // F16 - Load/Store Actions.
656 AddPromotedToType(ISD::LOAD, MVT::f16, MVT::i16);
658 AddPromotedToType(ISD::STORE, MVT::f16, MVT::i16);
659
660 // BF16 - Load/Store Actions.
662 AddPromotedToType(ISD::LOAD, MVT::bf16, MVT::i16);
664 AddPromotedToType(ISD::STORE, MVT::bf16, MVT::i16);
665
666 if (!Subtarget->useRealTrue16Insts() ||
667 !Subtarget->d16PreservesUnusedBits()) {
668 for (MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
670 AddPromotedToType(ISD::ATOMIC_LOAD, VT, MVT::i32);
671 }
672 }
673
674 if (!Subtarget->useRealTrue16Insts()) {
675 for (MVT VT : {MVT::i16, MVT::f16, MVT::bf16}) {
678 }
679 }
680
681 // F16 - VOP1 Actions.
684 MVT::f16, Custom);
685
686 // BF16 - VOP1 Actions.
687 if (Subtarget->hasBF16TransInsts())
689
690 // F16 - VOP2 Actions.
691 setOperationAction({ISD::BR_CC, ISD::SELECT_CC}, {MVT::f16, MVT::bf16},
692 Expand);
696
697 // F16 - VOP3 Actions.
699 if (STI.hasMadF16())
701
702 for (MVT VT :
703 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
704 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
705 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
706 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
707 switch (Op) {
708 case ISD::LOAD:
709 case ISD::STORE:
710 case ISD::ATOMIC_LOAD:
713 case ISD::BITCAST:
714 case ISD::UNDEF:
715 case ISD::POISON:
720 case ISD::IS_FPCLASS:
721 break;
724 case ISD::FSIN:
725 case ISD::FCOS:
727 break;
728 default:
730 break;
731 }
732 }
733 }
734
735 // v_perm_b32 can handle either of these.
736 setOperationAction(ISD::BSWAP, {MVT::i16, MVT::v2i16}, Legal);
738
739 // Legalize vector types for sat conversions to select v_cvt_pk_[iu]16_f32.
740 if (Subtarget->hasVCvtPkIU16F32())
743 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
744 Custom);
745
746 // XXX - Do these do anything? Vector constants turn into build_vector.
747 setOperationAction(ISD::Constant, {MVT::v2i16, MVT::v2f16}, Legal);
748
750 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Legal);
751
753 AddPromotedToType(ISD::STORE, MVT::v2i16, MVT::i32);
755 AddPromotedToType(ISD::STORE, MVT::v2f16, MVT::i32);
756
758 AddPromotedToType(ISD::LOAD, MVT::v2i16, MVT::i32);
760 AddPromotedToType(ISD::LOAD, MVT::v2f16, MVT::i32);
761
762 setOperationAction(ISD::AND, MVT::v2i16, Promote);
763 AddPromotedToType(ISD::AND, MVT::v2i16, MVT::i32);
764 setOperationAction(ISD::OR, MVT::v2i16, Promote);
765 AddPromotedToType(ISD::OR, MVT::v2i16, MVT::i32);
766 setOperationAction(ISD::XOR, MVT::v2i16, Promote);
767 AddPromotedToType(ISD::XOR, MVT::v2i16, MVT::i32);
768
770 AddPromotedToType(ISD::LOAD, MVT::v4i16, MVT::v2i32);
772 AddPromotedToType(ISD::LOAD, MVT::v4f16, MVT::v2i32);
773 setOperationAction(ISD::LOAD, MVT::v4bf16, Promote);
774 AddPromotedToType(ISD::LOAD, MVT::v4bf16, MVT::v2i32);
775
777 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
779 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
781 AddPromotedToType(ISD::STORE, MVT::v4bf16, MVT::v2i32);
782
784 AddPromotedToType(ISD::LOAD, MVT::v8i16, MVT::v4i32);
786 AddPromotedToType(ISD::LOAD, MVT::v8f16, MVT::v4i32);
787 setOperationAction(ISD::LOAD, MVT::v8bf16, Promote);
788 AddPromotedToType(ISD::LOAD, MVT::v8bf16, MVT::v4i32);
789
791 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
793 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
794
796 AddPromotedToType(ISD::STORE, MVT::v8i16, MVT::v4i32);
798 AddPromotedToType(ISD::STORE, MVT::v8f16, MVT::v4i32);
800 AddPromotedToType(ISD::STORE, MVT::v8bf16, MVT::v4i32);
801
802 setOperationAction(ISD::LOAD, MVT::v16i16, Promote);
803 AddPromotedToType(ISD::LOAD, MVT::v16i16, MVT::v8i32);
804 setOperationAction(ISD::LOAD, MVT::v16f16, Promote);
805 AddPromotedToType(ISD::LOAD, MVT::v16f16, MVT::v8i32);
806 setOperationAction(ISD::LOAD, MVT::v16bf16, Promote);
807 AddPromotedToType(ISD::LOAD, MVT::v16bf16, MVT::v8i32);
808
810 AddPromotedToType(ISD::STORE, MVT::v16i16, MVT::v8i32);
812 AddPromotedToType(ISD::STORE, MVT::v16f16, MVT::v8i32);
813 setOperationAction(ISD::STORE, MVT::v16bf16, Promote);
814 AddPromotedToType(ISD::STORE, MVT::v16bf16, MVT::v8i32);
815
816 setOperationAction(ISD::LOAD, MVT::v32i16, Promote);
817 AddPromotedToType(ISD::LOAD, MVT::v32i16, MVT::v16i32);
818 setOperationAction(ISD::LOAD, MVT::v32f16, Promote);
819 AddPromotedToType(ISD::LOAD, MVT::v32f16, MVT::v16i32);
820 setOperationAction(ISD::LOAD, MVT::v32bf16, Promote);
821 AddPromotedToType(ISD::LOAD, MVT::v32bf16, MVT::v16i32);
822
824 AddPromotedToType(ISD::STORE, MVT::v32i16, MVT::v16i32);
826 AddPromotedToType(ISD::STORE, MVT::v32f16, MVT::v16i32);
827 setOperationAction(ISD::STORE, MVT::v32bf16, Promote);
828 AddPromotedToType(ISD::STORE, MVT::v32bf16, MVT::v16i32);
829
831 MVT::v2i32, Expand);
833
835 MVT::v4i32, Expand);
836
838 MVT::v8i32, Expand);
839
840 setOperationAction(ISD::BUILD_VECTOR, {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
841 Subtarget->hasVOP3PInsts() ? Legal : Custom);
842
843 setOperationAction(ISD::FNEG, {MVT::v2f16, MVT::v2bf16}, Legal);
844 // This isn't really legal, but this avoids the legalizer unrolling it (and
845 // allows matching fneg (fabs x) patterns)
846 setOperationAction(ISD::FABS, {MVT::v2f16, MVT::v2bf16}, Legal);
847
848 // Can do this in one BFI plus a constant materialize.
850 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
851 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
852 MVT::v32f16, MVT::v32bf16},
853 Custom);
854 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
857 MVT::f16, Legal);
858
861 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16}, Custom);
862 } else {
865 MVT::f16, Custom);
866
868 Legal);
869
872 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
873 Custom);
874
876 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
877 Expand);
878 }
879
880 for (MVT Vec16 :
881 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
882 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
885 Vec16, Custom);
886 }
887 }
888
889 if (Subtarget->hasVOP3PInsts()) {
893 MVT::v2i16, Legal);
894
897 MVT::v2f16, Legal);
898
900 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Custom);
901
903 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
904 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
905 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
906 Custom);
907
908 for (MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
909 // Split vector operations.
914 VT, Custom);
915
916 for (MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
917 // Split vector operations.
920 VT, Custom);
921
922 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
925 MVT::v2f16, Legal);
926 } else {
928 Legal);
929
932 {MVT::v2f16, MVT::v4f16}, Custom);
933 }
934 setOperationAction(ISD::FEXP, MVT::v2f16, Custom);
935 setOperationAction(ISD::SELECT, {MVT::v4i16, MVT::v4f16, MVT::v4bf16},
936 Custom);
937
938 if (Subtarget->hasBF16PackedInsts()) {
942 MVT::v2bf16, Legal);
943
944 for (MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
945 // Split vector operations.
949 VT, Custom);
950 }
951
952 if (Subtarget->hasAnyPackedFP32Ops()) {
954 MVT::v2f32, Legal);
956 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
957 Custom);
958 }
959 if (Subtarget->hasAnyPackedFP64Ops()) {
962 MVT::v2f64, Legal);
965 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64}, Custom);
966
967 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
970 MVT::v2f64, Legal);
971
974 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64}, Custom);
975 } else {
977 Legal);
980 MVT::v2f64, Custom);
983 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64},
984 Custom);
985 }
986 }
987
988 if (Subtarget->hasAnyPackedU64Ops()) {
990 MVT::v2i64, Legal);
992 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
993 Custom);
994 }
995 }
996
998
999 if (Subtarget->has16BitInsts()) {
1001 AddPromotedToType(ISD::SELECT, MVT::v2i16, MVT::i32);
1003 AddPromotedToType(ISD::SELECT, MVT::v2f16, MVT::i32);
1004 setOperationAction(ISD::SELECT, MVT::v2bf16, Promote);
1005 AddPromotedToType(ISD::SELECT, MVT::v2bf16, MVT::i32);
1006 } else {
1007 // Legalization hack.
1008 setOperationAction(ISD::SELECT, {MVT::v2i16, MVT::v2f16}, Custom);
1009
1011 }
1012
1014 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
1015 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1016 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
1017 MVT::v32f16, MVT::v32bf16},
1018 Custom);
1019
1021
1022 if (Subtarget->useVMulU64Inst())
1023 setOperationAction(ISD::MUL, MVT::i64, Legal);
1024 else if (Subtarget->hasScalarSMulU64())
1026
1027 if (Subtarget->hasMad64_32())
1029
1030 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
1032 // Type legalization cannot expand the i128 pointer of a buffer resource
1033 // prefetch; lowerPREFETCH drops the prefetch instead.
1035
1036 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
1038 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16}, Legal);
1039 } else {
1040 // FIXME: For nnan fmaximum, emit the fmaximum3 instead of fmaxnum
1041 if (Subtarget->hasMinimum3Maximum3F32())
1043
1044 if (Subtarget->hasMinimum3Maximum3PKF16()) {
1046
1047 // If only the vector form is available, we need to widen to a vector.
1048 if (!Subtarget->hasMinimum3Maximum3F16())
1050 MVT::v2f16);
1051 }
1052 }
1053
1054 if (Subtarget->hasVOP3PInsts()) {
1055 // We want to break these into v2f16 pieces, not scalarize.
1057 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1058 Custom);
1059 }
1060
1061 if (Subtarget->useMinMaxI64Insts())
1063 Legal);
1064
1066 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1067 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1068 MVT::i8},
1069 Custom);
1070
1072 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1073 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1074 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1075 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1076 Custom);
1077
1078 // The s_buffer_load intrinsics accept any result type in IR, but only a few
1079 // of them can be selected. Mark the remaining illegal result types Custom so
1080 // ReplaceNodeResults gets a chance to diagnose them instead of letting the
1081 // type legalizer abort. Its INTRINSIC_WO_CHAIN case dispatches on the
1082 // intrinsic ID, but INTRINSIC_W_CHAIN does not, so remember the types added
1083 // here to keep other chained intrinsics on generic legalization.
1084 for (MVT VT : MVT::all_valuetypes()) {
1085 if (VT.isScalableVector() || isTypeLegal(VT))
1086 continue;
1090 SBufferLoadDiagnosticVTs.set(VT.SimpleTy);
1091 }
1092 }
1093
1095 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1096 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1097 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1098 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1099 Custom);
1100
1106
1107 // TODO: Could move this to custom lowering, could benefit from combines on
1108 // extract of relevant bits.
1110
1112
1113 if (Subtarget->hasBF16ConversionInsts()) {
1115 {MVT::bf16, MVT::v2bf16}, Custom);
1117 }
1118
1119 if (Subtarget->hasBF16TransInsts()) {
1121 }
1122
1123 const bool HasE5M3ConversionInsts =
1124 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
1125 if (Subtarget->hasOCPFP8ConversionInsts() || HasE5M3ConversionInsts) {
1126 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f32, MVT::v2f32},
1127 Custom);
1129
1130 // i8 result promotes to i16, wider vectors split down to v2i8, and v2i8 is
1131 // handled in ReplaceNodeResults before the legalizer splits it per lane.
1132 setOperationAction(ISD::CONVERT_TO_ARBITRARY_FP, {MVT::i16, MVT::v2i8},
1133 Custom);
1134 }
1135
1136 if (Subtarget->hasFP8F16ConversionInsts()) {
1137 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f16, MVT::v2f16},
1138 Custom);
1139 }
1140
1141 if (Subtarget->hasCvtPkF16F32Inst()) {
1143 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1144 Custom);
1145 }
1146
1149 ISD::SUB,
1150 ISD::MUL,
1151 ISD::FADD,
1152 ISD::FSUB,
1153 ISD::FDIV,
1154 ISD::FMUL,
1163 ISD::FMA,
1164 ISD::ABS,
1165 ISD::SMIN,
1166 ISD::SMAX,
1167 ISD::UMIN,
1168 ISD::UMAX,
1169 ISD::SETCC,
1171 ISD::SMIN,
1172 ISD::SMAX,
1173 ISD::UMIN,
1174 ISD::UMAX,
1177 ISD::AND,
1178 ISD::OR,
1179 ISD::XOR,
1180 ISD::SHL,
1181 ISD::SRL,
1182 ISD::SRA,
1183 ISD::FSHR,
1195
1196 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1198
1199 // All memory operations. Some folding on the pointer operand is done to help
1200 // matching the constant offsets in the addressing modes.
1202 ISD::STORE,
1227
1228 // FIXME: In other contexts we pretend this is a per-function property.
1230
1232}
1233
1234const GCNSubtarget *SITargetLowering::getSubtarget() const { return Subtarget; }
1235
1237 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1238 return RCRegs;
1239}
1240
1241//===----------------------------------------------------------------------===//
1242// TargetLowering queries
1243//===----------------------------------------------------------------------===//
1244
1245// v_mad_mix* support a conversion from f16 to f32.
1246//
1247// There is only one special case when denormals are enabled we don't currently,
1248// where this is OK to use.
1249bool SITargetLowering::isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode,
1250 EVT DestVT, EVT SrcVT) const {
1251 return DestVT.getScalarType() == MVT::f32 &&
1252 ((((Opcode == ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1253 (Opcode == ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1254 SrcVT.getScalarType() == MVT::f16) ||
1255 (Opcode == ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1256 SrcVT.getScalarType() == MVT::bf16)) &&
1257 // TODO: This probably only requires no input flushing?
1259}
1260
1262 LLT DestTy, LLT SrcTy) const {
1263 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1264 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1265 DestTy.getScalarSizeInBits() == 32 &&
1266 SrcTy.getScalarSizeInBits() == 16 &&
1267 // TODO: This probably only requires no input flushing?
1268 denormalModeIsFlushAllF32(*MI.getMF());
1269}
1270
1272 // SI has some legal vector types, but no legal vector operations. Say no
1273 // shuffles are legal in order to prefer scalarizing some vector operations.
1274 return false;
1275}
1276
1279 EVT VT) const {
1282
1283 if (VT.isVector()) {
1284 EVT ScalarVT = VT.getScalarType();
1285 unsigned Size = ScalarVT.getSizeInBits();
1286 if (Size == 16) {
1287 return Subtarget->has16BitInsts()
1288 ? MVT::getVectorVT(ScalarVT.getSimpleVT(), 2)
1289 : MVT::i32;
1290 }
1291
1292 if (Size < 16)
1293 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1294 return Size == 32 ? ScalarVT.getSimpleVT() : MVT::i32;
1295 }
1296
1297 if (!Subtarget->has16BitInsts() && VT.getSizeInBits() == 16)
1298 return MVT::i32;
1299
1300 if (VT.getSizeInBits() > 32)
1301 return MVT::i32;
1302
1304}
1305
1308 EVT VT) const {
1311
1312 if (VT.isVector()) {
1313 unsigned NumElts = VT.getVectorNumElements();
1314 EVT ScalarVT = VT.getScalarType();
1315 unsigned Size = ScalarVT.getSizeInBits();
1316
1317 // FIXME: Should probably promote 8-bit vectors to i16.
1318 if (Size == 16)
1319 return (NumElts + 1) / 2;
1320
1321 if (Size <= 32)
1322 return NumElts;
1323
1324 if (Size > 32)
1325 return NumElts * ((Size + 31) / 32);
1326 } else if (VT.getSizeInBits() > 32)
1327 return (VT.getSizeInBits() + 31) / 32;
1328
1330}
1331
1333 LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT,
1334 unsigned &NumIntermediates, MVT &RegisterVT) const {
1335 if (CC != CallingConv::AMDGPU_KERNEL && VT.isVector()) {
1336 unsigned NumElts = VT.getVectorNumElements();
1337 EVT ScalarVT = VT.getScalarType();
1338 unsigned Size = ScalarVT.getSizeInBits();
1339 // FIXME: We should fix the ABI to be the same on targets without 16-bit
1340 // support, but unless we can properly handle 3-vectors, it will be still be
1341 // inconsistent.
1342 if (Size == 16) {
1343 MVT SimpleIntermediateVT =
1345 IntermediateVT = SimpleIntermediateVT;
1346 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1347 NumIntermediates = (NumElts + 1) / 2;
1348 return (NumElts + 1) / 2;
1349 }
1350
1351 if (Size == 32) {
1352 RegisterVT = ScalarVT.getSimpleVT();
1353 IntermediateVT = RegisterVT;
1354 NumIntermediates = NumElts;
1355 return NumIntermediates;
1356 }
1357
1358 if (Size < 16 && Subtarget->has16BitInsts()) {
1359 // FIXME: Should probably form v2i16 pieces
1360 RegisterVT = MVT::i16;
1361 IntermediateVT = ScalarVT;
1362 NumIntermediates = NumElts;
1363 return NumIntermediates;
1364 }
1365
1366 if (Size != 16 && Size <= 32) {
1367 RegisterVT = MVT::i32;
1368 IntermediateVT = ScalarVT;
1369 NumIntermediates = NumElts;
1370 return NumIntermediates;
1371 }
1372
1373 if (Size > 32) {
1374 RegisterVT = MVT::i32;
1375 IntermediateVT = RegisterVT;
1376 NumIntermediates = NumElts * ((Size + 31) / 32);
1377 return NumIntermediates;
1378 }
1379 }
1380
1382 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1383}
1384
1386 const DataLayout &DL, Type *Ty,
1387 unsigned MaxNumLanes) {
1388 assert(MaxNumLanes != 0);
1389
1390 LLVMContext &Ctx = Ty->getContext();
1391 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1392 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1393 return EVT::getVectorVT(Ctx, TLI.getValueType(DL, VT->getElementType()),
1394 NumElts);
1395 }
1396
1397 return TLI.getValueType(DL, Ty);
1398}
1399
1400// Peek through TFE struct returns to only use the data size.
1402 const DataLayout &DL, Type *Ty,
1403 unsigned MaxNumLanes) {
1404 auto *ST = dyn_cast<StructType>(Ty);
1405 if (!ST)
1406 return memVTFromLoadIntrData(TLI, DL, Ty, MaxNumLanes);
1407
1408 // TFE intrinsics return an aggregate type.
1409 assert(ST->getNumContainedTypes() == 2 &&
1410 ST->getContainedType(1)->isIntegerTy(32));
1411 return memVTFromLoadIntrData(TLI, DL, ST->getContainedType(0), MaxNumLanes);
1412}
1413
1414/// Map address space 7 to MVT::amdgpuBufferFatPointer because that's its
1415/// in-memory representation. This return value is a custom type because there
1416/// is no MVT::i160 and adding one breaks integer promotion logic. While this
1417/// could cause issues during codegen, these address space 7 pointers will be
1418/// rewritten away by then. Therefore, we can return MVT::amdgpuBufferFatPointer
1419/// in order to allow pre-codegen passes that query TargetTransformInfo, often
1420/// for cost modeling, to work. (This also sets us up decently for doing the
1421/// buffer lowering in GlobalISel if SelectionDAG ever goes away.)
1423 if (AMDGPUAS::BUFFER_FAT_POINTER == AS && DL.getPointerSizeInBits(AS) == 160)
1424 return MVT::amdgpuBufferFatPointer;
1426 DL.getPointerSizeInBits(AS) == 192)
1427 return MVT::amdgpuBufferStridedPointer;
1429}
1430/// Similarly, the in-memory representation of a p7 is {p8, i32}, aka
1431/// v8i32 when padding is added.
1432/// The in-memory representation of a p9 is {p8, i32, i32}, which is
1433/// also v8i32 with padding.
1435 if ((AMDGPUAS::BUFFER_FAT_POINTER == AS &&
1436 DL.getPointerSizeInBits(AS) == 160) ||
1438 DL.getPointerSizeInBits(AS) == 192))
1439 return MVT::v8i32;
1441}
1442
1443static unsigned getIntrMemWidth(unsigned IntrID) {
1444 switch (IntrID) {
1445 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1446 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1447 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1448 return 8;
1449 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1450 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1451 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1452 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1453 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1454 case Intrinsic::amdgcn_flat_load_monitor_b32:
1455 case Intrinsic::amdgcn_global_load_monitor_b32:
1456 return 32;
1457 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1458 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1459 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1460 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1461 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1462 case Intrinsic::amdgcn_flat_load_monitor_b64:
1463 case Intrinsic::amdgcn_global_load_monitor_b64:
1464 return 64;
1465 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1466 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1467 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1468 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1469 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1470 case Intrinsic::amdgcn_flat_load_monitor_b128:
1471 case Intrinsic::amdgcn_global_load_monitor_b128:
1472 return 128;
1473 default:
1474 llvm_unreachable("Unknown width");
1475 }
1476}
1477
1479 unsigned ArgIdx) {
1480 Value *OrderingArg = CI.getArgOperand(ArgIdx);
1481 unsigned Ord = cast<ConstantInt>(OrderingArg)->getZExtValue();
1482 switch (AtomicOrderingCABI(Ord)) {
1485 break;
1488 break;
1491 break;
1492 default:
1494 }
1495}
1496
1497static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx) {
1498 MDNode *ScopeMD = cast<MDNode>(
1499 cast<MetadataAsValue>(CI.getArgOperand(ArgIdx))->getMetadata());
1500 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1501 return CI.getContext().getOrInsertSyncScopeID(Scope);
1502}
1503
1505 const CallBase &CI,
1506 MachineFunction &MF,
1507 unsigned IntrID) const {
1509 if (CI.hasMetadata(LLVMContext::MD_invariant_load))
1511 if (CI.hasMetadata(LLVMContext::MD_nontemporal))
1513 Flags |= getTargetMMOFlags(CI);
1514
1515 if (const AMDGPU::RsrcIntrinsic *RsrcIntr =
1517 AttributeSet Attr =
1519 MemoryEffects ME = Attr.getMemoryEffects();
1520 if (ME.doesNotAccessMemory())
1521 return;
1522
1523 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1524 if (!IsSPrefetch) {
1525 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1526 if (Aux->getZExtValue() & AMDGPU::CPol::VOLATILE)
1528 }
1529
1531
1532 IntrinsicInfo Info;
1533 // TODO: Should images get their own address space?
1535
1536 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = nullptr;
1537 if (RsrcIntr->IsImage) {
1538 const AMDGPU::ImageDimIntrinsicInfo *Intr =
1540 BaseOpcode = AMDGPU::getMIMGBaseOpcodeInfo(Intr->BaseOpcode);
1541 Info.align.reset();
1542 }
1543
1544 Value *RsrcArg = CI.getArgOperand(RsrcIntr->RsrcArg);
1545 if (auto *RsrcPtrTy = dyn_cast<PointerType>(RsrcArg->getType())) {
1546 if (RsrcPtrTy->getAddressSpace() == AMDGPUAS::BUFFER_RESOURCE)
1547 // We conservatively set the memory operand of a buffer intrinsic to the
1548 // base resource pointer, so that we can access alias information about
1549 // those pointers. Cases like "this points at the same value
1550 // but with a different offset" are handled in
1551 // areMemAccessesTriviallyDisjoint.
1552 Info.ptrVal = RsrcArg;
1553 }
1554
1555 if (ME.onlyReadsMemory()) {
1556 if (RsrcIntr->IsImage) {
1557 unsigned MaxNumLanes = 4;
1558
1559 if (!BaseOpcode->Gather4) {
1560 // If this isn't a gather, we may have excess loaded elements in the
1561 // IR type. Check the dmask for the real number of elements loaded.
1562 unsigned DMask =
1563 cast<ConstantInt>(CI.getArgOperand(0))->getZExtValue();
1564 MaxNumLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1565 }
1566
1567 Info.memVT = memVTFromLoadIntrReturn(*this, MF.getDataLayout(),
1568 CI.getType(), MaxNumLanes);
1569 } else {
1570 Info.memVT =
1572 std::numeric_limits<unsigned>::max());
1573 }
1574
1575 // FIXME: What does alignment mean for an image?
1576 Info.opc = ISD::INTRINSIC_W_CHAIN;
1577 Info.flags = Flags | MachineMemOperand::MOLoad;
1578 } else if (ME.onlyWritesMemory()) {
1579 Info.opc = ISD::INTRINSIC_VOID;
1580
1581 Type *DataTy = CI.getArgOperand(0)->getType();
1582 if (RsrcIntr->IsImage) {
1583 unsigned DMask = cast<ConstantInt>(CI.getArgOperand(1))->getZExtValue();
1584 unsigned DMaskLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1585 Info.memVT = memVTFromLoadIntrData(*this, MF.getDataLayout(), DataTy,
1586 DMaskLanes);
1587 } else
1588 Info.memVT = getValueType(MF.getDataLayout(), DataTy);
1589
1590 Info.flags = Flags | MachineMemOperand::MOStore;
1591 } else {
1592 // Atomic, NoReturn Sampler or prefetch
1593 Info.opc = CI.getType()->isVoidTy() ? ISD::INTRINSIC_VOID
1595
1596 switch (IntrID) {
1597 default:
1598 Info.flags = Flags | MachineMemOperand::MOLoad;
1599 if (!IsSPrefetch)
1600 Info.flags |= MachineMemOperand::MOStore;
1601
1602 if ((RsrcIntr->IsImage && BaseOpcode->NoReturn) || IsSPrefetch) {
1603 // Fake memory access type for no return sampler intrinsics
1604 Info.memVT = MVT::i32;
1605 } else {
1606 // XXX - Should this be volatile without known ordering?
1607 Info.flags |= MachineMemOperand::MOVolatile;
1608 Info.memVT = MVT::getVT(CI.getArgOperand(0)->getType());
1609 }
1610 break;
1611 case Intrinsic::amdgcn_raw_buffer_load_lds:
1612 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1613 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1614 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1615 case Intrinsic::amdgcn_struct_buffer_load_lds:
1616 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1617 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1618 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1619 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1620
1621 // Entry 0: Load from buffer.
1622 // Don't set an offset, since the pointer value always represents the
1623 // base of the buffer.
1624 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1625 Info.flags = Flags | MachineMemOperand::MOLoad;
1626 Infos.push_back(Info);
1627
1628 // Entry 1: Store to LDS.
1629 // Instruction offset is applied, and an additional per-lane offset
1630 // which we simulate using a larger memory type.
1631 Info.memVT = EVT::getIntegerVT(
1632 CI.getContext(), Width * 8 * Subtarget->getWavefrontSize());
1633 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1634 Info.offset = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 2))
1635 ->getZExtValue();
1636 Info.fallbackAddressSpace = AMDGPUAS::LOCAL_ADDRESS;
1637 Info.flags = Flags | MachineMemOperand::MOStore;
1638 Infos.push_back(Info);
1639 return;
1640 }
1641 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1642 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1643 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1644 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1645 Info.memVT =
1647 std::numeric_limits<unsigned>::max());
1648 Info.flags = Flags | MachineMemOperand::MOLoad;
1649 Infos.push_back(Info);
1650 return;
1651 }
1652 }
1653 }
1654 Infos.push_back(Info);
1655 return;
1656 }
1657
1658 IntrinsicInfo Info;
1659 switch (IntrID) {
1660 case Intrinsic::amdgcn_ds_ordered_add:
1661 case Intrinsic::amdgcn_ds_ordered_swap: {
1662 Info.opc = ISD::INTRINSIC_W_CHAIN;
1663 Info.memVT = MVT::getVT(CI.getType());
1664 Info.ptrVal = CI.getOperand(0);
1665 Info.align.reset();
1667
1668 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(4));
1669 if (!Vol->isZero())
1670 Info.flags |= MachineMemOperand::MOVolatile;
1671
1672 Infos.push_back(Info);
1673 return;
1674 }
1675 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1676 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1677 Info.opc = ISD::INTRINSIC_W_CHAIN;
1678 Info.memVT = MVT::getVT(CI.getOperand(0)->getType());
1679 Info.ptrVal = nullptr;
1680 Info.fallbackAddressSpace = AMDGPUAS::STREAMOUT_REGISTER;
1682 Infos.push_back(Info);
1683 return;
1684 }
1685 case Intrinsic::amdgcn_ds_append:
1686 case Intrinsic::amdgcn_ds_consume: {
1687 Info.opc = ISD::INTRINSIC_W_CHAIN;
1688 Info.memVT = MVT::getVT(CI.getType());
1689 Info.ptrVal = CI.getOperand(0);
1690 Info.align.reset();
1692
1693 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(1));
1694 if (!Vol->isZero())
1695 Info.flags |= MachineMemOperand::MOVolatile;
1696
1697 Infos.push_back(Info);
1698 return;
1699 }
1700 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1701 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1702 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1705 Info.memVT = MVT::getVT(CI.getType());
1706 Info.ptrVal = CI.getOperand(0);
1707 Info.memVT = MVT::i64;
1708 Info.size = 8;
1709 Info.align.reset();
1711 Info.order = AtomicOrdering::Monotonic;
1712 Infos.push_back(Info);
1713 return;
1714 }
1715 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1716 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1717 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1718 Info.opc = ISD::INTRINSIC_W_CHAIN;
1719 Info.memVT =
1720 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1721 ? CI.getType()
1723 ->getElementType(0)); // XXX: what is correct VT?
1724
1725 Info.fallbackAddressSpace = AMDGPUAS::BUFFER_RESOURCE;
1726 Info.align.reset();
1727 Info.flags = Flags | MachineMemOperand::MOLoad |
1729 Infos.push_back(Info);
1730 return;
1731 }
1732 case Intrinsic::amdgcn_global_atomic_fmin_num:
1733 case Intrinsic::amdgcn_global_atomic_fmax_num:
1734 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1735 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1736 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1737 Info.opc = ISD::INTRINSIC_W_CHAIN;
1738 Info.memVT = MVT::getVT(CI.getType());
1739 Info.ptrVal = CI.getOperand(0);
1740 Info.align.reset();
1741 Info.flags =
1744 Infos.push_back(Info);
1745 return;
1746 }
1747 case Intrinsic::amdgcn_cluster_load_b32:
1748 case Intrinsic::amdgcn_cluster_load_b64:
1749 case Intrinsic::amdgcn_cluster_load_b128:
1750 case Intrinsic::amdgcn_ds_load_tr6_b96:
1751 case Intrinsic::amdgcn_ds_load_tr4_b64:
1752 case Intrinsic::amdgcn_ds_load_tr8_b64:
1753 case Intrinsic::amdgcn_ds_load_tr16_b128:
1754 case Intrinsic::amdgcn_global_load_tr6_b96:
1755 case Intrinsic::amdgcn_global_load_tr4_b64:
1756 case Intrinsic::amdgcn_global_load_tr_b64:
1757 case Intrinsic::amdgcn_global_load_tr_b128:
1758 case Intrinsic::amdgcn_ds_read_tr4_b64:
1759 case Intrinsic::amdgcn_ds_read_tr6_b96:
1760 case Intrinsic::amdgcn_ds_read_tr8_b64:
1761 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1762 Info.opc = ISD::INTRINSIC_W_CHAIN;
1763 Info.memVT = MVT::getVT(CI.getType());
1764 Info.ptrVal = CI.getOperand(0);
1765 Info.align.reset();
1766 Info.flags = Flags | MachineMemOperand::MOLoad;
1767 Infos.push_back(Info);
1768 return;
1769 }
1770 case Intrinsic::amdgcn_flat_load_monitor_b32:
1771 case Intrinsic::amdgcn_flat_load_monitor_b64:
1772 case Intrinsic::amdgcn_flat_load_monitor_b128:
1773 case Intrinsic::amdgcn_global_load_monitor_b32:
1774 case Intrinsic::amdgcn_global_load_monitor_b64:
1775 case Intrinsic::amdgcn_global_load_monitor_b128: {
1776 Info.opc = ISD::INTRINSIC_W_CHAIN;
1777 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1778 Info.ptrVal = CI.getOperand(0);
1779 Info.align.reset();
1780 Info.flags = MachineMemOperand::MOLoad;
1781 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1782 Info.ssid = parseSyncscopeMDArg(CI, 2);
1783 Infos.push_back(Info);
1784 return;
1785 }
1786 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1787 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1788 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1789 Info.opc = ISD::INTRINSIC_W_CHAIN;
1790 Info.memVT = MVT::getVT(CI.getType());
1791 Info.ptrVal = CI.getOperand(0);
1792 Info.align.reset();
1794 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1795 Info.ssid = parseSyncscopeMDArg(CI, 2);
1796 Infos.push_back(Info);
1797 return;
1798 }
1799 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1800 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1801 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1802 Info.opc = ISD::INTRINSIC_VOID;
1803 Info.memVT = MVT::getVT(CI.getArgOperand(1)->getType());
1804 Info.ptrVal = CI.getArgOperand(0);
1805 Info.align.reset();
1807 Info.order = parseAtomicOrderingCABIArg(CI, 2);
1808 Info.ssid = parseSyncscopeMDArg(CI, 3);
1809 Infos.push_back(Info);
1810 return;
1811 }
1812 case Intrinsic::amdgcn_ds_gws_init:
1813 case Intrinsic::amdgcn_ds_gws_barrier:
1814 case Intrinsic::amdgcn_ds_gws_sema_v:
1815 case Intrinsic::amdgcn_ds_gws_sema_br:
1816 case Intrinsic::amdgcn_ds_gws_sema_p:
1817 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1818 Info.opc = ISD::INTRINSIC_VOID;
1819
1820 const GCNTargetMachine &TM =
1821 static_cast<const GCNTargetMachine &>(getTargetMachine());
1822
1824 Info.ptrVal = MFI->getGWSPSV(TM);
1825
1826 // This is an abstract access, but we need to specify a type and size.
1827 Info.memVT = MVT::i32;
1828 Info.size = 4;
1829 Info.align = Align(4);
1830
1831 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1832 Info.flags = Flags | MachineMemOperand::MOLoad;
1833 else
1834 Info.flags = Flags | MachineMemOperand::MOStore;
1835 Infos.push_back(Info);
1836 return;
1837 }
1838 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1839 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1840 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1841 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1842 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1843 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1844 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1845 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1846 // Entry 0: Load from source (global/flat).
1847 Info.opc = ISD::INTRINSIC_VOID;
1848 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1849 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1850 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1851 Info.flags = Flags | MachineMemOperand::MOLoad;
1852 Infos.push_back(Info);
1853
1854 // Entry 1: Store to LDS (same offset).
1855 Info.flags = Flags | MachineMemOperand::MOStore;
1856 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1857 Infos.push_back(Info);
1858 return;
1859 }
1860 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1861 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1862 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1863 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1864 // Entry 0: Load from LDS.
1865 Info.opc = ISD::INTRINSIC_VOID;
1866 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1867 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1868 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1869 Info.flags = Flags | MachineMemOperand::MOLoad;
1870 Infos.push_back(Info);
1871
1872 // Entry 1: Store to global (same offset).
1873 Info.flags = Flags | MachineMemOperand::MOStore;
1874 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1875 Infos.push_back(Info);
1876 return;
1877 }
1878 case Intrinsic::amdgcn_av_load_b8:
1879 case Intrinsic::amdgcn_av_load_b16:
1880 case Intrinsic::amdgcn_av_load_b32:
1881 case Intrinsic::amdgcn_av_load_b64:
1882 case Intrinsic::amdgcn_av_load_b128:
1883 case Intrinsic::amdgcn_av_store_b8:
1884 case Intrinsic::amdgcn_av_store_b16:
1885 case Intrinsic::amdgcn_av_store_b32:
1886 case Intrinsic::amdgcn_av_store_b64:
1887 case Intrinsic::amdgcn_av_store_b128: {
1888 bool IsStore = CI.getType()->isVoidTy();
1889 Type *DataTy = IsStore ? CI.getArgOperand(1)->getType() : CI.getType();
1890 Info.opc = IsStore ? ISD::INTRINSIC_VOID : ISD::INTRINSIC_W_CHAIN;
1891 Info.memVT = MVT::getVT(DataTy);
1892 Info.ptrVal = CI.getArgOperand(0);
1893 Info.align = Align(Info.memVT.getStoreSize());
1894 Info.flags |=
1896 // Pretend to be atomic so that SIMemoryLegalizer::expandStore sets cache
1897 // flags appropriately.
1898 Info.order = AtomicOrdering::Monotonic;
1899
1900 LLVMContext &Ctx = CI.getContext();
1901 unsigned ScopeIdx = CI.arg_size() - 1;
1902 MDNode *ScopeMD = cast<MDNode>(
1903 cast<MetadataAsValue>(CI.getArgOperand(ScopeIdx))->getMetadata());
1904 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1905 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1906 Infos.push_back(Info);
1907 return;
1908 }
1909 case Intrinsic::amdgcn_load_to_lds:
1910 case Intrinsic::amdgcn_load_async_to_lds:
1911 case Intrinsic::amdgcn_global_load_lds:
1912 case Intrinsic::amdgcn_global_load_async_lds: {
1913 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1914 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1915 bool IsVolatile = Aux->getZExtValue() & AMDGPU::CPol::VOLATILE;
1916 if (IsVolatile)
1918
1919 // Entry 0: Load from source (global/flat).
1920 Info.opc = ISD::INTRINSIC_VOID;
1921 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1922 Info.ptrVal = CI.getArgOperand(0); // Source pointer
1923 Info.offset = cast<ConstantInt>(CI.getArgOperand(3))->getSExtValue();
1924 Info.flags = Flags | MachineMemOperand::MOLoad;
1925 Infos.push_back(Info);
1926
1927 // Entry 1: Store to LDS.
1928 // Same offset from the instruction, but an additional per-lane offset is
1929 // added. Represent that using a wider memory type.
1930 Info.memVT = EVT::getIntegerVT(CI.getContext(),
1931 Width * 8 * Subtarget->getWavefrontSize());
1932 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1933 Info.flags = Flags | MachineMemOperand::MOStore;
1934 Infos.push_back(Info);
1935 return;
1936 }
1937 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1938 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1939 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1940 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1941 Info.opc = ISD::INTRINSIC_W_CHAIN;
1942
1943 const GCNTargetMachine &TM =
1944 static_cast<const GCNTargetMachine &>(getTargetMachine());
1945
1947 Info.ptrVal = MFI->getGWSPSV(TM);
1948
1949 // This is an abstract access, but we need to specify a type and size.
1950 Info.memVT = MVT::i32;
1951 Info.size = 4;
1952 Info.align = Align(4);
1953
1955 Infos.push_back(Info);
1956 return;
1957 }
1958 case Intrinsic::amdgcn_s_prefetch_data:
1959 case Intrinsic::amdgcn_s_prefetch_inst:
1960 case Intrinsic::amdgcn_flat_prefetch:
1961 case Intrinsic::amdgcn_global_prefetch: {
1962 Info.opc = ISD::INTRINSIC_VOID;
1963 Info.memVT = EVT::getIntegerVT(CI.getContext(), 8);
1964 Info.ptrVal = CI.getArgOperand(0);
1965 Info.flags = Flags | MachineMemOperand::MOLoad;
1966 Infos.push_back(Info);
1967 return;
1968 }
1969 default:
1970 return;
1971 }
1972}
1973
1976 Type *&AccessTy) const {
1977 Value *Ptr = nullptr;
1978 switch (II->getIntrinsicID()) {
1979 case Intrinsic::amdgcn_cluster_load_b128:
1980 case Intrinsic::amdgcn_cluster_load_b64:
1981 case Intrinsic::amdgcn_cluster_load_b32:
1982 case Intrinsic::amdgcn_ds_append:
1983 case Intrinsic::amdgcn_ds_consume:
1984 case Intrinsic::amdgcn_ds_load_tr8_b64:
1985 case Intrinsic::amdgcn_ds_load_tr16_b128:
1986 case Intrinsic::amdgcn_ds_load_tr4_b64:
1987 case Intrinsic::amdgcn_ds_load_tr6_b96:
1988 case Intrinsic::amdgcn_ds_read_tr4_b64:
1989 case Intrinsic::amdgcn_ds_read_tr6_b96:
1990 case Intrinsic::amdgcn_ds_read_tr8_b64:
1991 case Intrinsic::amdgcn_ds_read_tr16_b64:
1992 case Intrinsic::amdgcn_ds_ordered_add:
1993 case Intrinsic::amdgcn_ds_ordered_swap:
1994 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1995 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1996 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1997 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1998 case Intrinsic::amdgcn_global_atomic_fmax_num:
1999 case Intrinsic::amdgcn_global_atomic_fmin_num:
2000 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
2001 case Intrinsic::amdgcn_global_load_tr_b64:
2002 case Intrinsic::amdgcn_global_load_tr_b128:
2003 case Intrinsic::amdgcn_global_load_tr4_b64:
2004 case Intrinsic::amdgcn_global_load_tr6_b96:
2005 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
2006 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
2007 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
2008 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
2009 case Intrinsic::amdgcn_av_load_b8:
2010 case Intrinsic::amdgcn_av_load_b16:
2011 case Intrinsic::amdgcn_av_load_b32:
2012 case Intrinsic::amdgcn_av_load_b64:
2013 case Intrinsic::amdgcn_av_load_b128:
2014 case Intrinsic::amdgcn_av_store_b8:
2015 case Intrinsic::amdgcn_av_store_b16:
2016 case Intrinsic::amdgcn_av_store_b32:
2017 case Intrinsic::amdgcn_av_store_b64:
2018 case Intrinsic::amdgcn_av_store_b128:
2019 Ptr = II->getArgOperand(0);
2020 break;
2021 case Intrinsic::amdgcn_load_to_lds:
2022 case Intrinsic::amdgcn_load_async_to_lds:
2023 case Intrinsic::amdgcn_global_load_lds:
2024 case Intrinsic::amdgcn_global_load_async_lds:
2025 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
2026 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
2027 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
2028 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
2029 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
2030 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
2031 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
2032 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
2033 Ptr = II->getArgOperand(1);
2034 break;
2035 default:
2036 return false;
2037 }
2038 AccessTy = II->getType();
2039 Ops.push_back(Ptr);
2040 return true;
2041}
2042
2044 unsigned AddrSpace) const {
2045 if (!Subtarget->hasFlatInstOffsets()) {
2046 // Flat instructions do not have offsets, and only have the register
2047 // address.
2048 return AM.BaseOffs == 0 && AM.Scale == 0;
2049 }
2050
2052 FlatAddrSpace FlatVariant =
2053 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS ? FlatAddrSpace::FlatGlobal
2054 : AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ? FlatAddrSpace::FlatScratch
2055 : FlatAddrSpace::FLAT;
2056
2057 return AM.Scale == 0 &&
2058 (AM.BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
2059 AM.BaseOffs, AddrSpace, FlatVariant));
2060}
2061
2063 if (Subtarget->hasFlatGlobalInsts())
2065
2066 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
2067 // Assume the we will use FLAT for all global memory accesses
2068 // on VI.
2069 // FIXME: This assumption is currently wrong. On VI we still use
2070 // MUBUF instructions for the r + i addressing mode. As currently
2071 // implemented, the MUBUF instructions only work on buffer < 4GB.
2072 // It may be possible to support > 4GB buffers with MUBUF instructions,
2073 // by setting the stride value in the resource descriptor which would
2074 // increase the size limit to (stride * 4GB). However, this is risky,
2075 // because it has never been validated.
2077 }
2078
2079 return isLegalMUBUFAddressingMode(AM);
2080}
2081
2082bool SITargetLowering::isLegalMUBUFAddressingMode(const AddrMode &AM) const {
2083 // MUBUF / MTBUF instructions have a 12-bit unsigned byte offset, and
2084 // additionally can do r + r + i with addr64. 32-bit has more addressing
2085 // mode options. Depending on the resource constant, it can also do
2086 // (i64 r0) + (i32 r1) * (i14 i).
2087 //
2088 // Private arrays end up using a scratch buffer most of the time, so also
2089 // assume those use MUBUF instructions. Scratch loads / stores are currently
2090 // implemented as mubuf instructions with offen bit set, so slightly
2091 // different than the normal addr64.
2092 const SIInstrInfo *TII = Subtarget->getInstrInfo();
2093 if (!TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2094 return false;
2095
2096 // FIXME: Since we can split immediate into soffset and immediate offset,
2097 // would it make sense to allow any immediate?
2098
2099 switch (AM.Scale) {
2100 case 0: // r + i or just i, depending on HasBaseReg.
2101 return true;
2102 case 1:
2103 return true; // We have r + r or r + i.
2104 case 2:
2105 if (AM.HasBaseReg) {
2106 // Reject 2 * r + r.
2107 return false;
2108 }
2109
2110 // Allow 2 * r as r + r
2111 // Or 2 * r + i is allowed as r + r + i.
2112 return true;
2113 default: // Don't allow n * r
2114 return false;
2115 }
2116}
2117
2119 const AddrMode &AM, Type *Ty,
2120 unsigned AS,
2121 Instruction *I) const {
2122 // No global is ever allowed as a base.
2123 if (AM.BaseGV)
2124 return false;
2125
2126 if (AS == AMDGPUAS::GLOBAL_ADDRESS)
2127 return isLegalGlobalAddressingMode(AM);
2128
2129 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
2133 // If the offset isn't a multiple of 4, it probably isn't going to be
2134 // correctly aligned.
2135 // FIXME: Can we get the real alignment here?
2136 if (AM.BaseOffs % 4 != 0)
2137 return isLegalMUBUFAddressingMode(AM);
2138
2139 if (!Subtarget->hasScalarSubwordLoads()) {
2140 // There are no SMRD extloads, so if we have to do a small type access we
2141 // will use a MUBUF load.
2142 // FIXME?: We also need to do this if unaligned, but we don't know the
2143 // alignment here.
2144 if (Ty->isSized() && DL.getTypeStoreSize(Ty) < 4)
2145 return isLegalGlobalAddressingMode(AM);
2146 }
2147
2148 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS) {
2149 // SMRD instructions have an 8-bit, dword offset on SI.
2150 if (!isUInt<8>(AM.BaseOffs / 4))
2151 return false;
2152 } else if (Subtarget->getGeneration() == AMDGPUSubtarget::SEA_ISLANDS) {
2153 // On CI+, this can also be a 32-bit literal constant offset. If it fits
2154 // in 8-bits, it can use a smaller encoding.
2155 if (!isUInt<32>(AM.BaseOffs / 4))
2156 return false;
2157 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX9) {
2158 // On VI, these use the SMEM format and the offset is 20-bit in bytes.
2159 if (!isUInt<20>(AM.BaseOffs))
2160 return false;
2161 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX12) {
2162 // On GFX9 the offset is signed 21-bit in bytes (but must not be negative
2163 // for S_BUFFER_* instructions).
2164 if (!isInt<21>(AM.BaseOffs))
2165 return false;
2166 } else {
2167 // On GFX12, all offsets are signed 24-bit in bytes.
2168 if (!isInt<24>(AM.BaseOffs))
2169 return false;
2170 }
2171
2172 if ((AS == AMDGPUAS::CONSTANT_ADDRESS ||
2174 AM.BaseOffs < 0) {
2175 // Scalar (non-buffer) loads can only use a negative offset if
2176 // soffset+offset is non-negative. Since the compiler can only prove that
2177 // in a few special cases, it is safer to claim that negative offsets are
2178 // not supported.
2179 return false;
2180 }
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
2191 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
2192 return Subtarget->hasFlatScratchEnabled()
2194 : isLegalMUBUFAddressingMode(AM);
2195
2196 if (AS == AMDGPUAS::LOCAL_ADDRESS ||
2197 (AS == AMDGPUAS::REGION_ADDRESS && Subtarget->hasGDS())) {
2198 // Basic, single offset DS instructions allow a 16-bit unsigned immediate
2199 // field.
2200 // XXX - If doing a 4-byte aligned 8-byte type access, we effectively have
2201 // an 8-bit dword offset but we don't know the alignment here.
2202 if (!isUInt<16>(AM.BaseOffs))
2203 return false;
2204
2205 if (AM.Scale == 0) // r + i or just i, depending on HasBaseReg.
2206 return true;
2207
2208 if (AM.Scale == 1 && AM.HasBaseReg)
2209 return true;
2210
2211 return false;
2212 }
2213
2215 // For an unknown address space, this usually means that this is for some
2216 // reason being used for pure arithmetic, and not based on some addressing
2217 // computation. We don't have instructions that compute pointers with any
2218 // addressing modes, so treat them as having no offset like flat
2219 // instructions.
2221 }
2222
2223 // Assume a user alias of global for unknown address spaces.
2224 return isLegalGlobalAddressingMode(AM);
2225}
2226
2228 const MachineFunction &MF) const {
2230 return (MemVT.getSizeInBits() <= 4 * 32);
2231 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
2232 unsigned MaxPrivateBits = 8 * getSubtarget()->getMaxPrivateElementSize();
2233 return (MemVT.getSizeInBits() <= MaxPrivateBits);
2234 }
2236 return (MemVT.getSizeInBits() <= 2 * 32);
2237 return true;
2238}
2239
2241 unsigned Size, unsigned AddrSpace, Align Alignment,
2242 MachineMemOperand::Flags Flags, unsigned *IsFast) const {
2243 if (IsFast)
2244 *IsFast = 0;
2245
2246 if (AddrSpace == AMDGPUAS::LOCAL_ADDRESS ||
2247 AddrSpace == AMDGPUAS::REGION_ADDRESS) {
2248 // Check if alignment requirements for ds_read/write instructions are
2249 // disabled.
2250 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment < Align(4))
2251 return false;
2252
2253 Align RequiredAlignment(
2254 PowerOf2Ceil(divideCeil(Size, 8))); // Natural alignment.
2255 if (Subtarget->hasLDSMisalignedBugInWGPMode() && Size > 32 &&
2256 Alignment < RequiredAlignment)
2257 return false;
2258
2259 // Either, the alignment requirements are "enabled", or there is an
2260 // unaligned LDS access related hardware bug though alignment requirements
2261 // are "disabled". In either case, we need to check for proper alignment
2262 // requirements.
2263 //
2264 switch (Size) {
2265 case 64:
2266 // SI has a hardware bug in the LDS / GDS bounds checking: if the base
2267 // address is negative, then the instruction is incorrectly treated as
2268 // out-of-bounds even if base + offsets is in bounds. Split vectorized
2269 // loads here to avoid emitting ds_read2_b32. We may re-combine the
2270 // load later in the SILoadStoreOptimizer.
2271 if (!Subtarget->hasUsableDSOffset() && Alignment < Align(8))
2272 return false;
2273
2274 // 8 byte accessing via ds_read/write_b64 require 8-byte alignment, but we
2275 // can do a 4 byte aligned, 8 byte access in a single operation using
2276 // ds_read2/write2_b32 with adjacent offsets.
2277 RequiredAlignment = Align(4);
2278
2279 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2280 // We will either select ds_read_b64/ds_write_b64 or ds_read2_b32/
2281 // ds_write2_b32 depending on the alignment. In either case with either
2282 // alignment there is no faster way of doing this.
2283
2284 // The numbers returned here and below are not additive, it is a 'speed
2285 // rank'. They are just meant to be compared to decide if a certain way
2286 // of lowering an operation is faster than another. For that purpose
2287 // naturally aligned operation gets it bitsize to indicate that "it
2288 // operates with a speed comparable to N-bit wide load". With the full
2289 // alignment ds128 is slower than ds96 for example. If underaligned it
2290 // is comparable to a speed of a single dword access, which would then
2291 // mean 32 < 128 and it is faster to issue a wide load regardless.
2292 // 1 is simply "slow, don't do it". I.e. comparing an aligned load to a
2293 // wider load which will not be aligned anymore the latter is slower.
2294 if (IsFast)
2295 *IsFast = (Alignment >= RequiredAlignment) ? 64
2296 : (Alignment < Align(4)) ? 32
2297 : 1;
2298 return true;
2299 }
2300
2301 break;
2302 case 96:
2303 if (!Subtarget->hasDS96AndDS128())
2304 return false;
2305
2306 // 12 byte accessing via ds_read/write_b96 require 16-byte alignment on
2307 // gfx8 and older.
2308
2309 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2310 // Naturally aligned access is fastest. However, also report it is Fast
2311 // if memory is aligned less than DWORD. A narrow load or store will be
2312 // be equally slow as a single ds_read_b96/ds_write_b96, but there will
2313 // be more of them, so overall we will pay less penalty issuing a single
2314 // instruction.
2315
2316 // See comment on the values above.
2317 if (IsFast)
2318 *IsFast = (Alignment >= RequiredAlignment) ? 96
2319 : (Alignment < Align(4)) ? 32
2320 : 1;
2321 return true;
2322 }
2323
2324 break;
2325 case 128:
2326 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2327 return false;
2328
2329 // 16 byte accessing via ds_read/write_b128 require 16-byte alignment on
2330 // gfx8 and older, but we can do a 8 byte aligned, 16 byte access in a
2331 // single operation using ds_read2/write2_b64.
2332 RequiredAlignment = Align(8);
2333
2334 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2335 // Naturally aligned access is fastest. However, also report it is Fast
2336 // if memory is aligned less than DWORD. A narrow load or store will be
2337 // be equally slow as a single ds_read_b128/ds_write_b128, but there
2338 // will be more of them, so overall we will pay less penalty issuing a
2339 // single instruction.
2340
2341 // See comment on the values above.
2342 if (IsFast)
2343 *IsFast = (Alignment >= RequiredAlignment) ? 128
2344 : (Alignment < Align(4)) ? 32
2345 : 1;
2346 return true;
2347 }
2348
2349 break;
2350 default:
2351 if (Size > 32)
2352 return false;
2353
2354 break;
2355 }
2356
2357 // See comment on the values above.
2358 // Note that we have a single-dword or sub-dword here, so if underaligned
2359 // it is a slowest possible access, hence returned value is 0.
2360 if (IsFast)
2361 *IsFast = (Alignment >= RequiredAlignment) ? Size : 0;
2362
2363 return Alignment >= RequiredAlignment ||
2364 Subtarget->hasUnalignedDSAccessEnabled();
2365 }
2366
2367 // FIXME: We have to be conservative here and assume that flat operations
2368 // will access scratch. If we had access to the IR function, then we
2369 // could determine if any private memory was used in the function.
2370 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ||
2371 AddrSpace == AMDGPUAS::FLAT_ADDRESS) {
2372 bool AlignedBy4 = Alignment >= Align(4);
2373 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2374 if (IsFast)
2375 *IsFast = AlignedBy4 ? Size : 1;
2376 return true;
2377 }
2378
2379 if (IsFast)
2380 *IsFast = AlignedBy4;
2381
2382 return AlignedBy4;
2383 }
2384
2385 // So long as they are correct, wide global memory operations perform better
2386 // than multiple smaller memory ops -- even when misaligned
2387 if (AMDGPU::isExtendedGlobalAddrSpace(AddrSpace)) {
2388 if (IsFast)
2389 *IsFast = Size;
2390
2391 return Alignment >= Align(4) ||
2392 Subtarget->hasUnalignedBufferAccessEnabled();
2393 }
2394
2395 // Ensure robust out-of-bounds guarantees for buffer accesses are met when the
2396 // "amdgpu.buffer.oob.mode" module flag has not enabled relaxed untyped-buffer
2397 // OOB semantics. Normally hardware will ensure proper
2398 // out-of-bounds behavior, but in the edge case where an access starts
2399 // out-of-bounds and then enters in-bounds, the entire access would be treated
2400 // as out-of-bounds. Prevent misaligned memory accesses by requiring the
2401 // natural alignment of buffer accesses.
2402 if (AddrSpace == AMDGPUAS::BUFFER_FAT_POINTER ||
2403 AddrSpace == AMDGPUAS::BUFFER_RESOURCE ||
2404 AddrSpace == AMDGPUAS::BUFFER_STRIDED_POINTER) {
2405 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2406 Alignment < Align(PowerOf2Ceil(divideCeil(Size, 8))))
2407 return false;
2408 }
2409
2410 // Smaller than dword value must be aligned.
2411 if (Size < 32)
2412 return false;
2413
2414 // 8.1.6 - For Dword or larger reads or writes, the two LSBs of the
2415 // byte-address are ignored, thus forcing Dword alignment.
2416 // This applies to private, global, and constant memory.
2417 if (IsFast)
2418 *IsFast = 1;
2419
2420 return Size >= 32 && Alignment >= Align(4);
2421}
2422
2424 EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
2425 unsigned *IsFast) const {
2427 Alignment, Flags, IsFast);
2428}
2429
2431 LLVMContext &Context, const MemOp &Op,
2432 const AttributeList &FuncAttributes) const {
2433 // FIXME: Should account for address space here.
2434
2435 // The default fallback uses the private pointer size as a guess for a type to
2436 // use. Make sure we switch these to 64-bit accesses.
2437
2438 if (Op.size() >= 16 &&
2439 Op.isDstAligned(Align(4))) // XXX: Should only do for global
2440 return MVT::v4i32;
2441
2442 if (Op.size() >= 8 && Op.isDstAligned(Align(4)))
2443 return MVT::v2i32;
2444
2445 // Use the default.
2446 return MVT::Other;
2447}
2448
2450 const MemSDNode *MemNode = cast<MemSDNode>(N);
2451 return MemNode->getMemOperand()->getFlags() & MONoClobber;
2452}
2453
2458
2460 unsigned DestAS) const {
2461 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
2462 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
2463 Subtarget->hasGloballyAddressableScratch()) {
2464 // Flat -> private requires subtracting src_flat_scratch_base_lo.
2465 return false;
2466 }
2467
2468 // Flat -> private/local is a simple truncate.
2469 // Flat -> global is no-op
2470 return true;
2471 }
2472
2473 const GCNTargetMachine &TM =
2474 static_cast<const GCNTargetMachine &>(getTargetMachine());
2475 return TM.isNoopAddrSpaceCast(DL, SrcAS, DestAS);
2476}
2477
2485
2487 Type *Ty) const {
2488 // FIXME: Could be smarter if called for vector constants.
2489 return true;
2490}
2491
2494 unsigned Index) const {
2497
2498 // TODO: Add more cases that are cheap.
2499 if (Index == 0)
2502}
2503
2504bool SITargetLowering::isExtractVecEltCheap(EVT VT, unsigned Index) const {
2505 // TODO: This should be more aggressive, particular for 16-bit element
2506 // vectors. However there are some mixed improvements and regressions.
2507 EVT EltTy = VT.getVectorElementType();
2508 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2509 return EltTy.getSizeInBits() % MinAlign == 0;
2510}
2511
2513 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2514 switch (Op) {
2515 case ISD::LOAD:
2516 case ISD::STORE:
2517 return true;
2518 default:
2519 return false;
2520 }
2521 }
2522
2523 // SimplifySetCC uses this function to determine whether or not it should
2524 // create setcc with i1 operands. We don't have instructions for i1 setcc.
2525 if (VT == MVT::i1 && Op == ISD::SETCC)
2526 return false;
2527
2528 if (VT.getScalarType() == MVT::i64 &&
2530 return false;
2531
2533}
2534
2536 // Do not convert uniform loads to 16-bit.
2537 // Uniform 16-bit loads are legalized to i16 = trunc (zextload i16->i32)
2538 // to match subword load patterns. Allowing conversion back to a 16-bit
2539 // load would create an infinite loop.
2540 if (Subtarget->hasScalarSubwordLoads() && N->getOpcode() == ISD::LOAD &&
2541 !VT.isVector() && VT.getSizeInBits() == 16) {
2542 auto *Load = dyn_cast<LoadSDNode>(N);
2543 if (Load && isUniformLoad(Load)) {
2544 return false;
2545 }
2546 }
2547
2548 return isTypeDesirableForOp(N->getOpcode(), VT);
2549}
2550
2552 const MachineMemOperand *MMO = Load->getMemOperand();
2553
2554 // FIXME: We ought to able able to take the direct isDivergent result. We
2555 // cannot rely on the MMO for a uniformity check, and should stop using
2556 // it. This is a hack for 2 ways that the IR divergence analysis is superior
2557 // to the DAG divergence: Recognizing shift-of-workitem-id as always
2558 // uniform, and isSingleLaneExecution. These should be handled in the DAG
2559 // version, and then this can be dropped.
2560 if (Load->isDivergent() && !AMDGPU::isUniformMMO(MMO))
2561 return false;
2562
2563 return MMO->getSize().hasValue() &&
2564 Load->getAlign() >=
2565 Align(std::min(MMO->getSize().getValue().getKnownMinValue(),
2566 uint64_t(4))) &&
2567 (MMO->isInvariant() ||
2568 (Load->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS ||
2569 Load->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT) ||
2570 (Load->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS &&
2571 Load->isSimple() && isMemOpHasNoClobberedMemOperand(Load)));
2572}
2573
2576 // This isn't really a constant pool but close enough.
2579 return PtrInfo;
2580}
2581
2582SDValue SITargetLowering::lowerKernArgParameterPtr(SelectionDAG &DAG,
2583 const SDLoc &SL,
2584 SDValue Chain,
2585 uint64_t Offset) const {
2586 const DataLayout &DL = DAG.getDataLayout();
2590
2591 auto [InputPtrReg, RC, ArgTy] =
2592 Info->getPreloadedValue(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
2593
2594 // We may not have the kernarg segment argument if we have no kernel
2595 // arguments.
2596 if (!InputPtrReg)
2597 return DAG.getConstant(Offset, SL, PtrVT);
2598
2600 SDValue BasePtr = DAG.getCopyFromReg(
2601 Chain, SL, MRI.getLiveInVirtReg(InputPtrReg->getRegister()), PtrVT);
2602
2603 return DAG.getObjectPtrOffset(SL, BasePtr, TypeSize::getFixed(Offset));
2604}
2605
2606SDValue SITargetLowering::getImplicitArgPtr(SelectionDAG &DAG,
2607 const SDLoc &SL) const {
2610 return lowerKernArgParameterPtr(DAG, SL, DAG.getEntryNode(), Offset);
2611}
2612
2613SDValue SITargetLowering::getLDSKernelId(SelectionDAG &DAG,
2614 const SDLoc &SL) const {
2615
2617 std::optional<uint32_t> KnownSize =
2619 if (KnownSize.has_value())
2620 return DAG.getConstant(*KnownSize, SL, MVT::i32);
2621 return SDValue();
2622}
2623
2624SDValue SITargetLowering::convertArgType(SelectionDAG &DAG, EVT VT, EVT MemVT,
2625 const SDLoc &SL, SDValue Val,
2626 bool Signed,
2627 const ISD::InputArg *Arg) const {
2628 // First, if it is a widened vector, narrow it.
2629 if (VT.isVector() &&
2631 EVT NarrowedVT =
2634 Val = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, NarrowedVT, Val,
2635 DAG.getConstant(0, SL, MVT::i32));
2636 }
2637
2638 // Then convert the vector elements or scalar value.
2639 if (Arg && (Arg->Flags.isSExt() || Arg->Flags.isZExt()) && VT.bitsLT(MemVT)) {
2640 unsigned Opc = Arg->Flags.isZExt() ? ISD::AssertZext : ISD::AssertSext;
2641 Val = DAG.getNode(Opc, SL, MemVT, Val, DAG.getValueType(VT));
2642 }
2643
2644 if (MemVT.isFloatingPoint()) {
2645 if (VT.isFloatingPoint()) {
2646 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2647 } else {
2648 assert(!MemVT.isVector());
2649 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
2650 SDValue Cast = DAG.getBitcast(IntVT, Val);
2651 Val = DAG.getAnyExtOrTrunc(Cast, SL, VT);
2652 }
2653 } else if (Signed)
2654 Val = DAG.getSExtOrTrunc(Val, SL, VT);
2655 else
2656 Val = DAG.getZExtOrTrunc(Val, SL, VT);
2657
2658 return Val;
2659}
2660
2661SDValue SITargetLowering::lowerKernargMemParameter(
2662 SelectionDAG &DAG, EVT VT, EVT MemVT, const SDLoc &SL, SDValue Chain,
2663 uint64_t Offset, Align Alignment, bool Signed,
2664 const ISD::InputArg *Arg) const {
2665
2666 MachinePointerInfo PtrInfo =
2668
2669 // Try to avoid using an extload by loading earlier than the argument address,
2670 // and extracting the relevant bits. The load should hopefully be merged with
2671 // the previous argument.
2672 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
2673 // TODO: Handle align < 4 and size >= 4 (can happen with packed structs).
2674 int64_t AlignDownOffset = alignDown(Offset, 4);
2675 int64_t OffsetDiff = Offset - AlignDownOffset;
2676
2677 EVT IntVT = MemVT.changeTypeToInteger();
2678
2679 // TODO: If we passed in the base kernel offset we could have a better
2680 // alignment than 4, but we don't really need it.
2681 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2682 SDValue Load = DAG.getLoad(MVT::i32, SL, Chain, Ptr,
2683 PtrInfo.getWithOffset(AlignDownOffset), Align(4),
2686
2687 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, SL, MVT::i32);
2688 SDValue Extract = DAG.getNode(ISD::SRL, SL, MVT::i32, Load, ShiftAmt);
2689
2690 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, SL, IntVT, Extract);
2691 ArgVal = DAG.getNode(ISD::BITCAST, SL, MemVT, ArgVal);
2692 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal, Signed, Arg);
2693
2694 return DAG.getMergeValues({ArgVal, Load.getValue(1)}, SL);
2695 }
2696
2697 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, Offset);
2698 SDValue Load = DAG.getLoad(
2699 MemVT, SL, Chain, Ptr, PtrInfo.getWithOffset(Offset), Alignment,
2701
2702 SDValue Val = convertArgType(DAG, VT, MemVT, SL, Load, Signed, Arg);
2703 return DAG.getMergeValues({Val, Load.getValue(1)}, SL);
2704}
2705
2706/// Coerce an argument which was passed in a different ABI type to the original
2707/// expected value type.
2708SDValue SITargetLowering::convertABITypeToValueType(SelectionDAG &DAG,
2709 SDValue Val,
2710 CCValAssign &VA,
2711 const SDLoc &SL) const {
2712 EVT ValVT = VA.getValVT();
2713
2714 // If this is an 8 or 16-bit value, it is really passed promoted
2715 // to 32 bits. Insert an assert[sz]ext to capture this, then
2716 // truncate to the right size.
2717 switch (VA.getLocInfo()) {
2718 case CCValAssign::Full:
2719 return Val;
2720 case CCValAssign::BCvt:
2721 return DAG.getNode(ISD::BITCAST, SL, ValVT, Val);
2722 case CCValAssign::SExt:
2723 Val = DAG.getNode(ISD::AssertSext, SL, VA.getLocVT(), Val,
2724 DAG.getValueType(ValVT));
2725 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2726 case CCValAssign::ZExt:
2727 Val = DAG.getNode(ISD::AssertZext, SL, VA.getLocVT(), Val,
2728 DAG.getValueType(ValVT));
2729 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2730 case CCValAssign::AExt:
2731 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2732 default:
2733 llvm_unreachable("Unknown loc info!");
2734 }
2735}
2736
2737SDValue SITargetLowering::lowerStackParameter(SelectionDAG &DAG,
2738 CCValAssign &VA, const SDLoc &SL,
2739 SDValue Chain,
2740 const ISD::InputArg &Arg) const {
2742 MachineFrameInfo &MFI = MF.getFrameInfo();
2743
2744 if (Arg.Flags.isByVal()) {
2745 unsigned Size = Arg.Flags.getByValSize();
2746 int FrameIdx = MFI.CreateFixedObject(Size, VA.getLocMemOffset(), false);
2747 return DAG.getFrameIndex(FrameIdx, MVT::i32);
2748 }
2749
2750 unsigned ArgOffset = VA.getLocMemOffset();
2751 unsigned ArgSize = VA.getValVT().getStoreSize();
2752
2753 int FI = MFI.CreateFixedObject(ArgSize, ArgOffset, true);
2754
2755 // Create load nodes to retrieve arguments from the stack.
2756 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
2757
2758 // For NON_EXTLOAD, generic code in getLoad assert(ValVT == MemVT)
2760 MVT MemVT = VA.getValVT();
2761
2762 switch (VA.getLocInfo()) {
2763 default:
2764 break;
2765 case CCValAssign::BCvt:
2766 MemVT = VA.getLocVT();
2767 break;
2768 case CCValAssign::SExt:
2769 ExtType = ISD::SEXTLOAD;
2770 break;
2771 case CCValAssign::ZExt:
2772 ExtType = ISD::ZEXTLOAD;
2773 break;
2774 case CCValAssign::AExt:
2775 ExtType = ISD::EXTLOAD;
2776 break;
2777 }
2778
2779 SDValue ArgValue = DAG.getExtLoad(
2780 ExtType, SL, VA.getLocVT(), Chain, FIN,
2782
2783 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2784 if (ConvertedVal == ArgValue)
2785 return ConvertedVal;
2786
2787 return DAG.getMergeValues({ConvertedVal, ArgValue.getValue(1)}, SL);
2788}
2789
2790SDValue SITargetLowering::lowerWorkGroupId(
2791 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2794 AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const {
2795 if (!Subtarget->hasClusters())
2796 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2797
2798 // Clusters are supported. Return the global position in the grid. If clusters
2799 // are enabled, WorkGroupIdPV returns the cluster ID not the workgroup ID.
2800
2801 // WorkGroupIdXYZ = ClusterId == 0 ?
2802 // ClusterIdXYZ :
2803 // ClusterIdXYZ * (ClusterMaxIdXYZ + 1) + ClusterWorkGroupIdXYZ
2804 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2805 SDLoc SL(ClusterIdXYZ);
2806 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2807 SDValue One = DAG.getConstant(1, SL, VT);
2808 SDValue ClusterSizeXYZ = DAG.getNode(ISD::ADD, SL, VT, ClusterMaxIdXYZ, One);
2809 SDValue ClusterWorkGroupIdXYZ =
2810 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2811 SDValue GlobalIdXYZ =
2812 DAG.getNode(ISD::ADD, SL, VT, ClusterWorkGroupIdXYZ,
2813 DAG.getNode(ISD::MUL, SL, VT, ClusterIdXYZ, ClusterSizeXYZ));
2814
2815 switch (MFI.getClusterDims().getKind()) {
2818 return GlobalIdXYZ;
2820 return ClusterIdXYZ;
2822 using namespace AMDGPU::Hwreg;
2823 SDValue ClusterIdField =
2824 DAG.getTargetConstant(HwregEncoding::encode(ID_IB_STS2, 6, 4), SL, VT);
2825 SDNode *GetReg =
2826 DAG.getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2827 SDValue ClusterId(GetReg, 0);
2828 SDValue Zero = DAG.getConstant(0, SL, VT);
2829 return DAG.getNode(ISD::SELECT_CC, SL, VT, ClusterId, Zero, ClusterIdXYZ,
2830 GlobalIdXYZ, DAG.getCondCode(ISD::SETEQ));
2831 }
2832 }
2833
2834 llvm_unreachable("nothing should reach here");
2835}
2836
2837SDValue SITargetLowering::getPreloadedValue(
2838 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2840 const ArgDescriptor *Reg = nullptr;
2841 const TargetRegisterClass *RC = nullptr;
2842 LLT Ty;
2843
2845 const ArgDescriptor WorkGroupIDX =
2846 ArgDescriptor::createRegister(AMDGPU::TTMP9);
2847 // If GridZ is not programmed in an entry function then the hardware will set
2848 // it to all zeros, so there is no need to mask the GridY value in the low
2849 // order bits.
2850 const ArgDescriptor WorkGroupIDY = ArgDescriptor::createRegister(
2851 AMDGPU::TTMP7,
2852 AMDGPU::isEntryFunctionCC(CC) && !MFI.hasWorkGroupIDZ() ? ~0u : 0xFFFFu);
2853 const ArgDescriptor WorkGroupIDZ =
2854 ArgDescriptor::createRegister(AMDGPU::TTMP7, 0xFFFF0000u);
2855 const ArgDescriptor ClusterWorkGroupIDX =
2856 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000000Fu);
2857 const ArgDescriptor ClusterWorkGroupIDY =
2858 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000000F0u);
2859 const ArgDescriptor ClusterWorkGroupIDZ =
2860 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00000F00u);
2861 const ArgDescriptor ClusterWorkGroupMaxIDX =
2862 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000F000u);
2863 const ArgDescriptor ClusterWorkGroupMaxIDY =
2864 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000F0000u);
2865 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2866 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00F00000u);
2867 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2868 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0F000000u);
2869
2870 auto LoadConstant = [&](unsigned N) {
2871 return DAG.getConstant(N, SDLoc(), VT);
2872 };
2873
2874 if (Subtarget->hasArchitectedSGPRs() &&
2877 AMDGPU::ClusterDimsAttr ClusterDims = MFI.getClusterDims();
2878 bool HasFixedDims = ClusterDims.isFixedDims();
2879
2880 switch (PVID) {
2882 Reg = &WorkGroupIDX;
2883 RC = &AMDGPU::SReg_32RegClass;
2884 Ty = LLT::scalar(32);
2885 break;
2887 Reg = &WorkGroupIDY;
2888 RC = &AMDGPU::SReg_32RegClass;
2889 Ty = LLT::scalar(32);
2890 break;
2892 Reg = &WorkGroupIDZ;
2893 RC = &AMDGPU::SReg_32RegClass;
2894 Ty = LLT::scalar(32);
2895 break;
2897 if (HasFixedDims && ClusterDims.getDims()[0] == 1)
2898 return LoadConstant(0);
2899 Reg = &ClusterWorkGroupIDX;
2900 RC = &AMDGPU::SReg_32RegClass;
2901 Ty = LLT::scalar(32);
2902 break;
2904 if (HasFixedDims && ClusterDims.getDims()[1] == 1)
2905 return LoadConstant(0);
2906 Reg = &ClusterWorkGroupIDY;
2907 RC = &AMDGPU::SReg_32RegClass;
2908 Ty = LLT::scalar(32);
2909 break;
2911 if (HasFixedDims && ClusterDims.getDims()[2] == 1)
2912 return LoadConstant(0);
2913 Reg = &ClusterWorkGroupIDZ;
2914 RC = &AMDGPU::SReg_32RegClass;
2915 Ty = LLT::scalar(32);
2916 break;
2918 if (HasFixedDims)
2919 return LoadConstant(ClusterDims.getDims()[0] - 1);
2920 Reg = &ClusterWorkGroupMaxIDX;
2921 RC = &AMDGPU::SReg_32RegClass;
2922 Ty = LLT::scalar(32);
2923 break;
2925 if (HasFixedDims)
2926 return LoadConstant(ClusterDims.getDims()[1] - 1);
2927 Reg = &ClusterWorkGroupMaxIDY;
2928 RC = &AMDGPU::SReg_32RegClass;
2929 Ty = LLT::scalar(32);
2930 break;
2932 if (HasFixedDims)
2933 return LoadConstant(ClusterDims.getDims()[2] - 1);
2934 Reg = &ClusterWorkGroupMaxIDZ;
2935 RC = &AMDGPU::SReg_32RegClass;
2936 Ty = LLT::scalar(32);
2937 break;
2939 Reg = &ClusterWorkGroupMaxFlatID;
2940 RC = &AMDGPU::SReg_32RegClass;
2941 Ty = LLT::scalar(32);
2942 break;
2943 default:
2944 break;
2945 }
2946 }
2947
2948 if (!Reg)
2949 std::tie(Reg, RC, Ty) = MFI.getPreloadedValue(PVID);
2950 if (!Reg) {
2952 // It's possible for a kernarg intrinsic call to appear in a kernel with
2953 // no allocated segment, in which case we do not add the user sgpr
2954 // argument, so just return null.
2955 return DAG.getConstant(0, SDLoc(), VT);
2956 }
2957
2958 // It's undefined behavior if a function marked with the amdgpu-no-*
2959 // attributes uses the corresponding intrinsic.
2960 return DAG.getPOISON(VT);
2961 }
2962
2963 return loadInputValue(DAG, RC, VT, SDLoc(DAG.getEntryNode()), *Reg);
2964}
2965
2967 CallingConv::ID CallConv,
2968 ArrayRef<ISD::InputArg> Ins, BitVector &Skipped,
2969 FunctionType *FType,
2970 SIMachineFunctionInfo *Info) {
2971 for (unsigned I = 0, E = Ins.size(), PSInputNum = 0; I != E; ++I) {
2972 const ISD::InputArg *Arg = &Ins[I];
2973
2974 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2975 "vector type argument should have been split");
2976
2977 // First check if it's a PS input addr.
2978 if (CallConv == CallingConv::AMDGPU_PS && !Arg->Flags.isInReg() &&
2979 PSInputNum <= 15) {
2980 bool SkipArg = !Arg->Used && !Info->isPSInputAllocated(PSInputNum);
2981
2982 // Inconveniently only the first part of the split is marked as isSplit,
2983 // so skip to the end. We only want to increment PSInputNum once for the
2984 // entire split argument.
2985 if (Arg->Flags.isSplit()) {
2986 while (!Arg->Flags.isSplitEnd()) {
2987 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2988 "unexpected vector split in ps argument type");
2989 if (!SkipArg)
2990 Splits.push_back(*Arg);
2991 Arg = &Ins[++I];
2992 }
2993 }
2994
2995 if (SkipArg) {
2996 // We can safely skip PS inputs.
2997 Skipped.set(Arg->getOrigArgIndex());
2998 ++PSInputNum;
2999 continue;
3000 }
3001
3002 Info->markPSInputAllocated(PSInputNum);
3003 if (Arg->Used)
3004 Info->markPSInputEnabled(PSInputNum);
3005
3006 ++PSInputNum;
3007 }
3008
3009 Splits.push_back(*Arg);
3010 }
3011}
3012
3013// Allocate special inputs passed in VGPRs.
3015 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3016 SIMachineFunctionInfo &Info) const {
3017 const LLT I32 = LLT::integer(32);
3019
3020 if (Info.hasWorkItemIDX()) {
3021 Register Reg = AMDGPU::VGPR0;
3022 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3023
3024 CCInfo.AllocateReg(Reg);
3025 unsigned Mask =
3026 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
3027 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
3028 }
3029
3030 if (Info.hasWorkItemIDY()) {
3031 assert(Info.hasWorkItemIDX());
3032 if (Subtarget->hasPackedTID()) {
3033 Info.setWorkItemIDY(
3034 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 10));
3035 } else {
3036 unsigned Reg = AMDGPU::VGPR1;
3037 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3038
3039 CCInfo.AllocateReg(Reg);
3040 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg));
3041 }
3042 }
3043
3044 if (Info.hasWorkItemIDZ()) {
3045 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
3046 if (Subtarget->hasPackedTID()) {
3047 Info.setWorkItemIDZ(
3048 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 20));
3049 } else {
3050 unsigned Reg = AMDGPU::VGPR2;
3051 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), I32);
3052
3053 CCInfo.AllocateReg(Reg);
3054 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg));
3055 }
3056 }
3057}
3058
3060 const TargetRegisterClass *RC,
3061 unsigned NumArgRegs) {
3062 ArrayRef<MCPhysReg> ArgSGPRs = ArrayRef(RC->begin(), 32);
3063 unsigned RegIdx = CCInfo.getFirstUnallocated(ArgSGPRs);
3064 if (RegIdx == ArgSGPRs.size())
3065 report_fatal_error("ran out of SGPRs for arguments");
3066
3067 unsigned Reg = ArgSGPRs[RegIdx];
3068 Reg = CCInfo.AllocateReg(Reg);
3069 assert(Reg != AMDGPU::NoRegister);
3070
3071 MachineFunction &MF = CCInfo.getMachineFunction();
3072 MF.addLiveIn(Reg, RC);
3074}
3075
3076// If this has a fixed position, we still should allocate the register in the
3077// CCInfo state. Technically we could get away with this for values passed
3078// outside of the normal argument range.
3080 const TargetRegisterClass *RC,
3081 MCRegister Reg) {
3082 Reg = CCInfo.AllocateReg(Reg);
3083 assert(Reg != AMDGPU::NoRegister);
3084 MachineFunction &MF = CCInfo.getMachineFunction();
3085 MF.addLiveIn(Reg, RC);
3086}
3087
3088static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg) {
3089 if (Arg) {
3090 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_32RegClass,
3091 Arg.getRegister());
3092 } else
3093 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_32RegClass, 32);
3094}
3095
3096static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg) {
3097 if (Arg) {
3098 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_64RegClass,
3099 Arg.getRegister());
3100 } else
3101 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_64RegClass, 16);
3102}
3103
3104/// Allocate implicit function VGPR arguments in fixed registers.
3106 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3107 SIMachineFunctionInfo &Info) const {
3108 Register Reg = CCInfo.AllocateReg(AMDGPU::VGPR31);
3109 if (!Reg)
3110 report_fatal_error("failed to allocate VGPR for implicit arguments");
3111
3112 const unsigned Mask = 0x3ff;
3113 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
3114 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg, Mask << 10));
3115 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg, Mask << 20));
3116}
3117
3119 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3120 SIMachineFunctionInfo &Info) const {
3121 auto &ArgInfo = Info.getArgInfo();
3122 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3123
3124 // TODO: Unify handling with private memory pointers.
3125 if (UserSGPRInfo.hasDispatchPtr())
3126 allocateSGPR64Input(CCInfo, ArgInfo.DispatchPtr);
3127
3128 if (UserSGPRInfo.hasQueuePtr())
3129 allocateSGPR64Input(CCInfo, ArgInfo.QueuePtr);
3130
3131 // Implicit arg ptr takes the place of the kernarg segment pointer. This is a
3132 // constant offset from the kernarg segment.
3133 if (Info.hasImplicitArgPtr())
3134 allocateSGPR64Input(CCInfo, ArgInfo.ImplicitArgPtr);
3135
3136 if (UserSGPRInfo.hasDispatchID())
3137 allocateSGPR64Input(CCInfo, ArgInfo.DispatchID);
3138
3139 // flat_scratch_init is not applicable for non-kernel functions.
3140
3141 if (Info.hasWorkGroupIDX())
3142 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDX);
3143
3144 if (Info.hasWorkGroupIDY())
3145 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDY);
3146
3147 if (Info.hasWorkGroupIDZ())
3148 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDZ);
3149
3150 if (Info.hasLDSKernelId())
3151 allocateSGPR32Input(CCInfo, ArgInfo.LDSKernelId);
3152}
3153
3154// Allocate special inputs passed in user SGPRs.
3156 MachineFunction &MF,
3157 const SIRegisterInfo &TRI,
3158 SIMachineFunctionInfo &Info) const {
3159 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3160 if (UserSGPRInfo.hasImplicitBufferPtr()) {
3161 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(TRI);
3162 MF.addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3163 CCInfo.AllocateReg(ImplicitBufferPtrReg);
3164 }
3165
3166 // FIXME: How should these inputs interact with inreg / custom SGPR inputs?
3167 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
3168 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(TRI);
3169 MF.addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3170 CCInfo.AllocateReg(PrivateSegmentBufferReg);
3171 }
3172
3173 if (UserSGPRInfo.hasDispatchPtr()) {
3174 Register DispatchPtrReg = Info.addDispatchPtr(TRI);
3175 MF.addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3176 CCInfo.AllocateReg(DispatchPtrReg);
3177 }
3178
3179 if (UserSGPRInfo.hasQueuePtr()) {
3180 Register QueuePtrReg = Info.addQueuePtr(TRI);
3181 MF.addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3182 CCInfo.AllocateReg(QueuePtrReg);
3183 }
3184
3185 if (UserSGPRInfo.hasKernargSegmentPtr()) {
3187 Register InputPtrReg = Info.addKernargSegmentPtr(TRI);
3188 CCInfo.AllocateReg(InputPtrReg);
3189
3190 Register VReg = MF.addLiveIn(InputPtrReg, &AMDGPU::SGPR_64RegClass);
3191 MRI.setType(VReg, LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS, 64));
3192 }
3193
3194 if (UserSGPRInfo.hasDispatchID()) {
3195 Register DispatchIDReg = Info.addDispatchID(TRI);
3196 MF.addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3197 CCInfo.AllocateReg(DispatchIDReg);
3198 }
3199
3200 if (UserSGPRInfo.hasFlatScratchInit() && !getSubtarget()->isAmdPalOS()) {
3201 Register FlatScratchInitReg = Info.addFlatScratchInit(TRI);
3202 MF.addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3203 CCInfo.AllocateReg(FlatScratchInitReg);
3204 }
3205
3206 if (UserSGPRInfo.hasPrivateSegmentSize()) {
3207 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(TRI);
3208 MF.addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3209 CCInfo.AllocateReg(PrivateSegmentSizeReg);
3210 }
3211
3212 // TODO: Add GridWorkGroupCount user SGPRs when used. For now with HSA we read
3213 // these from the dispatch pointer.
3214}
3215
3216// Allocate pre-loaded kernel arguemtns. Arguments to be preloading must be
3217// sequential starting from the first argument.
3219 CCState &CCInfo, SmallVectorImpl<CCValAssign> &ArgLocs,
3221 const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const {
3222 Function &F = MF.getFunction();
3223 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3224 GCNUserSGPRUsageInfo &SGPRInfo = Info.getUserSGPRInfo();
3225 bool InPreloadSequence = true;
3226 unsigned InIdx = 0;
3227 bool AlignedForImplictArgs = false;
3228 unsigned ImplicitArgOffset = 0;
3229 for (auto &Arg : F.args()) {
3230 if (!InPreloadSequence || !Arg.hasInRegAttr())
3231 break;
3232
3233 unsigned ArgIdx = Arg.getArgNo();
3234 // Don't preload non-original args or parts not in the current preload
3235 // sequence.
3236 if (InIdx < Ins.size() &&
3237 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3238 break;
3239
3240 for (; InIdx < Ins.size() && Ins[InIdx].isOrigArg() &&
3241 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3242 InIdx++) {
3243 assert(ArgLocs[ArgIdx].isMemLoc());
3244 auto &ArgLoc = ArgLocs[InIdx];
3245 const Align KernelArgBaseAlign = Align(16);
3246 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3247 Align Alignment = commonAlignment(KernelArgBaseAlign, ArgOffset);
3248 unsigned NumAllocSGPRs =
3249 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3250
3251 // Fix alignment for hidden arguments.
3252 if (Arg.hasAttribute("amdgpu-hidden-argument")) {
3253 if (!AlignedForImplictArgs) {
3254 ImplicitArgOffset =
3255 alignTo(LastExplicitArgOffset,
3256 Subtarget->getAlignmentForImplicitArgPtr()) -
3257 LastExplicitArgOffset;
3258 AlignedForImplictArgs = true;
3259 }
3260 ArgOffset += ImplicitArgOffset;
3261 }
3262
3263 // Arg is preloaded into the previous SGPR.
3264 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3265 assert(InIdx >= 1 && "No previous SGPR");
3266 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3267 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3268 continue;
3269 }
3270
3271 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3272 unsigned PaddingSGPRs = alignTo(Padding, 4) / 4;
3273 // Check for free user SGPRs for preloading.
3274 if (PaddingSGPRs + NumAllocSGPRs > SGPRInfo.getNumFreeUserSGPRs()) {
3275 InPreloadSequence = false;
3276 break;
3277 }
3278
3279 // Preload this argument.
3280 const TargetRegisterClass *RC =
3281 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3282 SmallVectorImpl<MCRegister> *PreloadRegs =
3283 Info.addPreloadedKernArg(TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3284
3285 if (PreloadRegs->size() > 1)
3286 RC = &AMDGPU::SGPR_32RegClass;
3287 for (auto &Reg : *PreloadRegs) {
3288 assert(Reg);
3289 MF.addLiveIn(Reg, RC);
3290 CCInfo.AllocateReg(Reg);
3291 }
3292
3293 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3294 }
3295 }
3296}
3297
3299 const SIRegisterInfo &TRI,
3300 SIMachineFunctionInfo &Info) const {
3301 // Always allocate this last since it is a synthetic preload.
3302 if (Info.hasLDSKernelId()) {
3303 Register Reg = Info.addLDSKernelId();
3304 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3305 CCInfo.AllocateReg(Reg);
3306 }
3307}
3308
3309// Allocate special input registers that are initialized per-wave.
3312 CallingConv::ID CallConv,
3313 bool IsShader) const {
3314 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3315 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3316 // Note: user SGPRs are handled by the front-end for graphics shaders
3317 // Pad up the used user SGPRs with dead inputs.
3318
3319 // TODO: NumRequiredSystemSGPRs computation should be adjusted appropriately
3320 // before enabling architected SGPRs for workgroup IDs.
3321 assert(!HasArchitectedSGPRs && "Unhandled feature for the subtarget");
3322
3323 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3324 // Note we do not count the PrivateSegmentWaveByteOffset. We do not want to
3325 // rely on it to reach 16 since if we end up having no stack usage, it will
3326 // not really be added.
3327 unsigned NumRequiredSystemSGPRs =
3328 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3329 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3330 for (unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3331 Register Reg = Info.addReservedUserSGPR();
3332 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3333 CCInfo.AllocateReg(Reg);
3334 }
3335 }
3336
3337 if (!HasArchitectedSGPRs) {
3338 if (Info.hasWorkGroupIDX()) {
3339 Register Reg = Info.addWorkGroupIDX();
3340 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3341 CCInfo.AllocateReg(Reg);
3342 }
3343
3344 if (Info.hasWorkGroupIDY()) {
3345 Register Reg = Info.addWorkGroupIDY();
3346 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3347 CCInfo.AllocateReg(Reg);
3348 }
3349
3350 if (Info.hasWorkGroupIDZ()) {
3351 Register Reg = Info.addWorkGroupIDZ();
3352 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3353 CCInfo.AllocateReg(Reg);
3354 }
3355 }
3356
3357 if (Info.hasWorkGroupInfo()) {
3358 Register Reg = Info.addWorkGroupInfo();
3359 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3360 CCInfo.AllocateReg(Reg);
3361 }
3362
3363 if (Info.hasPrivateSegmentWaveByteOffset()) {
3364 // Scratch wave offset passed in system SGPR.
3365 unsigned PrivateSegmentWaveByteOffsetReg;
3366
3367 if (IsShader) {
3368 PrivateSegmentWaveByteOffsetReg =
3369 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3370
3371 // This is true if the scratch wave byte offset doesn't have a fixed
3372 // location.
3373 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3374 PrivateSegmentWaveByteOffsetReg = findFirstFreeSGPR(CCInfo);
3375 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3376 }
3377 } else
3378 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3379
3380 MF.addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3381 CCInfo.AllocateReg(PrivateSegmentWaveByteOffsetReg);
3382 }
3383
3384 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3385 Info.getNumPreloadedSGPRs() >= 16);
3386}
3387
3389 MachineFunction &MF,
3390 const SIRegisterInfo &TRI,
3391 SIMachineFunctionInfo &Info) {
3392 // Now that we've figured out where the scratch register inputs are, see if
3393 // should reserve the arguments and use them directly.
3394 MachineFrameInfo &MFI = MF.getFrameInfo();
3395 bool HasStackObjects = MFI.hasStackObjects();
3396 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3397
3398 // Record that we know we have non-spill stack objects so we don't need to
3399 // check all stack objects later.
3400 if (HasStackObjects)
3401 Info.setHasNonSpillStackObjects(true);
3402
3403 // Everything live out of a block is spilled with fast regalloc, so it's
3404 // almost certain that spilling will be required.
3406 HasStackObjects = true;
3407
3408 // For now assume stack access is needed in any callee functions, so we need
3409 // the scratch registers to pass in.
3410 bool RequiresStackAccess = HasStackObjects || MFI.hasCalls();
3411
3412 if (!ST.hasFlatScratchEnabled()) {
3413 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.getFunction())) {
3414 // If we have stack objects, we unquestionably need the private buffer
3415 // resource. For the Code Object V2 ABI, this will be the first 4 user
3416 // SGPR inputs. We can reserve those and use them directly.
3417
3418 Register PrivateSegmentBufferReg =
3420 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3421 } else {
3422 unsigned ReservedBufferReg = TRI.reservedPrivateSegmentBufferReg(MF);
3423 // We tentatively reserve the last registers (skipping the last registers
3424 // which may contain VCC, FLAT_SCR, and XNACK). After register allocation,
3425 // we'll replace these with the ones immediately after those which were
3426 // really allocated. In the prologue copies will be inserted from the
3427 // argument to these reserved registers.
3428
3429 // Without HSA, relocations are used for the scratch pointer and the
3430 // buffer resource setup is always inserted in the prologue. Scratch wave
3431 // offset is still in an input SGPR.
3432 Info.setScratchRSrcReg(ReservedBufferReg);
3433 }
3434 }
3435
3437
3438 // For entry functions we have to set up the stack pointer if we use it,
3439 // whereas non-entry functions get this "for free". This means there is no
3440 // intrinsic advantage to using S32 over S34 in cases where we do not have
3441 // calls but do need a frame pointer (i.e. if we are requested to have one
3442 // because frame pointer elimination is disabled). To keep things simple we
3443 // only ever use S32 as the call ABI stack pointer, and so using it does not
3444 // imply we need a separate frame pointer.
3445 //
3446 // Try to use s32 as the SP, but move it if it would interfere with input
3447 // arguments. This won't work with calls though.
3448 //
3449 // FIXME: Move SP to avoid any possible inputs, or find a way to spill input
3450 // registers.
3451 if (!MRI.isLiveIn(AMDGPU::SGPR32)) {
3452 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3453 } else {
3455
3456 if (MFI.hasCalls())
3457 report_fatal_error("call in graphics shader with too many input SGPRs");
3458
3459 for (unsigned Reg : AMDGPU::SGPR_32RegClass) {
3460 if (!MRI.isLiveIn(Reg)) {
3461 Info.setStackPtrOffsetReg(Reg);
3462 break;
3463 }
3464 }
3465
3466 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3467 report_fatal_error("failed to find register for SP");
3468 }
3469
3470 // hasFP should be accurate for entry functions even before the frame is
3471 // finalized, because it does not rely on the known stack size, only
3472 // properties like whether variable sized objects are present.
3473 if (ST.getFrameLowering()->hasFP(MF)) {
3474 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3475 }
3476}
3477
3480 return !Info->isEntryFunction();
3481}
3482
3484
3486 MachineBasicBlock *Entry,
3487 const SmallVectorImpl<MachineBasicBlock *> &Exits) const {
3489
3490 const MCPhysReg *IStart = TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3491 if (!IStart)
3492 return;
3493
3494 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3495 MachineRegisterInfo *MRI = &Entry->getParent()->getRegInfo();
3496 MachineBasicBlock::iterator MBBI = Entry->begin();
3497 for (const MCPhysReg *I = IStart; *I; ++I) {
3498 const TargetRegisterClass *RC = nullptr;
3499 if (AMDGPU::SReg_64RegClass.contains(*I))
3500 RC = &AMDGPU::SGPR_64RegClass;
3501 else if (AMDGPU::SReg_32RegClass.contains(*I))
3502 RC = &AMDGPU::SGPR_32RegClass;
3503 else
3504 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3505
3506 Register NewVR = MRI->createVirtualRegister(RC);
3507 // Create copy from CSR to a virtual register.
3508 Entry->addLiveIn(*I);
3509 BuildMI(*Entry, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY), NewVR)
3510 .addReg(*I);
3511
3512 // Insert the copy-back instructions right before the terminator.
3513 for (auto *Exit : Exits)
3514 BuildMI(*Exit, Exit->getFirstTerminator(), DebugLoc(),
3515 TII->get(TargetOpcode::COPY), *I)
3516 .addReg(NewVR);
3517 }
3518}
3519
3521 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
3522 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3523 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
3525
3527 const Function &Fn = MF.getFunction();
3530 bool IsError = false;
3531
3532 if (Subtarget->isAmdHsaOS() && AMDGPU::isGraphics(CallConv)) {
3534 Fn, "unsupported non-compute shaders with HSA", DL.getDebugLoc()));
3535 IsError = true;
3536 }
3537
3540 BitVector Skipped(Fn.arg_size());
3541 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
3542 *DAG.getContext());
3543
3544 bool IsGraphics = AMDGPU::isGraphics(CallConv);
3545 bool IsKernel = AMDGPU::isKernel(CallConv);
3546 bool IsEntryFunc = AMDGPU::isEntryFunctionCC(CallConv);
3547
3548 if (IsGraphics) {
3549 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info->getUserSGPRInfo();
3550 assert(!UserSGPRInfo.hasDispatchPtr() &&
3551 !UserSGPRInfo.hasKernargSegmentPtr() && !Info->hasWorkGroupInfo() &&
3552 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3553 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3554 (void)UserSGPRInfo;
3555 if (!Subtarget->hasFlatScratchEnabled())
3556 assert(!UserSGPRInfo.hasFlatScratchInit());
3557 if ((CallConv != CallingConv::AMDGPU_CS &&
3558 CallConv != CallingConv::AMDGPU_Gfx &&
3559 CallConv != CallingConv::AMDGPU_Gfx_WholeWave) ||
3560 !Subtarget->hasArchitectedSGPRs())
3561 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3562 !Info->hasWorkGroupIDZ());
3563 }
3564
3565 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3566
3567 if (CallConv == CallingConv::AMDGPU_PS) {
3568 processPSInputArgs(Splits, CallConv, Ins, Skipped, FType, Info);
3569
3570 // At least one interpolation mode must be enabled or else the GPU will
3571 // hang.
3572 //
3573 // Check PSInputAddr instead of PSInputEnable. The idea is that if the user
3574 // set PSInputAddr, the user wants to enable some bits after the compilation
3575 // based on run-time states. Since we can't know what the final PSInputEna
3576 // will look like, so we shouldn't do anything here and the user should take
3577 // responsibility for the correct programming.
3578 //
3579 // Otherwise, the following restrictions apply:
3580 // - At least one of PERSP_* (0xF) or LINEAR_* (0x70) must be enabled.
3581 // - If POS_W_FLOAT (11) is enabled, at least one of PERSP_* must be
3582 // enabled too.
3583 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3584 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3585 CCInfo.AllocateReg(AMDGPU::VGPR0);
3586 CCInfo.AllocateReg(AMDGPU::VGPR1);
3587 Info->markPSInputAllocated(0);
3588 Info->markPSInputEnabled(0);
3589 }
3590 if (Subtarget->isAmdPalOS()) {
3591 // For isAmdPalOS, the user does not enable some bits after compilation
3592 // based on run-time states; the register values being generated here are
3593 // the final ones set in hardware. Therefore we need to apply the
3594 // workaround to PSInputAddr and PSInputEnable together. (The case where
3595 // a bit is set in PSInputAddr but not PSInputEnable is where the
3596 // frontend set up an input arg for a particular interpolation mode, but
3597 // nothing uses that input arg. Really we should have an earlier pass
3598 // that removes such an arg.)
3599 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3600 if ((PsInputBits & 0x7F) == 0 ||
3601 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3602 Info->markPSInputEnabled(llvm::countr_zero(Info->getPSInputAddr()));
3603 }
3604 } else if (IsKernel) {
3605 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3606 } else {
3607 Splits.append(IsWholeWaveFunc ? std::next(Ins.begin()) : Ins.begin(),
3608 Ins.end());
3609 }
3610
3611 if (IsKernel)
3612 analyzeFormalArgumentsCompute(CCInfo, Ins);
3613
3614 if (IsEntryFunc) {
3615 allocateSpecialEntryInputVGPRs(CCInfo, MF, *TRI, *Info);
3616 allocateHSAUserSGPRs(CCInfo, MF, *TRI, *Info);
3617 if (IsKernel && Subtarget->hasKernargPreload())
3618 allocatePreloadKernArgSGPRs(CCInfo, ArgLocs, Ins, MF, *TRI, *Info);
3619
3620 allocateLDSKernelId(CCInfo, MF, *TRI, *Info);
3621 } else if (!IsGraphics) {
3622 // For the fixed ABI, pass workitem IDs in the last argument register.
3623 allocateSpecialInputVGPRsFixed(CCInfo, MF, *TRI, *Info);
3624
3625 // FIXME: Sink this into allocateSpecialInputSGPRs
3626 if (!Subtarget->hasFlatScratchEnabled())
3627 CCInfo.AllocateReg(Info->getScratchRSrcReg());
3628
3629 allocateSpecialInputSGPRs(CCInfo, MF, *TRI, *Info);
3630 }
3631
3632 if (!IsKernel) {
3633 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, isVarArg);
3634 CCInfo.AnalyzeFormalArguments(Splits, AssignFn);
3635
3636 // This assumes the registers are allocated by CCInfo in ascending order
3637 // with no gaps.
3638 Info->setNumWaveDispatchSGPRs(
3639 CCInfo.getFirstUnallocated(AMDGPU::SGPR_32RegClass.getRegisters()));
3640 Info->setNumWaveDispatchVGPRs(
3641 CCInfo.getFirstUnallocated(AMDGPU::VGPR_32RegClass.getRegisters()));
3642 } else if (Info->getNumKernargPreloadedSGPRs()) {
3643 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3644 }
3645
3647
3648 if (IsWholeWaveFunc) {
3649 SDValue Setup = DAG.getNode(AMDGPUISD::WHOLE_WAVE_SETUP, DL,
3650 {MVT::i1, MVT::Other}, Chain);
3651 InVals.push_back(Setup.getValue(0));
3652 Chains.push_back(Setup.getValue(1));
3653 }
3654
3655 // FIXME: This is the minimum kernel argument alignment. We should improve
3656 // this to the maximum alignment of the arguments.
3657 //
3658 // FIXME: Alignment of explicit arguments totally broken with non-0 explicit
3659 // kern arg offset.
3660 const Align KernelArgBaseAlign = Align(16);
3661
3662 for (unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.size(), ArgIdx = 0; i != e;
3663 ++i) {
3664 const ISD::InputArg &Arg = Ins[i];
3665 if ((Arg.isOrigArg() && Skipped[Arg.getOrigArgIndex()]) || IsError) {
3666 InVals.push_back(DAG.getPOISON(Arg.VT));
3667 continue;
3668 }
3669
3670 CCValAssign &VA = ArgLocs[ArgIdx++];
3671 MVT VT = VA.getLocVT();
3672
3673 if (IsEntryFunc && VA.isMemLoc()) {
3674 VT = Ins[i].VT;
3675 EVT MemVT = VA.getLocVT();
3676
3677 const uint64_t Offset = VA.getLocMemOffset();
3678 Align Alignment = commonAlignment(KernelArgBaseAlign, Offset);
3679
3680 if (Arg.Flags.isByRef()) {
3681 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, Chain, Offset);
3682
3683 const GCNTargetMachine &TM =
3684 static_cast<const GCNTargetMachine &>(getTargetMachine());
3685 if (!TM.isNoopAddrSpaceCast(DAG.getDataLayout(),
3687 Arg.Flags.getPointerAddrSpace())) {
3690 }
3691
3692 InVals.push_back(Ptr);
3693 continue;
3694 }
3695
3696 SDValue NewArg;
3697 if (Arg.isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3698 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
3699 // In this case the argument is packed into the previous preload SGPR.
3700 int64_t AlignDownOffset = alignDown(Offset, 4);
3701 int64_t OffsetDiff = Offset - AlignDownOffset;
3702 EVT IntVT = MemVT.changeTypeToInteger();
3703
3704 const SIMachineFunctionInfo *Info =
3707 Register Reg =
3708 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3709
3710 assert(Reg);
3711 Register VReg = MRI.getLiveInVirtReg(Reg);
3712 SDValue Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3713
3714 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, DL, MVT::i32);
3715 SDValue Extract = DAG.getNode(ISD::SRL, DL, MVT::i32, Copy, ShiftAmt);
3716
3717 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Extract);
3718 ArgVal = DAG.getNode(ISD::BITCAST, DL, MemVT, ArgVal);
3719 NewArg = convertArgType(DAG, VT, MemVT, DL, ArgVal,
3720 Ins[i].Flags.isSExt(), &Ins[i]);
3721
3722 NewArg = DAG.getMergeValues({NewArg, Copy.getValue(1)}, DL);
3723 } else {
3724 const SIMachineFunctionInfo *Info =
3727 const SmallVectorImpl<MCRegister> &PreloadRegs =
3728 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3729
3730 SDValue Copy;
3731 if (PreloadRegs.size() == 1) {
3732 Register VReg = MRI.getLiveInVirtReg(PreloadRegs[0]);
3733 const TargetRegisterClass *RC = MRI.getRegClass(VReg);
3734 NewArg = DAG.getCopyFromReg(
3735 Chain, DL, VReg,
3737 TRI->getRegSizeInBits(*RC)));
3738
3739 } else {
3740 // If the kernarg alignment does not match the alignment of the SGPR
3741 // tuple RC that can accommodate this argument, it will be built up
3742 // via copies from from the individual SGPRs that the argument was
3743 // preloaded to.
3745 for (auto Reg : PreloadRegs) {
3746 Register VReg = MRI.getLiveInVirtReg(Reg);
3747 Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3748 Elts.push_back(Copy);
3749 }
3750 NewArg =
3751 DAG.getBuildVector(EVT::getVectorVT(*DAG.getContext(), MVT::i32,
3752 PreloadRegs.size()),
3753 DL, Elts);
3754 }
3755
3756 // If the argument was preloaded to multiple consecutive 32-bit
3757 // registers because of misalignment between addressable SGPR tuples
3758 // and the argument size, we can still assume that because of kernarg
3759 // segment alignment restrictions that NewArg's size is the same as
3760 // MemVT and just do a bitcast. If MemVT is less than 32-bits we add a
3761 // truncate since we cannot preload to less than a single SGPR and the
3762 // MemVT may be smaller.
3763 EVT MemVTInt =
3765 if (MemVT.bitsLT(NewArg.getSimpleValueType()))
3766 NewArg = DAG.getNode(ISD::TRUNCATE, DL, MemVTInt, NewArg);
3767
3768 NewArg = DAG.getBitcast(MemVT, NewArg);
3769 NewArg = convertArgType(DAG, VT, MemVT, DL, NewArg,
3770 Ins[i].Flags.isSExt(), &Ins[i]);
3771 NewArg = DAG.getMergeValues({NewArg, Chain}, DL);
3772 }
3773 } else {
3774 // Hidden arguments that are in the kernel signature must be preloaded
3775 // to user SGPRs. Print a diagnostic error if a hidden argument is in
3776 // the argument list and is not preloaded.
3777 if (Arg.isOrigArg()) {
3778 Argument *OrigArg = Fn.getArg(Arg.getOrigArgIndex());
3779 if (OrigArg->hasAttribute("amdgpu-hidden-argument")) {
3781 *OrigArg->getParent(),
3782 "hidden argument in kernel signature was not preloaded",
3783 DL.getDebugLoc()));
3784 }
3785 }
3786
3787 NewArg =
3788 lowerKernargMemParameter(DAG, VT, MemVT, DL, Chain, Offset,
3789 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3790 }
3791 Chains.push_back(NewArg.getValue(1));
3792
3793 auto *ParamTy =
3794 dyn_cast<PointerType>(FType->getParamType(Ins[i].getOrigArgIndex()));
3795 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS &&
3796 ParamTy &&
3797 (ParamTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
3798 ParamTy->getAddressSpace() == AMDGPUAS::REGION_ADDRESS)) {
3799 // On SI local pointers are just offsets into LDS, so they are always
3800 // less than 16-bits. On CI and newer they could potentially be
3801 // real pointers, so we can't guarantee their size.
3802 NewArg = DAG.getNode(ISD::AssertZext, DL, NewArg.getValueType(), NewArg,
3803 DAG.getValueType(MVT::i16));
3804 }
3805
3806 InVals.push_back(NewArg);
3807 continue;
3808 }
3809 if (!IsEntryFunc && VA.isMemLoc()) {
3810 SDValue Val = lowerStackParameter(DAG, VA, DL, Chain, Arg);
3811 InVals.push_back(Val);
3812 if (!Arg.Flags.isByVal())
3813 Chains.push_back(Val.getValue(1));
3814 continue;
3815 }
3816
3817 assert(VA.isRegLoc() && "Parameter must be in a register!");
3818
3819 Register Reg = VA.getLocReg();
3820 const TargetRegisterClass *RC = nullptr;
3821 if (AMDGPU::VGPR_32RegClass.contains(Reg))
3822 RC = &AMDGPU::VGPR_32RegClass;
3823 else if (AMDGPU::SGPR_32RegClass.contains(Reg))
3824 RC = &AMDGPU::SGPR_32RegClass;
3825 else
3826 llvm_unreachable("Unexpected register class in LowerFormalArguments!");
3827
3828 Reg = MF.addLiveIn(Reg, RC);
3829 SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, VT);
3830 if (Arg.Flags.isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3831 // FIXME: Need to forward the chains created by `CopyFromReg`s, make sure
3832 // they will read physical regs before any side effect instructions.
3833 SDValue ReadFirstLane =
3834 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3836 ReadFirstLane, Val);
3837 }
3838
3839 if (Arg.Flags.isSRet()) {
3840 // The return object should be reasonably addressable.
3841 Val = annotateStackObjectPointer(Val, DAG, DL,
3843 }
3844
3845 Val = convertABITypeToValueType(DAG, Val, VA, DL);
3846 InVals.push_back(Val);
3847 }
3848
3849 // Start adding system SGPRs.
3850 if (IsEntryFunc)
3851 allocateSystemSGPRs(CCInfo, MF, *Info, CallConv, IsGraphics);
3852
3853 unsigned StackArgSize = CCInfo.getStackSize();
3854 Info->setBytesInStackArgArea(StackArgSize);
3855
3856 return Chains.empty() ? Chain
3857 : DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
3858}
3859
3860// TODO: If return values can't fit in registers, we should return as many as
3861// possible in registers before passing on stack.
3863 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
3864 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
3865 const Type *RetTy) const {
3866 // Replacing returns with sret/stack usage doesn't make sense for shaders.
3867 // FIXME: Also sort of a workaround for custom vector splitting in LowerReturn
3868 // for shaders. Vector types should be explicitly handled by CC.
3869 if (AMDGPU::isEntryFunctionCC(CallConv))
3870 return true;
3871
3873 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3874 if (!CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)))
3875 return false;
3876
3877 // We must use the stack if return would require unavailable registers.
3878 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3879 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3880 for (unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3881 if (CCInfo.isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3882 return false;
3883
3884 return true;
3885}
3886
3887SDValue
3889 bool isVarArg,
3891 const SmallVectorImpl<SDValue> &OutVals,
3892 const SDLoc &DL, SelectionDAG &DAG) const {
3896
3897 if (AMDGPU::isKernel(CallConv)) {
3898 return AMDGPUTargetLowering::LowerReturn(Chain, CallConv, isVarArg, Outs,
3899 OutVals, DL, DAG);
3900 }
3901
3902 bool IsShader = AMDGPU::isShader(CallConv);
3903
3904 Info->setIfReturnsVoid(Outs.empty());
3905 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3906
3907 // CCValAssign - represent the assignment of the return value to a location.
3909
3910 // CCState - Info about the registers and stack slots.
3911 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
3912 *DAG.getContext());
3913
3914 // Analyze outgoing return values.
3915 CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, isVarArg));
3916
3917 SDValue Glue;
3919 RetOps.push_back(Chain); // Operand #0 = Chain (updated below)
3920
3921 SDValue ReadFirstLane =
3922 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3923 // Copy the result values into the output registers.
3924 for (unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.size(); I != E;
3925 ++I, ++RealRVLocIdx) {
3926 CCValAssign &VA = RVLocs[I];
3927 assert(VA.isRegLoc() && "Can only return in registers!");
3928 // TODO: Partially return in registers if return values don't fit.
3929 SDValue Arg = OutVals[RealRVLocIdx];
3930
3931 // Copied from other backends.
3932 switch (VA.getLocInfo()) {
3933 case CCValAssign::Full:
3934 break;
3935 case CCValAssign::BCvt:
3936 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
3937 break;
3938 case CCValAssign::SExt:
3939 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
3940 break;
3941 case CCValAssign::ZExt:
3942 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
3943 break;
3944 case CCValAssign::AExt:
3945 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
3946 break;
3947 default:
3948 llvm_unreachable("Unknown loc info!");
3949 }
3950 if (TRI->isSGPRPhysReg(VA.getLocReg()))
3952 ReadFirstLane, Arg);
3953 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Glue);
3954 Glue = Chain.getValue(1);
3955 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
3956 }
3957
3958 // FIXME: Does sret work properly?
3959 if (!Info->isEntryFunction()) {
3960 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
3961 const MCPhysReg *I =
3962 TRI->getCalleeSavedRegsViaCopy(&DAG.getMachineFunction());
3963 if (I) {
3964 for (; *I; ++I) {
3965 if (AMDGPU::SReg_64RegClass.contains(*I))
3966 RetOps.push_back(DAG.getRegister(*I, MVT::i64));
3967 else if (AMDGPU::SReg_32RegClass.contains(*I))
3968 RetOps.push_back(DAG.getRegister(*I, MVT::i32));
3969 else
3970 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3971 }
3972 }
3973 }
3974
3975 // Update chain and glue.
3976 RetOps[0] = Chain;
3977 if (Glue.getNode())
3978 RetOps.push_back(Glue);
3979
3980 unsigned Opc = AMDGPUISD::ENDPGM;
3981 if (!IsWaveEnd)
3982 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3983 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3984 : AMDGPUISD::RET_GLUE;
3985 return DAG.getNode(Opc, DL, MVT::Other, RetOps);
3986}
3987
3989 SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
3990 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3991 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, bool IsThisReturn,
3992 SDValue ThisVal) const {
3993 CCAssignFn *RetCC = CCAssignFnForReturn(CallConv, IsVarArg);
3994
3995 // Assign locations to each value returned by this call.
3997 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
3998 *DAG.getContext());
3999 CCInfo.AnalyzeCallResult(Ins, RetCC);
4000
4001 // Copy all of the result registers out of their specified physreg.
4002 for (CCValAssign VA : RVLocs) {
4003 SDValue Val;
4004
4005 if (VA.isRegLoc()) {
4006 Val =
4007 DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), InGlue);
4008 Chain = Val.getValue(1);
4009 InGlue = Val.getValue(2);
4010 } else if (VA.isMemLoc()) {
4011 report_fatal_error("TODO: return values in memory");
4012 } else
4013 llvm_unreachable("unknown argument location type");
4014
4015 switch (VA.getLocInfo()) {
4016 case CCValAssign::Full:
4017 break;
4018 case CCValAssign::BCvt:
4019 Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
4020 break;
4021 case CCValAssign::ZExt:
4022 Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val,
4023 DAG.getValueType(VA.getValVT()));
4024 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4025 break;
4026 case CCValAssign::SExt:
4027 Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val,
4028 DAG.getValueType(VA.getValVT()));
4029 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4030 break;
4031 case CCValAssign::AExt:
4032 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
4033 break;
4034 default:
4035 llvm_unreachable("Unknown loc info!");
4036 }
4037
4038 InVals.push_back(Val);
4039 }
4040
4041 return Chain;
4042}
4043
4044// Add code to pass special inputs required depending on used features separate
4045// from the explicit user arguments present in the IR.
4047 CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info,
4048 SmallVectorImpl<std::pair<unsigned, SDValue>> &RegsToPass,
4049 SmallVectorImpl<SDValue> &MemOpChains, SDValue Chain) const {
4050 // If we don't have a call site, this was a call inserted by
4051 // legalization. These can never use special inputs.
4052 if (!CLI.CB)
4053 return;
4054
4055 SelectionDAG &DAG = CLI.DAG;
4056 const SDLoc &DL = CLI.DL;
4057 const Function &F = DAG.getMachineFunction().getFunction();
4058
4059 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
4060 const AMDGPUFunctionArgInfo &CallerArgInfo = Info.getArgInfo();
4061
4062 const AMDGPUFunctionArgInfo &CalleeArgInfo =
4064
4065 // TODO: Unify with private memory register handling. This is complicated by
4066 // the fact that at least in kernels, the input argument is not necessarily
4067 // in the same location as the input.
4068 // clang-format off
4069 static constexpr std::pair<AMDGPUFunctionArgInfo::PreloadedValue,
4070 std::array<StringLiteral, 2>> ImplicitAttrs[] = {
4071 {AMDGPUFunctionArgInfo::DISPATCH_PTR, {"amdgpu-no-dispatch-ptr", ""}},
4072 {AMDGPUFunctionArgInfo::QUEUE_PTR, {"amdgpu-no-queue-ptr", ""}},
4073 {AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR, {"amdgpu-no-implicitarg-ptr", ""}},
4074 {AMDGPUFunctionArgInfo::DISPATCH_ID, {"amdgpu-no-dispatch-id", ""}},
4075 {AMDGPUFunctionArgInfo::WORKGROUP_ID_X, {"amdgpu-no-workgroup-id-x", "amdgpu-no-cluster-id-x"}},
4076 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Y, {"amdgpu-no-workgroup-id-y", "amdgpu-no-cluster-id-y"}},
4077 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Z, {"amdgpu-no-workgroup-id-z", "amdgpu-no-cluster-id-z"}},
4078 {AMDGPUFunctionArgInfo::LDS_KERNEL_ID, {"amdgpu-no-lds-kernel-id", ""}},
4079 };
4080 // clang-format on
4081
4082 for (auto [InputID, Attrs] : ImplicitAttrs) {
4083 // If the callee does not use the attribute value, skip copying the value.
4084 if (all_of(Attrs, [&](StringRef Attr) {
4085 return Attr.empty() || CLI.CB->hasFnAttr(Attr);
4086 }))
4087 continue;
4088
4089 const auto [OutgoingArg, ArgRC, ArgTy] =
4090 CalleeArgInfo.getPreloadedValue(InputID);
4091 if (!OutgoingArg)
4092 continue;
4093
4094 const auto [IncomingArg, IncomingArgRC, Ty] =
4095 CallerArgInfo.getPreloadedValue(InputID);
4096 assert(IncomingArgRC == ArgRC);
4097
4098 // All special arguments are ints for now.
4099 EVT ArgVT = TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4100 SDValue InputReg;
4101
4102 if (IncomingArg) {
4103 InputReg = loadInputValue(DAG, ArgRC, ArgVT, DL, *IncomingArg);
4104 } else if (InputID == AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR) {
4105 // The implicit arg ptr is special because it doesn't have a corresponding
4106 // input for kernels, and is computed from the kernarg segment pointer.
4107 InputReg = getImplicitArgPtr(DAG, DL);
4108 } else if (InputID == AMDGPUFunctionArgInfo::LDS_KERNEL_ID) {
4109 std::optional<uint32_t> Id =
4111 if (Id.has_value()) {
4112 InputReg = DAG.getConstant(*Id, DL, ArgVT);
4113 } else {
4114 InputReg = DAG.getPOISON(ArgVT);
4115 }
4116 } else {
4117 // We may have proven the input wasn't needed, although the ABI is
4118 // requiring it. We just need to allocate the register appropriately.
4119 InputReg = DAG.getPOISON(ArgVT);
4120 }
4121
4122 if (OutgoingArg->isRegister()) {
4123 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4124 if (!CCInfo.AllocateReg(OutgoingArg->getRegister()))
4125 report_fatal_error("failed to allocate implicit input argument");
4126 } else {
4127 unsigned SpecialArgOffset =
4128 CCInfo.AllocateStack(ArgVT.getStoreSize(), Align(4));
4129 SDValue ArgStore =
4130 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4131 MemOpChains.push_back(ArgStore);
4132 }
4133 }
4134
4135 // Pack workitem IDs into a single register or pass it as is if already
4136 // packed.
4137
4138 auto [OutgoingArg, ArgRC, Ty] =
4140 if (!OutgoingArg)
4141 std::tie(OutgoingArg, ArgRC, Ty) =
4143 if (!OutgoingArg)
4144 std::tie(OutgoingArg, ArgRC, Ty) =
4146 if (!OutgoingArg)
4147 return;
4148
4149 const ArgDescriptor *IncomingArgX = std::get<0>(
4151 const ArgDescriptor *IncomingArgY = std::get<0>(
4153 const ArgDescriptor *IncomingArgZ = std::get<0>(
4155
4156 SDValue InputReg;
4157 SDLoc SL;
4158
4159 const bool NeedWorkItemIDX = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-x");
4160 const bool NeedWorkItemIDY = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-y");
4161 const bool NeedWorkItemIDZ = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-z");
4162
4163 // If incoming ids are not packed we need to pack them.
4164 if (IncomingArgX && !IncomingArgX->isMasked() && CalleeArgInfo.WorkItemIDX &&
4165 NeedWorkItemIDX) {
4166 if (Subtarget->getMaxWorkitemID(F, 0) != 0) {
4167 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgX);
4168 } else {
4169 InputReg = DAG.getConstant(0, DL, MVT::i32);
4170 }
4171 }
4172
4173 if (IncomingArgY && !IncomingArgY->isMasked() && CalleeArgInfo.WorkItemIDY &&
4174 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(F, 1) != 0) {
4175 SDValue Y = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgY);
4176 Y = DAG.getNode(ISD::SHL, SL, MVT::i32, Y,
4177 DAG.getShiftAmountConstant(10, MVT::i32, SL));
4178 InputReg = InputReg.getNode()
4179 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Y)
4180 : Y;
4181 }
4182
4183 if (IncomingArgZ && !IncomingArgZ->isMasked() && CalleeArgInfo.WorkItemIDZ &&
4184 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(F, 2) != 0) {
4185 SDValue Z = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgZ);
4186 Z = DAG.getNode(ISD::SHL, SL, MVT::i32, Z,
4187 DAG.getShiftAmountConstant(20, MVT::i32, SL));
4188 InputReg = InputReg.getNode()
4189 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Z)
4190 : Z;
4191 }
4192
4193 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4194 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4195 // We're in a situation where the outgoing function requires the workitem
4196 // ID, but the calling function does not have it (e.g a graphics function
4197 // calling a C calling convention function). This is illegal, but we need
4198 // to produce something.
4199 InputReg = DAG.getPOISON(MVT::i32);
4200 } else {
4201 // Workitem ids are already packed, any of present incoming arguments
4202 // will carry all required fields.
4203 ArgDescriptor IncomingArg =
4204 ArgDescriptor::createArg(IncomingArgX ? *IncomingArgX
4205 : IncomingArgY ? *IncomingArgY
4206 : *IncomingArgZ,
4207 ~0u);
4208 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, IncomingArg);
4209 }
4210 }
4211
4212 if (OutgoingArg->isRegister()) {
4213 if (InputReg)
4214 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4215
4216 CCInfo.AllocateReg(OutgoingArg->getRegister());
4217 } else {
4218 unsigned SpecialArgOffset = CCInfo.AllocateStack(4, Align(4));
4219 if (InputReg) {
4220 SDValue ArgStore =
4221 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4222 MemOpChains.push_back(ArgStore);
4223 }
4224 }
4225}
4226
4228 SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg,
4230 const SmallVectorImpl<SDValue> &OutVals,
4231 const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const {
4232 if (AMDGPU::isChainCC(CalleeCC))
4233 return true;
4234
4235 if (!AMDGPU::mayTailCallThisCC(CalleeCC))
4236 return false;
4237
4238 // For a divergent call target, we need to do a waterfall loop over the
4239 // possible callees which precludes us from using a simple jump.
4240 if (Callee->isDivergent())
4241 return false;
4242
4244 const Function &CallerF = MF.getFunction();
4245 CallingConv::ID CallerCC = CallerF.getCallingConv();
4247 const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC);
4248
4249 // Kernels aren't callable, and don't have a live in return address so it
4250 // doesn't make sense to do a tail call with entry functions.
4251 if (!CallerPreserved)
4252 return false;
4253
4254 bool CCMatch = CallerCC == CalleeCC;
4255
4257 if (AMDGPU::canGuaranteeTCO(CalleeCC) && CCMatch)
4258 return true;
4259 return false;
4260 }
4261
4262 // TODO: Can we handle var args?
4263 if (IsVarArg)
4264 return false;
4265
4266 for (const Argument &Arg : CallerF.args()) {
4267 if (Arg.hasByValAttr())
4268 return false;
4269 }
4270
4271 LLVMContext &Ctx = *DAG.getContext();
4272
4273 // Check that the call results are passed in the same way.
4274 if (!CCState::resultsCompatible(CalleeCC, CallerCC, MF, Ctx, Ins,
4275 CCAssignFnForCall(CalleeCC, IsVarArg),
4276 CCAssignFnForCall(CallerCC, IsVarArg)))
4277 return false;
4278
4279 // The callee has to preserve all registers the caller needs to preserve.
4280 if (!CCMatch) {
4281 const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC);
4282 if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4283 return false;
4284 }
4285
4286 // Nothing more to check if the callee is taking no arguments.
4287 if (Outs.empty())
4288 return true;
4289
4291 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4292
4293 // FIXME: We are not allocating special input registers, so we will be
4294 // deciding based on incorrect register assignments.
4295 CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CalleeCC, IsVarArg));
4296
4297 const SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
4298 // If the stack arguments for this call do not fit into our own save area then
4299 // the call cannot be made tail.
4300 // TODO: Is this really necessary?
4301 if (CCInfo.getStackSize() > FuncInfo->getBytesInStackArgArea())
4302 return false;
4303
4304 for (const auto &[CCVA, ArgVal] : zip_equal(ArgLocs, OutVals)) {
4305 // FIXME: What about inreg arguments that end up passed in memory?
4306 if (!CCVA.isRegLoc())
4307 continue;
4308
4309 // If we are passing an argument in an SGPR, and the value is divergent,
4310 // this call requires a waterfall loop.
4311 if (ArgVal->isDivergent() && TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4312 LLVM_DEBUG(
4313 dbgs() << "Cannot tail call due to divergent outgoing argument in "
4314 << printReg(CCVA.getLocReg(), TRI) << '\n');
4315 return false;
4316 }
4317 }
4318
4319 const MachineRegisterInfo &MRI = MF.getRegInfo();
4320 return parametersInCSRMatch(MRI, CallerPreserved, ArgLocs, OutVals);
4321}
4322
4324 if (!CI->isTailCall())
4325 return false;
4326
4327 const Function *ParentFn = CI->getFunction();
4329 return false;
4330 return true;
4331}
4332
4333namespace {
4334// Chain calls have special arguments that we need to handle. These are
4335// tagging along at the end of the arguments list(s), after the SGPR and VGPR
4336// arguments (index 0 and 1 respectively).
4337enum ChainCallArgIdx {
4338 Exec = 2,
4339 Flags,
4340 NumVGPRs,
4341 FallbackExec,
4342 FallbackCallee
4343};
4344} // anonymous namespace
4345
4346// The wave scratch offset register is used as the global base pointer.
4348 SmallVectorImpl<SDValue> &InVals) const {
4349 CallingConv::ID CallConv = CLI.CallConv;
4350 bool IsChainCallConv = AMDGPU::isChainCC(CallConv);
4351
4352 SelectionDAG &DAG = CLI.DAG;
4353
4354 const SDLoc &DL = CLI.DL;
4355 SDValue Chain = CLI.Chain;
4356 SDValue Callee = CLI.Callee;
4357
4358 llvm::SmallVector<SDValue, 6> ChainCallSpecialArgs;
4359 bool UsesDynamicVGPRs = false;
4360 if (IsChainCallConv) {
4361 // The last arguments should be the value that we need to put in EXEC,
4362 // followed by the flags and any other arguments with special meanings.
4363 // Pop them out of CLI.Outs and CLI.OutVals before we do any processing so
4364 // we don't treat them like the "real" arguments.
4365 auto RequestedExecIt =
4366 llvm::find_if(CLI.Outs, [](const ISD::OutputArg &Arg) {
4367 return Arg.OrigArgIndex == 2;
4368 });
4369 assert(RequestedExecIt != CLI.Outs.end() && "No node for EXEC");
4370
4371 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.Outs.begin();
4372 CLI.OutVals.erase(CLI.OutVals.begin() + SpecialArgsBeginIdx,
4373 CLI.OutVals.end());
4374 CLI.Outs.erase(RequestedExecIt, CLI.Outs.end());
4375
4376 assert(CLI.Outs.back().OrigArgIndex < 2 &&
4377 "Haven't popped all the special args");
4378
4379 TargetLowering::ArgListEntry RequestedExecArg =
4380 CLI.Args[ChainCallArgIdx::Exec];
4381 if (!RequestedExecArg.Ty->isIntegerTy(Subtarget->getWavefrontSize()))
4382 return lowerUnhandledCall(CLI, InVals, "Invalid value for EXEC");
4383
4384 // Convert constants into TargetConstants, so they become immediate operands
4385 // instead of being selected into S_MOV.
4386 auto PushNodeOrTargetConstant = [&](TargetLowering::ArgListEntry Arg) {
4387 if (const auto *ArgNode = dyn_cast<ConstantSDNode>(Arg.Node)) {
4388 ChainCallSpecialArgs.push_back(DAG.getTargetConstant(
4389 ArgNode->getAPIntValue(), DL, ArgNode->getValueType(0)));
4390 } else
4391 ChainCallSpecialArgs.push_back(Arg.Node);
4392 };
4393
4394 PushNodeOrTargetConstant(RequestedExecArg);
4395
4396 // Process any other special arguments depending on the value of the flags.
4397 TargetLowering::ArgListEntry Flags = CLI.Args[ChainCallArgIdx::Flags];
4398
4399 const APInt &FlagsValue = cast<ConstantSDNode>(Flags.Node)->getAPIntValue();
4400 if (FlagsValue.isZero()) {
4401 if (CLI.Args.size() > ChainCallArgIdx::Flags + 1)
4402 return lowerUnhandledCall(CLI, InVals,
4403 "no additional args allowed if flags == 0");
4404 } else if (FlagsValue.isOneBitSet(0)) {
4405 if (CLI.Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4406 return lowerUnhandledCall(CLI, InVals, "expected 3 additional args");
4407 }
4408
4409 if (!Subtarget->isWave32()) {
4410 return lowerUnhandledCall(
4411 CLI, InVals, "dynamic VGPR mode is only supported for wave32");
4412 }
4413
4414 UsesDynamicVGPRs = true;
4415 std::for_each(CLI.Args.begin() + ChainCallArgIdx::NumVGPRs,
4416 CLI.Args.end(), PushNodeOrTargetConstant);
4417 }
4418 }
4419
4421 SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
4423 bool &IsTailCall = CLI.IsTailCall;
4424 bool IsVarArg = CLI.IsVarArg;
4425 bool IsSibCall = false;
4427
4428 if (Callee.isUndef() || isNullConstant(Callee)) {
4429 if (!CLI.IsTailCall) {
4430 for (ISD::InputArg &Arg : CLI.Ins)
4431 InVals.push_back(DAG.getPOISON(Arg.VT));
4432 }
4433
4434 return Chain;
4435 }
4436
4437 if (IsVarArg) {
4438 return lowerUnhandledCall(CLI, InVals,
4439 "unsupported call to variadic function ");
4440 }
4441
4442 if (!CLI.CB)
4443 return lowerUnhandledCall(CLI, InVals, "unsupported libcall legalization");
4444
4445 if (IsTailCall && MF.getTarget().Options.GuaranteedTailCallOpt) {
4446 return lowerUnhandledCall(CLI, InVals,
4447 "unsupported required tail call to function ");
4448 }
4449
4450 if (IsTailCall) {
4451 IsTailCall = isEligibleForTailCallOptimization(Callee, CallConv, IsVarArg,
4452 Outs, OutVals, Ins, DAG);
4453 if (!IsTailCall &&
4454 ((CLI.CB && CLI.CB->isMustTailCall()) || IsChainCallConv)) {
4455 report_fatal_error("failed to perform tail call elimination on a call "
4456 "site marked musttail or on llvm.amdgcn.cs.chain");
4457 }
4458
4459 bool TailCallOpt = MF.getTarget().Options.GuaranteedTailCallOpt;
4460
4461 // A sibling call is one where we're under the usual C ABI and not planning
4462 // to change that but can still do a tail call:
4463 if (!TailCallOpt && IsTailCall)
4464 IsSibCall = true;
4465
4466 if (IsTailCall)
4467 ++NumTailCalls;
4468 }
4469
4472 SmallVector<SDValue, 8> MemOpChains;
4473
4474 // Analyze operands of the call, assigning locations to each operand.
4476 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
4477 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, IsVarArg);
4478
4479 if (CallConv != CallingConv::AMDGPU_Gfx && !AMDGPU::isChainCC(CallConv) &&
4481 // With a fixed ABI, allocate fixed registers before user arguments.
4482 passSpecialInputs(CLI, CCInfo, *Info, RegsToPass, MemOpChains, Chain);
4483 }
4484
4485 // Mark the scratch resource descriptor as allocated so the CC analysis
4486 // does not assign user arguments to these registers, matching the callee.
4487 if (!Subtarget->hasFlatScratchEnabled()) {
4488 CCInfo.AllocateReg(
4490 }
4491
4492 CCInfo.AnalyzeCallOperands(Outs, AssignFn);
4493
4494 // Get a count of how many bytes are to be pushed on the stack.
4495 unsigned NumBytes = CCInfo.getStackSize();
4496
4497 if (IsSibCall) {
4498 // Since we're not changing the ABI to make this a tail call, the memory
4499 // operands are already available in the caller's incoming argument space.
4500 NumBytes = 0;
4501 }
4502
4503 // FPDiff is the byte offset of the call's argument area from the callee's.
4504 // Stores to callee stack arguments will be placed in FixedStackSlots offset
4505 // by this amount for a tail call. In a sibling call it must be 0 because the
4506 // caller will deallocate the entire stack and the callee still expects its
4507 // arguments to begin at SP+0. Completely unused for non-tail calls.
4508 int32_t FPDiff = 0;
4509 MachineFrameInfo &MFI = MF.getFrameInfo();
4510 auto *TRI = Subtarget->getRegisterInfo();
4511
4512 // Adjust the stack pointer for the new arguments...
4513 // These operations are automatically eliminated by the prolog/epilog pass
4514 if (!IsSibCall)
4515 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL);
4516
4517 if (!IsSibCall || IsChainCallConv) {
4518 if (!Subtarget->hasFlatScratchEnabled()) {
4519 SmallVector<SDValue, 4> CopyFromChains;
4520
4521 // In the HSA case, this should be an identity copy.
4522 SDValue ScratchRSrcReg =
4523 DAG.getCopyFromReg(Chain, DL, Info->getScratchRSrcReg(), MVT::v4i32);
4524 RegsToPass.emplace_back(
4526 ScratchRSrcReg);
4527 CopyFromChains.push_back(ScratchRSrcReg.getValue(1));
4528 Chain = DAG.getTokenFactor(DL, CopyFromChains);
4529 }
4530 }
4531
4532 const unsigned NumSpecialInputs = RegsToPass.size();
4533
4534 MVT PtrVT = MVT::i32;
4535
4536 // Walk the register/memloc assignments, inserting copies/loads.
4537 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4538 CCValAssign &VA = ArgLocs[i];
4539 SDValue Arg = OutVals[i];
4540
4541 // Promote the value if needed.
4542 switch (VA.getLocInfo()) {
4543 case CCValAssign::Full:
4544 break;
4545 case CCValAssign::BCvt:
4546 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
4547 break;
4548 case CCValAssign::ZExt:
4549 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
4550 break;
4551 case CCValAssign::SExt:
4552 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
4553 break;
4554 case CCValAssign::AExt:
4555 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
4556 break;
4557 case CCValAssign::FPExt:
4558 Arg = DAG.getNode(ISD::FP_EXTEND, DL, VA.getLocVT(), Arg);
4559 break;
4560 default:
4561 llvm_unreachable("Unknown loc info!");
4562 }
4563
4564 if (VA.isRegLoc()) {
4565 RegsToPass.push_back(std::pair(VA.getLocReg(), Arg));
4566 } else {
4567 assert(VA.isMemLoc());
4568
4569 SDValue DstAddr;
4570 MachinePointerInfo DstInfo;
4571
4572 unsigned LocMemOffset = VA.getLocMemOffset();
4573 int32_t Offset = LocMemOffset;
4574
4575 SDValue PtrOff = DAG.getConstant(Offset, DL, PtrVT);
4576 MaybeAlign Alignment;
4577
4578 if (IsTailCall) {
4579 ISD::ArgFlagsTy Flags = Outs[i].Flags;
4580 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4581 : VA.getValVT().getStoreSize();
4582
4583 // FIXME: We can have better than the minimum byval required alignment.
4584 Alignment =
4585 Flags.isByVal()
4586 ? Flags.getNonZeroByValAlign()
4587 : commonAlignment(Subtarget->getStackAlignment(), Offset);
4588
4589 Offset = Offset + FPDiff;
4590 int FI = MFI.CreateFixedObject(OpSize, Offset, true);
4591
4592 DstAddr = DAG.getFrameIndex(FI, PtrVT);
4593 DstInfo = MachinePointerInfo::getFixedStack(MF, FI);
4594
4595 // Make sure any stack arguments overlapping with where we're storing
4596 // are loaded before this eventual operation. Otherwise they'll be
4597 // clobbered.
4598
4599 // FIXME: Why is this really necessary? This seems to just result in a
4600 // lot of code to copy the stack and write them back to the same
4601 // locations, which are supposed to be immutable?
4602 Chain = addTokenForArgument(Chain, DAG, MFI, FI);
4603 } else {
4604 // Stores to the argument stack area are relative to the stack pointer.
4605 SDValue SP = DAG.getCopyFromReg(Chain, DL, Info->getStackPtrOffsetReg(),
4606 MVT::i32);
4607 DstAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, SP, PtrOff);
4608 DstInfo = MachinePointerInfo::getStack(MF, LocMemOffset);
4609 Alignment =
4610 commonAlignment(Subtarget->getStackAlignment(), LocMemOffset);
4611 }
4612
4613 if (Outs[i].Flags.isByVal()) {
4614 SDValue SizeNode =
4615 DAG.getConstant(Outs[i].Flags.getByValSize(), DL, MVT::i32);
4616 SDValue Cpy =
4617 DAG.getMemcpy(Chain, DL, DstAddr, Arg, SizeNode,
4618 Outs[i].Flags.getNonZeroByValAlign(),
4619 Outs[i].Flags.getNonZeroByValAlign(),
4620 /*isVol = */ false, /*AlwaysInline = */ true,
4621 /*CI=*/nullptr, std::nullopt, DstInfo,
4623
4624 MemOpChains.push_back(Cpy);
4625 } else {
4626 SDValue Store =
4627 DAG.getStore(Chain, DL, Arg, DstAddr, DstInfo, Alignment);
4628 MemOpChains.push_back(Store);
4629 }
4630 }
4631 }
4632
4633 if (!MemOpChains.empty())
4634 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
4635
4636 SDValue ReadFirstLaneID =
4637 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4638
4639 SDValue TokenGlue;
4640 if (CLI.ConvergenceControlToken) {
4641 TokenGlue = DAG.getNode(ISD::CONVERGENCECTRL_GLUE, DL, MVT::Glue,
4643 }
4644
4645 // Build a sequence of copy-to-reg nodes chained together with token chain
4646 // and flag operands which copy the outgoing args into the appropriate regs.
4647 SDValue InGlue;
4648
4649 unsigned ArgIdx = 0;
4650 for (auto [Reg, Val] : RegsToPass) {
4651 if (ArgIdx++ >= NumSpecialInputs &&
4652 (IsChainCallConv || !Val->isDivergent()) && TRI->isSGPRPhysReg(Reg)) {
4653 // For chain calls, the inreg arguments are required to be
4654 // uniform. Speculatively Insert a readfirstlane in case we cannot prove
4655 // they are uniform.
4656 //
4657 // For other calls, if an inreg arguments is known to be uniform,
4658 // speculatively insert a readfirstlane in case it is in a VGPR.
4659 //
4660 // FIXME: We need to execute this in a waterfall loop if it is a divergent
4661 // value, so let that continue to produce invalid code.
4662
4663 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Val});
4664 if (TokenGlue)
4665 ReadfirstlaneArgs.push_back(TokenGlue);
4667 ReadfirstlaneArgs);
4668 }
4669
4670 Chain = DAG.getCopyToReg(Chain, DL, Reg, Val, InGlue);
4671 InGlue = Chain.getValue(1);
4672 }
4673
4674 // We don't usually want to end the call-sequence here because we would tidy
4675 // the frame up *after* the call, however in the ABI-changing tail-call case
4676 // we've carefully laid out the parameters so that when sp is reset they'll be
4677 // in the correct location.
4678 if (IsTailCall && !IsSibCall) {
4679 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
4680 InGlue = Chain.getValue(1);
4681 }
4682
4683 std::vector<SDValue> Ops({Chain});
4684
4685 // Add a redundant copy of the callee global which will not be legalized, as
4686 // we need direct access to the callee later.
4688 const GlobalValue *GV = GSD->getGlobal();
4689 Ops.push_back(Callee);
4690 Ops.push_back(DAG.getTargetGlobalAddress(GV, DL, MVT::i64));
4691 } else {
4692 if (IsTailCall) {
4693 // isEligibleForTailCallOptimization considered whether the call target is
4694 // divergent, but we may still end up with a uniform value in a VGPR.
4695 // Insert a readfirstlane just in case.
4696 SDValue ReadFirstLaneID =
4697 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4698
4699 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Callee});
4700 if (TokenGlue)
4701 ReadfirstlaneArgs.push_back(TokenGlue); // Wire up convergence token.
4702 Callee = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Callee.getValueType(),
4703 ReadfirstlaneArgs);
4704 }
4705
4706 Ops.push_back(Callee);
4707 Ops.push_back(DAG.getTargetConstant(0, DL, MVT::i64));
4708 }
4709
4710 if (IsTailCall) {
4711 // Each tail call may have to adjust the stack by a different amount, so
4712 // this information must travel along with the operation for eventual
4713 // consumption by emitEpilogue.
4714 Ops.push_back(DAG.getTargetConstant(FPDiff, DL, MVT::i32));
4715 }
4716
4717 if (IsChainCallConv)
4718 llvm::append_range(Ops, ChainCallSpecialArgs);
4719
4720 // Add argument registers to the end of the list so that they are known live
4721 // into the call.
4722 for (auto &[Reg, Val] : RegsToPass)
4723 Ops.push_back(DAG.getRegister(Reg, Val.getValueType()));
4724
4725 // Add a register mask operand representing the call-preserved registers.
4726 const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
4727 assert(Mask && "Missing call preserved mask for calling convention");
4728 Ops.push_back(DAG.getRegisterMask(Mask));
4729
4730 if (SDValue Token = CLI.ConvergenceControlToken) {
4732 GlueOps.push_back(Token);
4733 if (InGlue)
4734 GlueOps.push_back(InGlue);
4735
4736 InGlue = SDValue(DAG.getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, DL,
4737 MVT::Glue, GlueOps),
4738 0);
4739 }
4740
4741 if (InGlue)
4742 Ops.push_back(InGlue);
4743
4744 // If we're doing a tall call, use a TC_RETURN here rather than an
4745 // actual call instruction.
4746 if (IsTailCall) {
4747 MFI.setHasTailCall();
4748 unsigned OPC = AMDGPUISD::TC_RETURN;
4749 switch (CallConv) {
4751 OPC = AMDGPUISD::TC_RETURN_GFX;
4752 break;
4755 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4756 : AMDGPUISD::TC_RETURN_CHAIN;
4757 break;
4758 }
4759
4760 // If the caller is a whole wave function, we need to use a special opcode
4761 // so we can patch up EXEC.
4762 if (Info->isWholeWaveFunction())
4763 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4764
4765 SDValue Ret = DAG.getNode(OPC, DL, MVT::Other, Ops);
4766 DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
4767 return Ret;
4768 }
4769
4770 // Returns a chain and a flag for retval copy to use.
4771 SDValue Call = DAG.getNode(AMDGPUISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops);
4772 DAG.addNoMergeSiteInfo(Call.getNode(), CLI.NoMerge);
4773 Chain = Call.getValue(0);
4774 InGlue = Call.getValue(1);
4775
4776 uint64_t CalleePopBytes = NumBytes;
4777 Chain = DAG.getCALLSEQ_END(Chain, 0, CalleePopBytes, InGlue, DL);
4778 if (!Ins.empty())
4779 InGlue = Chain.getValue(1);
4780
4781 // Handle result values, copying them out of physregs into vregs that we
4782 // return.
4783 return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG,
4784 InVals, /*IsThisReturn=*/false, SDValue());
4785}
4786
4787// This is similar to the default implementation in ExpandDYNAMIC_STACKALLOC,
4788// except for:
4789// 1. Stack growth direction(default: downwards, AMDGPU: upwards), and
4790// 2. Scale size where, scale = wave-reduction(alloca-size) * wave-size
4792 SelectionDAG &DAG) const {
4793 const MachineFunction &MF = DAG.getMachineFunction();
4795
4796 SDLoc dl(Op);
4797 EVT VT = Op.getValueType();
4798 SDValue Chain = Op.getOperand(0);
4799 Register SPReg = Info->getStackPtrOffsetReg();
4800
4801 // Chain the dynamic stack allocation so that it doesn't modify the stack
4802 // pointer when other instructions are using the stack.
4803 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, dl);
4804
4805 SDValue Size = Op.getOperand(1);
4806 SDValue BaseAddr = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
4807 Align Alignment = cast<ConstantSDNode>(Op.getOperand(2))->getAlignValue();
4808
4809 const TargetFrameLowering *TFL = Subtarget->getFrameLowering();
4811 "Stack grows upwards for AMDGPU");
4812
4813 Chain = BaseAddr.getValue(1);
4814 // When using flat-scratch, the stack offset is unscaled.
4815 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4816 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4817
4818 Align StackAlign = TFL->getStackAlign();
4819 if (Alignment > StackAlign) {
4820 uint64_t ScaledAlignment = Alignment.value()
4821 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4822 uint64_t StackAlignMask = ScaledAlignment - 1;
4823 SDValue TmpAddr = DAG.getNode(ISD::ADD, dl, VT, BaseAddr,
4824 DAG.getConstant(StackAlignMask, dl, VT));
4825 BaseAddr = DAG.getNode(ISD::AND, dl, VT, TmpAddr,
4826 DAG.getSignedConstant(-ScaledAlignment, dl, VT));
4827 }
4828
4829 assert(Size.getValueType() == MVT::i32 && "Size must be 32-bit");
4830 SDValue NewSP;
4832 // Increase the stack pointer by the size of the alloca.
4833 // If not using flat-scratch, we have to scale the size by the wave-size.
4834 SDValue ScaledSize =
4835 HasFlatScratch
4836 ? Size
4837 : DAG.getNode(ISD::SHL, dl, VT, Size,
4838 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4839 NewSP = DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value
4840 } else {
4841 // For dynamic sized alloca, perform wave-wide reduction to get max of
4842 // alloca size(divergent), and then scale it (when not using flat-scratch)
4843 // by wave-size.
4844 SDValue WaveReduction =
4845 DAG.getTargetConstant(Intrinsic::amdgcn_wave_reduce_umax, dl, MVT::i32);
4846 Size = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, WaveReduction,
4847 Size, DAG.getTargetConstant(0, dl, MVT::i32));
4848 SDValue ScaledSize = Size;
4849 if (!HasFlatScratch) {
4850 ScaledSize =
4851 DAG.getNode(ISD::SHL, dl, VT, Size,
4852 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4853 }
4854 NewSP =
4855 DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value in vgpr.
4856 SDValue ReadFirstLaneID =
4857 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, dl, MVT::i32);
4858 NewSP = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, ReadFirstLaneID,
4859 NewSP);
4860 }
4861
4862 Chain = DAG.getCopyToReg(Chain, dl, SPReg, NewSP); // Output chain
4863 SDValue CallSeqEnd = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), dl);
4864
4865 return DAG.getMergeValues({BaseAddr, CallSeqEnd}, dl);
4866}
4867
4869 if (Op.getValueType() != MVT::i32)
4870 return Op; // Defer to cannot select error.
4871
4873 SDLoc SL(Op);
4874
4875 SDValue CopyFromSP = DAG.getCopyFromReg(Op->getOperand(0), SL, SP, MVT::i32);
4876
4877 // Convert from wave uniform to swizzled vector address. This should protect
4878 // from any edge cases where the stacksave result isn't directly used with
4879 // stackrestore.
4880 SDValue VectorAddress =
4881 DAG.getNode(AMDGPUISD::WAVE_ADDRESS, SL, MVT::i32, CopyFromSP);
4882 return DAG.getMergeValues({VectorAddress, CopyFromSP.getValue(1)}, SL);
4883}
4884
4886 SelectionDAG &DAG) const {
4887 SDLoc SL(Op);
4888 assert(Op.getValueType() == MVT::i32);
4889
4890 uint32_t BothRoundHwReg =
4892 SDValue GetRoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
4893
4894 SDValue IntrinID =
4895 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
4896 SDValue GetReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, Op->getVTList(),
4897 Op.getOperand(0), IntrinID, GetRoundBothImm);
4898
4899 // There are two rounding modes, one for f32 and one for f64/f16. We only
4900 // report in the standard value range if both are the same.
4901 //
4902 // The raw values also differ from the expected FLT_ROUNDS values. Nearest
4903 // ties away from zero is not supported, and the other values are rotated by
4904 // 1.
4905 //
4906 // If the two rounding modes are not the same, report a target defined value.
4907
4908 // Mode register rounding mode fields:
4909 //
4910 // [1:0] Single-precision round mode.
4911 // [3:2] Double/Half-precision round mode.
4912 //
4913 // 0=nearest even; 1= +infinity; 2= -infinity, 3= toward zero.
4914 //
4915 // Hardware Spec
4916 // Toward-0 3 0
4917 // Nearest Even 0 1
4918 // +Inf 1 2
4919 // -Inf 2 3
4920 // NearestAway0 N/A 4
4921 //
4922 // We have to handle 16 permutations of a 4-bit value, so we create a 64-bit
4923 // table we can index by the raw hardware mode.
4924 //
4925 // (trunc (FltRoundConversionTable >> MODE.fp_round)) & 0xf
4926
4927 SDValue BitTable =
4929
4930 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4931 SDValue RoundModeTimesNumBits =
4932 DAG.getNode(ISD::SHL, SL, MVT::i32, GetReg, Two);
4933
4934 // TODO: We could possibly avoid a 64-bit shift and use a simpler table if we
4935 // knew only one mode was demanded.
4936 SDValue TableValue =
4937 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
4938 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
4939
4940 SDValue EntryMask = DAG.getConstant(0xf, SL, MVT::i32);
4941 SDValue TableEntry =
4942 DAG.getNode(ISD::AND, SL, MVT::i32, TruncTable, EntryMask);
4943
4944 // There's a gap in the 4-bit encoded table and actual enum values, so offset
4945 // if it's an extended value.
4946 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
4947 SDValue IsStandardValue =
4948 DAG.getSetCC(SL, MVT::i1, TableEntry, Four, ISD::SETULT);
4949 SDValue EnumOffset = DAG.getNode(ISD::ADD, SL, MVT::i32, TableEntry, Four);
4950 SDValue Result = DAG.getNode(ISD::SELECT, SL, MVT::i32, IsStandardValue,
4951 TableEntry, EnumOffset);
4952
4953 return DAG.getMergeValues({Result, GetReg.getValue(1)}, SL);
4954}
4955
4957 SelectionDAG &DAG) const {
4958 SDLoc SL(Op);
4959
4960 SDValue NewMode = Op.getOperand(1);
4961 assert(NewMode.getValueType() == MVT::i32);
4962
4963 // Index a table of 4-bit entries mapping from the C FLT_ROUNDS values to the
4964 // hardware MODE.fp_round values.
4965 if (auto *ConstMode = dyn_cast<ConstantSDNode>(NewMode)) {
4966 uint32_t ClampedVal = std::min(
4967 static_cast<uint32_t>(ConstMode->getZExtValue()),
4969 NewMode = DAG.getConstant(
4970 AMDGPU::decodeFltRoundToHWConversionTable(ClampedVal), SL, MVT::i32);
4971 } else {
4972 // If we know the input can only be one of the supported standard modes in
4973 // the range 0-3, we can use a simplified mapping to hardware values.
4974 KnownBits KB = DAG.computeKnownBits(NewMode);
4975 const bool UseReducedTable = KB.countMinLeadingZeros() >= 30;
4976 // The supported standard values are 0-3. The extended values start at 8. We
4977 // need to offset by 4 if the value is in the extended range.
4978
4979 if (UseReducedTable) {
4980 // Truncate to the low 32-bits.
4981 SDValue BitTable = DAG.getConstant(
4982 AMDGPU::FltRoundToHWConversionTable & 0xffff, SL, MVT::i32);
4983
4984 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4985 SDValue RoundModeTimesNumBits =
4986 DAG.getNode(ISD::SHL, SL, MVT::i32, NewMode, Two);
4987
4988 NewMode =
4989 DAG.getNode(ISD::SRL, SL, MVT::i32, BitTable, RoundModeTimesNumBits);
4990
4991 // TODO: SimplifyDemandedBits on the setreg source here can likely reduce
4992 // the table extracted bits into inline immediates.
4993 } else {
4994 // table_index = umin(value, value - 4)
4995 // MODE.fp_round = (bit_table >> (table_index << 2)) & 0xf
4996 SDValue BitTable =
4998
4999 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
5000 SDValue OffsetEnum = DAG.getNode(ISD::SUB, SL, MVT::i32, NewMode, Four);
5001 SDValue IndexVal =
5002 DAG.getNode(ISD::UMIN, SL, MVT::i32, NewMode, OffsetEnum);
5003
5004 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
5005 SDValue RoundModeTimesNumBits =
5006 DAG.getNode(ISD::SHL, SL, MVT::i32, IndexVal, Two);
5007
5008 SDValue TableValue =
5009 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
5010 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
5011
5012 // No need to mask out the high bits since the setreg will ignore them
5013 // anyway.
5014 NewMode = TruncTable;
5015 }
5016
5017 // Insert a readfirstlane in case the value is a VGPR. We could do this
5018 // earlier and keep more operations scalar, but that interferes with
5019 // combining the source.
5020 SDValue ReadFirstLaneID =
5021 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
5022 NewMode = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5023 ReadFirstLaneID, NewMode);
5024 }
5025
5026 // N.B. The setreg will be later folded into s_round_mode on supported
5027 // targets.
5028 SDValue IntrinID =
5029 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
5030 uint32_t BothRoundHwReg =
5032 SDValue RoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
5033
5034 SDValue SetReg =
5035 DAG.getNode(ISD::INTRINSIC_VOID, SL, Op->getVTList(), Op.getOperand(0),
5036 IntrinID, RoundBothImm, NewMode);
5037
5038 return SetReg;
5039}
5040
5042 unsigned AS = cast<MemSDNode>(Op)->getAddressSpace();
5043 if (AS == AMDGPUAS::BUFFER_RESOURCE)
5044 return Op.getOperand(0);
5046 return SDValue();
5047
5048 // I$ prefetch
5049 if (!Subtarget->hasSafeSmemPrefetch() && !Op.getConstantOperandVal(4))
5050 return SDValue();
5051
5052 // Prefetch the 64-bit address that a 32-bit constant pointer is cast to, as
5053 // a load does.
5054 SDValue Ptr = Op.getOperand(1);
5055 if (Ptr.getValueType() != MVT::i32)
5056 return Op;
5058 Ops[1] = DAG.getAddrSpaceCast(SDLoc(Op), MVT::i64, Ptr,
5061 return SDValue(DAG.UpdateNodeOperands(Op.getNode(), Ops), 0);
5062}
5063
5064// Work around DAG legality rules only based on the result type.
5066 bool IsStrict = Op.getOpcode() == ISD::STRICT_FP_EXTEND;
5067 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
5068 EVT SrcVT = Src.getValueType();
5069
5070 if (SrcVT.getScalarType() != MVT::bf16)
5071 return Op;
5072
5073 SDLoc SL(Op);
5074 SDValue BitCast =
5075 DAG.getNode(ISD::BITCAST, SL, SrcVT.changeTypeToInteger(), Src);
5076
5077 EVT DstVT = Op.getValueType();
5078 if (IsStrict)
5079 llvm_unreachable("Need STRICT_BF16_TO_FP");
5080
5081 return DAG.getNode(ISD::BF16_TO_FP, SL, DstVT, BitCast);
5082}
5083
5085 SDLoc SL(Op);
5086 if (Op.getValueType() != MVT::i64)
5087 return Op;
5088
5089 uint32_t ModeHwReg =
5091 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5092 uint32_t TrapHwReg =
5094 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5095
5096 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::Other);
5097 SDValue IntrinID =
5098 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
5099 SDValue GetModeReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5100 Op.getOperand(0), IntrinID, ModeHwRegImm);
5101 SDValue GetTrapReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5102 Op.getOperand(0), IntrinID, TrapHwRegImm);
5103 SDValue TokenReg =
5104 DAG.getNode(ISD::TokenFactor, SL, MVT::Other, GetModeReg.getValue(1),
5105 GetTrapReg.getValue(1));
5106
5107 SDValue CvtPtr =
5108 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, GetModeReg, GetTrapReg);
5109 SDValue Result = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
5110
5111 return DAG.getMergeValues({Result, TokenReg}, SL);
5112}
5113
5115 SDLoc SL(Op);
5116 if (Op.getOperand(1).getValueType() != MVT::i64)
5117 return Op;
5118
5119 SDValue Input = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op.getOperand(1));
5120 SDValue NewModeReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5121 DAG.getConstant(0, SL, MVT::i32));
5122 SDValue NewTrapReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5123 DAG.getConstant(1, SL, MVT::i32));
5124
5125 SDValue ReadFirstLaneID =
5126 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
5127 NewModeReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5128 ReadFirstLaneID, NewModeReg);
5129 NewTrapReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5130 ReadFirstLaneID, NewTrapReg);
5131
5132 unsigned ModeHwReg =
5134 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5135 unsigned TrapHwReg =
5137 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5138
5139 SDValue IntrinID =
5140 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
5141 SDValue SetModeReg =
5142 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5143 IntrinID, ModeHwRegImm, NewModeReg);
5144 SDValue SetTrapReg =
5145 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5146 IntrinID, TrapHwRegImm, NewTrapReg);
5147 return DAG.getNode(ISD::TokenFactor, SL, MVT::Other, SetTrapReg, SetModeReg);
5148}
5149
5151 const MachineFunction &MF) const {
5152 Register Reg =
5154 .Case("m0", AMDGPU::M0)
5155 .Case("exec", AMDGPU::EXEC)
5156 .Case("exec_lo", AMDGPU::EXEC_LO)
5157 .Case("exec_hi", AMDGPU::EXEC_HI)
5158 .Case("flat_scratch", AMDGPU::FLAT_SCR)
5159 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5160 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5161 .Case("src_flat_scratch_base", AMDGPU::SRC_FLAT_SCRATCH_BASE)
5162 .Case("src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
5163 .Case("src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
5164 .Default(Register());
5165 if (!Reg)
5166 return Reg;
5167
5168 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
5169 if (!Subtarget->hasFlatScrRegister() &&
5170 TRI->regsOverlap(Reg, AMDGPU::FLAT_SCR))
5171 return Register();
5172
5173 if (!Subtarget->hasGloballyAddressableScratch() &&
5174 TRI->regsOverlap(Reg, AMDGPU::SRC_FLAT_SCRATCH_BASE))
5175 return Register();
5176
5177 switch (Reg) {
5178 case AMDGPU::M0:
5179 case AMDGPU::EXEC_LO:
5180 case AMDGPU::EXEC_HI:
5181 case AMDGPU::FLAT_SCR_LO:
5182 case AMDGPU::FLAT_SCR_HI:
5183 case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
5184 case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
5185 if (VT.getSizeInBits() == 32)
5186 return Reg;
5187 break;
5188 case AMDGPU::EXEC:
5189 case AMDGPU::FLAT_SCR:
5190 case AMDGPU::SRC_FLAT_SCRATCH_BASE:
5191 if (VT.getSizeInBits() == 64)
5192 return Reg;
5193 break;
5194 default:
5195 llvm_unreachable("missing register type checking");
5196 }
5197
5199 Twine("invalid type for register \"" + StringRef(RegName) + "\"."));
5200}
5201
5202// If kill is not the last instruction, split the block so kill is always a
5203// proper terminator.
5206 MachineBasicBlock *BB) const {
5207 MachineBasicBlock *SplitBB = BB->splitAt(MI, /*UpdateLiveIns=*/true);
5209 MI.setDesc(TII->getKillTerminatorFromPseudo(MI.getOpcode()));
5210 return SplitBB;
5211}
5212
5213// Split block \p MBB at \p MI, as to insert a loop. If \p InstInLoop is true,
5214// \p MI will be the only instruction in the loop body block. Otherwise, it will
5215// be the first instruction in the remainder block.
5216//
5217/// \returns { LoopBody, Remainder }
5218static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5220 MachineFunction *MF = MBB.getParent();
5222
5223 // To insert the loop we need to split the block. Move everything after this
5224 // point to a new block, and insert a new empty block between the two.
5226 MachineBasicBlock *RemainderBB = MF->CreateMachineBasicBlock();
5228 ++MBBI;
5229
5230 MF->insert(MBBI, LoopBB);
5231 MF->insert(MBBI, RemainderBB);
5232
5233 LoopBB->addSuccessor(LoopBB);
5234 LoopBB->addSuccessor(RemainderBB);
5235
5236 // Move the rest of the block into a new block.
5237 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
5238
5239 if (InstInLoop) {
5240 auto Next = std::next(I);
5241
5242 // Move instruction to loop body.
5243 LoopBB->splice(LoopBB->begin(), &MBB, I, Next);
5244
5245 // Move the rest of the block.
5246 RemainderBB->splice(RemainderBB->begin(), &MBB, Next, MBB.end());
5247 } else {
5248 RemainderBB->splice(RemainderBB->begin(), &MBB, I, MBB.end());
5249 }
5250
5251 MBB.addSuccessor(LoopBB);
5252
5253 return std::pair(LoopBB, RemainderBB);
5254}
5255
5256/// Insert \p MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
5258 MachineBasicBlock *MBB = MI.getParent();
5260 auto I = MI.getIterator();
5261 auto E = std::next(I);
5262
5263 // clang-format off
5264 BuildMI(*MBB, E, MI.getDebugLoc(), TII->get(AMDGPU::S_WAITCNT))
5265 .addImm(0);
5266 // clang-format on
5267
5268 MIBundleBuilder Bundler(*MBB, I, E);
5269 finalizeBundle(*MBB, Bundler.begin());
5270}
5271
5274 MachineBasicBlock *BB) const {
5275 const DebugLoc &DL = MI.getDebugLoc();
5276
5278
5280
5281 // Apparently kill flags are only valid if the def is in the same block?
5282 if (MachineOperand *Src = TII->getNamedOperand(MI, AMDGPU::OpName::data0))
5283 Src->setIsKill(false);
5284
5285 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, *BB, true);
5286
5287 MachineBasicBlock::iterator I = LoopBB->end();
5288
5289 const unsigned EncodedReg = AMDGPU::Hwreg::HwregEncoding::encode(
5291
5292 // Clear TRAP_STS.MEM_VIOL
5293 BuildMI(*LoopBB, LoopBB->begin(), DL, TII->get(AMDGPU::S_SETREG_IMM32_B32))
5294 .addImm(0)
5295 .addImm(EncodedReg);
5296
5298
5299 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5300
5301 // Load and check TRAP_STS.MEM_VIOL
5302 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_GETREG_B32), Reg)
5303 .addImm(EncodedReg);
5304
5305 // clang-format off
5306 // FIXME: Do we need to use an isel pseudo that may clobber scc?
5307 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CMP_LG_U32))
5308 .addReg(Reg)
5309 .addImm(0);
5310 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
5311 .addMBB(LoopBB);
5312 // clang-format on
5313
5314 return RemainderBB;
5315}
5316
5317// Do a v_movrels_b32 or v_movreld_b32 for each unique value of \p IdxReg in the
5318// wavefront. If the value is uniform and just happens to be in a VGPR, this
5319// will only do one iteration. In the worst case, this will loop 64 times.
5320//
5321// TODO: Just use v_readlane_b32 if we know the VGPR has a uniform value.
5324 MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB,
5325 const DebugLoc &DL, const MachineOperand &Idx,
5326 unsigned InitReg, unsigned ResultReg, unsigned PhiReg,
5327 unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode,
5328 Register &SGPRIdxReg) {
5329
5330 MachineFunction *MF = OrigBB.getParent();
5331 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5332 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5335
5336 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5337 Register PhiExec = MRI.createVirtualRegister(BoolRC);
5338 Register NewExec = MRI.createVirtualRegister(BoolRC);
5339 Register CurrentIdxReg =
5340 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5341 Register CondReg = MRI.createVirtualRegister(BoolRC);
5342
5343 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiReg)
5344 .addReg(InitReg)
5345 .addMBB(&OrigBB)
5346 .addReg(ResultReg)
5347 .addMBB(&LoopBB);
5348
5349 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiExec)
5350 .addReg(InitSaveExecReg)
5351 .addMBB(&OrigBB)
5352 .addReg(NewExec)
5353 .addMBB(&LoopBB);
5354
5355 // Read the next variant <- also loop target.
5356 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5357 .addReg(Idx.getReg(), getUndefRegState(Idx.isUndef()));
5358
5359 // Compare the just read M0 value to all possible Idx values.
5360 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5361 .addReg(CurrentIdxReg)
5362 .addReg(Idx.getReg(), {}, Idx.getSubReg());
5363
5364 // Update EXEC, save the original EXEC value to VCC.
5365 BuildMI(LoopBB, I, DL, TII->get(LMC.AndSaveExecOpc), NewExec)
5366 .addReg(CondReg)
5367 .setOperandDead(3); // Dead scc
5368
5369 MRI.setSimpleHint(NewExec, CondReg);
5370
5371 if (UseGPRIdxMode) {
5372 if (Offset == 0) {
5373 SGPRIdxReg = CurrentIdxReg;
5374 } else {
5375 SGPRIdxReg = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
5376 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5377 .addReg(CurrentIdxReg)
5378 .addImm(Offset)
5379 .setOperandDead(3); // Dead scc
5380 }
5381 } else {
5382 // Move index from VCC into M0
5383 if (Offset == 0) {
5384 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5385 .addReg(CurrentIdxReg);
5386 } else {
5387 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5388 .addReg(CurrentIdxReg)
5389 .addImm(Offset)
5390 .setOperandDead(3); // Dead scc
5391 }
5392 }
5393
5394 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
5395 MachineInstr *InsertPt =
5396 BuildMI(LoopBB, I, DL, TII->get(LMC.XorTermOpc), LMC.ExecReg)
5397 .addReg(LMC.ExecReg)
5398 .addReg(NewExec)
5399 .setOperandDead(3); // Dead scc
5400
5401 // XXX - s_xor_b64 sets scc to 1 if the result is nonzero, so can we use
5402 // s_cbranch_scc0?
5403
5404 // Loop back to V_READFIRSTLANE_B32 if there are still variants to cover.
5405 // clang-format off
5406 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
5407 .addMBB(&LoopBB);
5408 // clang-format on
5409
5410 return InsertPt->getIterator();
5411}
5412
5413// This has slightly sub-optimal regalloc when the source vector is killed by
5414// the read. The register allocator does not understand that the kill is
5415// per-workitem, so is kept alive for the whole loop so we end up not re-using a
5416// subregister from it, using 1 more VGPR than necessary. This was saved when
5417// this was expanded after register allocation.
5420 unsigned InitResultReg, unsigned PhiReg, int Offset,
5421 bool UseGPRIdxMode, Register &SGPRIdxReg) {
5422 MachineFunction *MF = MBB.getParent();
5423 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5424 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5426 const DebugLoc &DL = MI.getDebugLoc();
5428
5429 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
5430 Register DstReg = MI.getOperand(0).getReg();
5431 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
5432 Register TmpExec = MRI.createVirtualRegister(BoolXExecRC);
5434
5435 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), TmpExec);
5436
5437 // Save the EXEC mask
5438 // clang-format off
5439 BuildMI(MBB, I, DL, TII->get(LMC.MovOpc), SaveExec)
5440 .addReg(LMC.ExecReg);
5441 // clang-format on
5442
5443 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, MBB, false);
5444
5445 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5446
5447 auto InsPt = emitLoadM0FromVGPRLoop(TII, MRI, MBB, *LoopBB, DL, *Idx,
5448 InitResultReg, DstReg, PhiReg, TmpExec,
5449 Offset, UseGPRIdxMode, SGPRIdxReg);
5450
5451 MachineBasicBlock *LandingPad = MF->CreateMachineBasicBlock();
5453 ++MBBI;
5454 MF->insert(MBBI, LandingPad);
5455 LoopBB->removeSuccessor(RemainderBB);
5456 LandingPad->addSuccessor(RemainderBB);
5457 LoopBB->addSuccessor(LandingPad);
5458 MachineBasicBlock::iterator First = LandingPad->begin();
5459 // clang-format off
5460 BuildMI(*LandingPad, First, DL, TII->get(LMC.MovOpc), LMC.ExecReg)
5461 .addReg(SaveExec);
5462 // clang-format on
5463
5464 return InsPt;
5465}
5466
5467// Returns subreg index, offset
5468static std::pair<unsigned, int>
5470 const TargetRegisterClass *SuperRC, unsigned VecReg,
5471 int Offset) {
5472 int NumElts = TRI.getRegSizeInBits(*SuperRC) / 32;
5473
5474 // Skip out of bounds offsets, or else we would end up using an undefined
5475 // register.
5476 if (Offset >= NumElts || Offset < 0)
5477 return std::pair(AMDGPU::sub0, Offset);
5478
5479 return std::pair(SIRegisterInfo::getSubRegFromChannel(Offset), 0);
5480}
5481
5484 int Offset) {
5485 MachineBasicBlock *MBB = MI.getParent();
5486 const DebugLoc &DL = MI.getDebugLoc();
5488
5489 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5490
5491 assert(Idx->getReg() != AMDGPU::NoRegister);
5492
5493 if (Offset == 0) {
5494 // clang-format off
5495 BuildMI(*MBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5496 .add(*Idx);
5497 // clang-format on
5498 } else {
5499 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5500 .add(*Idx)
5501 .addImm(Offset)
5502 .setOperandDead(3); // Dead scc
5503 }
5504}
5505
5508 int Offset) {
5509 MachineBasicBlock *MBB = MI.getParent();
5510 const DebugLoc &DL = MI.getDebugLoc();
5512
5513 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5514
5515 if (Offset == 0)
5516 return Idx->getReg();
5517
5518 Register Tmp = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5519 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), Tmp)
5520 .add(*Idx)
5521 .addImm(Offset)
5522 .setOperandDead(3); // Dead scc
5523 return Tmp;
5524}
5525
5528 const GCNSubtarget &ST) {
5529 const SIInstrInfo *TII = ST.getInstrInfo();
5530 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5531 MachineFunction *MF = MBB.getParent();
5533
5534 Register Dst = MI.getOperand(0).getReg();
5535 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5536 Register SrcReg = TII->getNamedOperand(MI, AMDGPU::OpName::src)->getReg();
5537 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5538
5539 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcReg);
5540 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5541
5542 unsigned SubReg;
5543 std::tie(SubReg, Offset) =
5544 computeIndirectRegAndOffset(TRI, VecRC, SrcReg, Offset);
5545
5546 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5547
5548 // Check for a SGPR index.
5549 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5551 const DebugLoc &DL = MI.getDebugLoc();
5552
5553 if (UseGPRIdxMode) {
5554 // TODO: Look at the uses to avoid the copy. This may require rescheduling
5555 // to avoid interfering with other uses, so probably requires a new
5556 // optimization pass.
5558
5559 const MCInstrDesc &GPRIDXDesc =
5560 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5561 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5562 .addReg(SrcReg)
5563 .addReg(Idx)
5564 .addImm(SubReg);
5565 } else {
5567
5568 BuildMI(MBB, I, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5569 .addReg(SrcReg, {}, SubReg)
5570 .addReg(SrcReg, RegState::Implicit);
5571 }
5572
5573 MI.eraseFromParent();
5574
5575 return &MBB;
5576 }
5577
5578 // Control flow needs to be inserted if indexing with a VGPR.
5579 const DebugLoc &DL = MI.getDebugLoc();
5581
5582 Register PhiReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5583 Register InitReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5584
5585 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), InitReg);
5586
5587 Register SGPRIdxReg;
5588 auto InsPt = loadM0FromVGPR(TII, MBB, MI, InitReg, PhiReg, Offset,
5589 UseGPRIdxMode, SGPRIdxReg);
5590
5591 MachineBasicBlock *LoopBB = InsPt->getParent();
5592
5593 if (UseGPRIdxMode) {
5594 const MCInstrDesc &GPRIDXDesc =
5595 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5596
5597 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5598 .addReg(SrcReg)
5599 .addReg(SGPRIdxReg)
5600 .addImm(SubReg);
5601 } else {
5602 BuildMI(*LoopBB, InsPt, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5603 .addReg(SrcReg, {}, SubReg)
5604 .addReg(SrcReg, RegState::Implicit);
5605 }
5606
5607 MI.eraseFromParent();
5608
5609 return LoopBB;
5610}
5611
5614 const GCNSubtarget &ST) {
5615 const SIInstrInfo *TII = ST.getInstrInfo();
5616 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5617 MachineFunction *MF = MBB.getParent();
5619
5620 Register Dst = MI.getOperand(0).getReg();
5621 const MachineOperand *SrcVec = TII->getNamedOperand(MI, AMDGPU::OpName::src);
5622 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5623 const MachineOperand *Val = TII->getNamedOperand(MI, AMDGPU::OpName::val);
5624 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5625 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcVec->getReg());
5626 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5627
5628 // This can be an immediate, but will be folded later.
5629 assert(Val->getReg());
5630
5631 unsigned SubReg;
5632 std::tie(SubReg, Offset) =
5633 computeIndirectRegAndOffset(TRI, VecRC, SrcVec->getReg(), Offset);
5634 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5635
5636 if (Idx->getReg() == AMDGPU::NoRegister) {
5638 const DebugLoc &DL = MI.getDebugLoc();
5639
5640 assert(Offset == 0);
5641
5642 BuildMI(MBB, I, DL, TII->get(TargetOpcode::INSERT_SUBREG), Dst)
5643 .add(*SrcVec)
5644 .add(*Val)
5645 .addImm(SubReg);
5646
5647 MI.eraseFromParent();
5648 return &MBB;
5649 }
5650
5651 // Check for a SGPR index.
5652 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5654 const DebugLoc &DL = MI.getDebugLoc();
5655
5656 if (UseGPRIdxMode) {
5658
5659 const MCInstrDesc &GPRIDXDesc =
5660 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5661 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5662 .addReg(SrcVec->getReg())
5663 .add(*Val)
5664 .addReg(Idx)
5665 .addImm(SubReg);
5666 } else {
5668
5669 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5670 TRI.getRegSizeInBits(*VecRC), 32, false);
5671 BuildMI(MBB, I, DL, MovRelDesc, Dst)
5672 .addReg(SrcVec->getReg())
5673 .add(*Val)
5674 .addImm(SubReg);
5675 }
5676 MI.eraseFromParent();
5677 return &MBB;
5678 }
5679
5680 // Control flow needs to be inserted if indexing with a VGPR.
5681 if (Val->isReg())
5682 MRI.clearKillFlags(Val->getReg());
5683
5684 const DebugLoc &DL = MI.getDebugLoc();
5685
5686 Register PhiReg = MRI.createVirtualRegister(VecRC);
5687
5688 Register SGPRIdxReg;
5689 auto InsPt = loadM0FromVGPR(TII, MBB, MI, SrcVec->getReg(), PhiReg, Offset,
5690 UseGPRIdxMode, SGPRIdxReg);
5691 MachineBasicBlock *LoopBB = InsPt->getParent();
5692
5693 if (UseGPRIdxMode) {
5694 const MCInstrDesc &GPRIDXDesc =
5695 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5696
5697 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5698 .addReg(PhiReg)
5699 .add(*Val)
5700 .addReg(SGPRIdxReg)
5701 .addImm(SubReg);
5702 } else {
5703 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5704 TRI.getRegSizeInBits(*VecRC), 32, false);
5705 BuildMI(*LoopBB, InsPt, DL, MovRelDesc, Dst)
5706 .addReg(PhiReg)
5707 .add(*Val)
5708 .addImm(SubReg);
5709 }
5710
5711 MI.eraseFromParent();
5712 return LoopBB;
5713}
5714
5716 MachineBasicBlock *BB) {
5717 // For targets older than GFX12, we emit a sequence of 32-bit operations.
5718 // For GFX12, we emit s_add_u64 and s_sub_u64.
5719 MachineFunction *MF = BB->getParent();
5720 const SIInstrInfo *TII = MF->getSubtarget<GCNSubtarget>().getInstrInfo();
5721 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5723 const DebugLoc &DL = MI.getDebugLoc();
5724 MachineOperand &Dest = MI.getOperand(0);
5725 MachineOperand &Src0 = MI.getOperand(1);
5726 MachineOperand &Src1 = MI.getOperand(2);
5727 bool IsAdd = (MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5728 if (ST.hasScalarAddSub64()) {
5729 // FIXME: If scc is used, this deletes the def
5730 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5731 // clang-format off
5732 BuildMI(*BB, MI, DL, TII->get(Opc), Dest.getReg())
5733 .add(Src0)
5734 .add(Src1);
5735 // clang-format on
5736 } else {
5737 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5738 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5739
5740 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5741 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5742
5743 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5744 MI, MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5745 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5746 MI, MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5747
5748 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5749 MI, MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5750 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5751 MI, MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5752
5753 const MachineOperand &ImpDefSCC = MI.getOperand(3);
5754 assert(ImpDefSCC.getReg() == AMDGPU::SCC && ImpDefSCC.isDef());
5755
5756 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5757 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5758 BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0).add(Src0Sub0).add(Src1Sub0);
5759 auto Hi = BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1)
5760 .add(Src0Sub1)
5761 .add(Src1Sub1);
5762 if (ImpDefSCC.isDead())
5763 Hi.setOperandDead(3);
5764 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
5765 .addReg(DestSub0)
5766 .addImm(AMDGPU::sub0)
5767 .addReg(DestSub1)
5768 .addImm(AMDGPU::sub1);
5769 }
5770 MI.eraseFromParent();
5771 return BB;
5772}
5773
5775 MachineFunction *MF = BB->getParent();
5776 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5777 const SIInstrInfo *TII = ST.getInstrInfo();
5778 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5780 const DebugLoc &DL = MI.getDebugLoc();
5781 Register Dst = MI.getOperand(0).getReg();
5782 const MachineOperand &Src0 = MI.getOperand(1);
5783 const MachineOperand &Src1 = MI.getOperand(2);
5784 Register SrcCond = MI.getOperand(3).getReg();
5785
5786 Register DstLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5787 Register DstHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5788 const TargetRegisterClass *CondRC = TRI->getWaveMaskRegClass();
5789 Register SrcCondCopy = MRI.createVirtualRegister(CondRC);
5790
5791 int Src0Idx =
5792 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
5793 int Src1Idx =
5794 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);
5795 const TargetRegisterClass *Src0RC =
5796 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src0Idx));
5797 const TargetRegisterClass *Src1RC =
5798 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src1Idx));
5799
5800 const TargetRegisterClass *Src0SubRC =
5801 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5802 const TargetRegisterClass *Src1SubRC =
5803 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5804
5805 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5806 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5807 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5808 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5809
5810 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5811 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5812 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5813 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5814
5815 BuildMI(*BB, MI, DL, TII->get(AMDGPU::COPY), SrcCondCopy).addReg(SrcCond);
5816 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstLo)
5817 .addImm(0)
5818 .add(Src0Sub0)
5819 .addImm(0)
5820 .add(Src1Sub0)
5821 .addReg(SrcCondCopy);
5822
5823 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstHi)
5824 .addImm(0)
5825 .add(Src0Sub1)
5826 .addImm(0)
5827 .add(Src1Sub1)
5828 .addReg(SrcCondCopy);
5829
5830 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE), Dst)
5831 .addReg(DstLo)
5832 .addImm(AMDGPU::sub0)
5833 .addReg(DstHi)
5834 .addImm(AMDGPU::sub1);
5835 MI.eraseFromParent();
5836}
5837
5839 switch (Opc) {
5840 case AMDGPU::S_MIN_U32:
5841 return std::numeric_limits<uint32_t>::max();
5842 case AMDGPU::S_MIN_I32:
5843 return std::numeric_limits<int32_t>::max();
5844 case AMDGPU::S_MAX_U32:
5845 return std::numeric_limits<uint32_t>::min();
5846 case AMDGPU::S_MAX_I32:
5847 return std::numeric_limits<int32_t>::min();
5848 case AMDGPU::V_ADD_F32_e64: // -0.0
5849 return 0x80000000;
5850 case AMDGPU::V_SUB_F32_e64: // +0.0
5851 return 0x0;
5852 case AMDGPU::S_ADD_I32:
5853 case AMDGPU::S_SUB_I32:
5854 case AMDGPU::S_OR_B32:
5855 case AMDGPU::S_XOR_B32:
5856 return std::numeric_limits<uint32_t>::min();
5857 case AMDGPU::S_AND_B32:
5858 return std::numeric_limits<uint32_t>::max();
5859 case AMDGPU::V_MIN_F32_e64:
5860 case AMDGPU::V_MAX_F32_e64:
5861 return 0x7fc00000; // qNAN
5862 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5863 return std::numeric_limits<uint64_t>::max();
5864 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5865 return std::numeric_limits<int64_t>::max();
5866 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5867 return std::numeric_limits<uint64_t>::min();
5868 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5869 return std::numeric_limits<int64_t>::min();
5870 case AMDGPU::V_MIN_F64_e64:
5871 case AMDGPU::V_MAX_F64_e64:
5872 case AMDGPU::V_MIN_NUM_F64_e64:
5873 case AMDGPU::V_MAX_NUM_F64_e64:
5874 return 0x7FF8000000000000; // qNAN
5875 case AMDGPU::S_ADD_U64_PSEUDO:
5876 case AMDGPU::S_SUB_U64_PSEUDO:
5877 case AMDGPU::S_OR_B64:
5878 case AMDGPU::S_XOR_B64:
5879 return std::numeric_limits<uint64_t>::min();
5880 case AMDGPU::S_AND_B64:
5881 return std::numeric_limits<uint64_t>::max();
5882 case AMDGPU::V_ADD_F64_e64:
5883 case AMDGPU::V_ADD_F64_pseudo_e64:
5884 return 0x8000000000000000; // -0.0
5885 default:
5886 llvm_unreachable("Unexpected opcode in getIdentityValueForWaveReduction");
5887 }
5888}
5889
5890static bool is32bitWaveReduceOperation(unsigned Opc) {
5891 return Opc == AMDGPU::S_MIN_U32 || Opc == AMDGPU::S_MIN_I32 ||
5892 Opc == AMDGPU::S_MAX_U32 || Opc == AMDGPU::S_MAX_I32 ||
5893 Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32 ||
5894 Opc == AMDGPU::S_AND_B32 || Opc == AMDGPU::S_OR_B32 ||
5895 Opc == AMDGPU::S_XOR_B32 || Opc == AMDGPU::V_MIN_F32_e64 ||
5896 Opc == AMDGPU::V_MAX_F32_e64 || Opc == AMDGPU::V_ADD_F32_e64 ||
5897 Opc == AMDGPU::V_SUB_F32_e64;
5898}
5899
5901 return Opc == AMDGPU::V_MIN_F32_e64 || Opc == AMDGPU::V_MAX_F32_e64 ||
5902 Opc == AMDGPU::V_ADD_F32_e64 || Opc == AMDGPU::V_SUB_F32_e64 ||
5903 Opc == AMDGPU::V_MIN_F64_e64 || Opc == AMDGPU::V_MAX_F64_e64 ||
5904 Opc == AMDGPU::V_MIN_NUM_F64_e64 || Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5905 Opc == AMDGPU::V_ADD_F64_e64 || Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5906}
5907
5908static std::tuple<unsigned, unsigned>
5910 unsigned DPPOpc;
5911 switch (Opc) {
5912 case AMDGPU::S_MIN_U32:
5913 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5914 break;
5915 case AMDGPU::S_MIN_I32:
5916 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5917 break;
5918 case AMDGPU::S_MAX_U32:
5919 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5920 break;
5921 case AMDGPU::S_MAX_I32:
5922 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5923 break;
5924 case AMDGPU::S_ADD_I32:
5925 case AMDGPU::S_SUB_I32:
5926 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5927 : AMDGPU::V_ADD_CO_U32_dpp;
5928 break;
5929 case AMDGPU::S_AND_B32:
5930 DPPOpc = AMDGPU::V_AND_B32_dpp;
5931 break;
5932 case AMDGPU::S_OR_B32:
5933 DPPOpc = AMDGPU::V_OR_B32_dpp;
5934 break;
5935 case AMDGPU::S_XOR_B32:
5936 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5937 break;
5938 case AMDGPU::V_ADD_F32_e64:
5939 case AMDGPU::V_SUB_F32_e64:
5940 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5941 break;
5942 case AMDGPU::V_MIN_F32_e64:
5943 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5944 break;
5945 case AMDGPU::V_MAX_F32_e64:
5946 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5947 break;
5948 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5949 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5950 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5951 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5952 case AMDGPU::S_ADD_U64_PSEUDO:
5953 case AMDGPU::S_SUB_U64_PSEUDO:
5954 case AMDGPU::S_AND_B64:
5955 case AMDGPU::S_OR_B64:
5956 case AMDGPU::S_XOR_B64:
5957 case AMDGPU::V_MIN_NUM_F64_e64:
5958 case AMDGPU::V_MIN_F64_e64:
5959 case AMDGPU::V_MAX_NUM_F64_e64:
5960 case AMDGPU::V_MAX_F64_e64:
5961 case AMDGPU::V_ADD_F64_pseudo_e64:
5962 case AMDGPU::V_ADD_F64_e64:
5963 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5964 break;
5965 default:
5966 llvm_unreachable("unhandled lane op");
5967 }
5968 unsigned ClampOpc = Opc;
5969 if (Opc == AMDGPU::V_SUB_F32_e64)
5970 ClampOpc = AMDGPU::V_ADD_F32_e64;
5971 if (!ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
5972 if (Opc == AMDGPU::S_SUB_I32)
5973 ClampOpc = AMDGPU::S_ADD_I32;
5974 if (Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO)
5975 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5976 else if (Opc == AMDGPU::S_AND_B64)
5977 ClampOpc = AMDGPU::V_AND_B32_e64;
5978 else if (Opc == AMDGPU::S_OR_B64)
5979 ClampOpc = AMDGPU::V_OR_B32_e64;
5980 else if (Opc == AMDGPU::S_XOR_B64)
5981 ClampOpc = AMDGPU::V_XOR_B32_e64;
5982 else
5983 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5984 }
5985 return {DPPOpc, ClampOpc};
5986}
5987
5988static std::pair<Register, Register>
5990 const TargetRegisterClass *SrcRC, const GCNSubtarget &ST,
5992 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5993 const SIInstrInfo *TII = ST.getInstrInfo();
5994 const TargetRegisterClass *SrcSubRC =
5995 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5996 Register Op1L =
5997 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5998 Register Op1H =
5999 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub1, SrcSubRC);
6000 return {Op1L, Op1H};
6001}
6002
6005 const GCNSubtarget &ST,
6006 unsigned Opc) {
6008 const SIRegisterInfo *TRI = ST.getRegisterInfo();
6009 const DebugLoc &DL = MI.getDebugLoc();
6010 const SIInstrInfo *TII = ST.getInstrInfo();
6011
6012 // Reduction operations depend on whether the input operand is SGPR or VGPR.
6013 Register SrcReg = MI.getOperand(1).getReg();
6014 bool isSGPR = TRI->isSGPRClass(MRI.getRegClass(SrcReg));
6015 Register DstReg = MI.getOperand(0).getReg();
6016 unsigned Stratergy = static_cast<unsigned>(MI.getOperand(2).getImm());
6017 enum WAVE_REDUCE_STRATEGY : unsigned { DEFAULT = 0, ITERATIVE = 1, DPP = 2 };
6018 MachineBasicBlock *RetBB = nullptr;
6019 unsigned MIOpc = MI.getOpcode();
6020 auto BuildRegSequence = [&](MachineBasicBlock &BB,
6022 Register Src0, Register Src1) {
6023 auto RegSequence =
6024 BuildMI(BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dst)
6025 .addReg(Src0)
6026 .addImm(AMDGPU::sub0)
6027 .addReg(Src1)
6028 .addImm(AMDGPU::sub1);
6029 return RegSequence;
6030 };
6031 if (isSGPR) {
6032 switch (Opc) {
6033 case AMDGPU::S_MIN_U32:
6034 case AMDGPU::S_MIN_I32:
6035 case AMDGPU::V_MIN_F32_e64:
6036 case AMDGPU::S_MAX_U32:
6037 case AMDGPU::S_MAX_I32:
6038 case AMDGPU::V_MAX_F32_e64:
6039 case AMDGPU::S_AND_B32:
6040 case AMDGPU::S_OR_B32: {
6041 // Idempotent operations.
6042 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstReg).addReg(SrcReg);
6043 RetBB = &BB;
6044 break;
6045 }
6046 case AMDGPU::V_CMP_LT_U64_e64: // umin
6047 case AMDGPU::V_CMP_LT_I64_e64: // min
6048 case AMDGPU::V_CMP_GT_U64_e64: // umax
6049 case AMDGPU::V_CMP_GT_I64_e64: // max
6050 case AMDGPU::V_MIN_F64_e64:
6051 case AMDGPU::V_MIN_NUM_F64_e64:
6052 case AMDGPU::V_MAX_F64_e64:
6053 case AMDGPU::V_MAX_NUM_F64_e64:
6054 case AMDGPU::S_AND_B64:
6055 case AMDGPU::S_OR_B64: {
6056 // Idempotent operations.
6057 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B64), DstReg).addReg(SrcReg);
6058 RetBB = &BB;
6059 break;
6060 }
6061 case AMDGPU::S_XOR_B32:
6062 case AMDGPU::S_XOR_B64:
6063 case AMDGPU::S_ADD_I32:
6064 case AMDGPU::S_ADD_U64_PSEUDO:
6065 case AMDGPU::V_ADD_F32_e64:
6066 case AMDGPU::V_ADD_F64_e64:
6067 case AMDGPU::V_ADD_F64_pseudo_e64:
6068 case AMDGPU::S_SUB_I32:
6069 case AMDGPU::S_SUB_U64_PSEUDO:
6070 case AMDGPU::V_SUB_F32_e64: {
6071 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
6072 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
6073 Register ExecMask = MRI.createVirtualRegister(WaveMaskRegClass);
6074 Register NumActiveLanes =
6075 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6076
6077 bool IsWave32 = ST.isWave32();
6078 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6079 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6080 unsigned BitCountOpc =
6081 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
6082
6083 BuildMI(BB, MI, DL, TII->get(MovOpc), ExecMask).addReg(ExecReg);
6084
6085 auto NewAccumulator =
6086 BuildMI(BB, MI, DL, TII->get(BitCountOpc), NumActiveLanes)
6087 .addReg(ExecMask)
6088 .setOperandDead(2); // Dead scc
6089
6090 switch (Opc) {
6091 case AMDGPU::S_XOR_B32:
6092 case AMDGPU::S_XOR_B64: {
6093 // Performing an XOR operation on a uniform value
6094 // depends on the parity of the number of active lanes.
6095 // For even parity, the result will be 0, for odd
6096 // parity the result will be the same as the input value.
6097 Register ParityRegister =
6098 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6099 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_AND_B32), ParityRegister)
6100 .addReg(NewAccumulator->getOperand(0).getReg())
6101 .addImm(1)
6102 .setOperandDead(3); // Dead scc
6103 // Check if Src is a known identity constant.
6104 if (TII->getImmOrMaterializedImm(MRI, SrcReg) == 1) {
6105 // 1 * parity(exec) = parity(exec)
6106 if (Opc == AMDGPU::S_XOR_B32) {
6107 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstReg)
6108 .addReg(ParityRegister);
6109 } else {
6110 Register DstHi =
6111 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6112 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstHi).addImm(0);
6113 BuildRegSequence(BB, MI, DstReg, ParityRegister, DstHi);
6114 }
6115 break;
6116 }
6117 if (Opc == AMDGPU::S_XOR_B32) {
6118 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6119 .addReg(SrcReg)
6120 .addReg(ParityRegister);
6121 } else {
6122 Register DestSub0 =
6123 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6124 Register DestSub1 =
6125 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6126 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6127 MRI.getRegClass(SrcReg), ST, MRI);
6128 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6129 .addReg(Op1L)
6130 .addReg(ParityRegister);
6131 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub1)
6132 .addReg(Op1H)
6133 .addReg(ParityRegister);
6134 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6135 }
6136 break;
6137 }
6138 case AMDGPU::S_SUB_I32: {
6139 Register NegatedVal = MRI.createVirtualRegister(DstRegClass);
6140 // Take the negation of the source operand.
6141 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedVal)
6142 .addImm(0)
6143 .addReg(SrcReg)
6144 .setOperandDead(3); // Dead scc
6145 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6146 .addReg(NegatedVal)
6147 .addReg(NewAccumulator->getOperand(0).getReg());
6148 break;
6149 }
6150 case AMDGPU::S_ADD_I32: {
6151 // Check if Src is a known identity constant.
6152 if (TII->getImmOrMaterializedImm(MRI, SrcReg) == 1) {
6153 // 1 * bitcount(exec) = bitcount(exec)
6154 BuildMI(BB, MI, DL, TII->get(AMDGPU::COPY), DstReg)
6155 .addReg(NewAccumulator->getOperand(0).getReg());
6156 break;
6157 }
6158 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6159 .addReg(SrcReg)
6160 .addReg(NewAccumulator->getOperand(0).getReg());
6161 break;
6162 }
6163 case AMDGPU::S_ADD_U64_PSEUDO:
6164 case AMDGPU::S_SUB_U64_PSEUDO: {
6165 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6166 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6167 Register Op1H_Op0L_Reg =
6168 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6169 Register Op1L_Op0H_Reg =
6170 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6171 Register CarryReg =
6172 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6173 Register AddReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6174 Register NegatedValLo =
6175 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6176 Register NegatedValHi =
6177 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6178 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6179 MRI.getRegClass(SrcReg), ST, MRI);
6180 // Check if Src is a known identity constant.
6181 if (Opc == AMDGPU::S_ADD_U64_PSEUDO &&
6182 TII->getImmOrMaterializedImm(MRI, SrcReg) == 1) {
6183 // 1 * bitcount(exec) = bitcount(exec)
6184 Register DstHi = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6185 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstHi).addImm(0);
6186 BuildRegSequence(BB, MI, DstReg,
6187 NewAccumulator->getOperand(0).getReg(), DstHi);
6188 break;
6189 }
6190 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6191 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedValLo)
6192 .addImm(0)
6193 .addReg(NewAccumulator->getOperand(0).getReg())
6194 .setOperandDead(3); // Dead scc
6195 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ASHR_I32), NegatedValHi)
6196 .addReg(NegatedValLo)
6197 .addImm(31)
6198 .setOperandDead(3); // Dead scc
6199 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1L_Op0H_Reg)
6200 .addReg(Op1L)
6201 .addReg(NegatedValHi);
6202 }
6203 Register LowOpcode = Opc == AMDGPU::S_SUB_U64_PSEUDO
6204 ? NegatedValLo
6205 : NewAccumulator->getOperand(0).getReg();
6206 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6207 .addReg(Op1L)
6208 .addReg(LowOpcode);
6209 if (ST.hasScalarMulHiInsts()) {
6210 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_HI_U32), CarryReg)
6211 .addReg(Op1L)
6212 .addReg(LowOpcode);
6213 } else {
6214 Register VCarryReg =
6215 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6216 Register LowOpVGPR =
6217 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6218 BuildMI(BB, MI, DL, TII->get(AMDGPU::COPY), LowOpVGPR)
6219 .addReg(LowOpcode);
6220 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6221 .addReg(Op1L)
6222 .addReg(LowOpVGPR);
6223 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6224 .addReg(VCarryReg);
6225 }
6226 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1H_Op0L_Reg)
6227 .addReg(Op1H)
6228 .addReg(LowOpcode);
6229
6230 Register HiVal = Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6231 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), HiVal)
6232 .addReg(CarryReg)
6233 .addReg(Op1H_Op0L_Reg)
6234 .setOperandDead(3); // Dead scc
6235
6236 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6237 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), DestSub1)
6238 .addReg(HiVal)
6239 .addReg(Op1L_Op0H_Reg)
6240 .setOperandDead(3); // Dead scc
6241 }
6242 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6243 break;
6244 }
6245 case AMDGPU::V_ADD_F32_e64:
6246 case AMDGPU::V_ADD_F64_e64:
6247 case AMDGPU::V_ADD_F64_pseudo_e64:
6248 case AMDGPU::V_SUB_F32_e64: {
6249 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6250 const TargetRegisterClass *VregRC = TII->getRegClass(TII->get(Opc), 0);
6251 Register ActiveLanesVreg = MRI.createVirtualRegister(VregRC);
6252 Register DstVreg = MRI.createVirtualRegister(VregRC);
6253 // Get number of active lanes as a float val.
6254 BuildMI(BB, MI, DL,
6255 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6256 : AMDGPU::V_CVT_F64_I32_e64),
6257 ActiveLanesVreg)
6258 .addReg(NewAccumulator->getOperand(0).getReg())
6259 .addImm(0) // clamp
6260 .addImm(0); // output-modifier
6261
6262 // Take negation of input for SUB reduction
6263 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6264 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6267 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6268 : ST.getGeneration() >= AMDGPUSubtarget::GFX12
6269 ? AMDGPU::V_MUL_F64_pseudo_e64
6270 : AMDGPU::V_MUL_F64_e64;
6271 auto DestVregInst = BuildMI(BB, MI, DL, TII->get(MulOpc),
6272 DstVreg)
6273 .addImm(srcMod) // src0 modifier
6274 .addReg(SrcReg)
6275 .addImm(SISrcMods::NONE) // src1 modifier
6276 .addReg(ActiveLanesVreg)
6277 .addImm(SISrcMods::NONE) // clamp
6278 .addImm(SISrcMods::NONE); // output-mod
6279 if (is32BitOpc) {
6280 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6281 .addReg(DstVreg);
6282 } else {
6283 Register LaneValueLoReg =
6284 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6285 Register LaneValueHiReg =
6286 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6287 auto [Op1L, Op1H] =
6288 ExtractSubRegs(MI, DestVregInst->getOperand(0), VregRC, ST, MRI);
6289 // lane value input should be in an sgpr
6290 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6291 LaneValueLoReg)
6292 .addReg(Op1L);
6293 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6294 LaneValueHiReg)
6295 .addReg(Op1H);
6296 NewAccumulator =
6297 BuildRegSequence(BB, MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6298 }
6299 }
6300 }
6301 RetBB = &BB;
6302 }
6303 }
6304 } else {
6306 Register SrcReg = MI.getOperand(1).getReg();
6307 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6309 bool NeedsMovDPP = !is32BitOpc;
6310 // Create virtual registers required for lowering.
6311 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
6312 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
6313 const TargetRegisterClass *SrcRegClass = MRI.getRegClass(SrcReg);
6314 bool IsWave32 = ST.isWave32();
6315 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6316 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6317 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6318 !ST.hasDPP()) { // If target doesn't support DPP operations, default to
6319 // iterative stratergy
6320
6321 // To reduce the VGPR using iterative approach, we need to iterate
6322 // over all the active lanes. Lowering consists of ComputeLoop,
6323 // which iterate over only active lanes. We use copy of EXEC register
6324 // as induction variable and every active lane modifies it using bitset0
6325 // so that we will get the next active lane for next iteration.
6326
6327 // Create Control flow for loop
6328 // Split MI's Machine Basic block into For loop
6329 auto [ComputeLoop, ComputeEnd] = splitBlockForLoop(MI, BB, true);
6330
6331 Register LoopIterator = MRI.createVirtualRegister(WaveMaskRegClass);
6332 Register IdentityValReg = MRI.createVirtualRegister(DstRegClass);
6333 Register AccumulatorReg = MRI.createVirtualRegister(DstRegClass);
6334 Register ActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6335 Register NewActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6336 Register FF1Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6337 Register LaneValueReg = MRI.createVirtualRegister(DstRegClass);
6338
6339 // Create initial values of induction variable from Exec, Accumulator and
6340 // insert branch instr to newly created ComputeBlock
6341 BuildMI(BB, I, DL, TII->get(MovOpcForExec), LoopIterator).addReg(ExecReg);
6342 uint64_t IdentityValue =
6343 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6344 ? 0x0 // +0.0 for double sub reduction
6346 BuildMI(BB, I, DL,
6347 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6348 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6349 IdentityValReg)
6350 .addImm(IdentityValue);
6351 // clang-format off
6352 BuildMI(BB, I, DL, TII->get(AMDGPU::S_BRANCH))
6353 .addMBB(ComputeLoop);
6354 // clang-format on
6355
6356 // Start constructing ComputeLoop
6357 I = ComputeLoop->begin();
6358 auto Accumulator =
6359 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), AccumulatorReg)
6360 .addReg(IdentityValReg)
6361 .addMBB(&BB);
6362 auto ActiveBits =
6363 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), ActiveBitsReg)
6364 .addReg(LoopIterator)
6365 .addMBB(&BB);
6366
6367 I = ComputeLoop->end();
6368 MachineInstr *NewAccumulator;
6369 // Perform the computations
6370 unsigned SFFOpc =
6371 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6372 BuildMI(*ComputeLoop, I, DL, TII->get(SFFOpc), FF1Reg)
6373 .addReg(ActiveBitsReg);
6374 if (is32BitOpc) {
6375 Register OpDstReg = DstReg;
6376 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6377 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6378 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6379 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6380 bool hasClamp =
6381 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1;
6382 bool hasOpSel =
6383 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel) != -1;
6384 bool hasOMod =
6385 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1;
6386 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6387 LaneValueReg)
6388 .addReg(SrcReg)
6389 .addReg(FF1Reg);
6390 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6391 // Get the Lane Value in VGPR to avoid the Constant Bus Restriction
6392 Register LaneValVgpr = MRI.createVirtualRegister(SrcRegClass);
6393 Register VgprResultReg = MRI.createVirtualRegister(SrcRegClass);
6394 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), LaneValVgpr)
6395 .addReg(LaneValueReg);
6396 OpDstReg = VgprResultReg;
6397 LaneValueReg = LaneValVgpr;
6398 }
6399 auto OpInstr = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), OpDstReg);
6400 if (hasSrc0Modifier)
6401 OpInstr.addImm(SISrcMods::NONE); // src0 modifier
6402 OpInstr.addReg(AccumulatorReg); // src0
6403 if (hasSrc1Modifier)
6404 OpInstr.addImm(SISrcMods::NONE); // src1 modifier
6405 OpInstr.addReg(LaneValueReg); // src1
6406 if (hasClamp)
6407 OpInstr.addImm(0); // clamp
6408 if (hasOpSel)
6409 OpInstr.addImm(0); // opsel
6410 if (hasOMod)
6411 OpInstr.addImm(0); // omod
6412 if (TII->isSALU(Opc))
6413 OpInstr.setOperandDead(3); // Dead scc
6414 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6415 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6416 DstReg)
6417 .addReg(OpDstReg);
6418 }
6419 } else {
6420 Register LaneValueLoReg =
6421 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6422 Register LaneValueHiReg =
6423 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6424 Register LaneValReg =
6425 MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
6426 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6427 MRI.getRegClass(SrcReg), ST, MRI);
6428 // lane value input should be in an sgpr
6429 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6430 LaneValueLoReg)
6431 .addReg(Op1L)
6432 .addReg(FF1Reg);
6433 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6434 LaneValueHiReg)
6435 .addReg(Op1H)
6436 .addReg(FF1Reg);
6437 auto LaneValue = BuildRegSequence(*ComputeLoop, I, LaneValReg,
6438 LaneValueLoReg, LaneValueHiReg);
6439 switch (Opc) {
6440 case AMDGPU::S_OR_B64:
6441 case AMDGPU::S_AND_B64:
6442 case AMDGPU::S_XOR_B64: {
6443 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6444 .addReg(Accumulator->getOperand(0).getReg())
6445 .addReg(LaneValue->getOperand(0).getReg())
6446 .setOperandDead(3); // Dead scc
6447 break;
6448 }
6449 case AMDGPU::V_CMP_GT_I64_e64:
6450 case AMDGPU::V_CMP_GT_U64_e64:
6451 case AMDGPU::V_CMP_LT_I64_e64:
6452 case AMDGPU::V_CMP_LT_U64_e64: {
6453 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6454 Register ComparisonResultReg =
6455 MRI.createVirtualRegister(WaveMaskRegClass);
6456 int SrcIdx =
6457 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6458 const TargetRegisterClass *VregClass =
6459 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6460 Register AccumulatorVReg = MRI.createVirtualRegister(VregClass);
6461 auto [SrcReg0Sub0, SrcReg0Sub1] = ExtractSubRegs(
6462 MI, Accumulator->getOperand(0), VregClass, ST, MRI);
6463 BuildRegSequence(*ComputeLoop, I, AccumulatorVReg, SrcReg0Sub0,
6464 SrcReg0Sub1);
6465 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), LaneMaskReg)
6466 .addReg(LaneValue->getOperand(0).getReg())
6467 .addReg(AccumulatorVReg);
6468
6469 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6470 BuildMI(*ComputeLoop, I, DL, TII->get(AndOpc), ComparisonResultReg)
6471 .addReg(LaneMaskReg)
6472 .addReg(ActiveBitsReg);
6473
6474 NewAccumulator = BuildMI(*ComputeLoop, I, DL,
6475 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6476 .addReg(LaneValue->getOperand(0).getReg())
6477 .addReg(Accumulator->getOperand(0).getReg());
6478 break;
6479 }
6480 case AMDGPU::V_MIN_F64_e64:
6481 case AMDGPU::V_MIN_NUM_F64_e64:
6482 case AMDGPU::V_MAX_F64_e64:
6483 case AMDGPU::V_MAX_NUM_F64_e64:
6484 case AMDGPU::V_ADD_F64_e64:
6485 case AMDGPU::V_ADD_F64_pseudo_e64: {
6486 int SrcIdx =
6487 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6488 const TargetRegisterClass *VregRC =
6489 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6490 Register AccumulatorVReg = MRI.createVirtualRegister(VregRC);
6491 Register DstVreg = MRI.createVirtualRegister(VregRC);
6492 Register LaneValLo =
6493 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6494 Register LaneValHi =
6495 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6496 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), AccumulatorVReg)
6497 .addReg(Accumulator->getOperand(0).getReg());
6498 unsigned Modifier =
6499 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6502 auto DstVregInst =
6503 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstVreg)
6504 .addImm(Modifier) // src0 modifiers
6505 .addReg(LaneValue->getOperand(0).getReg())
6506 .addImm(SISrcMods::NONE) // src1 modifiers
6507 .addReg(AccumulatorVReg)
6508 .addImm(SISrcMods::NONE) // clamp
6509 .addImm(SISrcMods::NONE); // omod
6510 auto ReadLaneLo =
6511 BuildMI(*ComputeLoop, I, DL,
6512 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6513 auto ReadLaneHi =
6514 BuildMI(*ComputeLoop, I, DL,
6515 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6516 MachineBasicBlock::iterator Iters = *ReadLaneLo;
6517 auto [Op1L, Op1H] = ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6518 VregRC, ST, MRI);
6519 ReadLaneLo.addReg(Op1L);
6520 ReadLaneHi.addReg(Op1H);
6521 NewAccumulator =
6522 BuildRegSequence(*ComputeLoop, I, DstReg, LaneValLo, LaneValHi);
6523 break;
6524 }
6525 case AMDGPU::S_ADD_U64_PSEUDO:
6526 case AMDGPU::S_SUB_U64_PSEUDO: {
6527 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6528 .addReg(Accumulator->getOperand(0).getReg())
6529 .addReg(LaneValue->getOperand(0).getReg())
6530 .setOperandDead(3); // Dead scc
6531 ComputeLoop =
6532 expand64BitScalarArithmetic(*NewAccumulator, ComputeLoop);
6533 break;
6534 }
6535 }
6536 }
6537 // Manipulate the iterator to get the next active lane
6538 unsigned BITSETOpc =
6539 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6540 BuildMI(*ComputeLoop, I, DL, TII->get(BITSETOpc), NewActiveBitsReg)
6541 .addReg(FF1Reg)
6542 .addReg(ActiveBitsReg);
6543
6544 // Add phi nodes
6545 Accumulator.addReg(DstReg).addMBB(ComputeLoop);
6546 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6547
6548 // Creating branching
6549 MachineInstrBuilder SetSCCInstr;
6550 if (!ST.hasScalarCompareEq64()) {
6551 // For targets <= gfx7, use an S_OR_B32/B64 instruction to set SCC.
6552 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6553 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6554 SetSCCInstr =
6555 BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc), LaneMaskReg);
6556 } else {
6557 unsigned CMPOpc =
6558 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6559 SetSCCInstr = BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc));
6560 }
6561 SetSCCInstr.addReg(NewActiveBitsReg);
6562 if (ST.hasScalarCompareEq64())
6563 SetSCCInstr.addImm(0);
6564 else
6565 SetSCCInstr.addReg(NewActiveBitsReg);
6566 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
6567 .addMBB(ComputeLoop);
6568
6569 RetBB = ComputeEnd;
6570 } else {
6571 assert(ST.hasDPP() && "Sub Target does not support DPP Operations");
6572 MachineBasicBlock *CurrBB = &BB;
6573 Register SrcWithIdentity = MRI.createVirtualRegister(SrcRegClass);
6574 Register IdentityVGPR = MRI.createVirtualRegister(SrcRegClass);
6575 Register IdentitySGPR = MRI.createVirtualRegister(DstRegClass);
6576 Register DPPRowShr1 = MRI.createVirtualRegister(SrcRegClass);
6577 Register DPPRowShr2 = MRI.createVirtualRegister(SrcRegClass);
6578 Register DPPRowShr4 = MRI.createVirtualRegister(SrcRegClass);
6579 Register DPPRowShr8 = MRI.createVirtualRegister(SrcRegClass);
6580 Register RowBcast15 = MRI.createVirtualRegister(SrcRegClass);
6581 Register ReducedValSGPR = MRI.createVirtualRegister(DstRegClass);
6582 Register NegatedReducedVal = MRI.createVirtualRegister(DstRegClass);
6583 Register RowBcast31 = MRI.createVirtualRegister(SrcRegClass);
6584 Register UndefExec = MRI.createVirtualRegister(WaveMaskRegClass);
6585 Register FinalDPPResult;
6586 MachineInstr *SrcWithIdentityInstr;
6587 MachineInstr *LastBcastInstr;
6588 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6589
6591 BuildMI(*CurrBB, MI, DL,
6592 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6593 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6594 IdentitySGPR)
6595 .addImm(IdentityValue);
6596 auto IdentityCopyInstr =
6597 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::COPY), IdentityVGPR)
6598 .addReg(IdentitySGPR);
6599 unsigned DPPOpc, ClampOpc;
6600 std::tie(DPPOpc, ClampOpc) = getDPPOpcForWaveReduction(Opc, ST);
6601 auto BuildSetInactiveInstr = [&](Register Dst, Register Src0,
6602 Register Src1) {
6603 return BuildMI(BB, MI, DL, TII->get(AMDGPU::V_SET_INACTIVE_B32),
6604 Dst)
6605 .addImm(0) // src0 modifiers
6606 .addReg(Src0) // src0
6607 .addImm(0) // src1 modifiers
6608 .addReg(Src1) // identity value for inactive lanes
6609 .addReg(UndefExec); // bool i1
6610 };
6611 auto BuildDPPMachineInstr = [&](Register Dst, Register Src,
6612 unsigned DPPCtrl) {
6613 auto DPPInstr =
6614 BuildMI(*CurrBB, MI, DL, TII->get(DPPOpc), Dst).addReg(Src); // old
6615 if (isFPOp && !NeedsMovDPP)
6616 DPPInstr.addImm(SISrcMods::NONE); // src0 modifier
6617 DPPInstr.addReg(Src); // src0
6618 if (isFPOp && !NeedsMovDPP)
6619 DPPInstr.addImm(SISrcMods::NONE); // src1 modifier
6620 if (!NeedsMovDPP)
6621 DPPInstr.addReg(Src); // src1
6622 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6623 DPPInstr.addImm(0); // clamp
6624 DPPInstr
6625 .addImm(DPPCtrl) // dpp-ctrl
6626 .addImm(0xf) // row-mask
6627 .addImm(0xf) // bank-mask
6628 .addImm(0); // bound-control
6629 };
6630 auto BuildClampInstr = [&](Register Dst, Register Src0, Register Src1,
6631 bool isAddSub = false,
6632 bool needsCarryIn = false,
6633 Register CarryIn = Register()) {
6634 unsigned InstrOpc = ClampOpc;
6635 Register CarryOutReg = MRI.createVirtualRegister(WaveMaskRegClass);
6636 if (needsCarryIn)
6637 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6638 auto ClampInstr = BuildMI(*CurrBB, MI, DL, TII->get(InstrOpc), Dst);
6639 if (isFPOp)
6640 ClampInstr.addImm(SISrcMods::NONE); // src0 mod
6641 if (isAddSub) {
6642 if (needsCarryIn)
6643 ClampInstr.addReg(CarryOutReg,
6645 RegState::Dead); // killed carry-out reg
6646 else
6647 ClampInstr.addReg(CarryOutReg, RegState::Define); // carry-out reg
6648 }
6649 ClampInstr.addReg(Src0); // src0
6650 if (isFPOp)
6651 ClampInstr.addImm(SISrcMods::NONE); // src1 mod
6652 ClampInstr.addReg(Src1); // src1
6653 if (needsCarryIn)
6654 ClampInstr.addReg(CarryIn); // carry-in reg
6655 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6656 ClampInstr.addImm(0); // clamp
6657 if (isFPOp)
6658 ClampInstr.addImm(0); // omod
6659 LastBcastInstr = ClampInstr;
6660 return CarryOutReg;
6661 };
6662 auto BuildPostDPPInstr = [&](Register Src0, Register Src1) {
6663 bool isAddSubOpc =
6664 Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO;
6665 bool isBitWiseOpc = Opc == AMDGPU::S_AND_B64 ||
6666 Opc == AMDGPU::S_OR_B64 || Opc == AMDGPU::S_XOR_B64;
6667 Register ReturnReg = MRI.createVirtualRegister(SrcRegClass);
6668 if (isAddSubOpc || isBitWiseOpc) {
6669 Register ResLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6670 Register ResHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6671 MachineOperand Src0Operand =
6672 MachineOperand::CreateReg(Src0, /*isDef=*/false);
6673 MachineOperand Src1Operand =
6674 MachineOperand::CreateReg(Src1, /*isDef=*/false);
6675 auto [Src0Lo, Src0Hi] =
6676 ExtractSubRegs(MI, Src0Operand, SrcRegClass, ST, MRI);
6677 auto [Src1Lo, Src1Hi] =
6678 ExtractSubRegs(MI, Src1Operand, SrcRegClass, ST, MRI);
6679 Register CarryReg = BuildClampInstr(
6680 ResLo, Src0Lo, Src1Lo, isAddSubOpc, /*needsCarryIn*/ false);
6681 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6682 /*needsCarryIn*/ isAddSubOpc, CarryReg);
6683 BuildRegSequence(*CurrBB, MI, ReturnReg, ResLo, ResHi);
6684 } else {
6685 if (isFPOp) {
6686 BuildMI(*CurrBB, MI, DL, TII->get(Opc), ReturnReg)
6687 .addImm(SISrcMods::NONE) // src0 modifiers
6688 .addReg(Src0)
6689 .addImm(SISrcMods::NONE) // src1 modifiers
6690 .addReg(Src1)
6691 .addImm(SISrcMods::NONE) // clamp
6692 .addImm(SISrcMods::NONE); // omod
6693 } else {
6694 Register CmpMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6695 BuildMI(*CurrBB, MI, DL, TII->get(Opc), CmpMaskReg)
6696 .addReg(Src0) // src0
6697 .addReg(Src1); // src1
6698 LastBcastInstr =
6699 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B64_PSEUDO),
6700 ReturnReg)
6701 .addReg(Src1) // src0
6702 .addReg(Src0) // src1
6703 .addReg(CmpMaskReg); // src2
6704 expand64BitV_CNDMASK(*LastBcastInstr, CurrBB);
6705 }
6706 }
6707 return ReturnReg;
6708 };
6709
6710 // Set inactive lanes to the identity value.
6711 if (is32BitOpc) {
6712 SrcWithIdentityInstr =
6713 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6714 } else {
6715 Register SrcWithIdentitylo =
6716 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6717 Register SrcWithIdentityhi =
6718 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6719 auto [Reg0Sub0, Reg0Sub1] = ExtractSubRegs(
6720 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST, MRI);
6721 auto [SrcReg0Sub0, SrcReg0Sub1] =
6722 ExtractSubRegs(MI, MI.getOperand(1), SrcRegClass, ST, MRI);
6723 MachineInstr *SetInactiveLoInstr =
6724 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6725 MachineInstr *SetInactiveHiInstr =
6726 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6727 SrcWithIdentityInstr =
6728 BuildRegSequence(*CurrBB, MI, SrcWithIdentity,
6729 SetInactiveLoInstr->getOperand(0).getReg(),
6730 SetInactiveHiInstr->getOperand(0).getReg());
6731 }
6732 // DPP reduction
6733 Register SrcWithIdentityReg =
6734 SrcWithIdentityInstr->getOperand(0).getReg();
6735 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6737 if (NeedsMovDPP)
6738 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6739
6740 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6742 if (NeedsMovDPP)
6743 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6744
6745 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6747 if (NeedsMovDPP)
6748 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6749
6750 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6752 if (NeedsMovDPP)
6753 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6754
6755 if (ST.hasDPPBroadcasts()) {
6756 BuildDPPMachineInstr(RowBcast15, DPPRowShr8, AMDGPU::DPP::BCAST15);
6757 if (NeedsMovDPP)
6758 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6759 } else {
6760 // magic constant: 0x1E0
6761 // To Set BIT_MODE : bit 15 = 0
6762 // XOR mask : bit [14:10] = 0
6763 // OR mask : bit [9:5] = 15
6764 // AND mask : bit [4:0] = 0
6765 if (is32BitOpc) {
6766 Register SwizzledValue =
6767 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6768 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6769 SwizzledValue)
6770 .addReg(DPPRowShr8) // addr
6771 .addImm(0x1E0) // swizzle offset (i16)
6772 .addImm(0x0); // gds (i1)
6773 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6774 } else {
6775 Register SwizzledValuelo =
6776 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6777 Register SwizzledValuehi =
6778 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6779 Register SwizzledValue64 = MRI.createVirtualRegister(SrcRegClass);
6780 MachineOperand DPPRowShr8Op =
6781 MachineOperand::CreateReg(DPPRowShr8, /*isDef=*/false);
6782 auto [Op1L, Op1H] =
6783 ExtractSubRegs(MI, DPPRowShr8Op, SrcRegClass, ST, MRI);
6784 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6785 SwizzledValuelo)
6786 .addReg(Op1L) // addr
6787 .addImm(0x1E0) // swizzle offset (i16)
6788 .addImm(0x0); // gds (i1)
6789 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6790 SwizzledValuehi)
6791 .addReg(Op1H) // addr
6792 .addImm(0x1E0) // swizzle offset (i16)
6793 .addImm(0x0); // gds (i1)
6794 BuildRegSequence(*CurrBB, MI, SwizzledValue64, SwizzledValuelo,
6795 SwizzledValuehi);
6796 if (NeedsMovDPP)
6797 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6798 else
6799 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6800 }
6801 }
6802 FinalDPPResult = RowBcast15;
6803 if (!IsWave32) {
6804 if (ST.hasDPPBroadcasts()) {
6805 BuildDPPMachineInstr(RowBcast31, RowBcast15, AMDGPU::DPP::BCAST31);
6806 if (NeedsMovDPP)
6807 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6808 } else {
6809 Register ShiftedThreadID =
6810 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6811 Register PermuteByteOffset =
6812 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6813 Register PermutedValue = MRI.createVirtualRegister(SrcRegClass);
6814 Register Lane32Offset =
6815 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6816 Register WordSizeConst =
6817 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6818 Register ThreadIDRegLo =
6819 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6820 Register ThreadIDReg =
6821 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6822 // Get the thread ID.
6823 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6824 ThreadIDRegLo)
6825 .addImm(-1)
6826 .addImm(0);
6827 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6828 ThreadIDReg)
6829 .addImm(-1)
6830 .addReg(ThreadIDRegLo);
6831 // shift each lane over by 32 positions, so value in 31st lane is
6832 // present in 63rd lane.
6833 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6834 .addImm(0x20);
6835 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_ADD_U32_e64),
6836 ShiftedThreadID)
6837 .addReg(ThreadIDReg)
6838 .addReg(Lane32Offset)
6839 .addImm(0); // clamp
6840 // multiply by reg size.
6841 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6842 .addImm(0x4);
6843 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MUL_LO_U32_e64),
6844 PermuteByteOffset)
6845 .addReg(WordSizeConst)
6846 .addReg(ShiftedThreadID);
6847 // Permute the lanes
6848 if (is32BitOpc) {
6849 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6850 PermutedValue)
6851 .addReg(PermuteByteOffset) // addr
6852 .addReg(RowBcast15) // data
6853 .addImm(0); // offset
6854 } else {
6855 Register PermutedValuelo =
6856 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6857 Register PermutedValuehi =
6858 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6859 MachineOperand RowBcast15Op =
6860 MachineOperand::CreateReg(RowBcast15, /*isDef=*/false);
6861 auto [RowBcast15Lo, RowBcast15Hi] =
6862 ExtractSubRegs(MI, RowBcast15Op, SrcRegClass, ST, MRI);
6863 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6864 PermutedValuelo)
6865 .addReg(PermuteByteOffset) // addr
6866 .addReg(RowBcast15Lo) // swizzle offset (i16)
6867 .addImm(0x0); // gds (i1)
6868 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6869 PermutedValuehi)
6870 .addReg(PermuteByteOffset) // addr
6871 .addReg(RowBcast15Hi) // swizzle offset (i16)
6872 .addImm(0x0); // gds (i1)
6873 BuildRegSequence(*CurrBB, MI, PermutedValue, PermutedValuelo,
6874 PermutedValuehi);
6875 }
6876 if (NeedsMovDPP)
6877 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6878 else
6879 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6880 }
6881 FinalDPPResult = RowBcast31;
6882 }
6883 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6884 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6885 Register NegatedValVGPR = MRI.createVirtualRegister(SrcRegClass);
6886 // Opc for f32 reduction is V_SUB_F32.
6887 // For f64, there is no equivalent V_SUB_F64 opcode, so use
6888 // V_ADD_F64/V_ADD_F64_pseudo, and negate the second operand.
6889 BuildMI(*CurrBB, MI, DL, TII->get(Opc),
6890 NegatedValVGPR)
6891 .addImm(SISrcMods::NONE) // src0 mods
6892 .addReg(IdentityVGPR) // src0
6893 .addImm(is32BitOpc ? SISrcMods::NONE : SISrcMods::NEG) // src1 mods
6894 .addReg(IsWave32 ? RowBcast15 : RowBcast31) // src1
6895 .addImm(SISrcMods::NONE) // clamp
6896 .addImm(SISrcMods::NONE); // omod
6897 FinalDPPResult = NegatedValVGPR;
6898 }
6899 // The final reduced value is in the last lane.
6900 if (is32BitOpc) {
6901 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6902 ReducedValSGPR)
6903 .addReg(FinalDPPResult)
6904 .addImm(ST.getWavefrontSize() - 1);
6905 } else {
6906 Register LaneValueLoReg =
6907 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6908 Register LaneValueHiReg =
6909 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6910 const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
6911 MachineOperand FinalDPPResultOperand =
6912 MachineOperand::CreateReg(FinalDPPResult, /*isDef=*/false);
6913 auto [Op1L, Op1H] =
6914 ExtractSubRegs(MI, FinalDPPResultOperand, SrcRC, ST, MRI);
6915 // lane value input should be in an sgpr
6916 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6917 LaneValueLoReg)
6918 .addReg(Op1L)
6919 .addImm(ST.getWavefrontSize() - 1);
6920 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6921 LaneValueHiReg)
6922 .addReg(Op1H)
6923 .addImm(ST.getWavefrontSize() - 1);
6924 BuildRegSequence(*CurrBB, MI, ReducedValSGPR, LaneValueLoReg,
6925 LaneValueHiReg);
6926 }
6927 if (Opc == AMDGPU::S_SUB_I32) {
6928 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6929 .addImm(0)
6930 .addReg(ReducedValSGPR)
6931 .setOperandDead(3); // Dead scc
6932 } else if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6933 auto NegatedValInstr =
6934 BuildMI(*CurrBB, MI, DL, TII->get(Opc), NegatedReducedVal)
6935 .addImm(0)
6936 .addReg(ReducedValSGPR)
6937 .setOperandDead(3); // Dead scc
6938 CurrBB = expand64BitScalarArithmetic(*NegatedValInstr, CurrBB);
6939 }
6940 // Mark the final result as a whole-wave-mode calculation.
6941 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::STRICT_WWM), DstReg)
6942 .addReg(Opc == AMDGPU::S_SUB_I32 || Opc == AMDGPU::S_SUB_U64_PSEUDO
6943 ? NegatedReducedVal
6944 : ReducedValSGPR);
6945 RetBB = CurrBB;
6946 }
6947 }
6948 MI.eraseFromParent();
6949 return RetBB;
6950}
6951
6954 MachineBasicBlock *BB) const {
6955 MachineFunction *MF = BB->getParent();
6957 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
6959 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
6961 const DebugLoc &DL = MI.getDebugLoc();
6962
6963 switch (MI.getOpcode()) {
6964 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6965 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_U32);
6966 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6967 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_U64_e64);
6968 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6969 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_I32);
6970 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6971 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_I64_e64);
6972 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6973 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MIN_F32_e64);
6974 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6975 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6976 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6977 ? AMDGPU::V_MIN_NUM_F64_e64
6978 : AMDGPU::V_MIN_F64_e64);
6979 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6980 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_U32);
6981 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6982 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_U64_e64);
6983 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6984 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_I32);
6985 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6986 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_I64_e64);
6987 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6988 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MAX_F32_e64);
6989 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6990 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6991 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6992 ? AMDGPU::V_MAX_NUM_F64_e64
6993 : AMDGPU::V_MAX_F64_e64);
6994 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6995 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_I32);
6996 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6997 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_U64_PSEUDO);
6998 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6999 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_ADD_F32_e64);
7000 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
7001 return lowerWaveReduce(MI, *BB, *getSubtarget(),
7002 ST.getGeneration() >= AMDGPUSubtarget::GFX12
7003 ? AMDGPU::V_ADD_F64_pseudo_e64
7004 : AMDGPU::V_ADD_F64_e64);
7005 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
7006 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_I32);
7007 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
7008 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_U64_PSEUDO);
7009 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
7010 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_SUB_F32_e64);
7011 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
7012 // There is no S/V_SUB_F64 opcode. Double type subtraction is expanded as
7013 // fadd + neg, by setting the NEG bit in the instruction.
7014 return lowerWaveReduce(MI, *BB, *getSubtarget(),
7015 ST.getGeneration() >= AMDGPUSubtarget::GFX12
7016 ? AMDGPU::V_ADD_F64_pseudo_e64
7017 : AMDGPU::V_ADD_F64_e64);
7018 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
7019 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B32);
7020 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
7021 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B64);
7022 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
7023 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B32);
7024 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
7025 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B64);
7026 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
7027 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B32);
7028 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
7029 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B64);
7030 case AMDGPU::S_UADDO_PSEUDO:
7031 case AMDGPU::S_USUBO_PSEUDO: {
7032 MachineOperand &Dest0 = MI.getOperand(0);
7033 MachineOperand &Dest1 = MI.getOperand(1);
7034 MachineOperand &Src0 = MI.getOperand(2);
7035 MachineOperand &Src1 = MI.getOperand(3);
7036
7037 unsigned Opc = (MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
7038 ? AMDGPU::S_ADD_U32
7039 : AMDGPU::S_SUB_U32;
7040 // clang-format off
7041 BuildMI(*BB, MI, DL, TII->get(Opc), Dest0.getReg())
7042 .add(Src0)
7043 .add(Src1);
7044 // clang-format on
7045
7046 unsigned SelOpc =
7047 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7048 BuildMI(*BB, MI, DL, TII->get(SelOpc), Dest1.getReg()).addImm(-1).addImm(0);
7049
7050 MI.eraseFromParent();
7051 return BB;
7052 }
7053 case AMDGPU::S_ADD_U64_PSEUDO:
7054 case AMDGPU::S_SUB_U64_PSEUDO: {
7055 return expand64BitScalarArithmetic(MI, BB);
7056 }
7057 case AMDGPU::V_ADD_U64_PSEUDO:
7058 case AMDGPU::V_SUB_U64_PSEUDO: {
7059 bool IsAdd = (MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
7060
7061 MachineOperand &Dest = MI.getOperand(0);
7062 MachineOperand &Src0 = MI.getOperand(1);
7063 MachineOperand &Src1 = MI.getOperand(2);
7064
7065 if (ST.hasAddSubU64Insts()) {
7066 auto I = BuildMI(*BB, MI, DL,
7067 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
7068 : AMDGPU::V_SUB_U64_e64),
7069 Dest.getReg())
7070 .add(Src0)
7071 .add(Src1)
7072 .addImm(0); // clamp
7073 TII->legalizeOperands(*I);
7074 MI.eraseFromParent();
7075 return BB;
7076 }
7077
7078 if (IsAdd && ST.hasLshlAddU64Inst()) {
7079 auto Add = BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_LSHL_ADD_U64_e64),
7080 Dest.getReg())
7081 .add(Src0)
7082 .addImm(0)
7083 .add(Src1);
7084 TII->legalizeOperands(*Add);
7085 MI.eraseFromParent();
7086 return BB;
7087 }
7088
7089 const auto *CarryRC = TRI->getWaveMaskRegClass();
7090
7091 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7092 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7093
7094 Register CarryReg = MRI.createVirtualRegister(CarryRC);
7095 Register DeadCarryReg = MRI.createVirtualRegister(CarryRC);
7096
7097 const TargetRegisterClass *Src0RC = Src0.isReg()
7098 ? MRI.getRegClass(Src0.getReg())
7099 : &AMDGPU::VReg_64RegClass;
7100 const TargetRegisterClass *Src1RC = Src1.isReg()
7101 ? MRI.getRegClass(Src1.getReg())
7102 : &AMDGPU::VReg_64RegClass;
7103
7104 const TargetRegisterClass *Src0SubRC =
7105 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
7106 const TargetRegisterClass *Src1SubRC =
7107 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
7108
7109 MachineOperand SrcReg0Sub0 = TII->buildExtractSubRegOrImm(
7110 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
7111 MachineOperand SrcReg1Sub0 = TII->buildExtractSubRegOrImm(
7112 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
7113
7114 MachineOperand SrcReg0Sub1 = TII->buildExtractSubRegOrImm(
7115 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
7116 MachineOperand SrcReg1Sub1 = TII->buildExtractSubRegOrImm(
7117 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
7118
7119 unsigned LoOpc =
7120 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
7121 MachineInstr *LoHalf = BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0)
7122 .addReg(CarryReg, RegState::Define)
7123 .add(SrcReg0Sub0)
7124 .add(SrcReg1Sub0)
7125 .addImm(0); // clamp bit
7126
7127 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7128 MachineInstr *HiHalf =
7129 BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1)
7130 .addReg(DeadCarryReg, RegState::Define | RegState::Dead)
7131 .add(SrcReg0Sub1)
7132 .add(SrcReg1Sub1)
7133 .addReg(CarryReg)
7134 .addImm(0); // clamp bit
7135
7136 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
7137 .addReg(DestSub0)
7138 .addImm(AMDGPU::sub0)
7139 .addReg(DestSub1)
7140 .addImm(AMDGPU::sub1);
7141 TII->legalizeOperands(*LoHalf);
7142 TII->legalizeOperands(*HiHalf);
7143 MI.eraseFromParent();
7144 return BB;
7145 }
7146 case AMDGPU::S_ADD_CO_PSEUDO:
7147 case AMDGPU::S_SUB_CO_PSEUDO: {
7148 // This pseudo has a chance to be selected
7149 // only from uniform add/subcarry node. All the VGPR operands
7150 // therefore assumed to be splat vectors.
7152 MachineOperand &Dest = MI.getOperand(0);
7153 MachineOperand &CarryDest = MI.getOperand(1);
7154 MachineOperand &Src0 = MI.getOperand(2);
7155 MachineOperand &Src1 = MI.getOperand(3);
7156 MachineOperand &Src2 = MI.getOperand(4);
7157 if (Src0.isReg() && TRI->isVectorRegister(MRI, Src0.getReg())) {
7158 Register RegOp0 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7159 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7160 .addReg(Src0.getReg());
7161 Src0.setReg(RegOp0);
7162 }
7163 if (Src1.isReg() && TRI->isVectorRegister(MRI, Src1.getReg())) {
7164 Register RegOp1 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7165 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7166 .addReg(Src1.getReg());
7167 Src1.setReg(RegOp1);
7168 }
7169 Register RegOp2 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7170 if (TRI->isVectorRegister(MRI, Src2.getReg())) {
7171 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7172 .addReg(Src2.getReg());
7173 Src2.setReg(RegOp2);
7174 }
7175
7176 if (ST.isWave64()) {
7177 if (ST.hasScalarCompareEq64()) {
7178 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U64))
7179 .addReg(Src2.getReg())
7180 .addImm(0);
7181 } else {
7182 const TargetRegisterClass *Src2RC = MRI.getRegClass(Src2.getReg());
7183 const TargetRegisterClass *SubRC =
7184 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7185 MachineOperand Src2Sub0 = TII->buildExtractSubRegOrImm(
7186 MII, MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7187 MachineOperand Src2Sub1 = TII->buildExtractSubRegOrImm(
7188 MII, MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7189 Register Src2_32 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7190
7191 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_OR_B32), Src2_32)
7192 .add(Src2Sub0)
7193 .add(Src2Sub1);
7194
7195 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7196 .addReg(Src2_32)
7197 .addImm(0);
7198 }
7199 } else {
7200 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7201 .addReg(Src2.getReg())
7202 .addImm(0);
7203 }
7204
7205 unsigned Opc = MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7206 ? AMDGPU::S_ADDC_U32
7207 : AMDGPU::S_SUBB_U32;
7208
7209 BuildMI(*BB, MII, DL, TII->get(Opc), Dest.getReg()).add(Src0).add(Src1);
7210
7211 unsigned SelOpc =
7212 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7213
7214 BuildMI(*BB, MII, DL, TII->get(SelOpc), CarryDest.getReg())
7215 .addImm(-1)
7216 .addImm(0);
7217
7218 MI.eraseFromParent();
7219 return BB;
7220 }
7221 case AMDGPU::SI_INIT_M0: {
7222 MachineOperand &M0Init = MI.getOperand(0);
7223 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7224 TII->get(M0Init.isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7225 AMDGPU::M0)
7226 .add(M0Init);
7227 MI.eraseFromParent();
7228 return BB;
7229 }
7230 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7231 // Set SCC to true, in case the barrier instruction gets converted to a NOP.
7232 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7233 TII->get(AMDGPU::S_CMP_EQ_U32))
7234 .addImm(0)
7235 .addImm(0);
7236 return BB;
7237 }
7238 case AMDGPU::GET_GROUPSTATICSIZE: {
7239 assert(getTargetMachine().getTargetTriple().getOS() == Triple::AMDHSA ||
7240 getTargetMachine().getTargetTriple().getOS() == Triple::AMDPAL);
7241 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_MOV_B32))
7242 .add(MI.getOperand(0))
7243 .addImm(MFI->getLDSSize());
7244 MI.eraseFromParent();
7245 return BB;
7246 }
7247 case AMDGPU::GET_SHADERCYCLESHILO: {
7248 assert(MF->getSubtarget<GCNSubtarget>().hasShaderCyclesHiLoRegisters());
7249 // The algorithm is:
7250 //
7251 // hi1 = getreg(SHADER_CYCLES_HI)
7252 // lo1 = getreg(SHADER_CYCLES_LO)
7253 // hi2 = getreg(SHADER_CYCLES_HI)
7254 //
7255 // If hi1 == hi2 then there was no overflow and the result is hi2:lo1.
7256 // Otherwise there was overflow and the result is hi2:0. In both cases the
7257 // result should represent the actual time at some point during the sequence
7258 // of three getregs.
7259 using namespace AMDGPU::Hwreg;
7260 Register RegHi1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7261 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi1)
7262 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7263 Register RegLo1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7264 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegLo1)
7265 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7266 Register RegHi2 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7267 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi2)
7268 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7269 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CMP_EQ_U32))
7270 .addReg(RegHi1)
7271 .addReg(RegHi2);
7272 Register RegLo = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7273 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CSELECT_B32), RegLo)
7274 .addReg(RegLo1)
7275 .addImm(0);
7276 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE))
7277 .add(MI.getOperand(0))
7278 .addReg(RegLo)
7279 .addImm(AMDGPU::sub0)
7280 .addReg(RegHi2)
7281 .addImm(AMDGPU::sub1);
7282 MI.eraseFromParent();
7283 return BB;
7284 }
7285 case AMDGPU::SI_INDIRECT_SRC_V1:
7286 case AMDGPU::SI_INDIRECT_SRC_V2:
7287 case AMDGPU::SI_INDIRECT_SRC_V3:
7288 case AMDGPU::SI_INDIRECT_SRC_V4:
7289 case AMDGPU::SI_INDIRECT_SRC_V5:
7290 case AMDGPU::SI_INDIRECT_SRC_V6:
7291 case AMDGPU::SI_INDIRECT_SRC_V7:
7292 case AMDGPU::SI_INDIRECT_SRC_V8:
7293 case AMDGPU::SI_INDIRECT_SRC_V9:
7294 case AMDGPU::SI_INDIRECT_SRC_V10:
7295 case AMDGPU::SI_INDIRECT_SRC_V11:
7296 case AMDGPU::SI_INDIRECT_SRC_V12:
7297 case AMDGPU::SI_INDIRECT_SRC_V16:
7298 case AMDGPU::SI_INDIRECT_SRC_V32:
7299 return emitIndirectSrc(MI, *BB, *getSubtarget());
7300 case AMDGPU::SI_INDIRECT_DST_V1:
7301 case AMDGPU::SI_INDIRECT_DST_V2:
7302 case AMDGPU::SI_INDIRECT_DST_V3:
7303 case AMDGPU::SI_INDIRECT_DST_V4:
7304 case AMDGPU::SI_INDIRECT_DST_V5:
7305 case AMDGPU::SI_INDIRECT_DST_V6:
7306 case AMDGPU::SI_INDIRECT_DST_V7:
7307 case AMDGPU::SI_INDIRECT_DST_V8:
7308 case AMDGPU::SI_INDIRECT_DST_V9:
7309 case AMDGPU::SI_INDIRECT_DST_V10:
7310 case AMDGPU::SI_INDIRECT_DST_V11:
7311 case AMDGPU::SI_INDIRECT_DST_V12:
7312 case AMDGPU::SI_INDIRECT_DST_V16:
7313 case AMDGPU::SI_INDIRECT_DST_V32:
7314 return emitIndirectDst(MI, *BB, *getSubtarget());
7315 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7316 case AMDGPU::SI_KILL_I1_PSEUDO:
7317 return splitKillBlock(MI, BB);
7318 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7320 return BB;
7321 }
7322 case AMDGPU::SI_BR_UNDEF: {
7323 MachineInstr *Br = BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
7324 .add(MI.getOperand(0));
7325 Br->getOperand(1).setIsUndef(); // read undef SCC
7326 MI.eraseFromParent();
7327 return BB;
7328 }
7329 case AMDGPU::ADJCALLSTACKUP:
7330 case AMDGPU::ADJCALLSTACKDOWN: {
7332 MachineInstrBuilder MIB(*MF, &MI);
7333 MIB.addReg(Info->getStackPtrOffsetReg(), RegState::ImplicitDefine)
7334 .addReg(Info->getStackPtrOffsetReg(), RegState::Implicit);
7335 return BB;
7336 }
7337 case AMDGPU::SI_CALL_ISEL: {
7338 unsigned ReturnAddrReg = TII->getRegisterInfo().getReturnAddressReg(*MF);
7339
7341 MIB = BuildMI(*BB, MI, DL, TII->get(AMDGPU::SI_CALL))
7342 .addDef(ReturnAddrReg, RegState::Dead);
7343
7344 for (const MachineOperand &MO : MI.operands())
7345 MIB.add(MO);
7346
7347 MIB.cloneMemRefs(MI);
7348 MIB.setMIFlags(MI.getFlags());
7349 MI.eraseFromParent();
7350 return BB;
7351 }
7352 case AMDGPU::V_ADDC_U32_e32:
7353 case AMDGPU::V_SUBB_U32_e32:
7354 case AMDGPU::V_SUBBREV_U32_e32:
7355 // These instructions have an implicit use of vcc which counts towards the
7356 // constant bus limit.
7357 TII->legalizeOperands(MI);
7358 return BB;
7359 case AMDGPU::DS_GWS_INIT:
7360 case AMDGPU::DS_GWS_SEMA_BR:
7361 case AMDGPU::DS_GWS_BARRIER:
7362 case AMDGPU::DS_GWS_SEMA_V:
7363 case AMDGPU::DS_GWS_SEMA_P:
7364 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7365 // A s_waitcnt 0 is required to be the instruction immediately following.
7366 if (getSubtarget()->hasGWSAutoReplay()) {
7368 return BB;
7369 }
7370
7371 return emitGWSMemViolTestLoop(MI, BB);
7372 case AMDGPU::S_SETREG_B32: {
7373 // Try to optimize cases that only set the denormal mode or rounding mode.
7374 //
7375 // If the s_setreg_b32 fully sets all of the bits in the rounding mode or
7376 // denormal mode to a constant, we can use s_round_mode or s_denorm_mode
7377 // instead.
7378 //
7379 // FIXME: This could be predicates on the immediate, but tablegen doesn't
7380 // allow you to have a no side effect instruction in the output of a
7381 // sideeffecting pattern.
7382 auto [ID, Offset, Width] =
7383 AMDGPU::Hwreg::HwregEncoding::decode(MI.getOperand(1).getImm());
7384 if (ID != AMDGPU::Hwreg::ID_MODE)
7385 return BB;
7386
7387 const unsigned WidthMask = maskTrailingOnes<unsigned>(Width);
7388 const unsigned SetMask = WidthMask << Offset;
7389
7390 if (getSubtarget()->hasDenormModeInst()) {
7391 unsigned SetDenormOp = 0;
7392 unsigned SetRoundOp = 0;
7393
7394 // The dedicated instructions can only set the whole denorm or round mode
7395 // at once, not a subset of bits in either.
7396 if (SetMask ==
7398 // If this fully sets both the round and denorm mode, emit the two
7399 // dedicated instructions for these.
7400 SetRoundOp = AMDGPU::S_ROUND_MODE;
7401 SetDenormOp = AMDGPU::S_DENORM_MODE;
7402 } else if (SetMask == AMDGPU::Hwreg::FP_ROUND_MASK) {
7403 SetRoundOp = AMDGPU::S_ROUND_MODE;
7404 } else if (SetMask == AMDGPU::Hwreg::FP_DENORM_MASK) {
7405 SetDenormOp = AMDGPU::S_DENORM_MODE;
7406 }
7407
7408 if (SetRoundOp || SetDenormOp) {
7409 MachineInstr *Def = MRI.getVRegDef(MI.getOperand(0).getReg());
7410 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7411 unsigned ImmVal = Def->getOperand(1).getImm();
7412 if (SetRoundOp) {
7413 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetRoundOp))
7414 .addImm(ImmVal & 0xf);
7415
7416 // If we also have the denorm mode, get just the denorm mode bits.
7417 ImmVal >>= 4;
7418 }
7419
7420 if (SetDenormOp) {
7421 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetDenormOp))
7422 .addImm(ImmVal & 0xf);
7423 }
7424
7425 MI.eraseFromParent();
7426 return BB;
7427 }
7428 }
7429 }
7430
7431 // If only FP bits are touched, used the no side effects pseudo.
7432 if ((SetMask & (AMDGPU::Hwreg::FP_ROUND_MASK |
7433 AMDGPU::Hwreg::FP_DENORM_MASK)) == SetMask)
7434 MI.setDesc(TII->get(AMDGPU::S_SETREG_B32_mode));
7435
7436 return BB;
7437 }
7438 case AMDGPU::S_INVERSE_BALLOT_U32:
7439 case AMDGPU::S_INVERSE_BALLOT_U64:
7440 // These opcodes only exist to let SIFixSGPRCopies insert a readfirstlane if
7441 // necessary. After that they are equivalent to a COPY.
7442 MI.setDesc(TII->get(AMDGPU::COPY));
7443 return BB;
7444 case AMDGPU::ENDPGM_TRAP: {
7445 if (BB->succ_empty() && std::next(MI.getIterator()) == BB->end()) {
7446 MI.setDesc(TII->get(AMDGPU::S_ENDPGM));
7447 MI.addOperand(MachineOperand::CreateImm(0));
7448 return BB;
7449 }
7450
7451 // We need a block split to make the real endpgm a terminator. We also don't
7452 // want to break phis in successor blocks, so we can't just delete to the
7453 // end of the block.
7454
7455 MachineBasicBlock *SplitBB = BB->splitAt(MI, false /*UpdateLiveIns*/);
7457 MF->push_back(TrapBB);
7458 // clang-format off
7459 BuildMI(*TrapBB, TrapBB->end(), DL, TII->get(AMDGPU::S_ENDPGM))
7460 .addImm(0);
7461 BuildMI(*BB, &MI, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
7462 .addMBB(TrapBB);
7463 // clang-format on
7464
7465 BB->addSuccessor(TrapBB);
7466 MI.eraseFromParent();
7467 return SplitBB;
7468 }
7469 case AMDGPU::SIMULATED_TRAP: {
7470 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7471 MachineBasicBlock *SplitBB =
7472 TII->insertSimulatedTrap(MRI, *BB, MI, MI.getDebugLoc());
7473 MI.eraseFromParent();
7474 return SplitBB;
7475 }
7476 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7477 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7479
7480 // During ISel, it's difficult to propagate the original EXEC mask to use as
7481 // an input to SI_WHOLE_WAVE_FUNC_RETURN. Set it up here instead.
7482 MachineInstr *Setup = TII->getWholeWaveFunctionSetup(*BB->getParent());
7483 assert(Setup && "Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7484 Register OriginalExec = Setup->getOperand(0).getReg();
7485 MF->getRegInfo().clearKillFlags(OriginalExec);
7486 MI.getOperand(0).setReg(OriginalExec);
7487 return BB;
7488 }
7489 case AMDGPU::V_DOT2_F32_F16:
7490 case AMDGPU::V_DOT2_F32_BF16: {
7491 // Hint RA to assign dst and src2 the same physical register.
7492 // For targets without VOP2, but with VOPD, variant of the instruction this
7493 // is one of the conditions to attempt converting VOP3P to VOPD.
7494 MRI.setSimpleHint(MI.getOperand(0).getReg(), MI.getOperand(6).getReg());
7495 return BB;
7496 }
7497 case AMDGPU::SCHED_BARRIER:
7498 case AMDGPU::SCHED_GROUP_BARRIER:
7499 MI.getOperand(0).setImm(MI.getOperand(0).getImm() &
7500 static_cast<unsigned>(AMDGPU::SchedGroupMask::ALL));
7501 return BB;
7502 default:
7503 if (TII->isImage(MI) || TII->isMUBUF(MI)) {
7504 if (!MI.mayStore())
7506 return BB;
7507 }
7509 }
7510}
7511
7513 // This currently forces unfolding various combinations of fsub into fma with
7514 // free fneg'd operands. As long as we have fast FMA (controlled by
7515 // isFMAFasterThanFMulAndFAdd), we should perform these.
7516
7517 // When fma is quarter rate, for f64 where add / sub are at best half rate,
7518 // most of these combines appear to be cycle neutral but save on instruction
7519 // count / code size.
7520 return true;
7521}
7522
7524
7526 EVT VT) const {
7527 if (!VT.isVector()) {
7528 return MVT::i1;
7529 }
7530 return EVT::getVectorVT(Ctx, MVT::i1, VT.getVectorNumElements());
7531}
7532
7534 // TODO: Should i16 be used always if legal? For now it would force VALU
7535 // shifts.
7536 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7537}
7538
7540 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7541 ? Ty.changeElementSize(16)
7542 : Ty.changeElementSize(32);
7543}
7544
7545// Answering this is somewhat tricky and depends on the specific device which
7546// have different rates for fma or all f64 operations.
7547//
7548// v_fma_f64 and v_mul_f64 always take the same number of cycles as each other
7549// regardless of which device (although the number of cycles differs between
7550// devices), so it is always profitable for f64.
7551//
7552// v_fma_f32 takes 4 or 16 cycles depending on the device, so it is profitable
7553// only on full rate devices. Normally, we should prefer selecting v_mad_f32
7554// which we can always do even without fused FP ops since it returns the same
7555// result as the separate operations and since it is always full
7556// rate. Therefore, we lie and report that it is not faster for f32. v_mad_f32
7557// however does not support denormals, so we do report fma as faster if we have
7558// a fast fma device and require denormals.
7559//
7561 DenormalFPEnv FPEnv) const {
7562 VT = VT.getScalarType();
7563 if (!VT.isSimple())
7564 return false;
7565
7566 switch (VT.getSimpleVT().SimpleTy) {
7567 case MVT::f32: {
7568 // If mad is not available this depends only on if f32 fma is full rate.
7569 if (!Subtarget->hasMadMacF32Insts())
7570 return Subtarget->hasFastFMAF32();
7571
7572 // Otherwise f32 mad is always full rate and returns the same result as
7573 // the separate operations so should be preferred over fma.
7574 // However does not support denormals.
7576 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7577
7578 // If the subtarget has v_fmac_f32, that's just as good as v_mac_f32.
7579 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7580 }
7581 case MVT::f64:
7582 return true;
7583 case MVT::f16:
7584 case MVT::bf16:
7585 return Subtarget->has16BitInsts() &&
7587 default:
7588 break;
7589 }
7590
7591 return false;
7592}
7593
7598
7600 Type *Ty) const {
7602 getValueType(F.getDataLayout(), Ty, /*AllowUnknown=*/true),
7603 F.getDenormalFPEnv());
7604}
7605
7607 LLT Ty) const {
7608 switch (Ty.getScalarSizeInBits()) {
7609 case 16:
7610 return isFMAFasterThanFMulAndFAdd(MF, MVT::f16);
7611 case 32:
7612 return isFMAFasterThanFMulAndFAdd(MF, MVT::f32);
7613 case 64:
7614 return isFMAFasterThanFMulAndFAdd(MF, MVT::f64);
7615 default:
7616 break;
7617 }
7618
7619 return false;
7620}
7621
7623 // TODO: Check future ftz flag
7624 // v_mad_f32/v_mac_f32 do not support denormals.
7625 if (VT == MVT::f32)
7626 return Subtarget->hasMadMacF32Insts() &&
7628 if (VT == MVT::f16)
7629 return Subtarget->hasMadF16() &&
7631
7632 return false;
7633}
7634
7636 if (!Ty.isScalar())
7637 return false;
7638
7639 DenormalFPEnv FPEnv = getDenormalFPEnv(*MI.getMF());
7640 if (Ty.getScalarSizeInBits() == 16)
7641 return isFMADLegal(MVT::f16, FPEnv);
7642 if (Ty.getScalarSizeInBits() == 32)
7643 return isFMADLegal(MVT::f32, FPEnv);
7644
7645 return false;
7646}
7647
7649 const SDNode *N) const {
7650 return isFMADLegal(N->getValueType(0),
7652}
7653
7655 return isFMADLegal(getValueType(F.getDataLayout(), Ty->getScalarType(),
7656 /*AllowUnknown=*/true),
7657 F.getDenormalFPEnv());
7658}
7659
7660//===----------------------------------------------------------------------===//
7661// Custom DAG Lowering Operations
7662//===----------------------------------------------------------------------===//
7663
7664// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7665// wider vector type is legal.
7667 SelectionDAG &DAG) const {
7668 unsigned Opc = Op.getOpcode();
7669 EVT VT = Op.getValueType();
7671
7672 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
7673 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VT);
7674
7675 SDLoc SL(Op);
7676
7677 // Forward any trailing scalar operands unchanged to both halves.
7678 SmallVector<SDValue, 2> LoOps = {Lo};
7679 SmallVector<SDValue, 2> HiOps = {Hi};
7680 auto TrailingOps = drop_begin(Op->ops());
7681 LoOps.append(TrailingOps.begin(), TrailingOps.end());
7682 HiOps.append(TrailingOps.begin(), TrailingOps.end());
7683
7684 SDValue OpLo = DAG.getNode(Opc, SL, LoVT, LoOps, Op->getFlags());
7685 SDValue OpHi = DAG.getNode(Opc, SL, HiVT, HiOps, Op->getFlags());
7686
7687 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7688}
7689
7690// Enable lowering of ROTR for vxi32 types. This is a workaround for a
7691// regression whereby extra unnecessary instructions were added to codegen
7692// for rotr operations, casued by legalising v2i32 or. This resulted in extra
7693// instructions to extract the result from the vector.
7695 [[maybe_unused]] EVT VT = Op.getValueType();
7696
7697 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7698 VT == MVT::v16i32) &&
7699 "Unexpected ValueType.");
7700
7701 return DAG.UnrollVectorOp(Op.getNode());
7702}
7703
7704// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7705// wider vector type is legal.
7707 SelectionDAG &DAG) const {
7708 unsigned Opc = Op.getOpcode();
7709 EVT VT = Op.getValueType();
7711
7712 auto [Lo0, Hi0] = DAG.SplitVectorOperand(Op.getNode(), 0);
7713 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7714
7715 SDLoc SL(Op);
7716
7717 SDValue OpLo =
7718 DAG.getNode(Opc, SL, Lo0.getValueType(), Lo0, Lo1, Op->getFlags());
7719 SDValue OpHi =
7720 DAG.getNode(Opc, SL, Hi0.getValueType(), Hi0, Hi1, Op->getFlags());
7721
7722 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7723}
7724
7726 SelectionDAG &DAG) const {
7727 unsigned Opc = Op.getOpcode();
7728 EVT VT = Op.getValueType();
7730
7731 SDValue Op0 = Op.getOperand(0);
7732 SDValue Lo0, Hi0;
7733 if (Op0.getValueType().isVector())
7734 std::tie(Lo0, Hi0) = DAG.SplitVectorOperand(Op.getNode(), 0);
7735 else
7736 Lo0 = Hi0 = DAG.getFreeze(Op0);
7737
7738 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7739 auto [Lo2, Hi2] = DAG.SplitVectorOperand(Op.getNode(), 2);
7740
7741 SDLoc SL(Op);
7742 auto ResVT = DAG.GetSplitDestVTs(VT);
7743
7744 SDValue OpLo =
7745 DAG.getNode(Opc, SL, ResVT.first, Lo0, Lo1, Lo2, Op->getFlags());
7746 SDValue OpHi =
7747 DAG.getNode(Opc, SL, ResVT.second, Hi0, Hi1, Hi2, Op->getFlags());
7748
7749 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7750}
7751
7753 switch (Op.getOpcode()) {
7754 default:
7756 case ISD::BRCOND:
7757 return LowerBRCOND(Op, DAG);
7758 case ISD::RETURNADDR:
7759 return LowerRETURNADDR(Op, DAG);
7760 case ISD::SPONENTRY:
7761 return LowerSPONENTRY(Op, DAG);
7762 case ISD::LOAD: {
7763 SDValue Result = LowerLOAD(Op, DAG);
7764 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7765 "Load should return a value and a chain");
7766 return Result;
7767 }
7768 case ISD::FSQRT: {
7769 EVT VT = Op.getValueType();
7770 if (VT == MVT::f32)
7771 return lowerFSQRTF32(Op, DAG);
7772 if (VT == MVT::f64)
7773 return lowerFSQRTF64(Op, DAG);
7774 return SDValue();
7775 }
7776 case ISD::FSIN:
7777 case ISD::FCOS:
7778 return LowerTrig(Op, DAG);
7779 case ISD::SELECT:
7780 return LowerSELECT(Op, DAG);
7781 case ISD::FDIV:
7782 return LowerFDIV(Op, DAG);
7783 case ISD::FFREXP:
7784 return LowerFFREXP(Op, DAG);
7786 return LowerATOMIC_CMP_SWAP(Op, DAG);
7787 case ISD::STORE:
7788 return LowerSTORE(Op, DAG);
7789 case ISD::GlobalAddress: {
7792 return LowerGlobalAddress(MFI, Op, DAG);
7793 }
7794 case ISD::BlockAddress:
7795 return LowerBlockAddress(Op, DAG);
7797 return LowerExternalSymbol(Op, DAG);
7799 return LowerINTRINSIC_WO_CHAIN(Op, DAG);
7801 return LowerCONVERT_FROM_ARBITRARY_FP(Op, DAG);
7803 return LowerCONVERT_TO_ARBITRARY_FP(Op, DAG);
7805 return LowerINTRINSIC_W_CHAIN(Op, DAG);
7807 return LowerINTRINSIC_VOID(Op, DAG);
7808 case ISD::ADDRSPACECAST:
7809 return lowerADDRSPACECAST(Op, DAG);
7811 return lowerINSERT_SUBVECTOR(Op, DAG);
7813 return lowerINSERT_VECTOR_ELT(Op, DAG);
7815 return lowerEXTRACT_VECTOR_ELT(Op, DAG);
7817 return lowerVECTOR_SHUFFLE(Op, DAG);
7819 return lowerSCALAR_TO_VECTOR(Op, DAG);
7820 case ISD::BUILD_VECTOR:
7821 return lowerBUILD_VECTOR(Op, DAG);
7822 case ISD::FP_ROUND:
7824 return lowerFP_ROUND(Op, DAG);
7825 case ISD::TRAP:
7826 return lowerTRAP(Op, DAG);
7827 case ISD::DEBUGTRAP:
7828 return lowerDEBUGTRAP(Op, DAG);
7829 case ISD::ABS:
7830 case ISD::FABS:
7831 case ISD::FNEG:
7832 case ISD::FCANONICALIZE:
7833 case ISD::BSWAP:
7834 return splitUnaryVectorOp(Op, DAG);
7837 if (Op.getValueType().isVector() && Op.getValueType() != MVT::v2i16 &&
7838 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7839 return splitUnaryVectorOp(Op, DAG);
7840 return LowerFP_TO_INT_SAT(Op, DAG);
7841 case ISD::FSUB:
7842 if (Op.getValueType() == MVT::bf16) {
7843 // Custom expansion:
7844 // fsub bf16 %a, %b -> fadd v2bf16(widen %a), fneg v2bf16(widen %b)
7845 // Then extract back to bf16.
7846 //
7847 // We create fneg on v2bf16 (not bf16) so the instruction selector can
7848 // fold the negation into the packed add's neg_lo/neg_hi modifiers,
7849 // generating a single v_pk_add_bf16 instruction. If we negate bf16 first,
7850 // it becomes a separate v_xor instruction before widening.
7851 SDLoc DL(Op);
7852 SDValue Op0 = Op.getOperand(0);
7853 SDValue Op1 = Op.getOperand(1);
7854
7855 // Widen both operands to v2bf16
7856 SDValue Vec0 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op0);
7857 SDValue Vec1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op1);
7858
7859 // Create FNEG v2bf16 for the second operand
7860 SDValue NegVec1 = DAG.getNode(ISD::FNEG, DL, MVT::v2bf16, Vec1);
7861
7862 // Perform FADD v2bf16
7863 SDValue Result = DAG.getNode(ISD::FADD, DL, MVT::v2bf16, Vec0, NegVec1);
7864
7865 // Extract element 0 back to bf16
7866 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::bf16, Result,
7867 DAG.getConstant(0, DL, MVT::i32));
7868 }
7869 return SDValue();
7870 case ISD::FMINNUM:
7871 case ISD::FMAXNUM:
7872 return lowerFMINNUM_FMAXNUM(Op, DAG);
7873 case ISD::FMINIMUMNUM:
7874 case ISD::FMAXIMUMNUM:
7875 return lowerFMINIMUMNUM_FMAXIMUMNUM(Op, DAG);
7876 case ISD::FLDEXP:
7877 case ISD::STRICT_FLDEXP:
7878 return lowerFLDEXP(Op, DAG);
7879 case ISD::FMA:
7880 return splitTernaryVectorOp(Op, DAG);
7881 case ISD::FP_TO_SINT:
7882 case ISD::FP_TO_UINT:
7883 if (Subtarget->hasVCvtPkIU16F32() && Op.getValueType() == MVT::i16 &&
7884 Op.getOperand(0).getValueType() == MVT::f32) {
7885 // Make f32->i16 legal so we can select V_CVT_PK_[IU]16_F32.
7886 return Op;
7887 }
7888 return LowerFP_TO_INT(Op, DAG);
7889 case ISD::SHL:
7890 case ISD::SRA:
7891 case ISD::SRL:
7892 case ISD::ADD:
7893 case ISD::SUB:
7894 case ISD::SMIN:
7895 case ISD::SMAX:
7896 case ISD::UMIN:
7897 case ISD::UMAX:
7898 case ISD::FMINNUM_IEEE:
7899 case ISD::FMAXNUM_IEEE:
7900 case ISD::FMINIMUM:
7901 case ISD::FMAXIMUM:
7902 case ISD::UADDSAT:
7903 case ISD::USUBSAT:
7904 case ISD::SADDSAT:
7905 case ISD::SSUBSAT:
7906 case ISD::FADD:
7907 case ISD::FMUL:
7908 return splitBinaryVectorOp(Op, DAG);
7909 case ISD::FCOPYSIGN:
7910 return lowerFCOPYSIGN(Op, DAG);
7911 case ISD::MUL:
7912 return lowerMUL(Op, DAG);
7913 case ISD::SMULO:
7914 case ISD::UMULO:
7915 return lowerXMULO(Op, DAG);
7916 case ISD::SMUL_LOHI:
7917 case ISD::UMUL_LOHI:
7918 return lowerXMUL_LOHI(Op, DAG);
7920 return LowerDYNAMIC_STACKALLOC(Op, DAG);
7921 case ISD::STACKSAVE:
7922 return LowerSTACKSAVE(Op, DAG);
7923 case ISD::GET_ROUNDING:
7924 return lowerGET_ROUNDING(Op, DAG);
7925 case ISD::SET_ROUNDING:
7926 return lowerSET_ROUNDING(Op, DAG);
7927 case ISD::PREFETCH:
7928 return lowerPREFETCH(Op, DAG);
7929 case ISD::FP_EXTEND:
7931 return lowerFP_EXTEND(Op, DAG);
7932 case ISD::GET_FPENV:
7933 return lowerGET_FPENV(Op, DAG);
7934 case ISD::SET_FPENV:
7935 return lowerSET_FPENV(Op, DAG);
7936 case ISD::ROTR:
7937 return lowerROTR(Op, DAG);
7938 case ISD::INLINEASM:
7939 return LowerINLINEASM(Op, DAG);
7940 }
7941 return SDValue();
7942}
7943
7944// TFE results are dword granular: value dwords followed by one status dword.
7945static std::pair<SDValue, SDValue>
7947 LLVMContext &C = *DAG.getContext();
7948 unsigned NumValueDWords = divideCeil(VT.getSizeInBits(), 32);
7950 DAG.getVectorIdxConstant(NumValueDWords, DL));
7951 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, DL);
7952 SDValue ValueDWords =
7953 NumValueDWords == 1
7954 ? DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op, ZeroIdx)
7956 EVT::getVectorVT(C, MVT::i32, NumValueDWords), Op,
7957 ZeroIdx);
7958 if (!VT.isVector() && VT.getSizeInBits() < 32)
7959 ValueDWords =
7960 DAG.getNode(ISD::TRUNCATE, DL, VT.changeTypeToInteger(), ValueDWords);
7961 return {DAG.getNode(ISD::BITCAST, DL, VT, ValueDWords), Status};
7962}
7963
7964// Used for D16: Casts the result of an instruction into the right vector,
7965// packs values if loads return unpacked values.
7967 const SDLoc &DL, SelectionDAG &DAG,
7968 bool Unpacked) {
7969 if (!LoadVT.isVector())
7970 return Result;
7971
7972 // Cast back to the original packed type or to a larger type that is a
7973 // multiple of 32 bit for D16. Widening the return type is a required for
7974 // legalization.
7975 EVT FittingLoadVT = LoadVT;
7976 if ((LoadVT.getVectorNumElements() % 2) == 1) {
7977 FittingLoadVT =
7979 LoadVT.getVectorNumElements() + 1);
7980 }
7981
7982 if (Unpacked) { // From v2i32/v4i32 back to v2f16/v4f16.
7983 // Truncate to v2i16/v4i16.
7984 EVT IntLoadVT = FittingLoadVT.changeTypeToInteger();
7985
7986 // Workaround legalizer not scalarizing truncate after vector op
7987 // legalization but not creating intermediate vector trunc.
7989 DAG.ExtractVectorElements(Result, Elts);
7990 for (SDValue &Elt : Elts)
7991 Elt = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Elt);
7992
7993 // Pad illegal v1i16/v3fi6 to v4i16
7994 if ((LoadVT.getVectorNumElements() % 2) == 1)
7995 Elts.push_back(DAG.getPOISON(MVT::i16));
7996
7997 Result = DAG.getBuildVector(IntLoadVT, DL, Elts);
7998
7999 // Bitcast to original type (v2f16/v4f16).
8000 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
8001 }
8002
8003 // Cast back to the original packed type.
8004 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
8005}
8006
8007SDValue SITargetLowering::adjustLoadValueType(unsigned Opcode, MemSDNode *M,
8008 SelectionDAG &DAG,
8010 bool IsIntrinsic) const {
8011 SDLoc DL(M);
8012
8013 bool IsTFE = M->getNumValues() == 3;
8014 bool Unpacked = Subtarget->hasUnpackedD16VMem();
8015 EVT LoadVT = M->getValueType(0);
8016
8017 EVT EquivLoadVT = LoadVT;
8018 if (LoadVT.isVector()) {
8019 if (Unpacked) {
8020 EquivLoadVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
8021 LoadVT.getVectorNumElements());
8022 } else if ((LoadVT.getVectorNumElements() % 2) == 1) {
8023 // Widen v3f16 to legal type
8024 EquivLoadVT =
8026 LoadVT.getVectorNumElements() + 1);
8027 }
8028 }
8029
8030 if (IsTFE) {
8031 unsigned NumValueDWords = divideCeil(EquivLoadVT.getSizeInBits(), 32);
8032 EVT LoadDWordsVT =
8033 EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumValueDWords + 1);
8034 SDVTList VTList = DAG.getVTList(LoadDWordsVT, MVT::Other);
8036 Opcode, DL, VTList, Ops, M->getMemoryVT(), M->getMemOperand());
8037 auto [Value, Status] = splitTFEValueAndStatus(Load, EquivLoadVT, DL, DAG);
8038 SDValue Adjusted =
8039 adjustLoadValueTypeImpl(Value, LoadVT, DL, DAG, Unpacked);
8040 return DAG.getMergeValues({Adjusted, Status, Load.getValue(1)}, DL);
8041 }
8042
8043 // Change from v4f16/v2f16 to EquivLoadVT.
8044 SDVTList VTList = DAG.getVTList(EquivLoadVT, MVT::Other);
8045
8047 IsIntrinsic ? (unsigned)ISD::INTRINSIC_W_CHAIN : Opcode, DL, VTList, Ops,
8048 M->getMemoryVT(), M->getMemOperand());
8049
8050 SDValue Adjusted = adjustLoadValueTypeImpl(Load, LoadVT, DL, DAG, Unpacked);
8051
8052 return DAG.getMergeValues({Adjusted, Load.getValue(1)}, DL);
8053}
8054
8055SDValue SITargetLowering::lowerIntrinsicLoad(MemSDNode *M, bool IsFormat,
8056 SelectionDAG &DAG,
8057 ArrayRef<SDValue> Ops) const {
8058 SDLoc DL(M);
8059 EVT LoadVT = M->getValueType(0);
8060 EVT EltType = LoadVT.getScalarType();
8061 EVT IntVT = LoadVT.changeTypeToInteger();
8062
8063 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
8064
8065 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
8066 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
8068 "unsupported sub-dword format buffer load", DL.getDebugLoc()));
8069 return DAG.getMergeValues({DAG.getPOISON(LoadVT), M->getOperand(0)}, DL);
8070 }
8071
8072 assert(M->getNumValues() == 2 || M->getNumValues() == 3);
8073 bool IsTFE = M->getNumValues() == 3;
8074
8075 if (IsD16 && IsTFE && !Subtarget->hasBufferTFEFormatD16()) {
8076 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
8078 "TFE D16 format buffer load is not supported on this GPU",
8079 DL.getDebugLoc()));
8080 return DAG.getErrorMergeValues({M->value_begin(), M->value_end()},
8081 M->getOperand(0), DL);
8082 }
8083
8084 unsigned Opc = IsD16 ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_D16_TFE
8085 : AMDGPUISD::BUFFER_LOAD_FORMAT_D16)
8086 : IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
8087 : AMDGPUISD::BUFFER_LOAD_FORMAT)
8088 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
8089 : AMDGPUISD::BUFFER_LOAD;
8090
8091 if (IsD16)
8092 return adjustLoadValueType(Opc, M, DAG, Ops);
8093
8094 // Handle BUFFER_LOAD_BYTE/UBYTE/SHORT/USHORT overloaded intrinsics
8095 if (!IsD16 && !LoadVT.isVector() && EltType.getSizeInBits() < 32)
8096 return handleByteShortBufferLoads(DAG, LoadVT, DL, Ops, M->getMemOperand(),
8097 IsTFE);
8098
8099 if (isTypeLegal(LoadVT)) {
8100 return getMemIntrinsicNode(Opc, DL, M->getVTList(), Ops, IntVT,
8101 M->getMemOperand(), DAG);
8102 }
8103
8104 EVT CastVT = getEquivalentMemType(*DAG.getContext(), LoadVT);
8105 SDVTList VTList = IsTFE ? DAG.getVTList(CastVT, MVT::i32, MVT::Other)
8106 : DAG.getVTList(CastVT, MVT::Other);
8107 SDValue MemNode = getMemIntrinsicNode(Opc, DL, VTList, Ops, CastVT,
8108 M->getMemOperand(), DAG);
8109 SDValue Data = DAG.getNode(ISD::BITCAST, DL, LoadVT, MemNode);
8110 if (IsTFE)
8111 return DAG.getMergeValues({Data, MemNode.getValue(1), MemNode.getValue(2)},
8112 DL);
8113 return DAG.getMergeValues({Data, MemNode.getValue(1)}, DL);
8114}
8115
8117 SelectionDAG &DAG) {
8118 EVT VT = N->getValueType(0);
8119 SDValue Src = N->getOperand(1);
8120 SDLoc SL(N);
8121
8122 if (Src.getOpcode() == ISD::SETCC) {
8123 SDValue Op0 = Src.getOperand(0);
8124 SDValue Op1 = Src.getOperand(1);
8125 // Need to expand bfloat to float for comparison (setcc).
8126 if (Op0.getValueType() == MVT::bf16) {
8127 Op0 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op0);
8128 Op1 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op1);
8129 }
8130 // (ballot (ISD::SETCC ...)) -> (AMDGPUISD::SETCC ...)
8131 return DAG.getNode(AMDGPUISD::SETCC, SL, VT, Op0, Op1, Src.getOperand(2));
8132 }
8133 if (const ConstantSDNode *Arg = dyn_cast<ConstantSDNode>(Src)) {
8134 // (ballot 0) -> 0
8135 if (Arg->isZero())
8136 return DAG.getConstant(0, SL, VT);
8137
8138 // (ballot 1) -> EXEC/EXEC_LO
8139 if (Arg->isOne()) {
8140 Register Exec;
8141 if (VT.getScalarSizeInBits() == 32)
8142 Exec = AMDGPU::EXEC_LO;
8143 else if (VT.getScalarSizeInBits() == 64)
8144 Exec = AMDGPU::EXEC;
8145 else
8146 return SDValue();
8147
8148 return DAG.getCopyFromReg(DAG.getEntryNode(), SL, Exec, VT);
8149 }
8150 }
8151
8152 // (ballot (i1 $src)) -> (AMDGPUISD::SETCC (i32 (zext $src)) (i32 0)
8153 // ISD::SETNE)
8154 return DAG.getNode(
8155 AMDGPUISD::SETCC, SL, VT, DAG.getZExtOrTrunc(Src, SL, MVT::i32),
8156 DAG.getConstant(0, SL, MVT::i32), DAG.getCondCode(ISD::SETNE));
8157}
8158
8160 Intrinsic::ID IntrinsicID) {
8161 bool Signed = IntrinsicID == Intrinsic::amdgcn_sbfe;
8162 SDLoc DL(Op);
8163 EVT VT = Op.getValueType();
8164 SDValue Src = Op.getOperand(1);
8165 SDValue Offset = Op.getOperand(2);
8166 SDValue Width = Op.getOperand(3);
8167
8168 if (VT != MVT::i32) {
8171 Twine(Intrinsic::getBaseName(IntrinsicID)) + " only supports i32",
8172 DL.getDebugLoc()));
8173 return DAG.getPOISON(VT);
8174 }
8175
8176 return DAG.getNode(Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32, DL, VT,
8177 Src, Offset, Width);
8178}
8179
8181 EVT VT);
8182
8184 SelectionDAG &DAG) {
8185 EVT VT = N->getValueType(0);
8186 unsigned ValSize = VT.getSizeInBits();
8187 unsigned IID = N->getConstantOperandVal(0);
8188 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8189 IID == Intrinsic::amdgcn_permlanex16;
8190 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8191 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8192 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8193 IID == Intrinsic::amdgcn_permlane_up ||
8194 IID == Intrinsic::amdgcn_permlane_down ||
8195 IID == Intrinsic::amdgcn_permlane_xor;
8196 SDLoc SL(N);
8197 MVT IntVT = MVT::getIntegerVT(ValSize);
8198 const GCNSubtarget *ST = TLI.getSubtarget();
8199
8200 unsigned SplitSize = 32;
8201 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8202 ST->hasDPALU_DPP() &&
8203 AMDGPU::isLegalDPALU_DPPControl(*ST, N->getConstantOperandVal(3)))
8204 SplitSize = 64;
8205
8206 auto createLaneOp = [&DAG, &SL, N, IID](SDValue Src0, SDValue Src1,
8207 SDValue Src2, MVT ValT) -> SDValue {
8209 switch (IID) {
8210 case Intrinsic::amdgcn_permlane16:
8211 case Intrinsic::amdgcn_permlanex16:
8212 case Intrinsic::amdgcn_update_dpp:
8213 Operands.push_back(N->getOperand(6));
8214 Operands.push_back(N->getOperand(5));
8215 Operands.push_back(N->getOperand(4));
8216 [[fallthrough]];
8217 case Intrinsic::amdgcn_writelane:
8218 case Intrinsic::amdgcn_permlane_bcast:
8219 case Intrinsic::amdgcn_permlane_up:
8220 case Intrinsic::amdgcn_permlane_down:
8221 case Intrinsic::amdgcn_permlane_xor:
8222 Operands.push_back(Src2);
8223 [[fallthrough]];
8224 case Intrinsic::amdgcn_readlane:
8225 case Intrinsic::amdgcn_set_inactive:
8226 case Intrinsic::amdgcn_set_inactive_chain_arg:
8227 case Intrinsic::amdgcn_mov_dpp8:
8228 Operands.push_back(Src1);
8229 [[fallthrough]];
8230 case Intrinsic::amdgcn_readfirstlane:
8231 case Intrinsic::amdgcn_permlane64:
8232 Operands.push_back(Src0);
8233 break;
8234 default:
8235 llvm_unreachable("unhandled lane op");
8236 }
8237
8238 Operands.push_back(DAG.getTargetConstant(IID, SL, MVT::i32));
8239 std::reverse(Operands.begin(), Operands.end());
8240
8241 if (SDNode *GL = N->getGluedNode()) {
8242 assert(GL->getOpcode() == ISD::CONVERGENCECTRL_GLUE);
8243 GL = GL->getOperand(0).getNode();
8244 Operands.push_back(DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8245 SDValue(GL, 0)));
8246 }
8247
8248 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, ValT, Operands);
8249 };
8250
8251 SDValue Src0 = N->getOperand(1);
8252 SDValue Src1, Src2;
8253 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8254 IID == Intrinsic::amdgcn_mov_dpp8 ||
8255 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8256 IsPermlaneShuffle) {
8257 Src1 = N->getOperand(2);
8258 if (IID == Intrinsic::amdgcn_writelane ||
8259 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8260 IsPermlaneShuffle)
8261 Src2 = N->getOperand(3);
8262 }
8263
8264 if (ValSize == SplitSize) {
8265 // Already legal
8266 return SDValue();
8267 }
8268
8269 if (ValSize < 32) {
8270 bool IsFloat = VT.isFloatingPoint();
8271 Src0 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src0) : Src0,
8272 SL, MVT::i32);
8273
8274 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8275 Src1 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src1) : Src1,
8276 SL, MVT::i32);
8277 }
8278
8279 if (IID == Intrinsic::amdgcn_writelane) {
8280 Src2 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src2) : Src2,
8281 SL, MVT::i32);
8282 }
8283
8284 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8285 SDValue Trunc = DAG.getAnyExtOrTrunc(LaneOp, SL, IntVT);
8286 return IsFloat ? DAG.getBitcast(VT, Trunc) : Trunc;
8287 }
8288
8289 if (ValSize % SplitSize != 0)
8290 return SDValue();
8291
8292 auto unrollLaneOp = [&DAG, &SL](SDNode *N) -> SDValue {
8293 EVT VT = N->getValueType(0);
8294 unsigned NE = VT.getVectorNumElements();
8295 EVT EltVT = VT.getVectorElementType();
8297 unsigned NumOperands = N->getNumOperands();
8298 SmallVector<SDValue, 4> Operands(NumOperands);
8299 SDNode *GL = N->getGluedNode();
8300
8301 // only handle convergencectrl_glue
8303
8304 for (unsigned i = 0; i != NE; ++i) {
8305 for (unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8306 ++j) {
8307 SDValue Operand = N->getOperand(j);
8308 EVT OperandVT = Operand.getValueType();
8309 if (OperandVT.isVector()) {
8310 // A vector operand; extract a single element.
8311 EVT OperandEltVT = OperandVT.getVectorElementType();
8312 Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, OperandEltVT,
8313 Operand, DAG.getVectorIdxConstant(i, SL));
8314 } else {
8315 // A scalar operand; just use it as is.
8316 Operands[j] = Operand;
8317 }
8318 }
8319
8320 if (GL)
8321 Operands[NumOperands - 1] =
8322 DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8323 SDValue(GL->getOperand(0).getNode(), 0));
8324
8325 Scalars.push_back(DAG.getNode(N->getOpcode(), SL, EltVT, Operands));
8326 }
8327
8328 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NE);
8329 return DAG.getBuildVector(VecVT, SL, Scalars);
8330 };
8331
8332 if (VT.isVector()) {
8333 switch (MVT::SimpleValueType EltTy =
8335 case MVT::i32:
8336 case MVT::f32:
8337 if (SplitSize == 32) {
8338 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VT.getSimpleVT());
8339 return unrollLaneOp(LaneOp.getNode());
8340 }
8341 [[fallthrough]];
8342 case MVT::i16:
8343 case MVT::f16:
8344 case MVT::bf16: {
8345 unsigned SubVecNumElt =
8346 SplitSize / VT.getVectorElementType().getSizeInBits();
8347 MVT SubVecVT = MVT::getVectorVT(EltTy, SubVecNumElt);
8349 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8350 for (unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8351 Src0SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src0,
8352 DAG.getConstant(EltIdx, SL, MVT::i32));
8353
8354 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8355 IsPermLane16) {
8356 Src1SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src1,
8357 DAG.getConstant(EltIdx, SL, MVT::i32));
8358
8359 Pieces.push_back(
8360 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8361 } else if (IID == Intrinsic::amdgcn_writelane) {
8362 Src2SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src2,
8363 DAG.getConstant(EltIdx, SL, MVT::i32));
8364 Pieces.push_back(
8365 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8366 } else {
8367 Pieces.push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8368 }
8369
8370 EltIdx += SubVecNumElt;
8371 }
8372 return DAG.getNode(ISD::CONCAT_VECTORS, SL, VT, Pieces);
8373 }
8374 default:
8375 // Handle all other cases by bitcasting to i32 vectors
8376 break;
8377 }
8378 }
8379
8380 MVT VecVT =
8381 MVT::getVectorVT(MVT::getIntegerVT(SplitSize), ValSize / SplitSize);
8382 Src0 = DAG.getBitcast(VecVT, Src0);
8383
8384 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8385 Src1 = DAG.getBitcast(VecVT, Src1);
8386
8387 if (IID == Intrinsic::amdgcn_writelane)
8388 Src2 = DAG.getBitcast(VecVT, Src2);
8389
8390 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8391 SDValue UnrolledLaneOp = unrollLaneOp(LaneOp.getNode());
8392 return DAG.getBitcast(VT, UnrolledLaneOp);
8393}
8394
8396 SelectionDAG &DAG) {
8397 EVT VT = N->getValueType(0);
8398
8399 if (VT.getSizeInBits() != 32)
8400 return SDValue();
8401
8402 SDLoc SL(N);
8403
8404 SDValue Value = N->getOperand(1);
8405 SDValue Index = N->getOperand(2);
8406
8407 // ds_bpermute requires index to be multiplied by 4
8408 SDValue ShiftAmount = DAG.getShiftAmountConstant(2, MVT::i32, SL);
8409 SDValue ShiftedIndex =
8410 DAG.getNode(ISD::SHL, SL, Index.getValueType(), Index, ShiftAmount);
8411
8412 // Intrinsics will require i32 to operate on
8413 SDValue ValueI32 = DAG.getBitcast(MVT::i32, Value);
8414
8415 auto MakeIntrinsic = [&DAG, &SL](unsigned IID, MVT RetVT,
8416 SmallVector<SDValue> IntrinArgs) -> SDValue {
8418 Operands[0] = DAG.getTargetConstant(IID, SL, MVT::i32);
8419 Operands.append(IntrinArgs);
8420 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, RetVT, Operands);
8421 };
8422
8423 // If we can bpermute across the whole wave, then just do that
8424 if (TLI.getSubtarget()->supportsWaveWideBPermute()) {
8425 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8426 {ShiftedIndex, ValueI32});
8427 return DAG.getBitcast(VT, BPermute);
8428 }
8429
8430 assert(TLI.getSubtarget()->isWave64());
8431
8432 // Otherwise, we need to make use of whole wave mode
8433 SDValue PoisonVal = DAG.getPOISON(ValueI32->getValueType(0));
8434
8435 // Set inactive lanes to poison
8436 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8437 {ValueI32, PoisonVal});
8438 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8439 {ShiftedIndex, PoisonVal});
8440
8441 SDValue Swapped =
8442 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8443
8444 // Get permutation of each half, then we'll select which one to use
8445 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8446 {WWMIndex, WWMValue});
8447 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8448 MVT::i32, {WWMIndex, Swapped});
8449 SDValue BPermOtherHalfWWM =
8450 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8451
8452 // Select which side to take the permute from
8453 SDValue ThreadIDMask = DAG.getAllOnesConstant(SL, MVT::i32);
8454 // We can get away with only using mbcnt_lo here since we're only
8455 // trying to detect which side of 32 each lane is on, and mbcnt_lo
8456 // returns 32 for lanes 32-63.
8457 SDValue ThreadID =
8458 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8459 {ThreadIDMask, DAG.getTargetConstant(0, SL, MVT::i32)});
8460
8461 SDValue SameOrOtherHalf =
8462 DAG.getNode(ISD::AND, SL, MVT::i32,
8463 DAG.getNode(ISD::XOR, SL, MVT::i32, ThreadID, Index),
8464 DAG.getTargetConstant(32, SL, MVT::i32));
8465 SDValue UseSameHalf =
8466 DAG.getSetCC(SL, MVT::i1, SameOrOtherHalf,
8467 DAG.getConstant(0, SL, MVT::i32), ISD::SETEQ);
8468 SDValue Result = DAG.getSelect(SL, MVT::i32, UseSameHalf, BPermSameHalf,
8469 BPermOtherHalfWWM);
8470 return DAG.getBitcast(VT, Result);
8471}
8472
8475 SelectionDAG &DAG) const {
8476 switch (N->getOpcode()) {
8478 if (SDValue Res = lowerINSERT_VECTOR_ELT(SDValue(N, 0), DAG))
8479 Results.push_back(Res);
8480 return;
8481 }
8483 if (SDValue Res = lowerEXTRACT_VECTOR_ELT(SDValue(N, 0), DAG))
8484 Results.push_back(Res);
8485 return;
8486 }
8488 if (SDValue Res = LowerCONVERT_TO_ARBITRARY_FP(SDValue(N, 0), DAG))
8489 Results.push_back(Res);
8490 return;
8491 }
8493 unsigned IID = N->getConstantOperandVal(0);
8494 switch (IID) {
8495 case Intrinsic::amdgcn_wave_reduce_min:
8496 case Intrinsic::amdgcn_wave_reduce_umin:
8497 case Intrinsic::amdgcn_wave_reduce_max:
8498 case Intrinsic::amdgcn_wave_reduce_umax:
8499 case Intrinsic::amdgcn_wave_reduce_add:
8500 case Intrinsic::amdgcn_wave_reduce_sub:
8501 case Intrinsic::amdgcn_wave_reduce_and:
8502 case Intrinsic::amdgcn_wave_reduce_or:
8503 case Intrinsic::amdgcn_wave_reduce_xor: {
8504 EVT VT = N->getValueType(0);
8505 if (isTypeLegal(VT))
8506 return;
8507 SDLoc SL(N);
8508 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8509 IID == Intrinsic::amdgcn_wave_reduce_max ||
8510 IID == Intrinsic::amdgcn_wave_reduce_add ||
8511 IID == Intrinsic::amdgcn_wave_reduce_sub;
8512 unsigned ExtOpc = NeedsSignExt ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
8513 SDValue ExtSrc = DAG.getNode(ExtOpc, SL, MVT::i32, N->getOperand(1));
8514 SDValue Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
8515 N->getOperand(0), ExtSrc, N->getOperand(2));
8516 Results.push_back(DAG.getNode(ISD::TRUNCATE, SL, VT, Result));
8517 return;
8518 }
8519 case Intrinsic::amdgcn_make_buffer_rsrc:
8520 Results.push_back(lowerPointerAsRsrcIntrin(N, DAG));
8521 return;
8522 case Intrinsic::amdgcn_cvt_pkrtz: {
8523 SDValue Src0 = N->getOperand(1);
8524 SDValue Src1 = N->getOperand(2);
8525 SDLoc SL(N);
8526 SDValue Cvt =
8527 DAG.getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8528 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Cvt));
8529 return;
8530 }
8531 case Intrinsic::amdgcn_cvt_pknorm_i16:
8532 case Intrinsic::amdgcn_cvt_pknorm_u16:
8533 case Intrinsic::amdgcn_cvt_pk_i16:
8534 case Intrinsic::amdgcn_cvt_pk_u16: {
8535 SDValue Src0 = N->getOperand(1);
8536 SDValue Src1 = N->getOperand(2);
8537 SDLoc SL(N);
8538 unsigned Opcode;
8539
8540 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8541 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8542 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8543 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8544 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8545 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8546 else
8547 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8548
8549 EVT VT = N->getValueType(0);
8550 if (isTypeLegal(VT))
8551 Results.push_back(DAG.getNode(Opcode, SL, VT, Src0, Src1));
8552 else {
8553 SDValue Cvt = DAG.getNode(Opcode, SL, MVT::i32, Src0, Src1);
8554 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, Cvt));
8555 }
8556 return;
8557 }
8558 case Intrinsic::amdgcn_s_buffer_load: {
8559 SDValue Op = SDValue(N, 0);
8560 EVT VT = Op.getValueType();
8561 Results.push_back(lowerSBuffer(VT, VT, SDLoc(Op), DAG.getEntryNode(),
8562 Op.getOperand(1), Op.getOperand(2),
8563 Op.getOperand(3), DAG));
8564 return;
8565 }
8566 case Intrinsic::amdgcn_dead: {
8567 for (unsigned I = 0, E = N->getNumValues(); I < E; ++I)
8568 Results.push_back(DAG.getPOISON(N->getValueType(I)));
8569 return;
8570 }
8571 }
8572 break;
8573 }
8575 if (N->getConstantOperandVal(1) != Intrinsic::amdgcn_ptr_s_buffer_load &&
8576 N->getValueType(0).isSimple() &&
8577 SBufferLoadDiagnosticVTs[N->getSimpleValueType(0).SimpleTy])
8578 break;
8579 if (SDValue Res = LowerINTRINSIC_W_CHAIN(SDValue(N, 0), DAG)) {
8580 if (Res.getOpcode() == ISD::MERGE_VALUES) {
8581 // FIXME: Hacky
8582 for (unsigned I = 0; I < Res.getNumOperands(); I++) {
8583 Results.push_back(Res.getOperand(I));
8584 }
8585 } else {
8586 for (unsigned I = 0; I < N->getNumValues(); ++I)
8587 Results.push_back(Res.getValue(I));
8588 }
8589 return;
8590 }
8591
8592 break;
8593 }
8594 case ISD::SELECT: {
8595 SDLoc SL(N);
8596 EVT VT = N->getValueType(0);
8597 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
8598 SDValue LHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(1));
8599 SDValue RHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(2));
8600
8601 EVT SelectVT = NewVT;
8602 if (NewVT.bitsLT(MVT::i32)) {
8603 LHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, LHS);
8604 RHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, RHS);
8605 SelectVT = MVT::i32;
8606 }
8607
8608 SDValue NewSelect =
8609 DAG.getNode(ISD::SELECT, SL, SelectVT, N->getOperand(0), LHS, RHS);
8610
8611 if (NewVT != SelectVT)
8612 NewSelect = DAG.getNode(ISD::TRUNCATE, SL, NewVT, NewSelect);
8613 Results.push_back(DAG.getNode(ISD::BITCAST, SL, VT, NewSelect));
8614 return;
8615 }
8616 case ISD::FNEG: {
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::XOR, SL, MVT::i32, BC,
8624 DAG.getConstant(0x80008000, SL, MVT::i32));
8625 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8626 return;
8627 }
8628 case ISD::FABS: {
8629 if (N->getValueType(0) != MVT::v2f16)
8630 break;
8631
8632 SDLoc SL(N);
8633 SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::i32, N->getOperand(0));
8634
8635 SDValue Op = DAG.getNode(ISD::AND, SL, MVT::i32, BC,
8636 DAG.getConstant(0x7fff7fff, SL, MVT::i32));
8637 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8638 return;
8639 }
8640 case ISD::FSQRT: {
8641 if (N->getValueType(0) != MVT::f16)
8642 break;
8643 Results.push_back(lowerFSQRTF16(SDValue(N, 0), DAG));
8644 break;
8645 }
8646 default:
8648 break;
8649 }
8650}
8651
8652/// Helper function for LowerBRCOND
8653static SDNode *findUser(SDValue Value, unsigned Opcode) {
8654
8655 for (SDUse &U : Value->uses()) {
8656 if (U.get() != Value)
8657 continue;
8658
8659 if (U.getUser()->getOpcode() == Opcode)
8660 return U.getUser();
8661 }
8662 return nullptr;
8663}
8664
8665unsigned SITargetLowering::isCFIntrinsic(const SDNode *Intr) const {
8666 if (Intr->getOpcode() == ISD::INTRINSIC_W_CHAIN) {
8667 switch (Intr->getConstantOperandVal(1)) {
8668 case Intrinsic::amdgcn_if:
8669 return AMDGPUISD::IF;
8670 case Intrinsic::amdgcn_else:
8671 return AMDGPUISD::ELSE;
8672 case Intrinsic::amdgcn_loop:
8673 return AMDGPUISD::LOOP;
8674 case Intrinsic::amdgcn_end_cf:
8675 llvm_unreachable("should not occur");
8676 default:
8677 return 0;
8678 }
8679 }
8680
8681 // break, if_break, else_break are all only used as inputs to loop, not
8682 // directly as branch conditions.
8683 return 0;
8684}
8685
8692
8694 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8695 return false;
8696
8697 // FIXME: Either avoid relying on address space here or change the default
8698 // address space for functions to avoid the explicit check.
8699 return (GV->getValueType()->isFunctionTy() ||
8702}
8703
8705 return !shouldEmitFixup(GV) && !shouldEmitGOTReloc(GV);
8706}
8707
8709 if (!GV->hasExternalLinkage())
8710 return true;
8711
8712 // With object linking, external LDS declarations need relocations so the
8713 // linker can assign their offsets.
8715 if (const auto *GVar = dyn_cast<GlobalVariable>(GV)) {
8716 if (GVar->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
8717 GVar->getAddressSpace() == AMDGPUAS::BARRIER) {
8718 assert(GVar->isDeclaration() &&
8719 "AS 3 & 13 GVs should be declaration here "
8720 "when object linking is enabled");
8721 return false;
8722 }
8723 }
8724 }
8725
8726 const auto OS = getTargetMachine().getTargetTriple().getOS();
8727 return OS == Triple::AMDHSA || OS == Triple::AMDPAL;
8728}
8729
8730/// This transforms the control flow intrinsics to get the branch destination as
8731/// last parameter, also switches branch target with BR if the need arise
8732SDValue SITargetLowering::LowerBRCOND(SDValue BRCOND, SelectionDAG &DAG) const {
8733 SDLoc DL(BRCOND);
8734
8735 SDNode *Intr = BRCOND.getOperand(1).getNode();
8736 SDValue Target = BRCOND.getOperand(2);
8737 SDNode *BR = nullptr;
8738 SDNode *SetCC = nullptr;
8739
8740 switch (Intr->getOpcode()) {
8741 case ISD::SETCC: {
8742 // As long as we negate the condition everything is fine
8743 SetCC = Intr;
8744 Intr = SetCC->getOperand(0).getNode();
8745 break;
8746 }
8747 case ISD::XOR: {
8748 // Similar to SETCC, if we have (xor c, -1), we will be fine.
8749 SDValue LHS = Intr->getOperand(0);
8750 SDValue RHS = Intr->getOperand(1);
8751 if (auto *C = dyn_cast<ConstantSDNode>(RHS); C && C->getZExtValue()) {
8752 Intr = LHS.getNode();
8753 break;
8754 }
8755 [[fallthrough]];
8756 }
8757 default: {
8758 // Get the target from BR if we don't negate the condition
8759 BR = findUser(BRCOND, ISD::BR);
8760 assert(BR && "brcond missing unconditional branch user");
8761 Target = BR->getOperand(1);
8762 }
8763 }
8764
8765 unsigned CFNode = isCFIntrinsic(Intr);
8766 if (CFNode == 0) {
8767 // This is a uniform branch so we don't need to legalize.
8768 return BRCOND;
8769 }
8770
8771 bool HaveChain = Intr->getOpcode() == ISD::INTRINSIC_VOID ||
8773
8774 assert(!SetCC || (SetCC->getConstantOperandVal(1) == 1 &&
8775 SetCC->getOperandCondCode(2) == ISD::SETNE));
8776
8777 // operands of the new intrinsic call
8779 if (HaveChain)
8780 Ops.push_back(BRCOND.getOperand(0));
8781
8782 Ops.append(Intr->op_begin() + (HaveChain ? 2 : 1), Intr->op_end());
8783 Ops.push_back(Target);
8784
8785 ArrayRef<EVT> Res(Intr->value_begin() + 1, Intr->value_end());
8786
8787 // build the new intrinsic call
8788 SDNode *Result = DAG.getNode(CFNode, DL, DAG.getVTList(Res), Ops).getNode();
8789
8790 if (!HaveChain) {
8791 SDValue Ops[] = {SDValue(Result, 0), BRCOND.getOperand(0)};
8792
8794 }
8795
8796 if (BR) {
8797 // Give the branch instruction our target
8798 SDValue Ops[] = {BR->getOperand(0), BRCOND.getOperand(2)};
8799 SDValue NewBR = DAG.getNode(ISD::BR, DL, BR->getVTList(), Ops);
8800 DAG.ReplaceAllUsesWith(BR, NewBR.getNode());
8801 }
8802
8803 SDValue Chain = SDValue(Result, Result->getNumValues() - 1);
8804
8805 // Copy the intrinsic results to registers
8806 for (unsigned i = 1, e = Intr->getNumValues() - 1; i != e; ++i) {
8807 SDNode *CopyToReg = findUser(SDValue(Intr, i), ISD::CopyToReg);
8808 if (!CopyToReg)
8809 continue;
8810
8811 Chain = DAG.getCopyToReg(Chain, DL, CopyToReg->getOperand(1),
8812 SDValue(Result, i - 1), SDValue());
8813
8814 DAG.ReplaceAllUsesWith(SDValue(CopyToReg, 0), CopyToReg->getOperand(0));
8815 }
8816
8817 // Remove the old intrinsic from the chain
8818 DAG.ReplaceAllUsesOfValueWith(SDValue(Intr, Intr->getNumValues() - 1),
8819 Intr->getOperand(0));
8820
8821 return Chain;
8822}
8823
8824SDValue SITargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
8825 MVT VT = Op.getSimpleValueType();
8826 SDLoc DL(Op);
8827 // Checking the depth
8828 if (Op.getConstantOperandVal(0) != 0)
8829 return DAG.getConstant(0, DL, VT);
8830
8832 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8833 // Check for kernel and shader functions
8834 if (Info->isEntryFunction())
8835 return DAG.getConstant(0, DL, VT);
8836
8837 MachineFrameInfo &MFI = MF.getFrameInfo();
8838 // There is a call to @llvm.returnaddress in this function
8839 MFI.setReturnAddressIsTaken(true);
8840
8841 const SIRegisterInfo *TRI = getSubtarget()->getRegisterInfo();
8842 // Get the return address reg and mark it as an implicit live-in
8843 Register Reg = MF.addLiveIn(TRI->getReturnAddressReg(MF),
8844 getRegClassFor(VT, Op.getNode()->isDivergent()));
8845
8846 return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT);
8847}
8848
8849SDValue SITargetLowering::LowerSPONENTRY(SDValue Op, SelectionDAG &DAG) const {
8851 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
8852
8853 // For functions that set up their own stack, select the GET_STACK_BASE
8854 // pseudo.
8855 if (MFI->isBottomOfStack())
8856 return Op;
8857
8858 // For everything else, create a dummy stack object.
8859 int FI = MF.getFrameInfo().CreateFixedObject(1, 0, /*IsImmutable=*/false);
8860 return DAG.getFrameIndex(FI, Op.getValueType());
8861}
8862
8863SDValue SITargetLowering::getFPExtOrFPRound(SelectionDAG &DAG, SDValue Op,
8864 const SDLoc &DL, EVT VT) const {
8865 return Op.getValueType().bitsLE(VT)
8866 ? DAG.getNode(ISD::FP_EXTEND, DL, VT, Op)
8867 : DAG.getNode(ISD::FP_ROUND, DL, VT, Op,
8868 DAG.getTargetConstant(0, DL, MVT::i32));
8869}
8870
8871SDValue SITargetLowering::splitFP_ROUNDVectorOp(SDValue Op,
8872 SelectionDAG &DAG) const {
8873 EVT DstVT = Op.getValueType();
8874 unsigned NumElts = DstVT.getVectorNumElements();
8875 assert(NumElts > 2 && isPowerOf2_32(NumElts));
8876
8877 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
8878
8879 SDLoc DL(Op);
8880 unsigned Opc = Op.getOpcode();
8881 SDValue Flags = Op.getOperand(1);
8882 EVT HalfDstVT =
8883 EVT::getVectorVT(*DAG.getContext(), DstVT.getScalarType(), NumElts / 2);
8884 SDValue OpLo = DAG.getNode(Opc, DL, HalfDstVT, Lo, Flags);
8885 SDValue OpHi = DAG.getNode(Opc, DL, HalfDstVT, Hi, Flags);
8886
8887 return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, OpLo, OpHi);
8888}
8889
8890SDValue SITargetLowering::lowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const {
8891 bool IsStrict = Op->isStrictFPOpcode();
8892 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
8893 EVT SrcVT = Src.getValueType();
8894 EVT DstVT = Op.getValueType();
8895
8896 if (DstVT.isVectorOf(MVT::f16)) {
8897 assert(Subtarget->hasCvtPkF16F32Inst() && "support v_cvt_pk_f16_f32");
8898 if (SrcVT.getScalarType() != MVT::f32)
8899 return SDValue();
8900 return SrcVT == MVT::v2f32 ? Op : splitFP_ROUNDVectorOp(Op, DAG);
8901 }
8902
8903 if (SrcVT.getScalarType() != MVT::f64)
8904 return Op;
8905
8906 SDLoc DL(Op);
8907 if (DstVT == MVT::f16) {
8908 // TODO: Handle strictfp
8909 if (Op.getOpcode() != ISD::FP_ROUND)
8910 return Op;
8911
8912 if (!Subtarget->has16BitInsts()) {
8913 SDValue FpToFp16 = DAG.getNode(ISD::FP_TO_FP16, DL, MVT::i32, Src);
8914 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8915 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8916 }
8917 if (Op->getFlags().hasApproximateFuncs()) {
8918 SDValue Flags = Op.getOperand(1);
8919 SDValue Src32 = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, Src, Flags);
8920 return DAG.getNode(ISD::FP_ROUND, DL, MVT::f16, Src32, Flags);
8921 }
8922 SDValue FpToFp16 = LowerF64ToF16Safe(Src, DL, DAG);
8923 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8924 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8925 }
8926
8927 assert(DstVT.getScalarType() == MVT::bf16 &&
8928 "custom lower FP_ROUND for f16 or bf16");
8929 assert(Subtarget->hasBF16ConversionInsts() && "f32 -> bf16 is legal");
8930
8931 // Round-inexact-to-odd f64 to f32, then do the final rounding using the
8932 // hardware f32 -> bf16 instruction.
8933 EVT F32VT = SrcVT.changeElementType(*DAG.getContext(), MVT::f32);
8934 SDValue Rod = expandRoundInexactToOdd(F32VT, Src, DL, DAG);
8935 if (IsStrict) {
8936 return DAG.getNode(
8937 ISD::STRICT_FP_ROUND, DL, {DstVT, MVT::Other},
8938 {Op.getOperand(0), Rod, DAG.getTargetConstant(0, DL, MVT::i32)});
8939 }
8940 return DAG.getNode(ISD::FP_ROUND, DL, DstVT, Rod,
8941 DAG.getTargetConstant(0, DL, MVT::i32));
8942}
8943
8944SDValue SITargetLowering::lowerFMINNUM_FMAXNUM(SDValue Op,
8945 SelectionDAG &DAG) const {
8946 EVT VT = Op.getValueType();
8947 const MachineFunction &MF = DAG.getMachineFunction();
8948 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8949 bool IsIEEEMode = Info->getMode().IEEE;
8950
8951 // FIXME: Assert during selection that this is only selected for
8952 // ieee_mode. Currently a combine can produce the ieee version for non-ieee
8953 // mode functions, but this happens to be OK since it's only done in cases
8954 // where there is known no sNaN.
8955 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8956 return expandFMINNUM_FMAXNUM(Op.getNode(), DAG);
8957
8958 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8959 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8960 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8961 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8962 return splitBinaryVectorOp(Op, DAG);
8963 return Op;
8964}
8965
8966SDValue
8967SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(SDValue Op,
8968 SelectionDAG &DAG) const {
8969 EVT VT = Op.getValueType();
8970 const MachineFunction &MF = DAG.getMachineFunction();
8971 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8972 bool IsIEEEMode = Info->getMode().IEEE;
8973
8974 if (IsIEEEMode && !Subtarget->hasIEEEMinimumMaximumInsts())
8975 return expandFMINIMUMNUM_FMAXIMUMNUM(Op.getNode(), DAG);
8976
8977 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8978 VT == MVT::v32f16 || VT == MVT::v4bf16 || VT == MVT::v8bf16 ||
8979 VT == MVT::v16bf16 || VT == MVT::v32bf16 || VT == MVT::v4f64 ||
8980 VT == MVT::v8f64 || VT == MVT::v16f64 || VT == MVT::v32f64)
8981 return splitBinaryVectorOp(Op, DAG);
8982 return Op;
8983}
8984
8985SDValue SITargetLowering::lowerFLDEXP(SDValue Op, SelectionDAG &DAG) const {
8986 bool IsStrict = Op.getOpcode() == ISD::STRICT_FLDEXP;
8987 EVT VT = Op.getValueType();
8988 assert(VT == MVT::f16);
8989
8990 SDValue Exp = Op.getOperand(IsStrict ? 2 : 1);
8991 EVT ExpVT = Exp.getValueType();
8992 if (ExpVT == MVT::i16)
8993 return Op;
8994
8995 SDLoc DL(Op);
8996
8997 // Correct the exponent type for f16 to i16.
8998 // Clamp the range of the exponent to the instruction's range.
8999
9000 // TODO: This should be a generic narrowing legalization, and can easily be
9001 // for GlobalISel.
9002
9003 SDValue MinExp = DAG.getSignedConstant(minIntN(16), DL, ExpVT);
9004 SDValue ClampMin = DAG.getNode(ISD::SMAX, DL, ExpVT, Exp, MinExp);
9005
9006 SDValue MaxExp = DAG.getSignedConstant(maxIntN(16), DL, ExpVT);
9007 SDValue Clamp = DAG.getNode(ISD::SMIN, DL, ExpVT, ClampMin, MaxExp);
9008
9009 SDValue TruncExp = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Clamp);
9010
9011 if (IsStrict) {
9012 return DAG.getNode(ISD::STRICT_FLDEXP, DL, {VT, MVT::Other},
9013 {Op.getOperand(0), Op.getOperand(1), TruncExp});
9014 }
9015
9016 return DAG.getNode(ISD::FLDEXP, DL, VT, Op.getOperand(0), TruncExp);
9017}
9018
9020 switch (Op->getOpcode()) {
9021 case ISD::ABS:
9022 case ISD::SRA:
9023 case ISD::SMIN:
9024 case ISD::SMAX:
9025 return ISD::SIGN_EXTEND;
9026 case ISD::SRL:
9027 case ISD::UMIN:
9028 case ISD::UMAX:
9029 case ISD::USUBSAT:
9030 case ISD::UADDSAT:
9031 return ISD::ZERO_EXTEND;
9032 case ISD::ADD:
9033 case ISD::SUB:
9034 case ISD::AND:
9035 case ISD::OR:
9036 case ISD::XOR:
9037 case ISD::SHL:
9038 case ISD::SELECT:
9039 case ISD::MUL:
9040 // operation result won't be influenced by garbage high bits.
9041 // TODO: are all of those cases correct, and are there more?
9042 return ISD::ANY_EXTEND;
9043 case ISD::SETCC: {
9044 ISD::CondCode CC = Op.getOperandCondCode(2);
9046 }
9047 default:
9048 llvm_unreachable("unexpected opcode!");
9049 }
9050}
9051
9052SDValue
9053SITargetLowering::promoteUniformUnaryOpToI32(SDValue Op,
9054 DAGCombinerInfo &DCI) const {
9055 EVT OpTy = Op.getValueType();
9056 SelectionDAG &DAG = DCI.DAG;
9057 EVT ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
9058
9059 if (isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
9060 return SDValue();
9061
9062 SDLoc DL(Op);
9063 SDValue Input = Op.getOperand(0);
9064 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
9065 Input = DAG.getNode(ExtOp, DL, ExtTy, Input);
9066
9067 SDValue NewVal = DAG.getNode(Op.getOpcode(), DL, ExtTy, Input);
9068
9069 return DAG.getNode(ISD::TRUNCATE, DL, OpTy, NewVal);
9070}
9071
9072SDValue SITargetLowering::promoteUniformOpToI32(SDValue Op,
9073 DAGCombinerInfo &DCI) const {
9074 const unsigned Opc = Op.getOpcode();
9075 assert(Opc == ISD::ADD || Opc == ISD::SUB || Opc == ISD::SHL ||
9076 Opc == ISD::SRL || Opc == ISD::SRA || Opc == ISD::AND ||
9077 Opc == ISD::OR || Opc == ISD::XOR || Opc == ISD::MUL ||
9078 Opc == ISD::SETCC || Opc == ISD::SELECT || Opc == ISD::SMIN ||
9079 Opc == ISD::SMAX || Opc == ISD::UMIN || Opc == ISD::UMAX ||
9080 Opc == ISD::USUBSAT || Opc == ISD::UADDSAT);
9081
9082 EVT OpTy = (Opc != ISD::SETCC) ? Op.getValueType()
9083 : Op->getOperand(0).getValueType();
9084 auto &DAG = DCI.DAG;
9085 auto ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
9086
9087 if (DCI.isBeforeLegalizeOps() ||
9088 isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
9089 return SDValue();
9090
9091 SDLoc DL(Op);
9092 SDValue LHS;
9093 SDValue RHS;
9094 if (Opc == ISD::SELECT) {
9095 LHS = Op->getOperand(1);
9096 RHS = Op->getOperand(2);
9097 } else {
9098 LHS = Op->getOperand(0);
9099 RHS = Op->getOperand(1);
9100 }
9101
9102 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
9103 LHS = DAG.getNode(ExtOp, DL, ExtTy, {LHS});
9104
9105 // Special case: for shifts, the RHS always needs a zext.
9106 if (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA)
9107 RHS = DAG.getNode(ISD::ZERO_EXTEND, DL, ExtTy, {RHS});
9108 else
9109 RHS = DAG.getNode(ExtOp, DL, ExtTy, {RHS});
9110
9111 // setcc always return i1/i1 vec so no need to truncate after.
9112 if (Opc == ISD::SETCC) {
9113 ISD::CondCode CC = Op.getOperandCondCode(2);
9114 return DAG.getSetCC(DL, Op.getValueType(), LHS, RHS, CC);
9115 }
9116
9117 // For other ops, we extend the operation's return type as well so we need to
9118 // truncate back to the original type.
9119 SDValue NewVal;
9120 if (Opc == ISD::SELECT)
9121 NewVal = DAG.getNode(ISD::SELECT, DL, ExtTy, {Op->getOperand(0), LHS, RHS});
9122 else if (Opc == ISD::UADDSAT) {
9123 SDValue Sum = DAG.getNode(ISD::ADD, DL, ExtTy, LHS, RHS);
9124 SDValue MaxVal = DAG.getConstant(
9125 APInt::getMaxValue(OpTy.getScalarSizeInBits()).zext(32), DL, ExtTy);
9126 NewVal = DAG.getNode(ISD::UMIN, DL, ExtTy, Sum, MaxVal);
9127 } else
9128 NewVal = DAG.getNode(Opc, DL, ExtTy, {LHS, RHS});
9129
9130 return DAG.getZExtOrTrunc(NewVal, DL, OpTy);
9131}
9132
9133SDValue SITargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
9134 SDValue Mag = Op.getOperand(0);
9135 EVT MagVT = Mag.getValueType();
9136
9137 if (MagVT.getVectorNumElements() > 2)
9138 return splitBinaryVectorOp(Op, DAG);
9139
9140 SDValue Sign = Op.getOperand(1);
9141 EVT SignVT = Sign.getValueType();
9142
9143 if (MagVT == SignVT)
9144 return Op;
9145
9146 // fcopysign v2f16:mag, v2f32:sign ->
9147 // fcopysign v2f16:mag,
9148 // bitcast (trunc (srl (bitcast sign to v2i32), 16) to v2i16)
9149
9150 SDLoc SL(Op);
9151 SDValue SignAsInt32 = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Sign);
9152 SDValue ShiftAmt = DAG.getShiftAmountConstant(16, MVT::v2i32, SL);
9153 SDValue SignShifted =
9154 DAG.getNode(ISD::SRL, SL, MVT::v2i32, SignAsInt32, ShiftAmt);
9155 SDValue SignAsInt16 = DAG.getNode(ISD::TRUNCATE, SL, MVT::v2i16, SignShifted);
9156
9157 SDValue SignAsHalf16 = DAG.getNode(ISD::BITCAST, SL, MagVT, SignAsInt16);
9158
9159 return DAG.getNode(ISD::FCOPYSIGN, SL, MagVT, Mag, SignAsHalf16);
9160}
9161
9162// Custom lowering for vector multiplications and s_mul_u64.
9163SDValue SITargetLowering::lowerMUL(SDValue Op, SelectionDAG &DAG) const {
9164 EVT VT = Op.getValueType();
9165
9166 // Split vector operands.
9167 if (VT.isVector())
9168 return splitBinaryVectorOp(Op, DAG);
9169
9170 assert(VT == MVT::i64 && "The following code is a special for s_mul_u64");
9171
9172 // There are four ways to lower s_mul_u64:
9173 //
9174 // 1. If all the operands are uniform, then we lower it as it is.
9175 //
9176 // 2. If the operands are divergent, then we have to split s_mul_u64 in 32-bit
9177 // multiplications because there is not a vector equivalent of s_mul_u64.
9178 //
9179 // 3. If the cost model decides that it is more efficient to use vector
9180 // registers, then we have to split s_mul_u64 in 32-bit multiplications.
9181 // This happens in splitScalarSMULU64() in SIInstrInfo.cpp .
9182 //
9183 // 4. If the cost model decides to use vector registers and both of the
9184 // operands are zero-extended/sign-extended from 32-bits, then we split the
9185 // s_mul_u64 in two 32-bit multiplications. The problem is that it is not
9186 // possible to check if the operands are zero-extended or sign-extended in
9187 // SIInstrInfo.cpp. For this reason, here, we replace s_mul_u64 with
9188 // s_mul_u64_u32_pseudo if both operands are zero-extended and we replace
9189 // s_mul_u64 with s_mul_i64_i32_pseudo if both operands are sign-extended.
9190 // If the cost model decides that we have to use vector registers, then
9191 // splitScalarSMulPseudo() (in SIInstrInfo.cpp) split s_mul_u64_u32/
9192 // s_mul_i64_i32_pseudo in two vector multiplications. If the cost model
9193 // decides that we should use scalar registers, then s_mul_u64_u32_pseudo/
9194 // s_mul_i64_i32_pseudo is lowered as s_mul_u64 in expandPostRAPseudo() in
9195 // SIInstrInfo.cpp .
9196
9197 if (Op->isDivergent())
9198 return SDValue();
9199
9200 SDValue Op0 = Op.getOperand(0);
9201 SDValue Op1 = Op.getOperand(1);
9202 // If all the operands are zero-enteted to 32-bits, then we replace s_mul_u64
9203 // with s_mul_u64_u32_pseudo. If all the operands are sign-extended to
9204 // 32-bits, then we replace s_mul_u64 with s_mul_i64_i32_pseudo.
9205 KnownBits Op0KnownBits = DAG.computeKnownBits(Op0);
9206 unsigned Op0LeadingZeros = Op0KnownBits.countMinLeadingZeros();
9207 KnownBits Op1KnownBits = DAG.computeKnownBits(Op1);
9208 unsigned Op1LeadingZeros = Op1KnownBits.countMinLeadingZeros();
9209 SDLoc SL(Op);
9210 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9211 return SDValue(
9212 DAG.getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9213 unsigned Op0SignBits = DAG.ComputeNumSignBits(Op0);
9214 unsigned Op1SignBits = DAG.ComputeNumSignBits(Op1);
9215 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9216 return SDValue(
9217 DAG.getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9218 // If all the operands are uniform, then we lower s_mul_u64 as it is.
9219 return Op;
9220}
9221
9222SDValue SITargetLowering::lowerXMULO(SDValue Op, SelectionDAG &DAG) const {
9223 EVT VT = Op.getValueType();
9224 SDLoc SL(Op);
9225 SDValue LHS = Op.getOperand(0);
9226 SDValue RHS = Op.getOperand(1);
9227 bool isSigned = Op.getOpcode() == ISD::SMULO;
9228
9229 if (ConstantSDNode *RHSC = isConstOrConstSplat(RHS)) {
9230 const APInt &C = RHSC->getAPIntValue();
9231 // mulo(X, 1 << S) -> { X << S, (X << S) >> S != X }
9232 if (C.isPowerOf2()) {
9233 // smulo(x, signed_min) is same as umulo(x, signed_min).
9234 bool UseArithShift = isSigned && !C.isMinSignedValue();
9235 SDValue ShiftAmt = DAG.getConstant(C.logBase2(), SL, MVT::i32);
9236 SDValue Result = DAG.getNode(ISD::SHL, SL, VT, LHS, ShiftAmt);
9237 SDValue Overflow =
9238 DAG.getSetCC(SL, MVT::i1,
9239 DAG.getNode(UseArithShift ? ISD::SRA : ISD::SRL, SL, VT,
9240 Result, ShiftAmt),
9241 LHS, ISD::SETNE);
9242 return DAG.getMergeValues({Result, Overflow}, SL);
9243 }
9244 }
9245
9246 SDValue Result = DAG.getNode(ISD::MUL, SL, VT, LHS, RHS);
9247 SDValue Top =
9248 DAG.getNode(isSigned ? ISD::MULHS : ISD::MULHU, SL, VT, LHS, RHS);
9249
9250 SDValue Sign = isSigned
9251 ? DAG.getNode(ISD::SRA, SL, VT, Result,
9252 DAG.getConstant(VT.getScalarSizeInBits() - 1,
9253 SL, MVT::i32))
9254 : DAG.getConstant(0, SL, VT);
9255 SDValue Overflow = DAG.getSetCC(SL, MVT::i1, Top, Sign, ISD::SETNE);
9256
9257 return DAG.getMergeValues({Result, Overflow}, SL);
9258}
9259
9260SDValue SITargetLowering::lowerXMUL_LOHI(SDValue Op, SelectionDAG &DAG) const {
9261 if (Op->isDivergent()) {
9262 // Select to V_MAD_[IU]64_[IU]32.
9263 return Op;
9264 }
9265 if (Subtarget->hasSMulHi()) {
9266 // Expand to S_MUL_I32 + S_MUL_HI_[IU]32.
9267 return SDValue();
9268 }
9269 // The multiply is uniform but we would have to use V_MUL_HI_[IU]32 to
9270 // calculate the high part, so we might as well do the whole thing with
9271 // V_MAD_[IU]64_[IU]32.
9272 return Op;
9273}
9274
9275SDValue SITargetLowering::lowerTRAP(SDValue Op, SelectionDAG &DAG) const {
9276 if (!Subtarget->hasTrapHandler() ||
9277 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA)
9278 return lowerTrapEndpgm(Op, DAG);
9279
9280 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(Op, DAG)
9281 : lowerTrapHsaQueuePtr(Op, DAG);
9282}
9283
9284SDValue SITargetLowering::lowerTrapEndpgm(SDValue Op, SelectionDAG &DAG) const {
9285 SDLoc SL(Op);
9286 SDValue Chain = Op.getOperand(0);
9287 return DAG.getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9288}
9289
9290SDValue
9291SITargetLowering::loadImplicitKernelArgument(SelectionDAG &DAG, MVT VT,
9292 const SDLoc &DL, Align Alignment,
9293 ImplicitParameter Param) const {
9296 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, DAG.getEntryNode(), Offset);
9297 MachinePointerInfo PtrInfo =
9299 return DAG.getLoad(
9300 VT, DL, DAG.getEntryNode(), Ptr, PtrInfo.getWithOffset(Offset), Alignment,
9302}
9303
9304SDValue SITargetLowering::lowerTrapHsaQueuePtr(SDValue Op,
9305 SelectionDAG &DAG) const {
9306 SDLoc SL(Op);
9307 SDValue Chain = Op.getOperand(0);
9308
9309 SDValue QueuePtr;
9310 // For code object version 5, QueuePtr is passed through implicit kernarg.
9311 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9313 QueuePtr =
9314 loadImplicitKernelArgument(DAG, MVT::i64, SL, Align(8), QUEUE_PTR);
9315 } else {
9317 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9318 Register UserSGPR = Info->getQueuePtrUserSGPR();
9319
9320 if (UserSGPR == AMDGPU::NoRegister) {
9321 // We probably are in a function incorrectly marked with
9322 // amdgpu-no-queue-ptr. This is undefined. We don't want to delete the
9323 // trap, so just use a null pointer.
9324 QueuePtr = DAG.getConstant(0, SL, MVT::i64);
9325 } else {
9326 QueuePtr = CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR,
9327 MVT::i64);
9328 }
9329 }
9330
9331 SDValue SGPR01 = DAG.getRegister(AMDGPU::SGPR0_SGPR1, MVT::i64);
9332 SDValue ToReg = DAG.getCopyToReg(Chain, SL, SGPR01, QueuePtr, SDValue());
9333
9335 SDValue Ops[] = {ToReg, DAG.getTargetConstant(TrapID, SL, MVT::i16), SGPR01,
9336 ToReg.getValue(1)};
9337 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9338}
9339
9340SDValue SITargetLowering::lowerTrapHsa(SDValue Op, SelectionDAG &DAG) const {
9341 SDLoc SL(Op);
9342 SDValue Chain = Op.getOperand(0);
9343
9344 // We need to simulate the 's_trap 2' instruction on targets that run in
9345 // PRIV=1 (where it is treated as a nop).
9346 if (Subtarget->hasPrivEnabledTrap2NopBug())
9347 return DAG.getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9348
9350 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9351 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9352}
9353
9354SDValue SITargetLowering::lowerDEBUGTRAP(SDValue Op, SelectionDAG &DAG) const {
9355 SDLoc SL(Op);
9356 SDValue Chain = Op.getOperand(0);
9358
9359 if (!Subtarget->hasTrapHandler() ||
9360 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA) {
9361 LLVMContext &Ctx = MF.getFunction().getContext();
9362 Ctx.diagnose(DiagnosticInfoUnsupported(MF.getFunction(),
9363 "debugtrap handler not supported",
9364 Op.getDebugLoc(), DS_Warning));
9365 return Chain;
9366 }
9367
9368 uint64_t TrapID =
9370 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9371 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9372}
9373
9374/// When a divergent value (in VGPR) is passed to an inline asm with an SGPR
9375/// constraint ('s'), we need to insert v_readfirstlane to move the value from
9376/// VGPR to SGPR. This is done by modifying the CopyToReg nodes in the glue
9377/// chain that feed into the INLINEASM node.
9378SDValue SITargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
9379 unsigned NumOps = Op.getNumOperands();
9380
9381 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
9382 SmallSet<Register, 8> SGPRInputRegs;
9383
9384 unsigned NumVals = 0;
9385 for (unsigned I = InlineAsm::Op_FirstOperand; I < NumOps - 1;
9386 I += 1 + NumVals) {
9387 const InlineAsm::Flag Flags(Op.getConstantOperandVal(I));
9388 NumVals = Flags.getNumOperandRegisters();
9389
9390 unsigned RCID;
9391 bool IsSGPRInput = Flags.getKind() == InlineAsm::Kind::RegUse &&
9392 NumVals > 0 && Flags.hasRegClassConstraint(RCID) &&
9393 TRI->isSGPRClass(TRI->getRegClass(RCID));
9394
9395 for (unsigned J = 0; J < NumVals; ++J) {
9396 SDValue Val = Op.getOperand(I + 1 + J);
9397 if (const RegisterSDNode *RegNode =
9399 Register Reg = RegNode->getReg();
9400 if (IsSGPRInput || (Reg.isPhysical() && TRI->isSGPRPhysReg(Reg)))
9401 SGPRInputRegs.insert(Reg);
9402 }
9403 }
9404 }
9405
9406 if (SGPRInputRegs.empty())
9407 return Op;
9408
9409 // Walk the glue chain and insert readfirstlane for divergent SGPR inputs.
9410 SDLoc DL(Op);
9411 SDNode *N = Op.getOperand(NumOps - 1).getNode();
9412
9413 while (N && N->getOpcode() == ISD::CopyToReg) {
9414 Register Reg = cast<RegisterSDNode>(N->getOperand(1))->getReg();
9415 SDValue SrcVal = N->getOperand(2);
9416
9417 // Insert readfirstlane if copying a divergent value to an SGPR input.
9418 if (SrcVal->isDivergent() && SGPRInputRegs.count(Reg)) {
9419 SDValue ReadFirstLaneID =
9420 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
9421 SDValue ReadFirstLane =
9423 ReadFirstLaneID, SrcVal);
9424
9425 SmallVector<SDValue, 4> Ops = {N->getOperand(0), N->getOperand(1),
9426 ReadFirstLane};
9427 if (N->getNumOperands() > 3)
9428 Ops.push_back(N->getOperand(3)); // Glue input
9429
9430 DAG.UpdateNodeOperands(N, Ops);
9431 }
9432
9433 // Follow glue chain to next CopyToReg.
9434 SDNode *Next = nullptr;
9435 for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I) {
9436 if (N->getOperand(I).getValueType() == MVT::Glue) {
9437 Next = N->getOperand(I).getNode();
9438 break;
9439 }
9440 }
9441 N = Next;
9442 }
9443
9444 return Op;
9445}
9446
9447SDValue SITargetLowering::getSegmentAperture(unsigned AS, const SDLoc &DL,
9448 SelectionDAG &DAG) const {
9449 unsigned BaseAS = AS;
9450 unsigned SANum = AMDGPU::getSyntheticApertureNumber(AS);
9452 BaseAS = AMDGPUAS::LOCAL_ADDRESS;
9453
9454 SDValue Aperture = getBaseSegmentAperture(BaseAS, DL, DAG);
9455
9456 if (SANum != AMDGPU::SyntheticAperture::None) {
9457 SDValue Tag = DAG.getConstant(SANum, DL, MVT::i32);
9458 return DAG.getNode(ISD::OR, DL, MVT::i32, Aperture, Tag);
9459 }
9460
9461 return Aperture;
9462}
9463
9464SDValue SITargetLowering::getBaseSegmentAperture(unsigned AS, const SDLoc &DL,
9465 SelectionDAG &DAG) const {
9466 const bool IsLDS = (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::BARRIER);
9467
9468 if (Subtarget->hasApertureRegs()) {
9469 const unsigned ApertureRegNo =
9470 IsLDS ? AMDGPU::SRC_SHARED_BASE : AMDGPU::SRC_PRIVATE_BASE;
9471 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9472 !Subtarget->hasGloballyAddressableScratch()) &&
9473 "Cannot use src_private_base with globally addressable scratch!");
9474 // Note: this feature (register) is broken. When used as a 32-bit operand,
9475 // it returns a wrong value (all zeroes?). The real value is in the upper 32
9476 // bits.
9477 //
9478 // To work around the issue, emit a 64 bit copy from this register
9479 // then extract the high bits. Note that this shouldn't even result in a
9480 // shift being emitted and simply become a pair of registers (e.g.):
9481 // s_mov_b64 s[6:7], src_shared_base
9482 // v_mov_b32_e32 v1, s7
9483 SDValue Copy =
9484 DAG.getCopyFromReg(DAG.getEntryNode(), DL, ApertureRegNo, MVT::v2i32);
9485 return DAG.getExtractVectorElt(DL, MVT::i32, Copy, 1);
9486 }
9487
9488 // For code object version 5, private_base and shared_base are passed through
9489 // implicit kernargs.
9490 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9493 return loadImplicitKernelArgument(DAG, MVT::i32, DL, Align(4), Param);
9494 }
9495
9497 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9498 Register UserSGPR = Info->getQueuePtrUserSGPR();
9499 if (UserSGPR == AMDGPU::NoRegister) {
9500 // We probably are in a function incorrectly marked with
9501 // amdgpu-no-queue-ptr. This is undefined.
9502 return DAG.getPOISON(MVT::i32);
9503 }
9504
9505 SDValue QueuePtr =
9506 CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR, MVT::i64);
9507
9508 // Offset into amd_queue_t for group_segment_aperture_base_hi /
9509 // private_segment_aperture_base_hi.
9510 uint32_t StructOffset = IsLDS ? 0x40 : 0x44;
9511
9512 SDValue Ptr =
9513 DAG.getObjectPtrOffset(DL, QueuePtr, TypeSize::getFixed(StructOffset));
9514
9515 // TODO: Use custom target PseudoSourceValue.
9516 // TODO: We should use the value from the IR intrinsic call, but it might not
9517 // be available and how do we get it?
9518 MachinePointerInfo PtrInfo(AMDGPUAS::CONSTANT_ADDRESS);
9519 return DAG.getLoad(MVT::i32, DL, QueuePtr.getValue(1), Ptr, PtrInfo,
9520 commonAlignment(Align(64), StructOffset),
9523}
9524
9525/// Return true if the value is a known valid address, such that a null check is
9526/// not necessary.
9528 const AMDGPUTargetMachine &TM, unsigned AddrSpace) {
9530 return true;
9531
9532 if (auto *ConstVal = dyn_cast<ConstantSDNode>(Val))
9533 return ConstVal->getSExtValue() != AMDGPU::getNullPointerValue(AddrSpace);
9534
9535 // TODO: Search through arithmetic, handle arguments and loads
9536 // marked nonnull.
9537 return false;
9538}
9539
9540SDValue SITargetLowering::lowerADDRSPACECAST(SDValue Op,
9541 SelectionDAG &DAG) const {
9542 SDLoc SL(Op);
9543
9544 const AMDGPUTargetMachine &TM =
9545 static_cast<const AMDGPUTargetMachine &>(getTargetMachine());
9546
9547 const auto *ASC = cast<AddrSpaceCastSDNode>(Op);
9548 unsigned SrcAS = ASC->getSrcAddressSpace();
9549 SDValue Src = ASC->getOperand(0);
9550 unsigned DestAS = ASC->getDestAddressSpace();
9551 bool IsNonNull = ASC->getFlags().hasNonNull();
9552
9553 SDValue FlatNullPtr = DAG.getConstant(0, SL, MVT::i64);
9554
9555 // flat -> local/private/barrier
9556 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
9557 if (DestAS == AMDGPUAS::LOCAL_ADDRESS ||
9558 DestAS == AMDGPUAS::PRIVATE_ADDRESS || DestAS == AMDGPUAS::BARRIER) {
9559 SDValue Ptr = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9560
9561 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
9562 Subtarget->hasGloballyAddressableScratch()) {
9563 // flat -> private with globally addressable scratch: subtract
9564 // src_flat_scratch_base_lo.
9565 SDValue FlatScratchBaseLo(
9566 DAG.getMachineNode(
9567 AMDGPU::S_MOV_B32, SL, MVT::i32,
9568 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9569 0);
9570 Ptr = DAG.getNode(ISD::SUB, SL, MVT::i32, Ptr, FlatScratchBaseLo);
9571 }
9572
9573 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9574 return Ptr;
9575
9576 unsigned NullVal = AMDGPU::getNullPointerValue(DestAS);
9577 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9578 SDValue NonNull = DAG.getSetCC(SL, MVT::i1, Src, FlatNullPtr, ISD::SETNE);
9579
9580 return DAG.getNode(ISD::SELECT, SL, MVT::i32, NonNull, Ptr,
9581 SegmentNullPtr);
9582 }
9583 }
9584
9585 // local/private/barrier -> flat
9586 if (DestAS == AMDGPUAS::FLAT_ADDRESS) {
9587 if (SrcAS == AMDGPUAS::LOCAL_ADDRESS ||
9588 SrcAS == AMDGPUAS::PRIVATE_ADDRESS || SrcAS == AMDGPUAS::BARRIER) {
9589 SDValue CvtPtr;
9590 if (SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
9591 Subtarget->hasGloballyAddressableScratch()) {
9592 // For wave32: Addr = (TID[4:0] << 52) + FLAT_SCRATCH_BASE + privateAddr
9593 // For wave64: Addr = (TID[5:0] << 51) + FLAT_SCRATCH_BASE + privateAddr
9594 SDValue AllOnes = DAG.getSignedTargetConstant(-1, SL, MVT::i32);
9595 SDValue ThreadID = DAG.getConstant(0, SL, MVT::i32);
9596 ThreadID = DAG.getNode(
9597 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9598 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_lo, SL, MVT::i32),
9599 AllOnes, ThreadID);
9600 if (Subtarget->isWave64())
9601 ThreadID = DAG.getNode(
9602 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9603 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_hi, SL, MVT::i32),
9604 AllOnes, ThreadID);
9605 SDValue ShAmt = DAG.getShiftAmountConstant(
9606 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9607 SDValue SrcHi = DAG.getNode(ISD::SHL, SL, MVT::i32, ThreadID, ShAmt);
9608 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, SrcHi);
9609 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9610 // Accessing src_flat_scratch_base_lo as a 64-bit operand gives the full
9611 // 64-bit hi:lo value.
9612 SDValue FlatScratchBase = {
9613 DAG.getMachineNode(
9614 AMDGPU::S_MOV_B64, SL, MVT::i64,
9615 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9616 0};
9617 CvtPtr = DAG.getNode(ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9618 } else {
9619 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9620
9621 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Aperture);
9622 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9623 }
9624
9625 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9626 return CvtPtr;
9627
9628 unsigned NullVal = AMDGPU::getNullPointerValue(SrcAS);
9629 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9630
9631 SDValue NonNull =
9632 DAG.getSetCC(SL, MVT::i1, Src, SegmentNullPtr, ISD::SETNE);
9633
9634 return DAG.getNode(ISD::SELECT, SL, MVT::i64, NonNull, CvtPtr,
9635 FlatNullPtr);
9636 }
9637 }
9638
9639 if (SrcAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9640 Op.getValueType() == MVT::i64) {
9641 const SIMachineFunctionInfo *Info =
9642 DAG.getMachineFunction().getInfo<SIMachineFunctionInfo>();
9643 if (Info->get32BitAddressHighBits() == 0)
9644 return DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i64, Src);
9645
9646 SDValue Hi = DAG.getConstant(Info->get32BitAddressHighBits(), SL, MVT::i32);
9647 SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Hi);
9648 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
9649 }
9650
9651 if (DestAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9652 Src.getValueType() == MVT::i64)
9653 return DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9654
9655 // global <-> flat are no-ops and never emitted.
9656
9657 // Invalid casts are poison.
9658 return DAG.getPOISON(Op->getValueType(0));
9659}
9660
9661// This lowers an INSERT_SUBVECTOR by extracting the individual elements from
9662// the small vector and inserting them into the big vector. That is better than
9663// the default expansion of doing it via a stack slot. Even though the use of
9664// the stack slot would be optimized away afterwards, the stack slot itself
9665// remains.
9666SDValue SITargetLowering::lowerINSERT_SUBVECTOR(SDValue Op,
9667 SelectionDAG &DAG) const {
9668 SDValue Vec = Op.getOperand(0);
9669 SDValue Ins = Op.getOperand(1);
9670 SDValue Idx = Op.getOperand(2);
9671 EVT VecVT = Vec.getValueType();
9672 EVT InsVT = Ins.getValueType();
9673 EVT EltVT = VecVT.getVectorElementType();
9674 unsigned InsNumElts = InsVT.getVectorNumElements();
9675 unsigned IdxVal = Idx->getAsZExtVal();
9676 SDLoc SL(Op);
9677
9678 if (EltVT.getScalarSizeInBits() == 16 && IdxVal % 2 == 0) {
9679 // Insert 32-bit registers at a time.
9680 assert(InsNumElts % 2 == 0 && "expect legal vector types");
9681
9682 unsigned VecNumElts = VecVT.getVectorNumElements();
9683 EVT NewVecVT =
9684 EVT::getVectorVT(*DAG.getContext(), MVT::i32, VecNumElts / 2);
9685 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9687 MVT::i32, InsNumElts / 2);
9688
9689 Vec = DAG.getNode(ISD::BITCAST, SL, NewVecVT, Vec);
9690 Ins = DAG.getNode(ISD::BITCAST, SL, NewInsVT, Ins);
9691
9692 for (unsigned I = 0; I != InsNumElts / 2; ++I) {
9693 SDValue Elt;
9694 if (InsNumElts == 2) {
9695 Elt = Ins;
9696 } else {
9697 Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Ins,
9698 DAG.getConstant(I, SL, MVT::i32));
9699 }
9700 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, NewVecVT, Vec, Elt,
9701 DAG.getConstant(IdxVal / 2 + I, SL, MVT::i32));
9702 }
9703
9704 return DAG.getNode(ISD::BITCAST, SL, VecVT, Vec);
9705 }
9706
9707 for (unsigned I = 0; I != InsNumElts; ++I) {
9708 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Ins,
9709 DAG.getConstant(I, SL, MVT::i32));
9710 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, VecVT, Vec, Elt,
9711 DAG.getConstant(IdxVal + I, SL, MVT::i32));
9712 }
9713 return Vec;
9714}
9715
9716SDValue SITargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,
9717 SelectionDAG &DAG) const {
9718 SDValue Vec = Op.getOperand(0);
9719 SDValue InsVal = Op.getOperand(1);
9720 SDValue Idx = Op.getOperand(2);
9721 EVT VecVT = Vec.getValueType();
9722 EVT EltVT = VecVT.getVectorElementType();
9723 unsigned VecSize = VecVT.getSizeInBits();
9724 unsigned EltSize = EltVT.getSizeInBits();
9725 SDLoc SL(Op);
9726
9727 // Specially handle the case of v4i16 with static indexing.
9728 unsigned NumElts = VecVT.getVectorNumElements();
9729 auto *KIdx = dyn_cast<ConstantSDNode>(Idx);
9730 if (NumElts == 4 && EltSize == 16 && KIdx) {
9731 SDValue BCVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Vec);
9732
9733 SDValue LoHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9734 DAG.getConstant(0, SL, MVT::i32));
9735 SDValue HiHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9736 DAG.getConstant(1, SL, MVT::i32));
9737
9738 SDValue LoVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, LoHalf);
9739 SDValue HiVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, HiHalf);
9740
9741 unsigned Idx = KIdx->getZExtValue();
9742 bool InsertLo = Idx < 2;
9743 SDValue InsHalf = DAG.getNode(
9744 ISD::INSERT_VECTOR_ELT, SL, MVT::v2i16, InsertLo ? LoVec : HiVec,
9745 DAG.getNode(ISD::BITCAST, SL, MVT::i16, InsVal),
9746 DAG.getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9747
9748 InsHalf = DAG.getNode(ISD::BITCAST, SL, MVT::i32, InsHalf);
9749
9750 SDValue Concat =
9751 InsertLo ? DAG.getBuildVector(MVT::v2i32, SL, {InsHalf, HiHalf})
9752 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9753
9754 return DAG.getNode(ISD::BITCAST, SL, VecVT, Concat);
9755 }
9756
9757 // Static indexing does not lower to stack access, and hence there is no need
9758 // for special custom lowering to avoid stack access.
9759 if (isa<ConstantSDNode>(Idx))
9760 return SDValue();
9761
9762 // Avoid stack access for dynamic indexing by custom lowering to
9763 // v_bfi_b32 (v_bfm_b32 16, (shl idx, 16)), val, vec
9764 // Vectors wider than 64 bits do this on each 64-bit piece.
9765 assert(isPowerOf2_32(EltSize));
9766 unsigned PieceSize = std::min(VecSize, 64u);
9767 unsigned NumPieces = VecSize / PieceSize;
9768 unsigned EltsPerPiece = PieceSize / EltSize;
9769 MVT IntVT = MVT::getIntegerVT(PieceSize);
9770 EVT PieceVT = EVT::getVectorVT(*DAG.getContext(), EltVT, EltsPerPiece);
9771
9772 // Convert vector index to bit-index within its piece and get the required
9773 // bit mask. Using the index within the piece keeps the shift below 64.
9774 SDValue PieceIdx = Idx;
9775 if (NumPieces > 1)
9776 PieceIdx = DAG.getNode(ISD::AND, SL, MVT::i32, Idx,
9777 DAG.getConstant(EltsPerPiece - 1, SL, MVT::i32));
9778 const auto EltMask = maskTrailingOnes<uint64_t>(EltSize);
9779 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9780 SDValue ScaledIdx =
9781 DAG.getNode(ISD::SHL, SL, MVT::i32, PieceIdx, ScaleFactor);
9782 SDValue BFM = DAG.getNode(ISD::SHL, SL, IntVT,
9783 DAG.getConstant(EltMask, SL, IntVT), ScaledIdx);
9784
9785 // 1. Create a congruent vector with the target value in each element.
9786 SDValue ExtVal =
9787 DAG.getBitcast(IntVT, DAG.getSplatBuildVector(PieceVT, SL, InsVal));
9788
9789 auto InsertIntoPiece = [&](SDValue Piece, SDValue Mask) {
9790 // 2. Mask off all other indices except the required index within (1).
9791 SDValue LHS = DAG.getNode(ISD::AND, SL, IntVT, Mask, ExtVal);
9792
9793 // 3. Mask off the required index within the target vector.
9794 SDValue RHS =
9795 DAG.getNode(ISD::AND, SL, IntVT, DAG.getNOT(SL, Mask, IntVT), Piece);
9796
9797 // 4. Get (2) and (3) ORed into the target vector.
9798 return DAG.getNode(ISD::OR, SL, IntVT, LHS, RHS, SDNodeFlags::Disjoint);
9799 };
9800
9801 if (NumPieces == 1)
9802 return DAG.getBitcast(VecVT,
9803 InsertIntoPiece(DAG.getBitcast(IntVT, Vec), BFM));
9804
9805 // 5. Apply (2)-(4) to each 64-bit piece, with the mask cleared in every
9806 // piece except the one that holds the index, and rebuild the vector.
9807 MVT PiecesVT = MVT::getVectorVT(IntVT, NumPieces);
9808 SDValue BCVec = DAG.getBitcast(PiecesVT, Vec);
9809 SDValue PieceNo =
9810 DAG.getNode(ISD::SRL, SL, MVT::i32, Idx,
9811 DAG.getConstant(Log2_32(EltsPerPiece), SL, MVT::i32));
9812 SDValue Zero = DAG.getConstant(0, SL, IntVT);
9814 Pieces.reserve(NumPieces);
9815 for (unsigned I = 0; I != NumPieces; ++I) {
9816 SDValue CurPieceNo = DAG.getConstant(I, SL, MVT::i32);
9817 SDValue Piece =
9818 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, IntVT, BCVec, CurPieceNo);
9819 SDValue Mask =
9820 DAG.getSelectCC(SL, PieceNo, CurPieceNo, BFM, Zero, ISD::SETEQ);
9821 Pieces.push_back(InsertIntoPiece(Piece, Mask));
9822 }
9823
9824 return DAG.getBitcast(VecVT, DAG.getBuildVector(PiecesVT, SL, Pieces));
9825}
9826
9827SDValue SITargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op,
9828 SelectionDAG &DAG) const {
9829 SDLoc SL(Op);
9830
9831 EVT ResultVT = Op.getValueType();
9832 SDValue Vec = Op.getOperand(0);
9833 SDValue Idx = Op.getOperand(1);
9834 EVT VecVT = Vec.getValueType();
9835 unsigned VecSize = VecVT.getSizeInBits();
9836 EVT EltVT = VecVT.getVectorElementType();
9837
9838 DAGCombinerInfo DCI(DAG, AfterLegalizeVectorOps, true, nullptr);
9839
9840 // Make sure we do any optimizations that will make it easier to fold
9841 // source modifiers before obscuring it with bit operations.
9842
9843 // XXX - Why doesn't this get called when vector_shuffle is expanded?
9844 if (SDValue Combined = performExtractVectorEltCombine(Op.getNode(), DCI))
9845 return Combined;
9846
9847 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9848 SDValue Lo, Hi;
9849 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VecVT);
9850
9851 if (VecSize == 128) {
9852 SDValue V2 = DAG.getBitcast(MVT::v2i64, Vec);
9853 Lo = DAG.getBitcast(LoVT,
9854 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9855 DAG.getConstant(0, SL, MVT::i32)));
9856 Hi = DAG.getBitcast(HiVT,
9857 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9858 DAG.getConstant(1, SL, MVT::i32)));
9859 } else if (VecSize == 256) {
9860 SDValue V2 = DAG.getBitcast(MVT::v4i64, Vec);
9861 SDValue Parts[4];
9862 for (unsigned P = 0; P < 4; ++P) {
9863 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9864 DAG.getConstant(P, SL, MVT::i32));
9865 }
9866
9867 Lo = DAG.getBitcast(LoVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9868 Parts[0], Parts[1]));
9869 Hi = DAG.getBitcast(HiVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9870 Parts[2], Parts[3]));
9871 } else {
9872 assert(VecSize == 512);
9873
9874 SDValue V2 = DAG.getBitcast(MVT::v8i64, Vec);
9875 SDValue Parts[8];
9876 for (unsigned P = 0; P < 8; ++P) {
9877 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9878 DAG.getConstant(P, SL, MVT::i32));
9879 }
9880
9881 Lo = DAG.getBitcast(LoVT,
9882 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9883 Parts[0], Parts[1], Parts[2], Parts[3]));
9884 Hi = DAG.getBitcast(HiVT,
9885 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9886 Parts[4], Parts[5], Parts[6], Parts[7]));
9887 }
9888
9889 EVT IdxVT = Idx.getValueType();
9890 unsigned NElem = VecVT.getVectorNumElements();
9891 assert(isPowerOf2_32(NElem));
9892 SDValue IdxMask = DAG.getConstant(NElem / 2 - 1, SL, IdxVT);
9893 SDValue NewIdx = DAG.getNode(ISD::AND, SL, IdxVT, Idx, IdxMask);
9894 SDValue Half = DAG.getSelectCC(SL, Idx, IdxMask, Hi, Lo, ISD::SETUGT);
9895 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Half, NewIdx);
9896 }
9897
9898 assert(VecSize <= 64);
9899
9900 MVT IntVT = MVT::getIntegerVT(VecSize);
9901
9902 // If Vec is just a SCALAR_TO_VECTOR, then use the scalar integer directly.
9903 SDValue VecBC = peekThroughBitcasts(Vec);
9904 if (VecBC.getOpcode() == ISD::SCALAR_TO_VECTOR) {
9905 SDValue Src = VecBC.getOperand(0);
9906 Src = DAG.getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9907 Vec = DAG.getAnyExtOrTrunc(Src, SL, IntVT);
9908 }
9909
9910 unsigned EltSize = EltVT.getSizeInBits();
9911 assert(isPowerOf2_32(EltSize));
9912
9913 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9914
9915 // Convert vector index to bit-index (* EltSize)
9916 SDValue ScaledIdx = DAG.getNode(ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9917
9918 SDValue BC = DAG.getNode(ISD::BITCAST, SL, IntVT, Vec);
9919 SDValue Elt = DAG.getNode(ISD::SRL, SL, IntVT, BC, ScaledIdx);
9920
9921 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9922 SDValue Result = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Elt);
9923 return DAG.getNode(ISD::BITCAST, SL, ResultVT, Result);
9924 }
9925
9926 return DAG.getAnyExtOrTrunc(Elt, SL, ResultVT);
9927}
9928
9929static bool elementPairIsContiguous(ArrayRef<int> Mask, int Elt) {
9930 assert(Elt % 2 == 0);
9931 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9932}
9933
9934static bool elementPairIsOddToEven(ArrayRef<int> Mask, int Elt) {
9935 assert(Elt % 2 == 0);
9936 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9937 !(Mask[Elt + 1] & 1);
9938}
9939
9940SDValue SITargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
9941 SelectionDAG &DAG) const {
9942 SDLoc SL(Op);
9943 EVT ResultVT = Op.getValueType();
9944 ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
9945 MVT EltVT = ResultVT.getVectorElementType().getSimpleVT();
9946 const int NewSrcNumElts = 2;
9947 MVT PackVT = MVT::getVectorVT(EltVT, NewSrcNumElts);
9948 int SrcNumElts = Op.getOperand(0).getValueType().getVectorNumElements();
9949
9950 // Break up the shuffle into registers sized pieces.
9951 //
9952 // We're trying to form sub-shuffles that the register allocation pipeline
9953 // won't be able to figure out, like how to use v_pk_mov_b32 to do a register
9954 // blend or 16-bit op_sel. It should be able to figure out how to reassemble a
9955 // pair of copies into a consecutive register copy, so use the ordinary
9956 // extract_vector_elt lowering unless we can use the shuffle.
9957 //
9958 // TODO: This is a bit of hack, and we should probably always use
9959 // extract_subvector for the largest possible subvector we can (or at least
9960 // use it for PackVT aligned pieces). However we have worse support for
9961 // combines on them don't directly treat extract_subvector / insert_subvector
9962 // as legal. The DAG scheduler also ends up doing a worse job with the
9963 // extract_subvectors.
9964 const bool ShouldUseConsecutiveExtract = EltVT.getSizeInBits() == 16;
9965
9966 // vector_shuffle <0,1,6,7> lhs, rhs
9967 // -> concat_vectors (extract_subvector lhs, 0), (extract_subvector rhs, 2)
9968 //
9969 // vector_shuffle <6,7,2,3> lhs, rhs
9970 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 2)
9971 //
9972 // vector_shuffle <6,7,0,1> lhs, rhs
9973 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 0)
9974
9975 // Avoid scalarizing when both halves are reading from consecutive elements.
9976
9977 // If we're treating 2 element shuffles as legal, also create odd-to-even
9978 // shuffles of neighboring pairs.
9979 //
9980 // vector_shuffle <3,2,7,6> lhs, rhs
9981 // -> concat_vectors vector_shuffle <1, 0> (extract_subvector lhs, 0)
9982 // vector_shuffle <1, 0> (extract_subvector rhs, 2)
9983
9985 for (int I = 0, N = ResultVT.getVectorNumElements(); I != N; I += 2) {
9986 if (ShouldUseConsecutiveExtract &&
9988 const int Idx = SVN->getMaskElt(I);
9989 int VecIdx = Idx < SrcNumElts ? 0 : 1;
9990 int EltIdx = Idx < SrcNumElts ? Idx : Idx - SrcNumElts;
9991 SDValue SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT,
9992 SVN->getOperand(VecIdx),
9993 DAG.getConstant(EltIdx, SL, MVT::i32));
9994 Pieces.push_back(SubVec);
9995 } else if (elementPairIsOddToEven(SVN->getMask(), I) &&
9997 int Idx0 = SVN->getMaskElt(I);
9998 int Idx1 = SVN->getMaskElt(I + 1);
9999
10000 SDValue SrcOp0 = SVN->getOperand(0);
10001 SDValue SrcOp1 = SrcOp0;
10002 if (Idx0 >= SrcNumElts) {
10003 SrcOp0 = SVN->getOperand(1);
10004 Idx0 -= SrcNumElts;
10005 }
10006
10007 if (Idx1 >= SrcNumElts) {
10008 SrcOp1 = SVN->getOperand(1);
10009 Idx1 -= SrcNumElts;
10010 }
10011
10012 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
10013 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
10014
10015 // Extract nearest even aligned piece.
10016 SDValue SubVec0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp0,
10017 DAG.getConstant(AlignedIdx0, SL, MVT::i32));
10018 SDValue SubVec1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp1,
10019 DAG.getConstant(AlignedIdx1, SL, MVT::i32));
10020
10021 int NewMaskIdx0 = Idx0 - AlignedIdx0;
10022 int NewMaskIdx1 = Idx1 - AlignedIdx1;
10023
10024 SDValue Result0 = SubVec0;
10025 SDValue Result1 = SubVec0;
10026
10027 if (SubVec0 != SubVec1) {
10028 NewMaskIdx1 += NewSrcNumElts;
10029 Result1 = SubVec1;
10030 } else {
10031 Result1 = DAG.getPOISON(PackVT);
10032 }
10033
10034 SDValue Shuf = DAG.getVectorShuffle(PackVT, SL, Result0, Result1,
10035 {NewMaskIdx0, NewMaskIdx1});
10036 Pieces.push_back(Shuf);
10037 } else {
10038 const int Idx0 = SVN->getMaskElt(I);
10039 const int Idx1 = SVN->getMaskElt(I + 1);
10040 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
10041 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
10042 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
10043 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
10044
10045 SDValue Vec0 = SVN->getOperand(VecIdx0);
10046 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec0,
10047 DAG.getSignedConstant(EltIdx0, SL, MVT::i32));
10048
10049 SDValue Vec1 = SVN->getOperand(VecIdx1);
10050 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec1,
10051 DAG.getSignedConstant(EltIdx1, SL, MVT::i32));
10052 Pieces.push_back(DAG.getBuildVector(PackVT, SL, {Elt0, Elt1}));
10053 }
10054 }
10055
10056 return DAG.getNode(ISD::CONCAT_VECTORS, SL, ResultVT, Pieces);
10057}
10058
10059SDValue SITargetLowering::lowerSCALAR_TO_VECTOR(SDValue Op,
10060 SelectionDAG &DAG) const {
10061 SDValue SVal = Op.getOperand(0);
10062 EVT ResultVT = Op.getValueType();
10063 EVT SValVT = SVal.getValueType();
10064 SDValue UndefVal = DAG.getPOISON(SValVT);
10065 SDLoc SL(Op);
10066
10068 VElts.push_back(SVal);
10069 for (int I = 1, E = ResultVT.getVectorNumElements(); I < E; ++I)
10070 VElts.push_back(UndefVal);
10071
10072 return DAG.getBuildVector(ResultVT, SL, VElts);
10073}
10074
10075SDValue SITargetLowering::lowerBUILD_VECTOR(SDValue Op,
10076 SelectionDAG &DAG) const {
10077 SDLoc SL(Op);
10078 EVT VT = Op.getValueType();
10079
10080 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
10081 assert(!Subtarget->hasVOP3PInsts() && "this should be legal");
10082
10083 SDValue Lo = Op.getOperand(0);
10084 SDValue Hi = Op.getOperand(1);
10085
10086 // Avoid adding defined bits with the zero_extend.
10087 if (Hi.isUndef()) {
10088 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
10089 SDValue ExtLo = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Lo);
10090 return DAG.getNode(ISD::BITCAST, SL, VT, ExtLo);
10091 }
10092
10093 Hi = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Hi);
10094 Hi = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Hi);
10095
10096 SDValue ShlHi = DAG.getNode(ISD::SHL, SL, MVT::i32, Hi,
10097 DAG.getConstant(16, SL, MVT::i32));
10098 if (Lo.isUndef())
10099 return DAG.getNode(ISD::BITCAST, SL, VT, ShlHi);
10100
10101 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
10102 Lo = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Lo);
10103
10104 SDValue Or =
10105 DAG.getNode(ISD::OR, SL, MVT::i32, Lo, ShlHi, SDNodeFlags::Disjoint);
10106 return DAG.getNode(ISD::BITCAST, SL, VT, Or);
10107 }
10108
10109 // Split into 2-element chunks.
10110 const unsigned NumParts = VT.getVectorNumElements() / 2;
10111 EVT PartVT = MVT::getVectorVT(VT.getVectorElementType().getSimpleVT(), 2);
10112 MVT PartIntVT = MVT::getIntegerVT(PartVT.getSizeInBits());
10113
10115 for (unsigned P = 0; P < NumParts; ++P) {
10116 SDValue Vec = DAG.getBuildVector(
10117 PartVT, SL, {Op.getOperand(P * 2), Op.getOperand(P * 2 + 1)});
10118 Casts.push_back(DAG.getNode(ISD::BITCAST, SL, PartIntVT, Vec));
10119 }
10120
10121 SDValue Blend =
10122 DAG.getBuildVector(MVT::getVectorVT(PartIntVT, NumParts), SL, Casts);
10123 return DAG.getNode(ISD::BITCAST, SL, VT, Blend);
10124}
10125
10127 const GlobalAddressSDNode *GA) const {
10128 // Named barriers have fixed, non-relocated LDS addresses, so a constant
10129 // offset into an array of them can be folded into the address.
10131 const auto *GV = dyn_cast<GlobalVariable>(GA->getGlobal());
10132 return GV && AMDGPU::isNamedBarrier(*GV);
10133 }
10134
10135 // OSes that use ELF REL relocations (instead of RELA) can only store a
10136 // 32-bit addend in the instruction, so it is not safe to allow offset folding
10137 // which can create arbitrary 64-bit addends. (This is only a problem for
10138 // R_AMDGPU_*32_HI relocations since other relocation types are unaffected by
10139 // the high 32 bits of the addend.)
10140 //
10141 // This should be kept in sync with how HasRelocationAddend is initialized in
10142 // the constructor of ELFAMDGPUAsmBackend.
10143 if (!Subtarget->isAmdHsaOS())
10144 return false;
10145
10146 // We can fold offsets for anything that doesn't require a GOT relocation.
10147 return (GA->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS ||
10151}
10152
10153static SDValue
10155 const SDLoc &DL, int64_t Offset, EVT PtrVT,
10156 unsigned GAFlags = SIInstrInfo::MO_NONE) {
10157 assert(isInt<32>(Offset + 4) && "32-bit offset is expected!");
10158 // In order to support pc-relative addressing, the PC_ADD_REL_OFFSET SDNode is
10159 // lowered to the following code sequence:
10160 //
10161 // For constant address space:
10162 // s_getpc_b64 s[0:1]
10163 // s_add_u32 s0, s0, $symbol
10164 // s_addc_u32 s1, s1, 0
10165 //
10166 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10167 // a fixup or relocation is emitted to replace $symbol with a literal
10168 // constant, which is a pc-relative offset from the encoding of the $symbol
10169 // operand to the global variable.
10170 //
10171 // For global address space:
10172 // s_getpc_b64 s[0:1]
10173 // s_add_u32 s0, s0, $symbol@{gotpc}rel32@lo
10174 // s_addc_u32 s1, s1, $symbol@{gotpc}rel32@hi
10175 //
10176 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10177 // fixups or relocations are emitted to replace $symbol@*@lo and
10178 // $symbol@*@hi with lower 32 bits and higher 32 bits of a literal constant,
10179 // which is a 64-bit pc-relative offset from the encoding of the $symbol
10180 // operand to the global variable.
10181 if (((const GCNSubtarget &)DAG.getSubtarget()).has64BitLiterals()) {
10182 assert(GAFlags != SIInstrInfo::MO_NONE);
10183
10184 SDValue Ptr =
10185 DAG.getTargetGlobalAddress(GV, DL, MVT::i64, Offset, GAFlags + 2);
10186 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET64, DL, PtrVT, Ptr);
10187 }
10188
10189 SDValue PtrLo = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags);
10190 SDValue PtrHi;
10191 if (GAFlags == SIInstrInfo::MO_NONE)
10192 PtrHi = DAG.getTargetConstant(0, DL, MVT::i32);
10193 else
10194 PtrHi = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags + 1);
10195 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET, DL, PtrVT, PtrLo, PtrHi);
10196}
10197
10198SDValue SITargetLowering::LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI,
10199 SDValue Op,
10200 SelectionDAG &DAG) const {
10201 GlobalAddressSDNode *GSD = cast<GlobalAddressSDNode>(Op);
10202 SDLoc DL(GSD);
10203 EVT PtrVT = Op.getValueType();
10204
10205 const GlobalValue *GV = GSD->getGlobal();
10206 const unsigned AS = GSD->getAddressSpace();
10207 if (((AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::BARRIER) &&
10210 if (AS == AMDGPUAS::LOCAL_ADDRESS && GV->hasExternalLinkage()) {
10211 const GlobalVariable &GVar = *cast<GlobalVariable>(GV);
10212 // HIP uses an unsized array `extern __shared__ T s[]` or similar
10213 // zero-sized type in other languages to declare the dynamic shared
10214 // memory which size is not known at the compile time. They will be
10215 // allocated by the runtime and placed directly after the static
10216 // allocated ones. They all share the same offset.
10217 if (GVar.getGlobalSize(GVar.getDataLayout()) == 0) {
10218 assert(PtrVT == MVT::i32 && "32-bit pointer is expected.");
10219 // Adjust alignment for that dynamic shared memory array.
10221 MFI->setDynLDSAlign(F, GVar);
10222 MFI->setUsesDynamicLDS(true);
10223 return SDValue(
10224 DAG.getMachineNode(AMDGPU::GET_GROUPSTATICSIZE, DL, PtrVT), 0);
10225 }
10226 }
10228 }
10229
10230 if (AS == AMDGPUAS::BARRIER) {
10231 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, GSD->getOffset(),
10233 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0);
10234 }
10235
10236 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
10237 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, GSD->getOffset(),
10239 return DAG.getNode(AMDGPUISD::LDS, DL, MVT::i32, GA);
10240 }
10241
10242 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10243 if (Subtarget->has64BitLiterals()) {
10245 GV, DL, MVT::i64, GSD->getOffset(), SIInstrInfo::MO_ABS64);
10246 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B64, DL, MVT::i64, Addr),
10247 0);
10248 }
10249
10250 SDValue AddrLo = DAG.getTargetGlobalAddress(
10251 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_LO);
10252 AddrLo = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrLo), 0};
10253
10254 SDValue AddrHi = DAG.getTargetGlobalAddress(
10255 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_HI);
10256 AddrHi = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrHi), 0};
10257
10258 return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, AddrLo, AddrHi);
10259 }
10260
10261 if (shouldEmitFixup(GV))
10262 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT);
10263
10264 if (shouldEmitPCReloc(GV))
10265 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT,
10267
10268 SDValue GOTAddr = buildPCRelGlobalAddress(DAG, GV, DL, 0, PtrVT,
10270 PointerType *PtrTy =
10272 const DataLayout &DataLayout = DAG.getDataLayout();
10273 Align Alignment = DataLayout.getABITypeAlign(PtrTy);
10274 MachinePointerInfo PtrInfo =
10276
10277 return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), GOTAddr, PtrInfo, Alignment,
10280}
10281
10282SDValue SITargetLowering::LowerExternalSymbol(SDValue Op,
10283 SelectionDAG &DAG) const {
10284 // TODO: Handle this. It should be mostly the same as LowerGlobalAddress.
10285 const Function &Fn = DAG.getMachineFunction().getFunction();
10286 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10287 Fn, "unsupported external symbol", Op.getDebugLoc()));
10288 return DAG.getPOISON(Op.getValueType());
10289}
10290
10292 const SDLoc &DL, SDValue V) const {
10293 // We can't use S_MOV_B32 directly, because there is no way to specify m0 as
10294 // the destination register.
10295 //
10296 // We can't use CopyToReg, because MachineCSE won't combine COPY instructions,
10297 // so we will end up with redundant moves to m0.
10298 //
10299 // We use a pseudo to ensure we emit s_mov_b32 with m0 as the direct result.
10300
10301 // A Null SDValue creates a glue result.
10302 SDNode *M0 = DAG.getMachineNode(AMDGPU::SI_INIT_M0, DL, MVT::Other, MVT::Glue,
10303 V, Chain);
10304 return SDValue(M0, 0);
10305}
10306
10307SDValue SITargetLowering::lowerImplicitZextParam(SelectionDAG &DAG, SDValue Op,
10308 MVT VT,
10309 unsigned Offset) const {
10310 SDLoc SL(Op);
10311 SDValue Param = lowerKernargMemParameter(
10312 DAG, MVT::i32, MVT::i32, SL, DAG.getEntryNode(), Offset, Align(4), false);
10313 // The local size values will have the hi 16-bits as zero.
10314 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Param,
10315 DAG.getValueType(VT));
10316}
10317
10319 EVT VT) {
10322 "non-hsa intrinsic with hsa target", DL.getDebugLoc()));
10323 return DAG.getPOISON(VT);
10324}
10325
10327 EVT VT) {
10330 "intrinsic not supported on subtarget", DL.getDebugLoc()));
10331 return DAG.getPOISON(VT);
10332}
10333
10335 ArrayRef<SDValue> Elts) {
10336 assert(!Elts.empty());
10337 MVT Type;
10338 unsigned NumElts = Elts.size();
10339
10340 if (NumElts <= 12) {
10341 Type = MVT::getVectorVT(MVT::f32, NumElts);
10342 } else {
10343 assert(Elts.size() <= 16);
10344 Type = MVT::v16f32;
10345 NumElts = 16;
10346 }
10347
10348 SmallVector<SDValue, 16> VecElts(NumElts);
10349 for (unsigned i = 0; i < Elts.size(); ++i) {
10350 SDValue Elt = Elts[i];
10351 if (Elt.getValueType() != MVT::f32)
10352 Elt = DAG.getBitcast(MVT::f32, Elt);
10353 VecElts[i] = Elt;
10354 }
10355 for (unsigned i = Elts.size(); i < NumElts; ++i)
10356 VecElts[i] = DAG.getPOISON(MVT::f32);
10357
10358 if (NumElts == 1)
10359 return VecElts[0];
10360 return DAG.getBuildVector(Type, DL, VecElts);
10361}
10362
10363static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT,
10364 SDValue Src, int ExtraElts) {
10365 EVT SrcVT = Src.getValueType();
10366
10368
10369 if (SrcVT.isVector())
10370 DAG.ExtractVectorElements(Src, Elts);
10371 else
10372 Elts.push_back(Src);
10373
10374 SDValue Undef = DAG.getPOISON(SrcVT.getScalarType());
10375 while (ExtraElts--)
10376 Elts.push_back(Undef);
10377
10378 return DAG.getBuildVector(CastVT, DL, Elts);
10379}
10380
10381// Re-construct the required return value for a image load intrinsic.
10382// This is more complicated due to the optional use TexFailCtrl which means the
10383// required return type is an aggregate
10385 ArrayRef<EVT> ResultTypes, bool IsTexFail,
10386 bool Unpacked, bool IsD16, int DMaskPop,
10387 int NumVDataDwords, bool IsAtomicPacked16Bit,
10388 const SDLoc &DL) {
10389 // Determine the required return type. This is the same regardless of
10390 // IsTexFail flag
10391 EVT ReqRetVT = ResultTypes[0];
10392 int ReqRetNumElts = ReqRetVT.isVector() ? ReqRetVT.getVectorNumElements() : 1;
10393 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10394 ? (ReqRetNumElts + 1) / 2
10395 : ReqRetNumElts;
10396
10397 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10398
10399 MVT DataDwordVT =
10400 NumDataDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, NumDataDwords);
10401
10402 MVT MaskPopVT =
10403 MaskPopDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, MaskPopDwords);
10404
10405 SDValue Data(Result, 0);
10406 SDValue TexFail;
10407
10408 if (DMaskPop > 0 && Data.getValueType() != MaskPopVT) {
10409 SDValue ZeroIdx = DAG.getConstant(0, DL, MVT::i32);
10410 if (MaskPopVT.isVector()) {
10411 Data = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, MaskPopVT,
10412 SDValue(Result, 0), ZeroIdx);
10413 } else {
10414 Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MaskPopVT,
10415 SDValue(Result, 0), ZeroIdx);
10416 }
10417 }
10418
10419 if (DataDwordVT.isVector() && !IsAtomicPacked16Bit)
10420 Data = padEltsToUndef(DAG, DL, DataDwordVT, Data,
10421 NumDataDwords - MaskPopDwords);
10422
10423 if (IsD16)
10424 Data = adjustLoadValueTypeImpl(Data, ReqRetVT, DL, DAG, Unpacked);
10425
10426 EVT LegalReqRetVT = ReqRetVT;
10427 if (!ReqRetVT.isVector()) {
10428 if (!Data.getValueType().isInteger())
10429 Data = DAG.getNode(ISD::BITCAST, DL,
10430 Data.getValueType().changeTypeToInteger(), Data);
10431 Data = DAG.getNode(ISD::TRUNCATE, DL, ReqRetVT.changeTypeToInteger(), Data);
10432 } else {
10433 // We need to widen the return vector to a legal type
10434 if ((ReqRetVT.getVectorNumElements() % 2) == 1 &&
10435 ReqRetVT.getVectorElementType().getSizeInBits() == 16) {
10436 LegalReqRetVT =
10438 ReqRetVT.getVectorNumElements() + 1);
10439 }
10440 }
10441 Data = DAG.getNode(ISD::BITCAST, DL, LegalReqRetVT, Data);
10442
10443 if (IsTexFail) {
10444 TexFail =
10445 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, SDValue(Result, 0),
10446 DAG.getConstant(MaskPopDwords, DL, MVT::i32));
10447
10448 return DAG.getMergeValues({Data, TexFail, SDValue(Result, 1)}, DL);
10449 }
10450
10451 if (Result->getNumValues() == 1)
10452 return Data;
10453
10454 return DAG.getMergeValues({Data, SDValue(Result, 1)}, DL);
10455}
10456
10457static bool parseTexFail(SDValue TexFailCtrl, SelectionDAG &DAG, SDValue *TFE,
10458 SDValue *LWE, bool &IsTexFail) {
10459 auto *TexFailCtrlConst = cast<ConstantSDNode>(TexFailCtrl.getNode());
10460
10461 uint64_t Value = TexFailCtrlConst->getZExtValue();
10462 if (Value) {
10463 IsTexFail = true;
10464 }
10465
10466 SDLoc DL(TexFailCtrlConst);
10467 *TFE = DAG.getTargetConstant((Value & 0x1) ? 1 : 0, DL, MVT::i32);
10468 Value &= ~(uint64_t)0x1;
10469 *LWE = DAG.getTargetConstant((Value & 0x2) ? 1 : 0, DL, MVT::i32);
10470 Value &= ~(uint64_t)0x2;
10471
10472 return Value == 0;
10473}
10474
10476 MVT PackVectorVT,
10477 SmallVectorImpl<SDValue> &PackedAddrs,
10478 unsigned DimIdx, unsigned EndIdx,
10479 unsigned NumGradients) {
10480 SDLoc DL(Op);
10481 for (unsigned I = DimIdx; I < EndIdx; I++) {
10482 SDValue Addr = Op.getOperand(I);
10483
10484 // Gradients are packed with undef for each coordinate.
10485 // In <hi 16 bit>,<lo 16 bit> notation, the registers look like this:
10486 // 1D: undef,dx/dh; undef,dx/dv
10487 // 2D: dy/dh,dx/dh; dy/dv,dx/dv
10488 // 3D: dy/dh,dx/dh; undef,dz/dh; dy/dv,dx/dv; undef,dz/dv
10489 if (((I + 1) >= EndIdx) ||
10490 ((NumGradients / 2) % 2 == 1 && (I == DimIdx + (NumGradients / 2) - 1 ||
10491 I == DimIdx + NumGradients - 1))) {
10492 if (Addr.getValueType() != MVT::i16)
10493 Addr = DAG.getBitcast(MVT::i16, Addr);
10494 Addr = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Addr);
10495 } else {
10496 Addr = DAG.getBuildVector(PackVectorVT, DL, {Addr, Op.getOperand(I + 1)});
10497 I++;
10498 }
10499 Addr = DAG.getBitcast(MVT::f32, Addr);
10500 PackedAddrs.push_back(Addr);
10501 }
10502}
10503
10504/// Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and
10505/// return poison values of \p ResultTypes, preserving the chain if present.
10507 ArrayRef<EVT> ResultTypes,
10508 const SDLoc &DL, const Twine &Msg) {
10510 DAG.getMachineFunction().getFunction(), Msg, DL.getDebugLoc()));
10511 return DAG.getErrorMergeValues(ResultTypes, Op.getOperand(0), DL);
10512}
10513
10514SDValue SITargetLowering::lowerImage(SDValue Op,
10516 SelectionDAG &DAG, bool WithChain) const {
10517 SDLoc DL(Op);
10519 const GCNSubtarget *ST = &MF.getSubtarget<GCNSubtarget>();
10520 unsigned IntrOpcode = Intr->BaseOpcode;
10521 // For image atomic: use no-return opcode if result is unused.
10522 if (Intr->AtomicNoRetBaseOpcode != Intr->BaseOpcode &&
10523 !Op.getNode()->hasAnyUseOfValue(0))
10524 IntrOpcode = Intr->AtomicNoRetBaseOpcode;
10525 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10527 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfo(Intr->Dim);
10528 bool IsGFX10Plus = AMDGPU::isGFX10Plus(*Subtarget);
10529 bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
10530 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
10531 bool IsGFX13 = AMDGPU::isGFX13(*Subtarget);
10532
10533 SmallVector<EVT, 3> ResultTypes(Op->values());
10534 SmallVector<EVT, 3> OrigResultTypes(Op->values());
10535 if (BaseOpcode->NoReturn && BaseOpcode->Atomic)
10536 ResultTypes.erase(&ResultTypes[0]);
10537
10538 bool IsD16 = false;
10539 bool IsG16 = false;
10540 bool IsA16 = false;
10541 SDValue VData;
10542 int NumVDataDwords = 0;
10543 bool AdjustRetType = false;
10544 bool IsAtomicPacked16Bit = false;
10545
10546 // Offset of intrinsic arguments
10547 const unsigned ArgOffset = WithChain ? 2 : 1;
10548
10549 unsigned DMask;
10550 unsigned DMaskLanes = 0;
10551
10552 if (BaseOpcode->Atomic) {
10553 VData = Op.getOperand(2);
10554
10555 IsAtomicPacked16Bit =
10556 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10557 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10558 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10559 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10560
10561 if (!IsAtomicPacked16Bit && VData.getValueSizeInBits() != 32 &&
10562 VData.getValueSizeInBits() != 64) {
10563 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10564 "unsupported image atomic data type");
10565 }
10566
10567 bool Is64Bit = VData.getValueSizeInBits() == 64;
10568 if (BaseOpcode->AtomicX2) {
10569 SDValue VData2 = Op.getOperand(3);
10570 VData = DAG.getBuildVector(Is64Bit ? MVT::v2i64 : MVT::v2i32, DL,
10571 {VData, VData2});
10572 if (Is64Bit)
10573 VData = DAG.getBitcast(MVT::v4i32, VData);
10574
10575 if (!BaseOpcode->NoReturn)
10576 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10577
10578 DMask = Is64Bit ? 0xf : 0x3;
10579 NumVDataDwords = Is64Bit ? 4 : 2;
10580 } else {
10581 DMask = Is64Bit ? 0x3 : 0x1;
10582 NumVDataDwords = Is64Bit ? 2 : 1;
10583 }
10584 } else {
10585 DMask = Op->getConstantOperandVal(ArgOffset + Intr->DMaskIndex);
10586 DMaskLanes = BaseOpcode->Gather4 ? 4 : llvm::popcount(DMask);
10587
10588 if (BaseOpcode->Store) {
10589 VData = Op.getOperand(2);
10590
10591 MVT StoreVT = VData.getSimpleValueType();
10592 MVT StoreScalarVT = StoreVT.getScalarType();
10593 if (StoreScalarVT != MVT::f16 && StoreScalarVT.getSizeInBits() != 32 &&
10594 StoreScalarVT.getSizeInBits() != 64) {
10595 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10596 "unsupported image store data type");
10597 }
10598 if (StoreScalarVT == MVT::f16) {
10599 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10600 return Op; // D16 is unsupported for this instruction
10601
10602 IsD16 = true;
10603 VData = handleD16VData(VData, DAG, true);
10604 }
10605
10606 NumVDataDwords = (VData.getValueType().getSizeInBits() + 31) / 32;
10607 } else if (!BaseOpcode->NoReturn) {
10608 // Work out the num dwords based on the dmask popcount and underlying type
10609 // and whether packing is supported.
10610 MVT LoadVT = ResultTypes[0].getSimpleVT();
10611 MVT LoadScalarVT = LoadVT.getScalarType();
10612 if (LoadScalarVT != MVT::f16 && LoadScalarVT.getSizeInBits() != 32 &&
10613 LoadScalarVT.getSizeInBits() != 64) {
10614 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10615 "unsupported image load data type");
10616 }
10617 if (LoadScalarVT == MVT::f16) {
10618 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10619 return Op; // D16 is unsupported for this instruction
10620
10621 IsD16 = true;
10622 }
10623
10624 // Confirm that the return type is large enough for the dmask specified
10625 if ((LoadVT.isVector() && LoadVT.getVectorNumElements() < DMaskLanes) ||
10626 (!LoadVT.isVector() && DMaskLanes > 1))
10627 return Op;
10628
10629 // The sq block of gfx8 and gfx9 do not estimate register use correctly
10630 // for d16 image_gather4, image_gather4_l, and image_gather4_lz
10631 // instructions.
10632 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10633 !(BaseOpcode->Gather4 && Subtarget->hasImageGather4D16Bug()))
10634 NumVDataDwords = (DMaskLanes + 1) / 2;
10635 else
10636 NumVDataDwords = DMaskLanes;
10637
10638 AdjustRetType = true;
10639 }
10640 }
10641
10642 unsigned VAddrEnd = ArgOffset + Intr->VAddrEnd;
10644
10645 // Check for 16 bit addresses or derivatives and pack if true.
10646 MVT VAddrVT =
10647 Op.getOperand(ArgOffset + Intr->GradientStart).getSimpleValueType();
10648 MVT VAddrScalarVT = VAddrVT.getScalarType();
10649 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10650 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10651
10652 VAddrVT = Op.getOperand(ArgOffset + Intr->CoordStart).getSimpleValueType();
10653 VAddrScalarVT = VAddrVT.getScalarType();
10654 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10655 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10656
10657 // Push back extra arguments.
10658 for (unsigned I = Intr->VAddrStart; I < Intr->GradientStart; I++) {
10659 if (IsA16 && (Op.getOperand(ArgOffset + I).getValueType() == MVT::f16)) {
10660 assert(I == Intr->BiasIndex && "Got unexpected 16-bit extra argument");
10661 // Special handling of bias when A16 is on. Bias is of type half but
10662 // occupies full 32-bit.
10663 SDValue Bias = DAG.getBuildVector(
10664 MVT::v2f16, DL,
10665 {Op.getOperand(ArgOffset + I), DAG.getPOISON(MVT::f16)});
10666 VAddrs.push_back(Bias);
10667 } else {
10668 assert((!IsA16 || Intr->NumBiasArgs == 0 || I != Intr->BiasIndex) &&
10669 "Bias needs to be converted to 16 bit in A16 mode");
10670 VAddrs.push_back(Op.getOperand(ArgOffset + I));
10671 }
10672 }
10673
10674 if (BaseOpcode->Gradients && !ST->hasG16() && (IsA16 != IsG16)) {
10675 // 16 bit gradients are supported, but are tied to the A16 control
10676 // so both gradients and addresses must be 16 bit
10677 LLVM_DEBUG(
10678 dbgs() << "Failed to lower image intrinsic: 16 bit addresses "
10679 "require 16 bit args for both gradients and addresses");
10680 return Op;
10681 }
10682
10683 if (IsA16) {
10684 if (!ST->hasA16()) {
10685 LLVM_DEBUG(dbgs() << "Failed to lower image intrinsic: Target does not "
10686 "support 16 bit addresses\n");
10687 return Op;
10688 }
10689 }
10690
10691 // We've dealt with incorrect input so we know that if IsA16, IsG16
10692 // are set then we have to compress/pack operands (either address,
10693 // gradient or both)
10694 // In the case where a16 and gradients are tied (no G16 support) then we
10695 // have already verified that both IsA16 and IsG16 are true
10696 if (BaseOpcode->Gradients && IsG16 && ST->hasG16()) {
10697 // Activate g16
10698 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10700 IntrOpcode = G16MappingInfo->G16; // set new opcode to variant with _g16
10701 }
10702
10703 // Add gradients (packed or unpacked)
10704 if (IsG16) {
10705 // Pack the gradients
10706 // const int PackEndIdx = IsA16 ? VAddrEnd : (ArgOffset + Intr->CoordStart);
10707 packImage16bitOpsToDwords(DAG, Op, GradPackVectorVT, VAddrs,
10708 ArgOffset + Intr->GradientStart,
10709 ArgOffset + Intr->CoordStart, Intr->NumGradients);
10710 } else {
10711 for (unsigned I = ArgOffset + Intr->GradientStart;
10712 I < ArgOffset + Intr->CoordStart; I++)
10713 VAddrs.push_back(Op.getOperand(I));
10714 }
10715
10716 // Add addresses (packed or unpacked)
10717 if (IsA16) {
10718 packImage16bitOpsToDwords(DAG, Op, AddrPackVectorVT, VAddrs,
10719 ArgOffset + Intr->CoordStart, VAddrEnd,
10720 0 /* No gradients */);
10721 } else {
10722 // Add uncompressed address
10723 for (unsigned I = ArgOffset + Intr->CoordStart; I < VAddrEnd; I++)
10724 VAddrs.push_back(Op.getOperand(I));
10725 }
10726
10727 // If the register allocator cannot place the address registers contiguously
10728 // without introducing moves, then using the non-sequential address encoding
10729 // is always preferable, since it saves VALU instructions and is usually a
10730 // wash in terms of code size or even better.
10731 //
10732 // However, we currently have no way of hinting to the register allocator that
10733 // MIMG addresses should be placed contiguously when it is possible to do so,
10734 // so force non-NSA for the common 2-address case as a heuristic.
10735 //
10736 // SIShrinkInstructions will convert NSA encodings to non-NSA after register
10737 // allocation when possible.
10738 //
10739 // Partial NSA is allowed on GFX11+ where the final register is a contiguous
10740 // set of the remaining addresses.
10741 const unsigned NSAMaxSize = ST->getNSAMaxSize(BaseOpcode->Sampler);
10742 const bool HasPartialNSAEncoding = ST->hasPartialNSAEncoding();
10743 const bool UseNSA = ST->hasNSAEncoding() &&
10744 VAddrs.size() >= ST->getNSAThreshold(MF) &&
10745 (VAddrs.size() <= NSAMaxSize || HasPartialNSAEncoding);
10746 const bool UsePartialNSA =
10747 UseNSA && HasPartialNSAEncoding && VAddrs.size() > NSAMaxSize;
10748
10749 SDValue VAddr;
10750 if (UsePartialNSA) {
10751 VAddr = getBuildDwordsVector(DAG, DL,
10752 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10753 } else if (!UseNSA) {
10754 VAddr = getBuildDwordsVector(DAG, DL, VAddrs);
10755 }
10756
10757 SDValue True = DAG.getTargetConstant(1, DL, MVT::i1);
10758 SDValue False = DAG.getTargetConstant(0, DL, MVT::i1);
10759 SDValue Unorm;
10760 if (!BaseOpcode->Sampler) {
10761 Unorm = True;
10762 } else {
10763 uint64_t UnormConst =
10764 Op.getConstantOperandVal(ArgOffset + Intr->UnormIndex);
10765
10766 Unorm = UnormConst ? True : False;
10767 }
10768
10769 SDValue TFE;
10770 SDValue LWE;
10771 SDValue TexFail = Op.getOperand(ArgOffset + Intr->TexFailCtrlIndex);
10772 bool IsTexFail = false;
10773 if (!parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10774 return Op;
10775
10776 if (IsTexFail) {
10777 if (!DMaskLanes) {
10778 // Expecting to get an error flag since TFC is on - and dmask is 0
10779 // Force dmask to be at least 1 otherwise the instruction will fail
10780 DMask = 0x1;
10781 DMaskLanes = 1;
10782 NumVDataDwords = 1;
10783 }
10784 NumVDataDwords += 1;
10785 AdjustRetType = true;
10786 }
10787
10788 // Has something earlier tagged that the return type needs adjusting
10789 // This happens if the instruction is a load or has set TexFailCtrl flags
10790 if (AdjustRetType) {
10791 // NumVDataDwords reflects the true number of dwords required in the return
10792 // type
10793 if (DMaskLanes == 0 && !BaseOpcode->Store) {
10794 // This is a no-op load. This can be eliminated
10795 SDValue Undef = DAG.getPOISON(Op.getValueType());
10796 if (isa<MemSDNode>(Op))
10797 return DAG.getMergeValues({Undef, Op.getOperand(0)}, DL);
10798 return Undef;
10799 }
10800
10801 EVT NewVT = NumVDataDwords > 1 ? EVT::getVectorVT(*DAG.getContext(),
10802 MVT::i32, NumVDataDwords)
10803 : MVT::i32;
10804
10805 ResultTypes[0] = NewVT;
10806 if (ResultTypes.size() == 3) {
10807 // Original result was aggregate type used for TexFailCtrl results
10808 // The actual instruction returns as a vector type which has now been
10809 // created. Remove the aggregate result.
10810 ResultTypes.erase(&ResultTypes[1]);
10811 }
10812 }
10813
10814 unsigned CPol = Op.getConstantOperandVal(ArgOffset + Intr->CachePolicyIndex);
10815 // Keep GLC only when the atomic's result is actually used.
10816 if (BaseOpcode->Atomic && !BaseOpcode->NoReturn)
10818 if (CPol & ~((IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12) |
10820 return Op;
10821
10823 if (BaseOpcode->Store || BaseOpcode->Atomic)
10824 Ops.push_back(VData); // vdata
10825 if (UsePartialNSA) {
10826 append_range(Ops, ArrayRef(VAddrs).take_front(NSAMaxSize - 1));
10827 Ops.push_back(VAddr);
10828 } else if (UseNSA)
10829 append_range(Ops, VAddrs);
10830 else
10831 Ops.push_back(VAddr);
10832 SDValue Rsrc = Op.getOperand(ArgOffset + Intr->RsrcIndex);
10833 EVT RsrcVT = Rsrc.getValueType();
10834 bool IndexedRsrc = IsGFX13 && RsrcVT == MVT::i32;
10835 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32 && !IndexedRsrc)
10836 return Op;
10837 Ops.push_back(Rsrc);
10838 bool IsSampIndexed = false;
10839 if (BaseOpcode->Sampler) {
10840 SDValue Samp = Op.getOperand(ArgOffset + Intr->SampIndex);
10841 EVT SampVT = Samp.getValueType();
10842 IsSampIndexed = IsGFX13 && SampVT == MVT::i32;
10843 if (SampVT != MVT::v4i32 && !IsSampIndexed)
10844 return Op;
10845 Ops.push_back(Samp);
10846 }
10847 Ops.push_back(DAG.getTargetConstant(DMask, DL, MVT::i32));
10848 if (IsGFX10Plus)
10849 Ops.push_back(DAG.getTargetConstant(DimInfo->Encoding, DL, MVT::i32));
10850 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10851 Ops.push_back(Unorm);
10852 Ops.push_back(DAG.getTargetConstant(CPol, DL, MVT::i32));
10853 Ops.push_back(IsA16 && // r128, a16 for gfx9
10854 ST->hasFeature(AMDGPU::FeatureR128A16)
10855 ? True
10856 : False);
10857 if (IsGFX10Plus)
10858 Ops.push_back(IsA16 ? True : False);
10859
10860 if (!Subtarget->hasGFX90AInsts())
10861 Ops.push_back(TFE); // tfe
10862 else if (TFE->getAsZExtVal()) {
10863 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10865 "TFE is not supported on this GPU", DL.getDebugLoc()));
10866 }
10867
10868 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10869 Ops.push_back(LWE); // lwe
10870 if (!IsGFX10Plus)
10871 Ops.push_back(DimInfo->DA ? True : False);
10872 if (BaseOpcode->HasD16)
10873 Ops.push_back(IsD16 ? True : False);
10874 if (isa<MemSDNode>(Op))
10875 Ops.push_back(Op.getOperand(0)); // chain
10876
10877 int NumVAddrDwords =
10878 UseNSA ? VAddrs.size() : VAddr.getValueType().getSizeInBits() / 32;
10879 int Opcode = -1;
10880
10881 if (IsGFX13) {
10882 Opcode =
10883 AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx13, NumVDataDwords,
10884 NumVAddrDwords, IndexedRsrc, IsSampIndexed);
10885 } else if (IsGFX12Plus) {
10886 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx12,
10887 NumVDataDwords, NumVAddrDwords);
10888 } else if (IsGFX11Plus) {
10889 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10890 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10891 : AMDGPU::MIMGEncGfx11Default,
10892 NumVDataDwords, NumVAddrDwords);
10893 } else if (IsGFX10Plus) {
10894 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10895 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10896 : AMDGPU::MIMGEncGfx10Default,
10897 NumVDataDwords, NumVAddrDwords);
10898 } else {
10899 if (Subtarget->hasGFX90AInsts()) {
10900 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx90a,
10901 NumVDataDwords, NumVAddrDwords);
10902 if (Opcode == -1) {
10904 DAG, Op, OrigResultTypes, DL,
10905 "requested image instruction is not supported on this GPU");
10906 }
10907 }
10908 if (Opcode == -1 &&
10909 Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10910 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx8,
10911 NumVDataDwords, NumVAddrDwords);
10912 if (Opcode == -1)
10913 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx6,
10914 NumVDataDwords, NumVAddrDwords);
10915 }
10916 if (Opcode == -1)
10917 return Op;
10918
10919 MachineSDNode *NewNode = DAG.getMachineNode(Opcode, DL, ResultTypes, Ops);
10920 if (auto *MemOp = dyn_cast<MemSDNode>(Op)) {
10921 MachineMemOperand *MemRef = MemOp->getMemOperand();
10922 DAG.setNodeMemRefs(NewNode, {MemRef});
10923 }
10924
10925 if (BaseOpcode->NoReturn) {
10926 if (BaseOpcode->Atomic)
10927 return DAG.getMergeValues(
10928 {DAG.getPOISON(OrigResultTypes[0]), SDValue(NewNode, 0)}, DL);
10929
10930 return SDValue(NewNode, 0);
10931 }
10932
10933 if (BaseOpcode->AtomicX2) {
10935 DAG.ExtractVectorElements(SDValue(NewNode, 0), Elt, 0, 1);
10936 return DAG.getMergeValues({Elt[0], SDValue(NewNode, 1)}, DL);
10937 }
10938
10939 return constructRetValue(DAG, NewNode, OrigResultTypes, IsTexFail,
10940 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10941 NumVDataDwords, IsAtomicPacked16Bit, DL);
10942}
10943
10944SDValue SITargetLowering::lowerSBuffer(EVT VT, EVT MemVT, SDLoc DL,
10945 SDValue Chain, SDValue Rsrc,
10946 SDValue Offset, SDValue CachePolicy,
10947 SelectionDAG &DAG,
10948 MachineMemOperand *MMO) const {
10950 bool HasChainResult = MMO != nullptr;
10951
10952 // SBUFFER_LOAD only produces values that fill whole SGPRs, apart from the
10953 // subword loads below.
10954 bool IsSubwordLoad = (MemVT == MVT::i8 || MemVT == MVT::i16) &&
10955 Subtarget->hasScalarSubwordLoads();
10956 if ((!isTypeLegal(VT) || VT.getSizeInBits() % 32 != 0) && !IsSubwordLoad) {
10957 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10958 MF.getFunction(), "unsupported s_buffer_load result type",
10959 DL.getDebugLoc()));
10960 EVT ResultTypes[] = {VT, MVT::Other};
10961 return DAG.getErrorMergeValues(
10962 ArrayRef(ResultTypes, HasChainResult ? 2 : 1), Chain, DL);
10963 }
10964
10965 if (!HasChainResult) {
10966 const DataLayout &DataLayout = DAG.getDataLayout();
10968 DataLayout.getABITypeAlign(MemVT.getTypeForEVT(*DAG.getContext()));
10969
10970 MMO = MF.getMachineMemOperand(MachinePointerInfo(),
10974 MemVT.getStoreSize(), Alignment);
10975 }
10976
10977 if (!Offset->isDivergent()) {
10978 SDValue Ops[] = {Chain, Rsrc, Offset, CachePolicy};
10979
10980 // Lower llvm.amdgcn.*s.buffer.load.{i,u}N intrinsics. First, generate
10981 // s_buffer_load_u* for signed and unsigned load instructions. Next, DAG
10982 // combiner tries to merge the s_buffer_load_uN with a sext instruction
10983 // (performSignExtendInRegCombine()) and it replaces s_buffer_load_uN with
10984 // s_buffer_load_iN.
10985 auto HandleScalarSubwordLoads = [&](unsigned Opcode) -> SDValue {
10986 SDValue BufferLoad = DAG.getMemIntrinsicNode(
10987 Opcode, DL, DAG.getVTList(MVT::i32, MVT::Other), Ops, MemVT, MMO);
10988 SDValue LoadVal = DAG.getAnyExtOrTrunc(
10989 DAG.getNode(ISD::TRUNCATE, DL, MemVT, BufferLoad), DL, VT);
10990 if (HasChainResult)
10991 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
10992 return LoadVal;
10993 };
10994 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10995 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10996
10997 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10998 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10999
11000 // Widen vec3 load to vec4. Only 32-bit elements have a vec4 pattern.
11001 if (VT.isVector() && VT.getVectorNumElements() == 3 &&
11002 VT.getVectorElementType().getSizeInBits() == 32 &&
11003 !Subtarget->hasScalarDwordx3Loads()) {
11004 EVT WidenedVT =
11006 auto WidenedOp = DAG.getMemIntrinsicNode(
11007 AMDGPUISD::SBUFFER_LOAD, DL, DAG.getVTList(WidenedVT, MVT::Other),
11008 Ops, WidenedVT,
11009 MF.getMachineMemOperand(MMO, 0, WidenedVT.getStoreSize()));
11010 auto Subvector = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, WidenedOp,
11011 DAG.getVectorIdxConstant(0, DL));
11012 if (HasChainResult)
11013 return DAG.getMergeValues({Subvector, WidenedOp.getValue(1)}, DL);
11014 return Subvector;
11015 }
11016
11017 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_LOAD, DL,
11018 DAG.getVTList(VT, MVT::Other), Ops, MemVT,
11019 MMO);
11020 }
11021
11022 // We have a divergent offset. Emit a MUBUF buffer load instead. We can
11023 // assume that the buffer is unswizzled.
11024 SDValue Ops[] = {
11025 Chain, // Chain
11026 Rsrc, // rsrc
11027 DAG.getConstant(0, DL, MVT::i32), // vindex
11028 {}, // voffset
11029 {}, // soffset
11030 {}, // offset
11031 CachePolicy, // cachepolicy
11032 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11033 };
11034 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
11035 Subtarget->hasScalarSubwordLoads()) {
11036 setBufferOffsets(Offset, DAG, &Ops[3], Align(4));
11037 SDValue Load = handleByteShortBufferLoads(DAG, MemVT, DL, Ops, MMO);
11038 SDValue LoadVal = DAG.getAnyExtOrTrunc(Load.getOperand(0), DL, VT);
11039 if (HasChainResult)
11040 return DAG.getMergeValues({LoadVal, Load.getOperand(1)}, DL);
11041 return LoadVal;
11042 }
11043
11045 unsigned NumLoads = 1;
11046 MVT LoadVT = VT.getSimpleVT();
11047 unsigned NumElts = LoadVT.isVector() ? LoadVT.getVectorNumElements() : 1;
11048 assert((LoadVT.getScalarType() == MVT::i32 ||
11049 LoadVT.getScalarType() == MVT::f32));
11050
11051 if (NumElts == 8 || NumElts == 16) {
11052 NumLoads = NumElts / 4;
11053 LoadVT = MVT::getVectorVT(LoadVT.getScalarType(), 4);
11054 }
11055
11056 SDVTList VTList = DAG.getVTList({LoadVT, MVT::Other});
11057
11058 // Use the alignment to ensure that the required offsets will fit into the
11059 // immediate offsets.
11060 setBufferOffsets(Offset, DAG, &Ops[3],
11061 NumLoads > 1 ? Align(16 * NumLoads) : Align(4));
11062
11063 uint64_t InstOffset = Ops[5]->getAsZExtVal();
11064 unsigned LoadSize = LoadVT.getStoreSize();
11065 for (unsigned i = 0; i < NumLoads; ++i) {
11066 Ops[5] = DAG.getTargetConstant(InstOffset + 16 * i, DL, MVT::i32);
11067 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(MMO, 16 * i, LoadSize);
11068 Loads.push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD, DL, VTList, Ops,
11069 LoadVT, LoadMMO, DAG));
11070 }
11071
11072 if (NumElts == 8 || NumElts == 16) {
11073 SDValue LoadVal = DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Loads);
11074 if (HasChainResult) {
11075 SmallVector<SDValue, 4> LoadChains;
11076 for (SDValue Load : Loads)
11077 LoadChains.push_back(Load.getValue(1));
11078 SDValue Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, LoadChains);
11079 return DAG.getMergeValues({LoadVal, Chain}, DL);
11080 }
11081 return LoadVal;
11082 }
11083
11084 return Loads[0];
11085}
11086
11087SDValue SITargetLowering::lowerWaveID(SelectionDAG &DAG, SDValue Op) const {
11088 // With architected SGPRs, waveIDinGroup is in TTMP8[29:25].
11089 if (!Subtarget->hasArchitectedSGPRs())
11090 return {};
11091 SDLoc SL(Op);
11092 MVT VT = MVT::i32;
11093 SDValue TTMP8 = DAG.getCopyFromReg(DAG.getEntryNode(), SL, AMDGPU::TTMP8, VT);
11094 return DAG.getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
11095 DAG.getConstant(25, SL, VT), DAG.getConstant(5, SL, VT));
11096}
11097
11098SDValue SITargetLowering::lowerConstHwRegRead(SelectionDAG &DAG, SDValue Op,
11099 AMDGPU::Hwreg::Id HwReg,
11100 unsigned LowBit,
11101 unsigned Width) const {
11102 SDLoc SL(Op);
11103 using namespace AMDGPU::Hwreg;
11104 return {DAG.getMachineNode(
11105 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
11106 DAG.getTargetConstant(HwregEncoding::encode(HwReg, LowBit, Width),
11107 SL, MVT::i32)),
11108 0};
11109}
11110
11111SDValue SITargetLowering::lowerWorkitemID(SelectionDAG &DAG, SDValue Op,
11112 unsigned Dim,
11113 const ArgDescriptor &Arg) const {
11114 SDLoc SL(Op);
11116 unsigned MaxID = Subtarget->getMaxWorkitemID(MF.getFunction(), Dim);
11117 if (MaxID == 0)
11118 return DAG.getConstant(0, SL, MVT::i32);
11119
11120 // It's undefined behavior if a function marked with the amdgpu-no-*
11121 // attributes uses the corresponding intrinsic.
11122 if (!Arg)
11123 return DAG.getPOISON(Op->getValueType(0));
11124
11125 SDValue Val = loadInputValue(DAG, &AMDGPU::VGPR_32RegClass, MVT::i32,
11126 SDLoc(DAG.getEntryNode()), Arg);
11127
11128 // Don't bother inserting AssertZext for packed IDs since we're emitting the
11129 // masking operations anyway.
11130 //
11131 // TODO: We could assert the top bit is 0 for the source copy.
11132 if (Arg.isMasked())
11133 return Val;
11134
11135 // Preserve the known bits after expansion to a copy.
11136 EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), llvm::bit_width(MaxID));
11137 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Val,
11138 DAG.getValueType(SmallVT));
11139}
11140
11141SDValue SITargetLowering::lowerFromFP8(SDValue Op, bool IsBF8,
11142 SelectionDAG &DAG) const {
11143 SDLoc SL(Op);
11144 SDValue Src = Op.getOperand(0);
11145 EVT DstVT = Op.getValueType();
11146 bool IsF16 = DstVT.getVectorElementType() == MVT::f16;
11147 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
11148 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
11149
11150 unsigned Opc;
11151 if (IsF16)
11152 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11153 else
11154 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11155
11156 // Pack the two i8 lanes into the integer type the packed HW node reads. The
11157 // f16 form takes i16 and the f32 form takes i32. v2i8 bitcasts to i16
11158 // directly and the f32 node reads the low half of an any-extended i32.
11159 EVT PackedVT =
11161 SDValue AsI16 = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
11162 SDValue Packed = DAG.getAnyExtOrTrunc(AsI16, SL, PackedVT);
11163 return DAG.getNode(Opc, SL, DstVT, Packed);
11164}
11165
11166SDValue
11167SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(SDValue Op,
11168 SelectionDAG &DAG) const {
11169 // Handle the OCP FP8 formats (E4M3FN, E5M2) and unsigned E5M3 on subtargets
11170 // with matching HW conversions. Other formats use the generic expansion.
11171 APFloatBase::Semantics FPSemantic =
11172 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11173 const bool IsFP8 = FPSemantic == APFloatBase::S_Float8E4M3FN;
11174 const bool IsBF8 = FPSemantic == APFloatBase::S_Float8E5M2;
11175 const bool IsE5M3 = FPSemantic == APFloatBase::S_Float8E5M3FNU;
11176 const bool HasE5M3ConversionInsts =
11177 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11178 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11179 if (!IsSupported)
11180 return SDValue();
11181
11182 EVT DstVT = Op.getValueType();
11183 // The custom action for a v2i8 source also reaches half conversions on
11184 // targets which only have FP8-to-f32 instructions.
11185 if (DstVT.getScalarType() == MVT::f16 &&
11186 !Subtarget->hasFP8F16ConversionInsts())
11187 return SDValue();
11188
11189 if (IsE5M3) {
11190 if (DstVT.getScalarType() != MVT::f32)
11191 return SDValue();
11192
11193 SDLoc SL(Op);
11194 SDValue Src = Op.getOperand(0);
11195 assert((!DstVT.isVector() || DstVT == MVT::v2f32) &&
11196 "only the v2f32 vector result is custom lowered");
11197
11198 if (DstVT.isVector())
11199 Src = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
11200 Src = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
11201
11202 auto ConvertByte = [&](unsigned ByteSel) {
11203 return DAG.getNode(AMDGPUISD::CVT_F32_FP8_E5M3, SL, MVT::f32, Src,
11204 DAG.getTargetConstant(ByteSel, SL, MVT::i32));
11205 };
11206
11207 if (!DstVT.isVector())
11208 return ConvertByte(0);
11209 return DAG.getBuildVector(DstVT, SL, {ConvertByte(0), ConvertByte(1)});
11210 }
11211
11212 if (!DstVT.isVector()) {
11213 SDValue Src = Op.getOperand(0);
11214 if (Src.getValueType() != MVT::i32) {
11215 SDLoc SL(Op);
11216 SDValue SrcI32 = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
11217 return DAG.getNode(ISD::CONVERT_FROM_ARBITRARY_FP, SL, DstVT, SrcI32,
11218 Op.getOperand(1));
11219 }
11220 return Op;
11221 }
11222
11223 EVT EltVT = DstVT.getVectorElementType();
11224 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11225 return lowerFromFP8(Op, IsBF8, DAG);
11226 return SDValue();
11227}
11228
11229SDValue SITargetLowering::lowerToFP8(SDValue Op, bool IsBF8, bool IsE5M3,
11230 SelectionDAG &DAG) const {
11231 SDLoc SL(Op);
11232 SDValue Src = Op.getOperand(0);
11233 EVT ResVT = Op.getValueType();
11234 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11235 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11236 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11237 assert((!ResVT.isVector() || ResVT == MVT::v2i8) &&
11238 "only the v2i8 vector result is custom lowered");
11239
11240 if (IsF16) {
11241 unsigned Opc =
11242 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11243 SDValue Bytes = DAG.getNode(Opc, SL, MVT::i16, Src);
11244 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11245 }
11246
11247 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32
11248 : IsE5M3 ? AMDGPUISD::CVT_PK_FP8_F32_E5M3
11249 : AMDGPUISD::CVT_PK_FP8_F32;
11250 SDValue PoisonI32 = DAG.getPOISON(MVT::i32);
11251 SDValue WordSel = DAG.getTargetConstant(0, SL, MVT::i1);
11252
11253 if (!ResVT.isVector()) {
11254 // Convert one lane, the second is unused. Feed it the same source so the
11255 // instruction does not read an undefined register.
11256 SDValue Packed =
11257 DAG.getNode(Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11258 return DAG.getAnyExtOrTrunc(Packed, SL, ResVT);
11259 }
11260
11261 SDValue A = DAG.getExtractVectorElt(SL, MVT::f32, Src, 0);
11262 SDValue B = DAG.getExtractVectorElt(SL, MVT::f32, Src, 1);
11263 SDValue Packed = DAG.getNode(Opc, SL, MVT::i32, A, B, PoisonI32, WordSel);
11264 SDValue Bytes = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Packed);
11265 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11266}
11267
11268SDValue
11269SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(SDValue Op,
11270 SelectionDAG &DAG) const {
11271 // The OCP FP8 formats (E4M3FN, E5M2) and unsigned E5M3 map to HW conversions
11272 // on subtargets that support them. Everything else uses generic expansion.
11274 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11275 const bool IsFP8 = Sem == APFloatBase::S_Float8E4M3FN;
11276 const bool IsBF8 = Sem == APFloatBase::S_Float8E5M2;
11277 const bool IsE5M3 = Sem == APFloatBase::S_Float8E5M3FNU;
11278 const bool HasE5M3ConversionInsts =
11279 Subtarget->hasFP8ConversionInsts() && Subtarget->hasFP8E5M3Insts();
11280 const bool IsSupported = IsFP8 || IsBF8 || (IsE5M3 && HasE5M3ConversionInsts);
11281 if (!IsSupported)
11282 return SDValue();
11283
11284 // The HW conversions only support nearest-even. The OCP conversions do not
11285 // saturate. The unsigned E5M3 conversion always clamps out-of-range inputs,
11286 // which also refines the non-saturating form where those inputs are poison.
11287 if (static_cast<RoundingMode>(Op.getConstantOperandVal(2)) !=
11289 return SDValue();
11290 if (!IsE5M3 && Op.getConstantOperandVal(3) != 0)
11291 return SDValue();
11292
11293 EVT SrcEltVT = Op.getOperand(0).getValueType().getScalarType();
11294 // The f32 form is built here rather than by a tablegen pattern because the
11295 // HW result is i32 while the node result is i16 after the i8 promotion.
11296 if (SrcEltVT == MVT::f32)
11297 return lowerToFP8(Op, IsBF8, IsE5M3, DAG);
11298 if (!IsE5M3 && SrcEltVT == MVT::f16 &&
11299 Subtarget->hasF16FP8ConversionInsts()) {
11300 // A scalar conversion is selected from the generic node by tablegen, only
11301 // the illegal v2i8 result type needs lowering here.
11302 if (!Op.getValueType().isVector())
11303 return Op;
11304 return lowerToFP8(Op, IsBF8, false, DAG);
11305 }
11306 return SDValue();
11307}
11308
11309SDValue SITargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
11310 SelectionDAG &DAG) const {
11312 auto *MFI = MF.getInfo<SIMachineFunctionInfo>();
11313
11314 EVT VT = Op.getValueType();
11315 SDLoc DL(Op);
11316 unsigned IntrinsicID = Op.getConstantOperandVal(0);
11317
11318 // TODO: Should this propagate fast-math-flags?
11319
11320 switch (IntrinsicID) {
11321 case Intrinsic::amdgcn_wave_reduce_min:
11322 case Intrinsic::amdgcn_wave_reduce_umin:
11323 case Intrinsic::amdgcn_wave_reduce_fmin:
11324 case Intrinsic::amdgcn_wave_reduce_max:
11325 case Intrinsic::amdgcn_wave_reduce_umax:
11326 case Intrinsic::amdgcn_wave_reduce_fmax:
11327 case Intrinsic::amdgcn_wave_reduce_add:
11328 case Intrinsic::amdgcn_wave_reduce_fadd:
11329 case Intrinsic::amdgcn_wave_reduce_sub:
11330 case Intrinsic::amdgcn_wave_reduce_fsub:
11331 case Intrinsic::amdgcn_wave_reduce_and:
11332 case Intrinsic::amdgcn_wave_reduce_or:
11333 case Intrinsic::amdgcn_wave_reduce_xor: {
11334 EVT SrcVT = Op.getOperand(1).getValueType();
11335 if (SrcVT.getFixedSizeInBits() == 16) {
11336 bool IsFPOp = SrcVT.isFloatingPoint();
11337 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11338 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11339 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11340 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11341 unsigned ExtOpc = IsFPOp ? ISD::FP_EXTEND
11342 : NeedsSignExt ? ISD::SIGN_EXTEND
11344 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11345 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11346 SDValue ExtendedSrc = DAG.getNode(ExtOpc, DL, ExtType, Op.getOperand(1));
11347 SDValue Strategy = Op.getOperand(2);
11349 Op.getOperand(0), ExtendedSrc, Strategy);
11350 if (IsFPOp)
11351 return DAG.getNode(ISD::FP_ROUND, DL, SrcType, Result,
11352 DAG.getTargetConstant(1, DL, MVT::i32));
11353 else
11354 return DAG.getNode(ISD::TRUNCATE, DL, SrcType, Result);
11355 }
11356 return SDValue();
11357 }
11358 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11359 if (!MFI->getUserSGPRInfo().hasImplicitBufferPtr()) {
11360 const char *Error =
11361 Subtarget->hasArchitectedFlatScratch()
11362 ? "intrinsic not supported on subtarget"
11363 : !Subtarget->isMesa3DOS()
11364 ? "intrinsic not supported for OS"
11365 : "intrinsic not supported for calling convention";
11366 DAG.getContext()->diagnose(
11367 DiagnosticInfoUnsupported(MF.getFunction(), Error, DL.getDebugLoc()));
11368 return DAG.getPOISON(VT);
11369 }
11370
11371 return getPreloadedValue(DAG, *MFI, VT,
11373 }
11374 case Intrinsic::amdgcn_dispatch_ptr:
11375 case Intrinsic::amdgcn_queue_ptr: {
11376 if (!Subtarget->isAmdHsaOrMesa(MF.getFunction())) {
11377 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11378 MF.getFunction(), "unsupported hsa intrinsic without hsa target",
11379 DL.getDebugLoc()));
11380 return DAG.getPOISON(VT);
11381 }
11382
11383 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11386 return getPreloadedValue(DAG, *MFI, VT, RegID);
11387 }
11388 case Intrinsic::amdgcn_implicitarg_ptr: {
11389 if (MFI->isEntryFunction())
11390 return getImplicitArgPtr(DAG, DL);
11391 return getPreloadedValue(DAG, *MFI, VT,
11393 }
11394 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11395 if (!AMDGPU::isKernel(MF.getFunction())) {
11396 // This only makes sense to call in a kernel, so just lower to null.
11397 return DAG.getConstant(0, DL, VT);
11398 }
11399
11400 return getPreloadedValue(DAG, *MFI, VT,
11402 }
11403 case Intrinsic::amdgcn_dispatch_id: {
11404 return getPreloadedValue(DAG, *MFI, VT, AMDGPUFunctionArgInfo::DISPATCH_ID);
11405 }
11406 case Intrinsic::amdgcn_rcp:
11407 return DAG.getNode(AMDGPUISD::RCP, DL, VT, Op.getOperand(1));
11408 case Intrinsic::amdgcn_rsq:
11409 return DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11410 case Intrinsic::amdgcn_rsq_legacy:
11411 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11412 return emitRemovedIntrinsicError(DAG, DL, VT);
11413 return SDValue();
11414 case Intrinsic::amdgcn_rcp_legacy:
11415 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11416 return emitRemovedIntrinsicError(DAG, DL, VT);
11417 return DAG.getNode(AMDGPUISD::RCP_LEGACY, DL, VT, Op.getOperand(1));
11418 case Intrinsic::amdgcn_fma_legacy:
11419 case Intrinsic::amdgcn_sudot4:
11420 case Intrinsic::amdgcn_sudot8:
11421 case Intrinsic::amdgcn_tanh:
11422 return SDValue();
11423 case Intrinsic::amdgcn_rsq_clamp: {
11424 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11425 return DAG.getNode(AMDGPUISD::RSQ_CLAMP, DL, VT, Op.getOperand(1));
11426
11427 Type *Type = VT.getTypeForEVT(*DAG.getContext());
11428 APFloat Max = APFloat::getLargest(Type->getFltSemantics());
11429 APFloat Min = APFloat::getLargest(Type->getFltSemantics(), true);
11430
11431 SDValue Rsq = DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11432 SDValue Tmp =
11433 DAG.getNode(ISD::FMINNUM, DL, VT, Rsq, DAG.getConstantFP(Max, DL, VT));
11434 return DAG.getNode(ISD::FMAXNUM, DL, VT, Tmp,
11435 DAG.getConstantFP(Min, DL, VT));
11436 }
11437 case Intrinsic::r600_read_ngroups_x:
11438 if (Subtarget->isAmdHsaOS())
11439 return emitNonHSAIntrinsicError(DAG, DL, VT);
11440
11441 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11443 false);
11444 case Intrinsic::r600_read_ngroups_y:
11445 if (Subtarget->isAmdHsaOS())
11446 return emitNonHSAIntrinsicError(DAG, DL, VT);
11447
11448 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11450 false);
11451 case Intrinsic::r600_read_ngroups_z:
11452 if (Subtarget->isAmdHsaOS())
11453 return emitNonHSAIntrinsicError(DAG, DL, VT);
11454
11455 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11457 false);
11458 case Intrinsic::r600_read_local_size_x:
11459 if (Subtarget->isAmdHsaOS())
11460 return emitNonHSAIntrinsicError(DAG, DL, VT);
11461
11462 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11464 case Intrinsic::r600_read_local_size_y:
11465 if (Subtarget->isAmdHsaOS())
11466 return emitNonHSAIntrinsicError(DAG, DL, VT);
11467
11468 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11470 case Intrinsic::r600_read_local_size_z:
11471 if (Subtarget->isAmdHsaOS())
11472 return emitNonHSAIntrinsicError(DAG, DL, VT);
11473
11474 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11476 case Intrinsic::amdgcn_workgroup_id_x:
11477 return lowerWorkGroupId(DAG, *MFI, VT,
11481 case Intrinsic::amdgcn_workgroup_id_y:
11482 return lowerWorkGroupId(DAG, *MFI, VT,
11486 case Intrinsic::amdgcn_workgroup_id_z:
11487 return lowerWorkGroupId(DAG, *MFI, VT,
11491 case Intrinsic::amdgcn_cluster_id_x:
11492 return Subtarget->hasClusters()
11493 ? getPreloadedValue(DAG, *MFI, VT,
11495 : DAG.getPOISON(VT);
11496 case Intrinsic::amdgcn_cluster_id_y:
11497 return Subtarget->hasClusters()
11498 ? getPreloadedValue(DAG, *MFI, VT,
11500 : DAG.getPOISON(VT);
11501 case Intrinsic::amdgcn_cluster_id_z:
11502 return Subtarget->hasClusters()
11503 ? getPreloadedValue(DAG, *MFI, VT,
11505 : DAG.getPOISON(VT);
11506 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11507 return Subtarget->hasClusters()
11508 ? getPreloadedValue(
11509 DAG, *MFI, VT,
11511 : DAG.getPOISON(VT);
11512 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11513 return Subtarget->hasClusters()
11514 ? getPreloadedValue(
11515 DAG, *MFI, VT,
11517 : DAG.getPOISON(VT);
11518 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11519 return Subtarget->hasClusters()
11520 ? getPreloadedValue(
11521 DAG, *MFI, VT,
11523 : DAG.getPOISON(VT);
11524 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11525 return Subtarget->hasClusters()
11526 ? lowerConstHwRegRead(DAG, Op, AMDGPU::Hwreg::ID_IB_STS2, 21, 4)
11527 : SDValue();
11528 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11529 return Subtarget->hasClusters()
11530 ? getPreloadedValue(
11531 DAG, *MFI, VT,
11533 : DAG.getPOISON(VT);
11534 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11535 return Subtarget->hasClusters()
11536 ? getPreloadedValue(
11537 DAG, *MFI, VT,
11539 : DAG.getPOISON(VT);
11540 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11541 return Subtarget->hasClusters()
11542 ? getPreloadedValue(
11543 DAG, *MFI, VT,
11545 : DAG.getPOISON(VT);
11546 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11547 return Subtarget->hasClusters()
11548 ? getPreloadedValue(
11549 DAG, *MFI, VT,
11551 : DAG.getPOISON(VT);
11552 case Intrinsic::amdgcn_wave_id:
11553 return lowerWaveID(DAG, Op);
11554 case Intrinsic::amdgcn_lds_kernel_id: {
11555 if (MFI->isEntryFunction())
11556 return getLDSKernelId(DAG, DL);
11557 return getPreloadedValue(DAG, *MFI, VT,
11559 }
11560 case Intrinsic::amdgcn_workitem_id_x:
11561 return lowerWorkitemID(DAG, Op, 0, MFI->getArgInfo().WorkItemIDX);
11562 case Intrinsic::amdgcn_workitem_id_y:
11563 return lowerWorkitemID(DAG, Op, 1, MFI->getArgInfo().WorkItemIDY);
11564 case Intrinsic::amdgcn_workitem_id_z:
11565 return lowerWorkitemID(DAG, Op, 2, MFI->getArgInfo().WorkItemIDZ);
11566 case Intrinsic::amdgcn_wavefrontsize:
11567 return DAG.getConstant(MF.getSubtarget<GCNSubtarget>().getWavefrontSize(),
11568 SDLoc(Op), MVT::i32);
11569 case Intrinsic::amdgcn_s_buffer_load: {
11570 unsigned CPol = Op.getConstantOperandVal(3);
11571 // s_buffer_load, because of how it's optimized, can't be volatile
11572 // so reject ones with the volatile bit set.
11573 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
11576 return Op;
11577 return lowerSBuffer(VT, VT, DL, DAG.getEntryNode(), Op.getOperand(1),
11578 Op.getOperand(2), Op.getOperand(3), DAG);
11579 }
11580 case Intrinsic::amdgcn_fdiv_fast:
11581 return lowerFDIV_FAST(Op, DAG);
11582 case Intrinsic::amdgcn_sin:
11583 return DAG.getNode(AMDGPUISD::SIN_HW, DL, VT, Op.getOperand(1));
11584
11585 case Intrinsic::amdgcn_cos:
11586 return DAG.getNode(AMDGPUISD::COS_HW, DL, VT, Op.getOperand(1));
11587
11588 case Intrinsic::amdgcn_mul_u24:
11589 return DAG.getNode(AMDGPUISD::MUL_U24, DL, VT, Op.getOperand(1),
11590 Op.getOperand(2));
11591 case Intrinsic::amdgcn_mul_i24:
11592 return DAG.getNode(AMDGPUISD::MUL_I24, DL, VT, Op.getOperand(1),
11593 Op.getOperand(2));
11594
11595 case Intrinsic::amdgcn_log_clamp: {
11596 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11597 return SDValue();
11598
11599 return emitRemovedIntrinsicError(DAG, DL, VT);
11600 }
11601 case Intrinsic::amdgcn_fract:
11602 return DAG.getNode(AMDGPUISD::FRACT, DL, VT, Op.getOperand(1));
11603
11604 case Intrinsic::amdgcn_class: {
11605 SDValue Src = Op.getOperand(1);
11606 EVT SrcVT = Src.getValueType();
11607 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11608 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11609 if (!IsLegal) {
11610 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11612 "llvm.amdgcn.class only supports f16, f32, and f64",
11613 DL.getDebugLoc()));
11614 return DAG.getPOISON(VT);
11615 }
11616 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, VT, Src, Op.getOperand(2));
11617 }
11618 case Intrinsic::amdgcn_div_fmas:
11619 return DAG.getNode(AMDGPUISD::DIV_FMAS, DL, VT, Op.getOperand(1),
11620 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11621
11622 case Intrinsic::amdgcn_div_fixup:
11623 return DAG.getNode(AMDGPUISD::DIV_FIXUP, DL, VT, Op.getOperand(1),
11624 Op.getOperand(2), Op.getOperand(3));
11625
11626 case Intrinsic::amdgcn_div_scale: {
11627 const ConstantSDNode *Param = cast<ConstantSDNode>(Op.getOperand(3));
11628
11629 // Translate to the operands expected by the machine instruction. The
11630 // first parameter must be the same as the first instruction.
11631 SDValue Numerator = Op.getOperand(1);
11632 SDValue Denominator = Op.getOperand(2);
11633
11634 // Note this order is opposite of the machine instruction's operations,
11635 // which is s0.f = Quotient, s1.f = Denominator, s2.f = Numerator. The
11636 // intrinsic has the numerator as the first operand to match a normal
11637 // division operation.
11638
11639 SDValue Src0 = Param->isAllOnes() ? Numerator : Denominator;
11640
11641 return DAG.getNode(AMDGPUISD::DIV_SCALE, DL, Op->getVTList(), Src0,
11642 Denominator, Numerator);
11643 }
11644 case Intrinsic::amdgcn_ballot:
11645 return lowerBALLOTIntrinsic(*this, Op.getNode(), DAG);
11646 case Intrinsic::amdgcn_fmed3:
11647 return DAG.getNode(AMDGPUISD::FMED3, DL, VT, Op.getOperand(1),
11648 Op.getOperand(2), Op.getOperand(3), Op->getFlags());
11649 case Intrinsic::amdgcn_fdot2:
11650 return DAG.getNode(AMDGPUISD::FDOT2, DL, VT, Op.getOperand(1),
11651 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11652 case Intrinsic::amdgcn_fmul_legacy:
11653 return DAG.getNode(AMDGPUISD::FMUL_LEGACY, DL, VT, Op.getOperand(1),
11654 Op.getOperand(2));
11655 case Intrinsic::amdgcn_sbfe:
11656 case Intrinsic::amdgcn_ubfe:
11657 return lowerBFEIntrinsic(Op, DAG, IntrinsicID);
11658 case Intrinsic::amdgcn_cvt_pkrtz:
11659 case Intrinsic::amdgcn_cvt_pknorm_i16:
11660 case Intrinsic::amdgcn_cvt_pknorm_u16:
11661 case Intrinsic::amdgcn_cvt_pk_i16:
11662 case Intrinsic::amdgcn_cvt_pk_u16: {
11663 // FIXME: Stop adding cast if v2f16/v2i16 are legal.
11664 EVT VT = Op.getValueType();
11665 unsigned Opcode;
11666
11667 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11668 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11669 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11670 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11671 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11672 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11673 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11674 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11675 else
11676 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11677
11678 if (isTypeLegal(VT))
11679 return DAG.getNode(Opcode, DL, VT, Op.getOperand(1), Op.getOperand(2));
11680
11681 SDValue Node =
11682 DAG.getNode(Opcode, DL, MVT::i32, Op.getOperand(1), Op.getOperand(2));
11683 return DAG.getNode(ISD::BITCAST, DL, VT, Node);
11684 }
11685 case Intrinsic::amdgcn_fmad_ftz:
11686 return DAG.getNode(AMDGPUISD::FMAD_FTZ, DL, VT, Op.getOperand(1),
11687 Op.getOperand(2), Op.getOperand(3));
11688
11689 case Intrinsic::amdgcn_if_break:
11690 return SDValue(DAG.getMachineNode(AMDGPU::SI_IF_BREAK, DL, VT,
11691 Op->getOperand(1), Op->getOperand(2)),
11692 0);
11693
11694 case Intrinsic::amdgcn_groupstaticsize: {
11696 if (OS == Triple::AMDHSA || OS == Triple::AMDPAL)
11697 return Op;
11698
11699 const Module *M = MF.getFunction().getParent();
11700 const GlobalValue *GV =
11701 Intrinsic::getDeclarationIfExists(M, Intrinsic::amdgcn_groupstaticsize);
11702 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, 0,
11704 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11705 }
11706 case Intrinsic::amdgcn_is_shared:
11707 case Intrinsic::amdgcn_is_private: {
11708 SDLoc SL(Op);
11709 SDValue SrcVec =
11710 DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
11711 SDValue SrcHi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, SrcVec,
11712 DAG.getConstant(1, SL, MVT::i32));
11713
11714 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11716 : AMDGPUAS::PRIVATE_ADDRESS;
11717 if (AS == AMDGPUAS::PRIVATE_ADDRESS &&
11718 Subtarget->hasGloballyAddressableScratch()) {
11719 SDValue FlatScratchBaseHi(
11720 DAG.getMachineNode(
11721 AMDGPU::S_MOV_B32, DL, MVT::i32,
11722 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11723 0);
11724 // Test bits 63..58 against the aperture address.
11725 return DAG.getSetCC(
11726 SL, MVT::i1,
11727 DAG.getNode(ISD::XOR, SL, MVT::i32, SrcHi, FlatScratchBaseHi),
11728 DAG.getConstant(1u << 26, SL, MVT::i32), ISD::SETULT);
11729 }
11730
11731 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11732 return DAG.getSetCC(SL, MVT::i1, SrcHi, Aperture, ISD::SETEQ);
11733 }
11734 case Intrinsic::amdgcn_perm:
11735 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op.getOperand(1),
11736 Op.getOperand(2), Op.getOperand(3));
11737 case Intrinsic::amdgcn_reloc_constant: {
11738 Module *M = MF.getFunction().getParent();
11739 const MDNode *Metadata = cast<MDNodeSDNode>(Op.getOperand(1))->getMD();
11740 auto SymbolName = cast<MDString>(Metadata->getOperand(0))->getString();
11741 auto *RelocSymbol = cast<GlobalVariable>(
11742 M->getOrInsertGlobal(SymbolName, Type::getInt32Ty(M->getContext())));
11743 SDValue GA = DAG.getTargetGlobalAddress(RelocSymbol, DL, MVT::i32, 0,
11745 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11746 }
11747 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11748 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11749 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11750 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11751 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11752 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11753 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11754 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11755 if (Op.getOperand(4).getValueType() == MVT::i32)
11756 return SDValue();
11757
11758 SDLoc SL(Op);
11759 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i32);
11760 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11761 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11762 Op.getOperand(3), IndexKeyi32);
11763 }
11764 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11765 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11766 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11767 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11768 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11769 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11770 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11771 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11772 if (Op.getOperand(4).getValueType() == MVT::i64)
11773 return SDValue();
11774
11775 SDLoc SL(Op);
11776 auto IndexKeyi64 =
11777 Op.getOperand(4).getValueType() == MVT::v2i32
11778 ? DAG.getBitcast(MVT::i64, Op.getOperand(4))
11779 : DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i64);
11780 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11781 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11782 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11783 Op.getOperand(6)});
11784 }
11785 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11786 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11787 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11788 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11789 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11790 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11791 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11792 ? MVT::i64
11793 : MVT::i32;
11794 if (Op.getOperand(6).getValueType() == IndexKeyTy)
11795 return SDValue();
11796
11797 SDLoc SL(Op);
11798 auto IndexKey =
11799 Op.getOperand(6).getValueType().isVector()
11800 ? DAG.getBitcast(IndexKeyTy, Op.getOperand(6))
11801 : DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, IndexKeyTy);
11803 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11804 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11805 IndexKey, Op.getOperand(7), Op.getOperand(8)};
11806 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11807 Args.push_back(Op.getOperand(9));
11808 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(), Args);
11809 }
11810 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11811 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11812 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11813 if (Op.getOperand(6).getValueType() == MVT::i32)
11814 return SDValue();
11815
11816 SDLoc SL(Op);
11817 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, MVT::i32);
11818 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11819 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11820 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11821 IndexKeyi32, Op.getOperand(7)});
11822 }
11823 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11824 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11825 unsigned AFmt = (unsigned)Op.getConstantOperandVal(1);
11826 unsigned BFmt = (unsigned)Op.getConstantOperandVal(3);
11827 unsigned AScaleFmt = (unsigned)Op.getConstantOperandVal(8);
11828 unsigned BScaleFmt = (unsigned)Op.getConstantOperandVal(11);
11829 if (!AMDGPU::isValidWMMAScaleFmtCombination(AFmt, AScaleFmt, BFmt,
11830 BScaleFmt)) {
11832 "invalid matrix and scale format combination in wmma call");
11833 Op->print(errs());
11834 errs() << '\n';
11835 }
11836 return SDValue();
11837 }
11838 case Intrinsic::amdgcn_readlane:
11839 case Intrinsic::amdgcn_readfirstlane:
11840 case Intrinsic::amdgcn_writelane:
11841 case Intrinsic::amdgcn_permlane16:
11842 case Intrinsic::amdgcn_permlanex16:
11843 case Intrinsic::amdgcn_permlane64:
11844 case Intrinsic::amdgcn_set_inactive:
11845 case Intrinsic::amdgcn_set_inactive_chain_arg:
11846 case Intrinsic::amdgcn_mov_dpp8:
11847 case Intrinsic::amdgcn_update_dpp:
11848 case Intrinsic::amdgcn_permlane_bcast:
11849 case Intrinsic::amdgcn_permlane_up:
11850 case Intrinsic::amdgcn_permlane_down:
11851 case Intrinsic::amdgcn_permlane_xor:
11852 return lowerLaneOp(*this, Op.getNode(), DAG);
11853 case Intrinsic::amdgcn_dead: {
11855 for (const EVT ValTy : Op.getNode()->values())
11856 Poisons.push_back(DAG.getPOISON(ValTy));
11857 return DAG.getMergeValues(Poisons, SDLoc(Op));
11858 }
11859 case Intrinsic::amdgcn_wave_shuffle:
11860 return lowerWaveShuffle(*this, Op.getNode(), DAG);
11861 default:
11862 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11864 return lowerImage(Op, ImageDimIntr, DAG, false);
11865
11866 return Op;
11867 }
11868}
11869
11870// On targets not supporting constant in soffset field, turn zero to
11871// SGPR_NULL to avoid generating an extra s_mov with zero.
11873 const GCNSubtarget *Subtarget) {
11874 if (Subtarget->hasRestrictedSOffset() && isNullConstant(SOffset))
11875 return DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11876 return SOffset;
11877}
11878
11879SDValue SITargetLowering::lowerRawBufferAtomicIntrin(SDValue Op,
11880 SelectionDAG &DAG,
11881 unsigned NewOpcode) const {
11882 SDLoc DL(Op);
11883
11884 SDValue VData = Op.getOperand(2);
11885 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11886 SmallVector<EVT, 2> ResultTypes(Op->values());
11887 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11888 "unsupported buffer atomic data type");
11889 }
11890 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11891 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
11892 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
11893 SDValue Ops[] = {
11894 Op.getOperand(0), // Chain
11895 VData, // vdata
11896 Rsrc, // rsrc
11897 DAG.getConstant(0, DL, MVT::i32), // vindex
11898 VOffset, // voffset
11899 SOffset, // soffset
11900 Offset, // offset
11901 Op.getOperand(6), // cachepolicy
11902 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11903 };
11904
11905 auto *M = cast<MemSDNode>(Op);
11906
11907 EVT MemVT = VData.getValueType();
11908 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11909 M->getMemOperand());
11910}
11911
11912SDValue
11913SITargetLowering::lowerStructBufferAtomicIntrin(SDValue Op, SelectionDAG &DAG,
11914 unsigned NewOpcode) const {
11915 SDLoc DL(Op);
11916
11917 SDValue VData = Op.getOperand(2);
11918 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11919 SmallVector<EVT, 2> ResultTypes(Op->values());
11920 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11921 "unsupported buffer atomic data type");
11922 }
11923 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11924 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
11925 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
11926 SDValue Ops[] = {
11927 Op.getOperand(0), // Chain
11928 VData, // vdata
11929 Rsrc, // rsrc
11930 Op.getOperand(4), // vindex
11931 VOffset, // voffset
11932 SOffset, // soffset
11933 Offset, // offset
11934 Op.getOperand(7), // cachepolicy
11935 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
11936 };
11937
11938 auto *M = cast<MemSDNode>(Op);
11939
11940 EVT MemVT = VData.getValueType();
11941 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11942 M->getMemOperand());
11943}
11944
11946 SDLoc DL) {
11947 SDNode *N = Op.getNode();
11948 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
11949 unsigned NumOperands = N->getNumOperands();
11950 if (N->getOperand(NumOperands - 1) == Zero)
11951 return;
11953 Ops[NumOperands - 1] = Zero; // M0 = 0
11954 DAG.UpdateNodeOperands(N, Ops);
11955}
11956
11957SDValue SITargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
11958 SelectionDAG &DAG) const {
11959 unsigned IntrID = Op.getConstantOperandVal(1);
11960 SDLoc DL(Op);
11961
11962 switch (IntrID) {
11963 case Intrinsic::amdgcn_cluster_load_b32:
11964 case Intrinsic::amdgcn_cluster_load_b64:
11965 case Intrinsic::amdgcn_cluster_load_b128: {
11966 if (Subtarget->hasGFX1250_STRICT())
11968 return SDValue();
11969 }
11970 case Intrinsic::amdgcn_ds_ordered_add:
11971 case Intrinsic::amdgcn_ds_ordered_swap: {
11972 MemSDNode *M = cast<MemSDNode>(Op);
11973 SDValue Chain = M->getOperand(0);
11974 SDValue M0 = M->getOperand(2);
11975 SDValue Value = M->getOperand(3);
11976 unsigned IndexOperand = M->getConstantOperandVal(7);
11977 unsigned WaveRelease = M->getConstantOperandVal(8);
11978 unsigned WaveDone = M->getConstantOperandVal(9);
11979
11980 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11981 IndexOperand &= ~0x3f;
11982 unsigned CountDw = 0;
11983
11984 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10) {
11985 CountDw = (IndexOperand >> 24) & 0xf;
11986 IndexOperand &= ~(0xf << 24);
11987
11988 if (CountDw < 1 || CountDw > 4) {
11989 const Function &Fn = DAG.getMachineFunction().getFunction();
11990 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11991 Fn, "ds_ordered_count: dword count must be between 1 and 4",
11992 DL.getDebugLoc()));
11993 CountDw = 1;
11994 }
11995 }
11996
11997 if (IndexOperand) {
11998 const Function &Fn = DAG.getMachineFunction().getFunction();
11999 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12000 Fn, "ds_ordered_count: bad index operand", DL.getDebugLoc()));
12001 }
12002
12003 if (WaveDone && !WaveRelease) {
12004 // TODO: Move this to IR verifier
12005 const Function &Fn = DAG.getMachineFunction().getFunction();
12006 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12007 Fn, "ds_ordered_count: wave_done requires wave_release",
12008 DL.getDebugLoc()));
12009 }
12010
12011 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
12012 unsigned ShaderType =
12014 unsigned Offset0 = OrderedCountIndex << 2;
12015 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
12016
12017 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10)
12018 Offset1 |= (CountDw - 1) << 6;
12019
12020 if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX11)
12021 Offset1 |= ShaderType << 2;
12022
12023 unsigned Offset = Offset0 | (Offset1 << 8);
12024
12025 SDValue Ops[] = {
12026 Chain, Value, DAG.getTargetConstant(Offset, DL, MVT::i16),
12027 copyToM0(DAG, Chain, DL, M0).getValue(1), // Glue
12028 };
12029 return DAG.getMemIntrinsicNode(AMDGPUISD::DS_ORDERED_COUNT, DL,
12030 M->getVTList(), Ops, M->getMemoryVT(),
12031 M->getMemOperand());
12032 }
12033 case Intrinsic::amdgcn_ptr_s_buffer_load: {
12034 unsigned CPol = Op.getConstantOperandVal(4);
12035 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
12038 return Op;
12039
12040 MemSDNode *M = cast<MemSDNode>(Op);
12041 return lowerSBuffer(
12042 Op.getValueType(), M->getMemoryVT(), DL, Op.getOperand(0),
12043 bufferRsrcPtrToVector(Op.getOperand(2), DAG), Op.getOperand(3),
12044 Op.getOperand(4), DAG, M->getMemOperand());
12045 }
12046 case Intrinsic::amdgcn_raw_buffer_load:
12047 case Intrinsic::amdgcn_raw_ptr_buffer_load:
12048 case Intrinsic::amdgcn_raw_atomic_buffer_load:
12049 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
12050 case Intrinsic::amdgcn_raw_buffer_load_format:
12051 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
12052 const bool IsFormat =
12053 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
12054 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
12055
12056 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12057 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
12058 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
12059 SDValue Ops[] = {
12060 Op.getOperand(0), // Chain
12061 Rsrc, // rsrc
12062 DAG.getConstant(0, DL, MVT::i32), // vindex
12063 VOffset, // voffset
12064 SOffset, // soffset
12065 Offset, // offset
12066 Op.getOperand(5), // cachepolicy, swizzled buffer
12067 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12068 };
12069
12070 auto *M = cast<MemSDNode>(Op);
12071 return lowerIntrinsicLoad(M, IsFormat, DAG, Ops);
12072 }
12073 case Intrinsic::amdgcn_struct_buffer_load:
12074 case Intrinsic::amdgcn_struct_ptr_buffer_load:
12075 case Intrinsic::amdgcn_struct_buffer_load_format:
12076 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
12077 case Intrinsic::amdgcn_struct_atomic_buffer_load:
12078 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
12079 const bool IsFormat =
12080 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
12081 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
12082
12083 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12084 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12085 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12086 SDValue Ops[] = {
12087 Op.getOperand(0), // Chain
12088 Rsrc, // rsrc
12089 Op.getOperand(3), // vindex
12090 VOffset, // voffset
12091 SOffset, // soffset
12092 Offset, // offset
12093 Op.getOperand(6), // cachepolicy, swizzled buffer
12094 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12095 };
12096
12097 return lowerIntrinsicLoad(cast<MemSDNode>(Op), IsFormat, DAG, Ops);
12098 }
12099 case Intrinsic::amdgcn_raw_tbuffer_load:
12100 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
12101 MemSDNode *M = cast<MemSDNode>(Op);
12102 EVT LoadVT = Op.getValueType();
12103 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12104 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
12105 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
12106
12107 SDValue Ops[] = {
12108 Op.getOperand(0), // Chain
12109 Rsrc, // rsrc
12110 DAG.getConstant(0, DL, MVT::i32), // vindex
12111 VOffset, // voffset
12112 SOffset, // soffset
12113 Offset, // offset
12114 Op.getOperand(5), // format
12115 Op.getOperand(6), // cachepolicy, swizzled buffer
12116 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12117 };
12118
12119 if (LoadVT.getScalarSizeInBits() == 16)
12120 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12121 Ops);
12122 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
12123 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
12124 DAG);
12125 }
12126 case Intrinsic::amdgcn_struct_tbuffer_load:
12127 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
12128 MemSDNode *M = cast<MemSDNode>(Op);
12129 EVT LoadVT = Op.getValueType();
12130 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12131 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12132 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12133
12134 SDValue Ops[] = {
12135 Op.getOperand(0), // Chain
12136 Rsrc, // rsrc
12137 Op.getOperand(3), // vindex
12138 VOffset, // voffset
12139 SOffset, // soffset
12140 Offset, // offset
12141 Op.getOperand(6), // format
12142 Op.getOperand(7), // cachepolicy, swizzled buffer
12143 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12144 };
12145
12146 if (LoadVT.getScalarSizeInBits() == 16)
12147 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
12148 Ops);
12149 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
12150 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
12151 DAG);
12152 }
12153 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
12154 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
12155 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
12156 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
12157 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
12158 return lowerStructBufferAtomicIntrin(Op, DAG,
12159 AMDGPUISD::BUFFER_ATOMIC_FADD);
12160 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
12161 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
12162 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
12163 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
12164 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
12165 return lowerStructBufferAtomicIntrin(Op, DAG,
12166 AMDGPUISD::BUFFER_ATOMIC_FMIN);
12167 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
12168 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
12169 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
12170 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
12171 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
12172 return lowerStructBufferAtomicIntrin(Op, DAG,
12173 AMDGPUISD::BUFFER_ATOMIC_FMAX);
12174 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
12175 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
12176 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
12177 case Intrinsic::amdgcn_raw_buffer_atomic_add:
12178 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
12179 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12180 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
12181 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
12182 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12183 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
12184 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
12185 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
12186 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
12187 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
12188 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
12189 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
12190 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
12191 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
12192 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
12193 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
12194 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
12195 case Intrinsic::amdgcn_raw_buffer_atomic_and:
12196 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
12197 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12198 case Intrinsic::amdgcn_raw_buffer_atomic_or:
12199 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
12200 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12201 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
12202 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
12203 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12204 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
12205 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
12206 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12207 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12208 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12209 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12210 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12211 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12212 return lowerStructBufferAtomicIntrin(Op, DAG,
12213 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12214 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12215 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12216 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12217 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12218 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12219 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12220 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12221 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12222 return lowerStructBufferAtomicIntrin(Op, DAG,
12223 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12224 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12225 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12226 return lowerStructBufferAtomicIntrin(Op, DAG,
12227 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12228 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12229 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12230 return lowerStructBufferAtomicIntrin(Op, DAG,
12231 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12232 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12233 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12234 return lowerStructBufferAtomicIntrin(Op, DAG,
12235 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12236 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12237 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12238 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12239 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12240 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12241 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12242 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12243 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12244 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12245 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12246 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12247 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12248 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12249 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12250 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12251 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12252 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12253 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12254 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12255 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12256 return lowerStructBufferAtomicIntrin(Op, DAG,
12257 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12258 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12259 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12260 return lowerRawBufferAtomicIntrin(Op, DAG,
12261 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12262 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12263 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12264 return lowerStructBufferAtomicIntrin(Op, DAG,
12265 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12266 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12267 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12268 SDValue Src = Op.getOperand(2);
12269 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12270 SmallVector<EVT, 2> ResultTypes(Op->values());
12271 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12272 "unsupported buffer atomic data type");
12273 }
12274 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(4), DAG);
12275 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12276 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12277 SDValue Ops[] = {
12278 Op.getOperand(0), // Chain
12279 Op.getOperand(2), // src
12280 Op.getOperand(3), // cmp
12281 Rsrc, // rsrc
12282 DAG.getConstant(0, DL, MVT::i32), // vindex
12283 VOffset, // voffset
12284 SOffset, // soffset
12285 Offset, // offset
12286 Op.getOperand(7), // cachepolicy
12287 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12288 };
12289 EVT VT = Op.getValueType();
12290 auto *M = cast<MemSDNode>(Op);
12291
12292 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12293 Op->getVTList(), Ops, VT,
12294 M->getMemOperand());
12295 }
12296 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12297 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12298 SDValue Src = Op.getOperand(2);
12299 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12300 SmallVector<EVT, 2> ResultTypes(Op->values());
12301 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12302 "unsupported buffer atomic data type");
12303 }
12304 SDValue Rsrc = bufferRsrcPtrToVector(Op->getOperand(4), DAG);
12305 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(6), DAG);
12306 auto SOffset = selectSOffset(Op.getOperand(7), DAG, Subtarget);
12307 SDValue Ops[] = {
12308 Op.getOperand(0), // Chain
12309 Op.getOperand(2), // src
12310 Op.getOperand(3), // cmp
12311 Rsrc, // rsrc
12312 Op.getOperand(5), // vindex
12313 VOffset, // voffset
12314 SOffset, // soffset
12315 Offset, // offset
12316 Op.getOperand(8), // cachepolicy
12317 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12318 };
12319 EVT VT = Op.getValueType();
12320 auto *M = cast<MemSDNode>(Op);
12321
12322 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12323 Op->getVTList(), Ops, VT,
12324 M->getMemOperand());
12325 }
12326 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12327 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12328 MemSDNode *M = cast<MemSDNode>(Op);
12329 SDValue NodePtr = M->getOperand(2);
12330 SDValue RayExtent = M->getOperand(3);
12331 SDValue InstanceMask = M->getOperand(4);
12332 SDValue RayOrigin = M->getOperand(5);
12333 SDValue RayDir = M->getOperand(6);
12334 SDValue Offsets = M->getOperand(7);
12335 SDValue TDescr = M->getOperand(8);
12336
12337 assert(NodePtr.getValueType() == MVT::i64);
12338 assert(RayDir.getValueType() == MVT::v3f32);
12339
12340 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12341 const unsigned NumVDataDwords = 10;
12342 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12343 int Opcode = AMDGPU::getMIMGOpcode(
12344 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12345 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12346 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12347 assert(Opcode != -1);
12348
12350 Ops.push_back(NodePtr);
12351 Ops.push_back(DAG.getBuildVector(
12352 MVT::v2i32, DL,
12353 {DAG.getBitcast(MVT::i32, RayExtent),
12354 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12355 Ops.push_back(RayOrigin);
12356 Ops.push_back(RayDir);
12357 Ops.push_back(Offsets);
12358 Ops.push_back(TDescr);
12359 Ops.push_back(M->getChain());
12360
12361 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12362 MachineMemOperand *MemRef = M->getMemOperand();
12363 DAG.setNodeMemRefs(NewNode, {MemRef});
12364 return SDValue(NewNode, 0);
12365 }
12366 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12367 MemSDNode *M = cast<MemSDNode>(Op);
12368 SDValue NodePtr = M->getOperand(2);
12369 SDValue RayExtent = M->getOperand(3);
12370 SDValue RayOrigin = M->getOperand(4);
12371 SDValue RayDir = M->getOperand(5);
12372 SDValue RayInvDir = M->getOperand(6);
12373 SDValue TDescr = M->getOperand(7);
12374
12375 assert(NodePtr.getValueType() == MVT::i32 ||
12376 NodePtr.getValueType() == MVT::i64);
12377 assert(RayDir.getValueType() == MVT::v3f16 ||
12378 RayDir.getValueType() == MVT::v3f32);
12379
12380 const bool IsGFX11 = AMDGPU::isGFX11(*Subtarget);
12381 const bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
12382 const bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
12383 const bool IsA16 = RayDir.getValueType().getVectorElementType() == MVT::f16;
12384 const bool Is64 = NodePtr.getValueType() == MVT::i64;
12385 const unsigned NumVDataDwords = 4;
12386 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12387 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12388 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12389 NumVAddrs <= Subtarget->getNSAMaxSize()) ||
12390 IsGFX12Plus;
12391 const unsigned BaseOpcodes[2][2] = {
12392 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12393 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12394 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12395 int Opcode;
12396 if (UseNSA) {
12397 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12398 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12399 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12400 : AMDGPU::MIMGEncGfx10NSA,
12401 NumVDataDwords, NumVAddrDwords);
12402 } else {
12403 assert(!IsGFX12Plus);
12404 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12405 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12406 : AMDGPU::MIMGEncGfx10Default,
12407 NumVDataDwords, NumVAddrDwords);
12408 }
12409 assert(Opcode != -1);
12410
12412
12413 auto packLanes = [&DAG, &Ops, &DL](SDValue Op, bool IsAligned) {
12415 DAG.ExtractVectorElements(Op, Lanes, 0, 3);
12416 if (Lanes[0].getValueSizeInBits() == 32) {
12417 for (unsigned I = 0; I < 3; ++I)
12418 Ops.push_back(DAG.getBitcast(MVT::i32, Lanes[I]));
12419 } else {
12420 if (IsAligned) {
12421 Ops.push_back(DAG.getBitcast(
12422 MVT::i32,
12423 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[0], Lanes[1]})));
12424 Ops.push_back(Lanes[2]);
12425 } else {
12426 SDValue Elt0 = Ops.pop_back_val();
12427 Ops.push_back(DAG.getBitcast(
12428 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL, {Elt0, Lanes[0]})));
12429 Ops.push_back(DAG.getBitcast(
12430 MVT::i32,
12431 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[1], Lanes[2]})));
12432 }
12433 }
12434 };
12435
12436 if (UseNSA && IsGFX11Plus) {
12437 Ops.push_back(NodePtr);
12438 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12439 Ops.push_back(RayOrigin);
12440 if (IsA16) {
12441 SmallVector<SDValue, 3> DirLanes, InvDirLanes, MergedLanes;
12442 DAG.ExtractVectorElements(RayDir, DirLanes, 0, 3);
12443 DAG.ExtractVectorElements(RayInvDir, InvDirLanes, 0, 3);
12444 for (unsigned I = 0; I < 3; ++I) {
12445 MergedLanes.push_back(DAG.getBitcast(
12446 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL,
12447 {DirLanes[I], InvDirLanes[I]})));
12448 }
12449 Ops.push_back(DAG.getBuildVector(MVT::v3i32, DL, MergedLanes));
12450 } else {
12451 Ops.push_back(RayDir);
12452 Ops.push_back(RayInvDir);
12453 }
12454 } else {
12455 if (Is64)
12456 DAG.ExtractVectorElements(DAG.getBitcast(MVT::v2i32, NodePtr), Ops, 0,
12457 2);
12458 else
12459 Ops.push_back(NodePtr);
12460
12461 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12462 packLanes(RayOrigin, true);
12463 packLanes(RayDir, true);
12464 packLanes(RayInvDir, false);
12465 }
12466
12467 if (!UseNSA) {
12468 // Build a single vector containing all the operands so far prepared.
12469 if (NumVAddrDwords > 12) {
12470 SDValue Undef = DAG.getPOISON(MVT::i32);
12471 Ops.append(16 - Ops.size(), Undef);
12472 }
12473 assert(Ops.size() >= 8 && Ops.size() <= 12);
12474 SDValue MergedOps =
12475 DAG.getBuildVector(MVT::getVectorVT(MVT::i32, Ops.size()), DL, Ops);
12476 Ops.clear();
12477 Ops.push_back(MergedOps);
12478 }
12479
12480 Ops.push_back(TDescr);
12481 Ops.push_back(DAG.getTargetConstant(IsA16, DL, MVT::i1));
12482 Ops.push_back(M->getChain());
12483
12484 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12485 MachineMemOperand *MemRef = M->getMemOperand();
12486 DAG.setNodeMemRefs(NewNode, {MemRef});
12487 return SDValue(NewNode, 0);
12488 }
12489 case Intrinsic::amdgcn_global_atomic_fmin_num:
12490 case Intrinsic::amdgcn_global_atomic_fmax_num:
12491 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12492 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12493 MemSDNode *M = cast<MemSDNode>(Op);
12494 SDValue Ops[] = {
12495 M->getOperand(0), // Chain
12496 M->getOperand(2), // Ptr
12497 M->getOperand(3) // Value
12498 };
12499 unsigned Opcode = 0;
12500 switch (IntrID) {
12501 case Intrinsic::amdgcn_global_atomic_fmin_num:
12502 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12503 Opcode = ISD::ATOMIC_LOAD_FMIN;
12504 break;
12505 }
12506 case Intrinsic::amdgcn_global_atomic_fmax_num:
12507 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12508 Opcode = ISD::ATOMIC_LOAD_FMAX;
12509 break;
12510 }
12511 default:
12512 llvm_unreachable("unhandled atomic opcode");
12513 }
12514 return DAG.getAtomic(Opcode, SDLoc(Op), M->getMemoryVT(), M->getVTList(),
12515 Ops, M->getMemOperand());
12516 }
12517 case Intrinsic::amdgcn_s_alloc_vgpr: {
12518 SDValue NumVGPRs = Op.getOperand(2);
12519 if (!NumVGPRs->isDivergent())
12520 return Op;
12521
12522 SDValue ReadFirstLaneID =
12523 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
12524 NumVGPRs = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
12525 ReadFirstLaneID, NumVGPRs);
12526
12527 return DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, Op->getVTList(),
12528 Op.getOperand(0), Op.getOperand(1), NumVGPRs);
12529 }
12530 case Intrinsic::amdgcn_s_get_barrier_state:
12531 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12532 SDValue Chain = Op->getOperand(0);
12534 unsigned Opc;
12535
12536 if (isa<ConstantSDNode>(Op->getOperand(2))) {
12537 uint64_t BarID = cast<ConstantSDNode>(Op->getOperand(2))->getZExtValue();
12538 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12539 BarID = BarID & 0x3F;
12540 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12541 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
12542 Ops.push_back(K);
12543 Ops.push_back(Chain);
12544 } else {
12545 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12546 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12547 SDValue M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, Op->getOperand(2),
12548 DAG.getConstant(0x3F, DL, MVT::i32));
12549 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
12550 } else
12551 Ops.push_back(copyToM0(DAG, Chain, DL, Op->getOperand(2)).getValue(0));
12552 }
12553
12554 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
12555 return SDValue(NewMI, 0);
12556 }
12557 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12558 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12559 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12560 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12561 SDValue Chain = Op->getOperand(0);
12562 SDValue Ptr = Op->getOperand(2);
12563 EVT VT = Op->getValueType(0);
12564 return DAG.getAtomicLoad(ISD::NON_EXTLOAD, DL, MII->getMemoryVT(), VT,
12565 Chain, Ptr, MII->getMemOperand());
12566 }
12567 case Intrinsic::amdgcn_av_load_b8:
12568 case Intrinsic::amdgcn_av_load_b16:
12569 case Intrinsic::amdgcn_av_load_b32:
12570 case Intrinsic::amdgcn_av_load_b64:
12571 case Intrinsic::amdgcn_av_load_b128: {
12572 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12573 SDValue Chain = Op->getOperand(0);
12574 SDValue Ptr = Op->getOperand(2);
12575 EVT VT = Op->getValueType(0);
12576 // Lower to a regular ISD::LOAD. The MachineMemOperand carries Monotonic
12577 // ordering and syncscope so that SIMemoryLegalizer sets cache policy bits.
12578 // Address space filtering in the load_global/load_flat PatFrags selects
12579 // the correct GLOBAL vs FLAT instruction.
12580 return DAG.getLoad(VT, DL, Chain, Ptr, MII->getMemOperand());
12581 }
12582 case Intrinsic::amdgcn_flat_load_monitor_b32:
12583 case Intrinsic::amdgcn_flat_load_monitor_b64:
12584 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12585 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12586 SDValue Chain = Op->getOperand(0);
12587 SDValue Ptr = Op->getOperand(2);
12588 return DAG.getMemIntrinsicNode(AMDGPUISD::FLAT_LOAD_MONITOR, DL,
12589 Op->getVTList(), {Chain, Ptr},
12590 MII->getMemoryVT(), MII->getMemOperand());
12591 }
12592 case Intrinsic::amdgcn_global_load_monitor_b32:
12593 case Intrinsic::amdgcn_global_load_monitor_b64:
12594 case Intrinsic::amdgcn_global_load_monitor_b128: {
12595 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12596 SDValue Chain = Op->getOperand(0);
12597 SDValue Ptr = Op->getOperand(2);
12598 return DAG.getMemIntrinsicNode(AMDGPUISD::GLOBAL_LOAD_MONITOR, DL,
12599 Op->getVTList(), {Chain, Ptr},
12600 MII->getMemoryVT(), MII->getMemOperand());
12601 }
12602 default:
12603
12604 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12606 return lowerImage(Op, ImageDimIntr, DAG, true);
12607
12608 return SDValue();
12609 }
12610}
12611
12612// Call DAG.getMemIntrinsicNode for a load, but first widen a dwordx3 type to
12613// dwordx4 if on SI and handle TFE loads.
12614SDValue SITargetLowering::getMemIntrinsicNode(unsigned Opcode, const SDLoc &DL,
12615 SDVTList VTList,
12616 ArrayRef<SDValue> Ops, EVT MemVT,
12617 MachineMemOperand *MMO,
12618 SelectionDAG &DAG) const {
12619 LLVMContext &C = *DAG.getContext();
12621 EVT VT = VTList.VTs[0];
12622
12623 assert(VTList.NumVTs == 2 || VTList.NumVTs == 3);
12624 bool IsTFE = VTList.NumVTs == 3;
12625 if (IsTFE) {
12626 unsigned NumValueDWords = divideCeil(VT.getSizeInBits(), 32);
12627 unsigned NumOpDWords = NumValueDWords + 1;
12628 EVT OpDWordsVT = EVT::getVectorVT(C, MVT::i32, NumOpDWords);
12629 SDVTList OpDWordsVTList = DAG.getVTList(OpDWordsVT, VTList.VTs[2]);
12630 MachineMemOperand *OpDWordsMMO =
12631 MF.getMachineMemOperand(MMO, 0, NumOpDWords * 4);
12632 SDValue Op = getMemIntrinsicNode(Opcode, DL, OpDWordsVTList, Ops,
12633 OpDWordsVT, OpDWordsMMO, DAG);
12634 auto [Value, Status] = splitTFEValueAndStatus(Op, VT, DL, DAG);
12635 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
12636 }
12637
12638 if (!Subtarget->hasDwordx3LoadStores() &&
12639 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12640 EVT WidenedVT = EVT::getVectorVT(C, VT.getVectorElementType(), 4);
12641 EVT WidenedMemVT = EVT::getVectorVT(C, MemVT.getVectorElementType(), 4);
12642 MachineMemOperand *WidenedMMO = MF.getMachineMemOperand(MMO, 0, 16);
12643 SDVTList WidenedVTList = DAG.getVTList(WidenedVT, VTList.VTs[1]);
12644 SDValue Op = DAG.getMemIntrinsicNode(Opcode, DL, WidenedVTList, Ops,
12645 WidenedMemVT, WidenedMMO);
12647 DAG.getVectorIdxConstant(0, DL));
12648 return DAG.getMergeValues({Value, SDValue(Op.getNode(), 1)}, DL);
12649 }
12650
12651 return DAG.getMemIntrinsicNode(Opcode, DL, VTList, Ops, MemVT, MMO);
12652}
12653
12654SDValue SITargetLowering::handleD16VData(SDValue VData, SelectionDAG &DAG,
12655 bool ImageStore) const {
12656 EVT StoreVT = VData.getValueType();
12657
12658 // No change for f16 and legal vector D16 types.
12659 if (!StoreVT.isVector())
12660 return VData;
12661
12662 SDLoc DL(VData);
12663 unsigned NumElements = StoreVT.getVectorNumElements();
12664
12665 if (Subtarget->hasUnpackedD16VMem()) {
12666 // We need to unpack the packed data to store.
12667 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12668 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12669
12670 EVT EquivStoreVT =
12671 EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumElements);
12672 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, EquivStoreVT, IntVData);
12673 return DAG.UnrollVectorOp(ZExt.getNode());
12674 }
12675
12676 // The sq block of gfx8.1 does not estimate register use correctly for d16
12677 // image store instructions. The data operand is computed as if it were not a
12678 // d16 image instruction.
12679 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12680 // Bitcast to i16
12681 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12682 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12683
12684 // Decompose into scalars
12686 DAG.ExtractVectorElements(IntVData, Elts);
12687
12688 // Group pairs of i16 into v2i16 and bitcast to i32
12689 SmallVector<SDValue, 4> PackedElts;
12690 for (unsigned I = 0; I < Elts.size() / 2; I += 1) {
12691 SDValue Pair =
12692 DAG.getBuildVector(MVT::v2i16, DL, {Elts[I * 2], Elts[I * 2 + 1]});
12693 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12694 PackedElts.push_back(IntPair);
12695 }
12696 if ((NumElements % 2) == 1) {
12697 // Handle v3i16
12698 unsigned I = Elts.size() / 2;
12699 SDValue Pair = DAG.getBuildVector(MVT::v2i16, DL,
12700 {Elts[I * 2], DAG.getPOISON(MVT::i16)});
12701 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12702 PackedElts.push_back(IntPair);
12703 }
12704
12705 // Pad using UNDEF
12706 PackedElts.resize(Elts.size(), DAG.getPOISON(MVT::i32));
12707
12708 // Build final vector
12709 EVT VecVT =
12710 EVT::getVectorVT(*DAG.getContext(), MVT::i32, PackedElts.size());
12711 return DAG.getBuildVector(VecVT, DL, PackedElts);
12712 }
12713
12714 if (NumElements == 3) {
12715 EVT IntStoreVT =
12717 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12718
12719 EVT WidenedStoreVT = EVT::getVectorVT(
12720 *DAG.getContext(), StoreVT.getVectorElementType(), NumElements + 1);
12721 EVT WidenedIntVT = EVT::getIntegerVT(*DAG.getContext(),
12722 WidenedStoreVT.getStoreSizeInBits());
12723 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenedIntVT, IntVData);
12724 return DAG.getNode(ISD::BITCAST, DL, WidenedStoreVT, ZExt);
12725 }
12726
12727 assert(isTypeLegal(StoreVT));
12728 return VData;
12729}
12730
12731static bool isAsyncLDSDMA(Intrinsic::ID Intr) {
12732 switch (Intr) {
12733 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12734 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12735 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12736 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12737 case Intrinsic::amdgcn_load_async_to_lds:
12738 case Intrinsic::amdgcn_global_load_async_lds:
12739 return true;
12740 }
12741 return false;
12742}
12743
12744SDValue SITargetLowering::LowerINTRINSIC_VOID(SDValue Op,
12745 SelectionDAG &DAG) const {
12746 SDLoc DL(Op);
12747 SDValue Chain = Op.getOperand(0);
12748 unsigned IntrinsicID = Op.getConstantOperandVal(1);
12749
12750 switch (IntrinsicID) {
12751 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
12752 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
12753 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
12754 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
12755 if (Subtarget->hasGFX1250_STRICT())
12757 return SDValue();
12758 }
12759 case Intrinsic::amdgcn_exp_compr: {
12760 SDValue Src0 = Op.getOperand(4);
12761 SDValue Src1 = Op.getOperand(5);
12762 // Hack around illegal type on SI by directly selecting it.
12763 if (isTypeLegal(Src0.getValueType()))
12764 return SDValue();
12765
12766 const ConstantSDNode *Done = cast<ConstantSDNode>(Op.getOperand(6));
12767 SDValue Undef = DAG.getPOISON(MVT::f32);
12768 const SDValue Ops[] = {
12769 Op.getOperand(2), // tgt
12770 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src0), // src0
12771 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src1), // src1
12772 Undef, // src2
12773 Undef, // src3
12774 Op.getOperand(7), // vm
12775 DAG.getTargetConstant(1, DL, MVT::i1), // compr
12776 Op.getOperand(3), // en
12777 Op.getOperand(0) // Chain
12778 };
12779
12780 unsigned Opc = Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12781 return SDValue(DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops), 0);
12782 }
12783
12784 case Intrinsic::amdgcn_struct_tbuffer_store:
12785 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12786 SDValue VData = Op.getOperand(2);
12787 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12788 if (IsD16)
12789 VData = handleD16VData(VData, DAG);
12790 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12791 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12792 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12793 SDValue Ops[] = {
12794 Chain,
12795 VData, // vdata
12796 Rsrc, // rsrc
12797 Op.getOperand(4), // vindex
12798 VOffset, // voffset
12799 SOffset, // soffset
12800 Offset, // offset
12801 Op.getOperand(7), // format
12802 Op.getOperand(8), // cachepolicy, swizzled buffer
12803 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12804 };
12805 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12806 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12807 MemSDNode *M = cast<MemSDNode>(Op);
12808 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12809 M->getMemoryVT(), M->getMemOperand());
12810 }
12811
12812 case Intrinsic::amdgcn_raw_tbuffer_store:
12813 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12814 SDValue VData = Op.getOperand(2);
12815 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12816 if (IsD16)
12817 VData = handleD16VData(VData, DAG);
12818 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12819 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12820 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12821 SDValue Ops[] = {
12822 Chain,
12823 VData, // vdata
12824 Rsrc, // rsrc
12825 DAG.getConstant(0, DL, MVT::i32), // vindex
12826 VOffset, // voffset
12827 SOffset, // soffset
12828 Offset, // offset
12829 Op.getOperand(6), // format
12830 Op.getOperand(7), // cachepolicy, swizzled buffer
12831 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12832 };
12833 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12834 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12835 MemSDNode *M = cast<MemSDNode>(Op);
12836 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12837 M->getMemoryVT(), M->getMemOperand());
12838 }
12839
12840 case Intrinsic::amdgcn_raw_buffer_store:
12841 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12842 case Intrinsic::amdgcn_raw_buffer_store_format:
12843 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12844 const bool IsFormat =
12845 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12846 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12847
12848 SDValue VData = Op.getOperand(2);
12849 EVT VDataVT = VData.getValueType();
12850 EVT EltType = VDataVT.getScalarType();
12851 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12852
12853 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12854 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12856 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12857 return Chain;
12858 }
12859
12860 if (IsD16) {
12861 VData = handleD16VData(VData, DAG);
12862 VDataVT = VData.getValueType();
12863 }
12864
12865 if (!isTypeLegal(VDataVT)) {
12866 VData =
12867 DAG.getNode(ISD::BITCAST, DL,
12868 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12869 }
12870
12871 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12872 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12873 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12874 SDValue Ops[] = {
12875 Chain,
12876 VData,
12877 Rsrc,
12878 DAG.getConstant(0, DL, MVT::i32), // vindex
12879 VOffset, // voffset
12880 SOffset, // soffset
12881 Offset, // offset
12882 Op.getOperand(6), // cachepolicy, swizzled buffer
12883 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12884 };
12885 unsigned Opc =
12886 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12887 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12888 MemSDNode *M = cast<MemSDNode>(Op);
12889
12890 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12891 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12892 return handleByteShortBufferStores(DAG, VDataVT, DL, Ops, M);
12893
12894 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12895 M->getMemoryVT(), M->getMemOperand());
12896 }
12897
12898 case Intrinsic::amdgcn_struct_buffer_store:
12899 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12900 case Intrinsic::amdgcn_struct_buffer_store_format:
12901 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12902 const bool IsFormat =
12903 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12904 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12905
12906 SDValue VData = Op.getOperand(2);
12907 EVT VDataVT = VData.getValueType();
12908 EVT EltType = VDataVT.getScalarType();
12909 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12910
12911 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12912 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12914 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12915 return Chain;
12916 }
12917
12918 if (IsD16) {
12919 VData = handleD16VData(VData, DAG);
12920 VDataVT = VData.getValueType();
12921 }
12922
12923 if (!isTypeLegal(VDataVT)) {
12924 VData =
12925 DAG.getNode(ISD::BITCAST, DL,
12926 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12927 }
12928
12929 auto Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12930 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12931 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12932 SDValue Ops[] = {
12933 Chain,
12934 VData,
12935 Rsrc,
12936 Op.getOperand(4), // vindex
12937 VOffset, // voffset
12938 SOffset, // soffset
12939 Offset, // offset
12940 Op.getOperand(7), // cachepolicy, swizzled buffer
12941 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12942 };
12943 unsigned Opc =
12944 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12945 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12946 MemSDNode *M = cast<MemSDNode>(Op);
12947
12948 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12949 EVT VDataType = VData.getValueType().getScalarType();
12950 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12951 return handleByteShortBufferStores(DAG, VDataType, DL, Ops, M);
12952
12953 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12954 M->getMemoryVT(), M->getMemOperand());
12955 }
12956 case Intrinsic::amdgcn_raw_buffer_load_lds:
12957 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12958 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12959 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12960 case Intrinsic::amdgcn_struct_buffer_load_lds:
12961 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12962 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12963 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12964 unsigned Opc;
12965 bool HasVIndex =
12966 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12967 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12968 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12969 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12970 unsigned OpOffset = HasVIndex ? 1 : 0;
12971 SDValue VOffset = Op.getOperand(5 + OpOffset);
12972 bool HasVOffset = !isNullConstant(VOffset);
12973 unsigned Size = Op->getConstantOperandVal(4);
12974
12975 switch (Size) {
12976 default:
12977 return SDValue();
12978 case 1:
12979 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12980 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12981 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12982 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12983 break;
12984 case 2:
12985 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12986 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12987 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12988 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12989 break;
12990 case 4:
12991 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12992 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12993 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12994 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12995 break;
12996 case 12:
12997 if (!Subtarget->hasLDSLoadB96_B128())
12998 return SDValue();
12999 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
13000 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
13001 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
13002 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
13003 break;
13004 case 16:
13005 if (!Subtarget->hasLDSLoadB96_B128())
13006 return SDValue();
13007 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
13008 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
13009 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
13010 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
13011 break;
13012 }
13013
13014 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
13015
13017
13018 if (HasVIndex && HasVOffset)
13019 Ops.push_back(DAG.getBuildVector(MVT::v2i32, DL,
13020 {Op.getOperand(5), // VIndex
13021 VOffset}));
13022 else if (HasVIndex)
13023 Ops.push_back(Op.getOperand(5));
13024 else if (HasVOffset)
13025 Ops.push_back(VOffset);
13026
13027 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
13028 Ops.push_back(Rsrc);
13029 Ops.push_back(Op.getOperand(6 + OpOffset)); // soffset
13030 Ops.push_back(Op.getOperand(7 + OpOffset)); // imm offset
13031 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
13032 unsigned Aux = Op.getConstantOperandVal(8 + OpOffset);
13033 Ops.push_back(DAG.getTargetConstant(
13034 Aux & (IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12),
13035 DL, MVT::i16)); // cpol
13036 Ops.push_back(DAG.getTargetConstant(
13037 Aux & (IsGFX12Plus ? AMDGPU::CPol::SWZ : AMDGPU::CPol::SWZ_pregfx12)
13038 ? 1
13039 : 0,
13040 DL, MVT::i8)); // swz
13041 Ops.push_back(
13042 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
13043 Ops.push_back(M0Val.getValue(0)); // Chain
13044 Ops.push_back(M0Val.getValue(1)); // Glue
13045
13046 auto *M = cast<MemSDNode>(Op);
13047 auto *Load = DAG.getMachineNode(Opc, DL, M->getVTList(), Ops);
13048 DAG.setNodeMemRefs(Load, M->memoperands());
13049
13050 return SDValue(Load, 0);
13051 }
13052 // Buffers are handled by LowerBufferFatPointers, and we're going to go
13053 // for "trust me" that the remaining cases are global pointers until
13054 // such time as we can put two mem operands on an intrinsic.
13055 case Intrinsic::amdgcn_load_to_lds:
13056 case Intrinsic::amdgcn_load_async_to_lds:
13057 case Intrinsic::amdgcn_global_load_lds:
13058 case Intrinsic::amdgcn_global_load_async_lds: {
13059 if (!Subtarget->hasVMemToLDSLoad())
13060 return SDValue();
13061
13062 unsigned Opc;
13063 unsigned Size = Op->getConstantOperandVal(4);
13064 switch (Size) {
13065 default:
13066 return SDValue();
13067 case 1:
13068 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
13069 break;
13070 case 2:
13071 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
13072 break;
13073 case 4:
13074 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
13075 break;
13076 case 12:
13077 if (!Subtarget->hasLDSLoadB96_B128())
13078 return SDValue();
13079 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
13080 break;
13081 case 16:
13082 if (!Subtarget->hasLDSLoadB96_B128())
13083 return SDValue();
13084 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
13085 break;
13086 }
13087
13088 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
13089
13091
13092 SDValue Addr = Op.getOperand(2); // Global ptr
13093 SDValue VOffset;
13094 // Try to split SAddr and VOffset. Global and LDS pointers share the same
13095 // immediate offset, so we cannot use a regular SelectGlobalSAddr().
13096 if (Addr->isDivergent() && Addr->isAnyAdd()) {
13097 SDValue LHS = Addr.getOperand(0);
13098 SDValue RHS = Addr.getOperand(1);
13099
13100 if (LHS->isDivergent())
13101 std::swap(LHS, RHS);
13102
13103 if (!LHS->isDivergent() && RHS.getOpcode() == ISD::ZERO_EXTEND &&
13104 RHS.getOperand(0).getValueType() == MVT::i32) {
13105 // add (i64 sgpr), (zero_extend (i32 vgpr))
13106 Addr = LHS;
13107 VOffset = RHS.getOperand(0);
13108 }
13109 }
13110
13111 Ops.push_back(Addr);
13112 if (!Addr->isDivergent()) {
13114 if (!VOffset)
13115 VOffset =
13116 SDValue(DAG.getMachineNode(AMDGPU::V_MOV_B32_e32, DL, MVT::i32,
13117 DAG.getTargetConstant(0, DL, MVT::i32)),
13118 0);
13119 Ops.push_back(VOffset);
13120 }
13121
13122 Ops.push_back(Op.getOperand(5)); // Offset
13123
13124 unsigned Aux = Op.getConstantOperandVal(6);
13125 Ops.push_back(DAG.getTargetConstant(Aux & ~AMDGPU::CPol::VIRTUAL_BITS, DL,
13126 MVT::i32)); // CPol
13127 Ops.push_back(
13128 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
13129
13130 Ops.push_back(M0Val.getValue(0)); // Chain
13131 Ops.push_back(M0Val.getValue(1)); // Glue
13132
13133 auto *M = cast<MemSDNode>(Op);
13134 auto *Load = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13135 DAG.setNodeMemRefs(Load, M->memoperands());
13136
13137 return SDValue(Load, 0);
13138 }
13139 case Intrinsic::amdgcn_end_cf:
13140 return SDValue(DAG.getMachineNode(AMDGPU::SI_END_CF, DL, MVT::Other,
13141 Op->getOperand(2), Chain),
13142 0);
13143 case Intrinsic::amdgcn_s_barrier_signal_var: {
13144 // Member count of 0 means to re-use a previous member count,
13145 // which, if the named barrier is statically chosen, means we can use
13146 // the immarg form. Otherwisee, fall through to constructiong M0 as for
13147 // s_barrier_init.
13148 SDValue CntOp = Op->getOperand(3);
13149 auto *CntC = dyn_cast<ConstantSDNode>(CntOp);
13150 if (CntC && CntC->isZero()) {
13151 SDValue Chain = Op->getOperand(0);
13152 SDValue BarOp = Op->getOperand(2);
13154
13155 std::optional<uint64_t> BarVal;
13156 if (auto *C = dyn_cast<ConstantSDNode>(BarOp))
13157 BarVal = C->getZExtValue();
13158 else if (auto *GA = dyn_cast<GlobalAddressSDNode>(BarOp))
13160 *GA->getGlobal(), AMDGPUAS::BARRIER))
13161 BarVal = *Addr + GA->getOffset();
13162
13163 if (BarVal) {
13164 unsigned BarID = *BarVal & 0x3F;
13165 Ops.push_back(DAG.getTargetConstant(BarID, DL, MVT::i32));
13166 Ops.push_back(Chain);
13167 auto *NewMI = DAG.getMachineNode(AMDGPU::S_BARRIER_SIGNAL_IMM, DL,
13168 Op->getVTList(), Ops);
13169 return SDValue(NewMI, 0);
13170 }
13171 }
13172 [[fallthrough]];
13173 }
13174 case Intrinsic::amdgcn_s_barrier_init: {
13175 // these two intrinsics have two operands: barrier pointer and member count
13176 SDValue Chain = Op->getOperand(0);
13178 SDValue BarOp = Op->getOperand(2);
13179 SDValue CntOp = Op->getOperand(3);
13180 SDValue M0Val;
13181 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
13182 ? AMDGPU::S_BARRIER_INIT_M0
13183 : AMDGPU::S_BARRIER_SIGNAL_M0;
13184 // extract the BarrierID from bits 0-5 of BarOp
13185 SDValue BarID = DAG.getNode(ISD::AND, DL, MVT::i32, BarOp,
13186 DAG.getConstant(0x3F, DL, MVT::i32));
13187 // Member count should be put into M0[ShAmt:+CntMask width]
13188 // Barrier ID should be put into M0[5:0]
13189 unsigned CntMask = AMDGPU::getBarrierMemberCountBitMask(
13190 AMDGPU::getIsaVersion(Subtarget->getCPU()));
13191 SDValue MemberCnt = DAG.getNode(ISD::AND, DL, MVT::i32, CntOp,
13192 DAG.getConstant(CntMask, DL, MVT::i32));
13193 constexpr unsigned ShAmt = 16;
13194 M0Val = DAG.getNode(ISD::SHL, DL, MVT::i32, MemberCnt,
13195 DAG.getShiftAmountConstant(ShAmt, MVT::i32, DL));
13196
13197 M0Val = DAG.getNode(ISD::OR, DL, MVT::i32, M0Val, BarID);
13198
13199 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
13200
13201 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13202 return SDValue(NewMI, 0);
13203 }
13204 case Intrinsic::amdgcn_s_wakeup_barrier: {
13205 if (!Subtarget->hasSWakeupBarrier())
13206 return SDValue();
13207 [[fallthrough]];
13208 }
13209 case Intrinsic::amdgcn_s_barrier_join: {
13210 // these three intrinsics have one operand: barrier pointer
13211 SDValue Chain = Op->getOperand(0);
13213 SDValue BarOp = Op->getOperand(2);
13214 unsigned Opc;
13215
13216 if (isa<ConstantSDNode>(BarOp)) {
13217 uint64_t BarVal = cast<ConstantSDNode>(BarOp)->getZExtValue();
13218 switch (IntrinsicID) {
13219 default:
13220 return SDValue();
13221 case Intrinsic::amdgcn_s_barrier_join:
13222 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13223 break;
13224 case Intrinsic::amdgcn_s_wakeup_barrier:
13225 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13226 break;
13227 }
13228 // extract the BarrierID from bits 0-5 of the immediate
13229 unsigned BarID = BarVal & 0x3F;
13230 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
13231 Ops.push_back(K);
13232 Ops.push_back(Chain);
13233 } else {
13234 switch (IntrinsicID) {
13235 default:
13236 return SDValue();
13237 case Intrinsic::amdgcn_s_barrier_join:
13238 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13239 break;
13240 case Intrinsic::amdgcn_s_wakeup_barrier:
13241 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13242 break;
13243 }
13244 // extract the BarrierID from bits 0-5 of BarOp, copy to M0[5:0]
13245 SDValue M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, BarOp,
13246 DAG.getConstant(0x3F, DL, MVT::i32));
13247 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
13248 }
13249
13250 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13251 return SDValue(NewMI, 0);
13252 }
13253 case Intrinsic::amdgcn_s_prefetch_data:
13254 case Intrinsic::amdgcn_s_prefetch_inst: {
13255 // For non-global address space preserve the chain and remove the call.
13257 return Op.getOperand(0);
13258 return Op;
13259 }
13260 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13261 SDValue Ops[] = {
13262 Chain, bufferRsrcPtrToVector(Op.getOperand(2), DAG),
13263 Op.getOperand(3), // offset
13264 Op.getOperand(4), // length
13265 };
13266
13267 MemSDNode *M = cast<MemSDNode>(Op);
13268 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_PREFETCH_DATA, DL,
13269 Op->getVTList(), Ops, M->getMemoryVT(),
13270 M->getMemOperand());
13271 }
13272 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13273 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13274 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13275 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13276 SDValue Chain = Op->getOperand(0);
13277 SDValue Ptr = Op->getOperand(2);
13278 SDValue Val = Op->getOperand(3);
13279 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MII->getMemoryVT(), Chain, Val,
13280 Ptr, MII->getMemOperand());
13281 }
13282 case Intrinsic::amdgcn_av_store_b8:
13283 case Intrinsic::amdgcn_av_store_b16:
13284 case Intrinsic::amdgcn_av_store_b32:
13285 case Intrinsic::amdgcn_av_store_b64:
13286 case Intrinsic::amdgcn_av_store_b128: {
13287 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13288 SDValue Chain = Op->getOperand(0);
13289 SDValue Ptr = Op->getOperand(2);
13290 SDValue Val = Op->getOperand(3);
13291 return DAG.getStore(Chain, DL, Val, Ptr, MII->getMemOperand());
13292 }
13293 default: {
13294 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13296 return lowerImage(Op, ImageDimIntr, DAG, true);
13297
13298 return Op;
13299 }
13300 }
13301}
13302
13303// Return whether the operation has NoUnsignedWrap property.
13304static bool isNoUnsignedWrap(SDValue Addr) {
13305 return (Addr.getOpcode() == ISD::ADD &&
13306 Addr->getFlags().hasNoUnsignedWrap()) ||
13307 Addr->getOpcode() == ISD::OR;
13308}
13309
13311 EVT PtrVT) const {
13312 return PtrVT == MVT::i64;
13313}
13314
13316 EVT PtrVT) const {
13317 return true;
13318}
13319
13320// The raw.(t)buffer and struct.(t)buffer intrinsics have two offset args:
13321// offset (the offset that is included in bounds checking and swizzling, to be
13322// split between the instruction's voffset and immoffset fields) and soffset
13323// (the offset that is excluded from bounds checking and swizzling, to go in
13324// the instruction's soffset field). This function takes the first kind of
13325// offset and figures out how to split it between voffset and immoffset.
13326std::pair<SDValue, SDValue>
13327SITargetLowering::splitBufferOffsets(SDValue Offset, SelectionDAG &DAG) const {
13328 SDLoc DL(Offset);
13329 const unsigned MaxImm = SIInstrInfo::getMaxMUBUFImmOffset(*Subtarget);
13330 SDValue N0 = Offset;
13331 ConstantSDNode *C1 = nullptr;
13332
13333 if ((C1 = dyn_cast<ConstantSDNode>(N0)))
13334 N0 = SDValue();
13335 else if (DAG.isBaseWithConstantOffset(N0)) {
13336 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13337 // being added, so we can only safely match a 32-bit addition with no
13338 // unsigned overflow.
13339 bool CheckNUW = Subtarget->hasGFX1250Insts();
13340 if (!CheckNUW || isNoUnsignedWrap(N0)) {
13342 N0 = N0.getOperand(0);
13343 }
13344 }
13345
13346 if (C1) {
13347 unsigned ImmOffset = C1->getZExtValue();
13348 // If the immediate value is too big for the immoffset field, put only bits
13349 // that would normally fit in the immoffset field. The remaining value that
13350 // is copied/added for the voffset field is a large power of 2, and it
13351 // stands more chance of being CSEd with the copy/add for another similar
13352 // load/store.
13353 // However, do not do that rounding down if that is a negative
13354 // number, as it appears to be illegal to have a negative offset in the
13355 // vgpr, even if adding the immediate offset makes it positive.
13356 unsigned Overflow = ImmOffset & ~MaxImm;
13357 ImmOffset -= Overflow;
13358 if ((int32_t)Overflow < 0) {
13359 Overflow += ImmOffset;
13360 ImmOffset = 0;
13361 }
13362 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(ImmOffset, DL, MVT::i32));
13363 if (Overflow) {
13364 auto OverflowVal = DAG.getConstant(Overflow, DL, MVT::i32);
13365 if (!N0)
13366 N0 = OverflowVal;
13367 else {
13368 SDValue Ops[] = {N0, OverflowVal};
13369 N0 = DAG.getNode(ISD::ADD, DL, MVT::i32, Ops);
13370 }
13371 }
13372 }
13373 if (!N0)
13374 N0 = DAG.getConstant(0, DL, MVT::i32);
13375 if (!C1)
13376 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(0, DL, MVT::i32));
13377 return {N0, SDValue(C1, 0)};
13378}
13379
13380// Analyze a combined offset from an amdgcn_s_buffer_load intrinsic and store
13381// the three offsets (voffset, soffset and instoffset) into the SDValue[3] array
13382// pointed to by Offsets.
13383void SITargetLowering::setBufferOffsets(SDValue CombinedOffset,
13384 SelectionDAG &DAG, SDValue *Offsets,
13385 Align Alignment) const {
13386 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
13387 SDLoc DL(CombinedOffset);
13388 if (auto *C = dyn_cast<ConstantSDNode>(CombinedOffset)) {
13389 uint32_t Imm = C->getZExtValue();
13390 uint32_t SOffset, ImmOffset;
13391 if (TII->splitMUBUFOffset(Imm, SOffset, ImmOffset, Alignment)) {
13392 Offsets[0] = DAG.getConstant(0, DL, MVT::i32);
13393 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13394 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13395 return;
13396 }
13397 }
13398 if (DAG.isBaseWithConstantOffset(CombinedOffset)) {
13399 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13400 // being added, so we can only safely match a 32-bit addition with no
13401 // unsigned overflow.
13402 bool CheckNUW = Subtarget->hasGFX1250Insts();
13403 SDValue N0 = CombinedOffset.getOperand(0);
13404 SDValue N1 = CombinedOffset.getOperand(1);
13405 uint32_t SOffset, ImmOffset;
13406 int Offset = cast<ConstantSDNode>(N1)->getSExtValue();
13407 if (Offset >= 0 && (!CheckNUW || isNoUnsignedWrap(CombinedOffset)) &&
13408 TII->splitMUBUFOffset(Offset, SOffset, ImmOffset, Alignment)) {
13409 Offsets[0] = N0;
13410 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13411 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13412 return;
13413 }
13414 }
13415
13416 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13417 ? DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32)
13418 : DAG.getConstant(0, DL, MVT::i32);
13419
13420 Offsets[0] = CombinedOffset;
13421 Offsets[1] = SOffsetZero;
13422 Offsets[2] = DAG.getTargetConstant(0, DL, MVT::i32);
13423}
13424
13425SDValue SITargetLowering::bufferRsrcPtrToVector(SDValue MaybePointer,
13426 SelectionDAG &DAG) const {
13427 if (!MaybePointer.getValueType().isScalarInteger())
13428 return MaybePointer;
13429
13430 SDValue Rsrc = DAG.getBitcast(MVT::v4i32, MaybePointer);
13431 return Rsrc;
13432}
13433
13434// Wrap a global or flat pointer into a buffer intrinsic using the flags
13435// specified in the intrinsic.
13436SDValue SITargetLowering::lowerPointerAsRsrcIntrin(SDNode *Op,
13437 SelectionDAG &DAG) const {
13438 SDLoc Loc(Op);
13439
13440 SDValue Pointer = Op->getOperand(1);
13441 SDValue Stride = Op->getOperand(2);
13442 SDValue NumRecords = Op->getOperand(3);
13443 SDValue Flags = Op->getOperand(4);
13444
13445 SDValue ExtStride = DAG.getAnyExtOrTrunc(Stride, Loc, MVT::i32);
13446 SDValue Rsrc;
13447
13448 if (Subtarget->getBufferResourceNumRecordsWidth() == 45) {
13449 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i64);
13450 NumRecords = DAG.getNode(ISD::AND, Loc, MVT::i64, NumRecords,
13451 DAG.getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13452 SDValue Zero = DAG.getConstant(0, Loc, MVT::i32);
13453 // Build the lower 64-bit value, which has a 57-bit base and the lower 7-bit
13454 // num_records.
13455 SDValue ExtPointer = DAG.getAnyExtOrTrunc(Pointer, Loc, MVT::i64);
13456 SDValue NumRecordsLHS =
13457 DAG.getNode(ISD::SHL, Loc, MVT::i64, NumRecords,
13458 DAG.getShiftAmountConstant(57, MVT::i32, Loc));
13459 SDValue LowHalf =
13460 DAG.getNode(ISD::OR, Loc, MVT::i64, ExtPointer, NumRecordsLHS);
13461
13462 // Build the higher 64-bit value, which has the higher 38-bit num_records,
13463 // 6-bit zero (omit), 16-bit stride and scale and 4-bit flag.
13464 SDValue NumRecordsRHS =
13465 DAG.getNode(ISD::SRL, Loc, MVT::i64, NumRecords,
13466 DAG.getShiftAmountConstant(7, MVT::i32, Loc));
13467 SDValue ShiftedStride =
13468 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13469 DAG.getShiftAmountConstant(12, MVT::i32, Loc));
13470 SDValue ExtShiftedStrideVec =
13471 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedStride);
13472 SDValue ExtShiftedStride =
13473 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedStrideVec);
13474 SDValue ShiftedFlags =
13475 DAG.getNode(ISD::SHL, Loc, MVT::i32, Flags,
13476 DAG.getShiftAmountConstant(28, MVT::i32, Loc));
13477 SDValue ExtShiftedFlagsVec =
13478 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedFlags);
13479 SDValue ExtShiftedFlags =
13480 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedFlagsVec);
13481 SDValue CombinedFields =
13482 DAG.getNode(ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13483 SDValue HighHalf =
13484 DAG.getNode(ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13485
13486 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i64, LowHalf, HighHalf);
13487 } else {
13488 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i32);
13489 auto [LowHalf, HighHalf] =
13490 DAG.SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13491 SDValue Mask = DAG.getConstant(0x0000ffff, Loc, MVT::i32);
13492 SDValue Masked = DAG.getNode(ISD::AND, Loc, MVT::i32, HighHalf, Mask);
13493 SDValue ShiftedStride =
13494 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13495 DAG.getShiftAmountConstant(16, MVT::i32, Loc));
13496 SDValue NewHighHalf =
13497 DAG.getNode(ISD::OR, Loc, MVT::i32, Masked, ShiftedStride);
13498
13499 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v4i32, LowHalf, NewHighHalf,
13500 NumRecords, Flags);
13501 }
13502
13503 SDValue RsrcPtr = DAG.getNode(ISD::BITCAST, Loc, MVT::i128, Rsrc);
13504 return RsrcPtr;
13505}
13506
13507// Handle 8 bit and 16 bit buffer loads
13508SDValue SITargetLowering::handleByteShortBufferLoads(SelectionDAG &DAG,
13509 EVT LoadVT, SDLoc DL,
13511 MachineMemOperand *MMO,
13512 bool IsTFE) const {
13513 EVT IntVT = LoadVT.changeTypeToInteger();
13514
13515 if (IsTFE) {
13516 unsigned Opc = (LoadVT.getScalarType() == MVT::i8)
13517 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13518 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13520 MachineMemOperand *OpMMO = MF.getMachineMemOperand(MMO, 0, 8);
13521 SDVTList VTs = DAG.getVTList(MVT::v2i32, MVT::Other);
13522 SDValue Op = getMemIntrinsicNode(Opc, DL, VTs, Ops, MVT::v2i32, OpMMO, DAG);
13523 SDValue Status = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13524 DAG.getConstant(1, DL, MVT::i32));
13525 SDValue Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13526 DAG.getConstant(0, DL, MVT::i32));
13527 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Data);
13528 SDValue Value = DAG.getNode(ISD::BITCAST, DL, LoadVT, Trunc);
13529 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
13530 }
13531
13532 unsigned Opc = LoadVT.getScalarType() == MVT::i8
13533 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13534 : AMDGPUISD::BUFFER_LOAD_USHORT;
13535
13536 SDVTList ResList = DAG.getVTList(MVT::i32, MVT::Other);
13537 SDValue BufferLoad =
13538 DAG.getMemIntrinsicNode(Opc, DL, ResList, Ops, IntVT, MMO);
13539 SDValue LoadVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, BufferLoad);
13540 LoadVal = DAG.getNode(ISD::BITCAST, DL, LoadVT, LoadVal);
13541
13542 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
13543}
13544
13545// Handle 8 bit and 16 bit buffer stores
13546SDValue SITargetLowering::handleByteShortBufferStores(SelectionDAG &DAG,
13547 EVT VDataType, SDLoc DL,
13548 SDValue Ops[],
13549 MemSDNode *M) const {
13550 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13551 Ops[1] = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Ops[1]);
13552
13553 SDValue BufferStoreExt = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Ops[1]);
13554 Ops[1] = BufferStoreExt;
13555 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13556 : AMDGPUISD::BUFFER_STORE_SHORT;
13557 ArrayRef<SDValue> OpsRef = ArrayRef(&Ops[0], 9);
13558 return DAG.getMemIntrinsicNode(Opc, DL, M->getVTList(), OpsRef, VDataType,
13559 M->getMemOperand());
13560}
13561
13563 SDValue Op, const SDLoc &SL, EVT VT) {
13564 if (VT.bitsLT(Op.getValueType()))
13565 return DAG.getNode(ISD::TRUNCATE, SL, VT, Op);
13566
13567 switch (ExtType) {
13568 case ISD::SEXTLOAD:
13569 return DAG.getNode(ISD::SIGN_EXTEND, SL, VT, Op);
13570 case ISD::ZEXTLOAD:
13571 return DAG.getNode(ISD::ZERO_EXTEND, SL, VT, Op);
13572 case ISD::EXTLOAD:
13573 return DAG.getNode(ISD::ANY_EXTEND, SL, VT, Op);
13574 case ISD::NON_EXTLOAD:
13575 return Op;
13576 }
13577
13578 llvm_unreachable("invalid ext type");
13579}
13580
13581// Try to turn 8 and 16-bit scalar loads into SMEM eligible 32-bit loads.
13582// TODO: Skip this on GFX12 which does have scalar sub-dword loads.
13583SDValue SITargetLowering::widenLoad(LoadSDNode *Ld,
13584 DAGCombinerInfo &DCI) const {
13585 SelectionDAG &DAG = DCI.DAG;
13586 if (Ld->getAlign() < Align(4) || Ld->isDivergent())
13587 return SDValue();
13588
13589 // FIXME: Constant loads should all be marked invariant.
13590 unsigned AS = Ld->getAddressSpace();
13591 if (AS != AMDGPUAS::CONSTANT_ADDRESS &&
13593 (AS != AMDGPUAS::GLOBAL_ADDRESS || !Ld->isInvariant()))
13594 return SDValue();
13595
13596 // Don't do this early, since it may interfere with adjacent load merging for
13597 // illegal types. We can avoid losing alignment information for exotic types
13598 // pre-legalize.
13599 EVT MemVT = Ld->getMemoryVT();
13600 if ((MemVT.isSimple() && !DCI.isAfterLegalizeDAG()) ||
13601 MemVT.getSizeInBits() >= 32)
13602 return SDValue();
13603
13604 SDLoc SL(Ld);
13605
13606 assert((!MemVT.isVector() || Ld->getExtensionType() == ISD::NON_EXTLOAD) &&
13607 "unexpected vector extload");
13608
13609 // TODO: Drop only high part of range.
13610 SDValue Ptr = Ld->getBasePtr();
13611 SDValue NewLoad = DAG.getLoad(
13612 ISD::UNINDEXED, ISD::NON_EXTLOAD, MVT::i32, SL, Ld->getChain(), Ptr,
13613 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13614 Ld->getMemOperand()->getFlags(), Ld->getAAInfo()); // Drop ranges
13615
13616 EVT TruncVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
13617 if (MemVT.isFloatingPoint()) {
13618 assert(Ld->getExtensionType() == ISD::NON_EXTLOAD &&
13619 "unexpected fp extload");
13620 TruncVT = MemVT.changeTypeToInteger();
13621 }
13622
13623 SDValue Cvt = NewLoad;
13624 if (Ld->getExtensionType() == ISD::SEXTLOAD) {
13625 Cvt = DAG.getNode(ISD::SIGN_EXTEND_INREG, SL, MVT::i32, NewLoad,
13626 DAG.getValueType(TruncVT));
13627 } else if (Ld->getExtensionType() == ISD::ZEXTLOAD ||
13628 Ld->getExtensionType() == ISD::NON_EXTLOAD) {
13629 Cvt = DAG.getZeroExtendInReg(NewLoad, SL, TruncVT);
13630 } else {
13631 assert(Ld->getExtensionType() == ISD::EXTLOAD);
13632 }
13633
13634 EVT VT = Ld->getValueType(0);
13635 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
13636
13637 DCI.AddToWorklist(Cvt.getNode());
13638
13639 // We may need to handle exotic cases, such as i16->i64 extloads, so insert
13640 // the appropriate extension from the 32-bit load.
13641 Cvt = getLoadExtOrTrunc(DAG, Ld->getExtensionType(), Cvt, SL, IntVT);
13642 DCI.AddToWorklist(Cvt.getNode());
13643
13644 // Handle conversion back to floating point if necessary.
13645 Cvt = DAG.getNode(ISD::BITCAST, SL, VT, Cvt);
13646
13647 return DAG.getMergeValues({Cvt, NewLoad.getValue(1)}, SL);
13648}
13649
13651 const SIMachineFunctionInfo &Info) {
13652 // TODO: Should check if the address can definitely not access stack.
13653 if (Info.isEntryFunction())
13654 return Info.getUserSGPRInfo().hasFlatScratchInit();
13655 return true;
13656}
13657
13658SDValue SITargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
13659 SDLoc DL(Op);
13660 LoadSDNode *Load = cast<LoadSDNode>(Op);
13661 ISD::LoadExtType ExtType = Load->getExtensionType();
13662 EVT MemVT = Load->getMemoryVT();
13663 MachineMemOperand *MMO = Load->getMemOperand();
13664
13665 if (ExtType == ISD::NON_EXTLOAD && MemVT.getSizeInBits() < 32) {
13666 // Legalize uniform 16-bit loads to i16 = trunc (zextload i16->i32)
13667 // to match subword load patterns.
13668 // Only do this for loads that can use scalar subword load instructions.
13669 if (!MemVT.isVector() && MemVT.getSizeInBits() == 16 &&
13670 isTypeLegal(MemVT) && Subtarget->hasScalarSubwordLoads() &&
13672 SDValue Chain = Load->getChain();
13673 SDValue BasePtr = Load->getBasePtr();
13674
13675 // Load as i16 and zero-extend to i32 (matches S_LOAD_U16 behavior)
13676 SDValue NewLD = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain,
13677 BasePtr, MVT::i16, MMO);
13678
13679 // Truncate back to i16
13680 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, NewLD);
13681
13682 // For f16/bf16, bitcast from i16 to the original fp type
13683 SDValue Result = (MemVT == MVT::i16)
13684 ? Trunc
13685 : DAG.getNode(ISD::BITCAST, DL, MemVT, Trunc);
13686
13687 SDValue Ops[] = {Result, NewLD.getValue(1)};
13688 return DAG.getMergeValues(Ops, DL);
13689 }
13690
13691 if (MemVT == MVT::i16 && isTypeLegal(MVT::i16))
13692 return SDValue();
13693
13694 // FIXME: Copied from PPC
13695 // First, load into 32 bits, then truncate to 1 bit.
13696
13697 SDValue Chain = Load->getChain();
13698 SDValue BasePtr = Load->getBasePtr();
13699
13700 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13701
13702 SDValue NewLD = DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, BasePtr,
13703 RealMemVT, MMO);
13704
13705 if (!MemVT.isVector()) {
13706 SDValue Ops[] = {DAG.getNode(ISD::TRUNCATE, DL, MemVT, NewLD),
13707 NewLD.getValue(1)};
13708
13709 return DAG.getMergeValues(Ops, DL);
13710 }
13711
13713 for (unsigned I = 0, N = MemVT.getVectorNumElements(); I != N; ++I) {
13714 SDValue Elt = DAG.getNode(ISD::SRL, DL, MVT::i32, NewLD,
13715 DAG.getConstant(I, DL, MVT::i32));
13716
13717 Elts.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Elt));
13718 }
13719
13720 SDValue Ops[] = {DAG.getBuildVector(MemVT, DL, Elts), NewLD.getValue(1)};
13721
13722 return DAG.getMergeValues(Ops, DL);
13723 }
13724
13725 if (!MemVT.isVector())
13726 return SDValue();
13727
13728 assert(Op.getValueType().getVectorElementType() == MVT::i32 &&
13729 "Custom lowering for non-i32 vectors hasn't been implemented.");
13730
13731 Align Alignment = Load->getAlign();
13732 unsigned AS = Load->getAddressSpace();
13733 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13734 AS == AMDGPUAS::FLAT_ADDRESS &&
13735 Alignment.value() < MemVT.getStoreSize() && MemVT.getSizeInBits() > 32) {
13736 return SplitVectorLoad(Op, DAG);
13737 }
13738
13740 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
13741 // If there is a possibility that flat instruction access scratch memory
13742 // then we need to use the same legalization rules we use for private.
13743 if (AS == AMDGPUAS::FLAT_ADDRESS &&
13744 !Subtarget->hasMultiDwordFlatScratchAddressing())
13745 AS = addressMayBeAccessedAsPrivate(Load->getMemOperand(), *MFI)
13748
13749 unsigned NumElements = MemVT.getVectorNumElements();
13750
13751 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13753 (AS == AMDGPUAS::GLOBAL_ADDRESS && Load->isSimple() &&
13754 (Load->isInvariant() || isMemOpHasNoClobberedMemOperand(Load)))) {
13755 if ((!Op->isDivergent() || AMDGPU::isUniformMMO(MMO)) &&
13756 Alignment >= Align(4) && NumElements < 32) {
13757 if (MemVT.isPow2VectorType() ||
13758 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13759 return SDValue();
13760 return WidenOrSplitVectorLoad(Op, DAG);
13761 }
13762 // Non-uniform loads will be selected to MUBUF instructions, so they
13763 // have the same legalization requirements as global and private
13764 // loads.
13765 //
13766 }
13767 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13770 if (NumElements > 4)
13771 return SplitVectorLoad(Op, DAG);
13772 // v3 loads not supported on SI.
13773 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13774 return WidenOrSplitVectorLoad(Op, DAG);
13775
13776 // v3 and v4 loads are supported for private and global memory.
13777 return SDValue();
13778 }
13779 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
13780 // Depending on the setting of the private_element_size field in the
13781 // resource descriptor, we can only make private accesses up to a certain
13782 // size.
13783 switch (Subtarget->getMaxPrivateElementSize()) {
13784 case 4: {
13785 auto [Op0, Op1] = scalarizeVectorLoad(Load, DAG);
13786 return DAG.getMergeValues({Op0, Op1}, DL);
13787 }
13788 case 8:
13789 if (NumElements > 2)
13790 return SplitVectorLoad(Op, DAG);
13791 return SDValue();
13792 case 16:
13793 // Same as global/flat
13794 if (NumElements > 4)
13795 return SplitVectorLoad(Op, DAG);
13796 // v3 loads not supported on SI.
13797 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13798 return WidenOrSplitVectorLoad(Op, DAG);
13799
13800 return SDValue();
13801 default:
13802 llvm_unreachable("unsupported private_element_size");
13803 }
13804 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
13805 unsigned Fast = 0;
13806 auto Flags = Load->getMemOperand()->getFlags();
13808 Load->getAlign(), Flags, &Fast) &&
13809 Fast > 1)
13810 return SDValue();
13811
13812 if (MemVT.isVector())
13813 return SplitVectorLoad(Op, DAG);
13814 }
13815
13817 MemVT, *Load->getMemOperand())) {
13818 auto [Op0, Op1] = expandUnalignedLoad(Load, DAG);
13819 return DAG.getMergeValues({Op0, Op1}, DL);
13820 }
13821
13822 return SDValue();
13823}
13824
13825SDValue SITargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
13826 EVT VT = Op.getValueType();
13827 if (VT.getSizeInBits() == 128 || VT.getSizeInBits() == 256 ||
13828 VT.getSizeInBits() == 512)
13829 return splitTernaryVectorOp(Op, DAG);
13830
13831 assert(VT.getSizeInBits() == 64);
13832
13833 SDLoc DL(Op);
13834 SDValue Cond = DAG.getFreeze(Op.getOperand(0));
13835
13836 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
13837 SDValue One = DAG.getConstant(1, DL, MVT::i32);
13838
13839 SDValue LHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
13840 SDValue RHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(2));
13841
13842 SDValue Lo0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, Zero);
13843 SDValue Lo1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, Zero);
13844
13845 SDValue Lo = DAG.getSelect(DL, MVT::i32, Cond, Lo0, Lo1);
13846
13847 SDValue Hi0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, One);
13848 SDValue Hi1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, One);
13849
13850 SDValue Hi = DAG.getSelect(DL, MVT::i32, Cond, Hi0, Hi1);
13851
13852 SDValue Res = DAG.getBuildVector(MVT::v2i32, DL, {Lo, Hi});
13853 return DAG.getNode(ISD::BITCAST, DL, VT, Res);
13854}
13855
13856// Catch division cases where we can use shortcuts with rcp and rsq
13857// instructions.
13858SDValue SITargetLowering::lowerFastUnsafeFDIV(SDValue Op,
13859 SelectionDAG &DAG) const {
13860 SDLoc SL(Op);
13861 SDValue LHS = Op.getOperand(0);
13862 SDValue RHS = Op.getOperand(1);
13863 EVT VT = Op.getValueType();
13864 const SDNodeFlags Flags = Op->getFlags();
13865
13866 bool AllowInaccurateRcp = Flags.hasApproximateFuncs();
13867
13868 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
13869 // Without !fpmath accuracy information, we can't do more because we don't
13870 // know exactly whether rcp is accurate enough to meet !fpmath requirement.
13871 // f16 is always accurate enough
13872 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13873 return SDValue();
13874
13875 if (CLHS->isOne()) {
13876 // v_rcp_f32 and v_rsq_f32 do not support denormals, and according to
13877 // the CI documentation has a worst case error of 1 ulp.
13878 // OpenCL requires <= 2.5 ulp for 1.0 / x, so it should always be OK to
13879 // use it as long as we aren't trying to use denormals.
13880 //
13881 // v_rcp_f16 and v_rsq_f16 DO support denormals and 0.51ulp.
13882
13883 // 1.0 / sqrt(x) -> rsq(x)
13884
13885 // XXX - Is afn sufficient to do this for f64? The maximum ULP
13886 // error seems really high at 2^29 ULP.
13887 // 1.0 / x -> rcp(x)
13888 return DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13889 }
13890
13891 // Same as for 1.0, but expand the sign out of the constant.
13892 if (CLHS->isMinusOne()) {
13893 // -1.0 / x -> rcp (fneg x)
13894 SDValue FNegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
13895 return DAG.getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13896 }
13897 }
13898
13899 // For f16 and bf16 require afn or arcp.
13900 // For f32 require afn.
13901 if (!AllowInaccurateRcp &&
13902 ((VT != MVT::f16 && VT != MVT::bf16) || !Flags.hasAllowReciprocal()))
13903 return SDValue();
13904
13905 // Turn into multiply by the reciprocal.
13906 // x / y -> x * (1.0 / y)
13907 SDValue Recip = DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13908 return DAG.getNode(ISD::FMUL, SL, VT, LHS, Recip, Flags);
13909}
13910
13911SDValue SITargetLowering::lowerFastUnsafeFDIV64(SDValue Op,
13912 SelectionDAG &DAG) const {
13913 SDLoc SL(Op);
13914 SDValue X = Op.getOperand(0);
13915 SDValue Y = Op.getOperand(1);
13916 EVT VT = Op.getValueType();
13917 const SDNodeFlags Flags = Op->getFlags();
13918
13919 bool AllowInaccurateDiv = Flags.hasApproximateFuncs();
13920 if (!AllowInaccurateDiv)
13921 return SDValue();
13922
13923 const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(X);
13924 bool IsNegRcp = CLHS && CLHS->isMinusOne();
13925
13926 // Pull out the negation so it folds for free into the source modifiers.
13927 if (IsNegRcp)
13928 X = DAG.getConstantFP(1.0, SL, VT);
13929
13930 SDValue NegY = IsNegRcp ? Y : DAG.getNode(ISD::FNEG, SL, VT, Y);
13931 SDValue One = DAG.getConstantFP(1.0, SL, VT);
13932
13933 SDValue R = DAG.getNode(AMDGPUISD::RCP, SL, VT, Y);
13934 if (IsNegRcp)
13935 R = DAG.getNode(ISD::FNEG, SL, VT, R);
13936
13937 SDValue Tmp0 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13938
13939 R = DAG.getNode(ISD::FMA, SL, VT, Tmp0, R, R);
13940 SDValue Tmp1 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13941 R = DAG.getNode(ISD::FMA, SL, VT, Tmp1, R, R);
13942
13943 // Skip the last 2 correction terms for reciprocal.
13944 if (IsNegRcp || (CLHS && CLHS->isOne()))
13945 return R;
13946
13947 SDValue Ret = DAG.getNode(ISD::FMUL, SL, VT, X, R);
13948 SDValue Tmp2 = DAG.getNode(ISD::FMA, SL, VT, NegY, Ret, X);
13949 return DAG.getNode(ISD::FMA, SL, VT, Tmp2, R, Ret);
13950}
13951
13952static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13953 EVT VT, SDValue A, SDValue B, SDValue GlueChain,
13954 SDNodeFlags Flags) {
13955 if (GlueChain->getNumValues() <= 1) {
13956 return DAG.getNode(Opcode, SL, VT, A, B, Flags);
13957 }
13958
13959 assert(GlueChain->getNumValues() == 3);
13960
13961 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13962 switch (Opcode) {
13963 default:
13964 llvm_unreachable("no chain equivalent for opcode");
13965 case ISD::FMUL:
13966 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13967 break;
13968 }
13969
13970 return DAG.getNode(Opcode, SL, VTList,
13971 {GlueChain.getValue(1), A, B, GlueChain.getValue(2)},
13972 Flags);
13973}
13974
13975static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13976 EVT VT, SDValue A, SDValue B, SDValue C,
13977 SDValue GlueChain, SDNodeFlags Flags) {
13978 if (GlueChain->getNumValues() <= 1) {
13979 return DAG.getNode(Opcode, SL, VT, {A, B, C}, Flags);
13980 }
13981
13982 assert(GlueChain->getNumValues() == 3);
13983
13984 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13985 switch (Opcode) {
13986 default:
13987 llvm_unreachable("no chain equivalent for opcode");
13988 case ISD::FMA:
13989 Opcode = AMDGPUISD::FMA_W_CHAIN;
13990 break;
13991 }
13992
13993 return DAG.getNode(Opcode, SL, VTList,
13994 {GlueChain.getValue(1), A, B, C, GlueChain.getValue(2)},
13995 Flags);
13996}
13997
13998SDValue SITargetLowering::LowerFDIV16(SDValue Op, SelectionDAG &DAG) const {
13999 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
14000 return FastLowered;
14001
14002 SDLoc SL(Op);
14003 EVT VT = Op.getValueType();
14004 SDValue LHS = Op.getOperand(0);
14005 SDValue RHS = Op.getOperand(1);
14006
14007 SDValue LHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, LHS);
14008 SDValue RHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, RHS);
14009
14010 if (VT == MVT::bf16) {
14011 SDValue ExtDiv =
14012 DAG.getNode(ISD::FDIV, SL, MVT::f32, LHSExt, RHSExt, Op->getFlags());
14013 return DAG.getNode(ISD::FP_ROUND, SL, MVT::bf16, ExtDiv,
14014 DAG.getTargetConstant(0, SL, MVT::i32));
14015 }
14016
14017 assert(VT == MVT::f16);
14018
14019 // a32.u = opx(V_CVT_F32_F16, a.u); // CVT to F32
14020 // b32.u = opx(V_CVT_F32_F16, b.u); // CVT to F32
14021 // r32.u = opx(V_RCP_F32, b32.u); // rcp = 1 / d
14022 // q32.u = opx(V_MUL_F32, a32.u, r32.u); // q = n * rcp
14023 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
14024 // q32.u = opx(V_MAD_F32, e32.u, r32.u, q32.u); // q = n * rcp
14025 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
14026 // tmp.u = opx(V_MUL_F32, e32.u, r32.u);
14027 // tmp.u = opx(V_AND_B32, tmp.u, 0xff800000)
14028 // q32.u = opx(V_ADD_F32, tmp.u, q32.u);
14029 // q16.u = opx(V_CVT_F16_F32, q32.u);
14030 // q16.u = opx(V_DIV_FIXUP_F16, q16.u, b.u, a.u); // q = touchup(q, d, n)
14031
14032 // We will use ISD::FMA on targets that don't support ISD::FMAD.
14033 unsigned FMADOpCode =
14035 SDValue NegRHSExt = DAG.getNode(ISD::FNEG, SL, MVT::f32, RHSExt);
14036 SDValue Rcp =
14037 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt, Op->getFlags());
14038 SDValue Quot =
14039 DAG.getNode(ISD::FMUL, SL, MVT::f32, LHSExt, Rcp, Op->getFlags());
14040 SDValue Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
14041 Op->getFlags());
14042 Quot = DAG.getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot, Op->getFlags());
14043 Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
14044 Op->getFlags());
14045 SDValue Tmp = DAG.getNode(ISD::FMUL, SL, MVT::f32, Err, Rcp, Op->getFlags());
14046 SDValue TmpCast = DAG.getNode(ISD::BITCAST, SL, MVT::i32, Tmp);
14047 TmpCast = DAG.getNode(ISD::AND, SL, MVT::i32, TmpCast,
14048 DAG.getConstant(0xff800000, SL, MVT::i32));
14049 Tmp = DAG.getNode(ISD::BITCAST, SL, MVT::f32, TmpCast);
14050 Quot = DAG.getNode(ISD::FADD, SL, MVT::f32, Tmp, Quot, Op->getFlags());
14051 SDValue RDst = DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Quot,
14052 DAG.getTargetConstant(0, SL, MVT::i32));
14053 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst, RHS, LHS,
14054 Op->getFlags());
14055}
14056
14057// Faster 2.5 ULP division that does not support denormals.
14058SDValue SITargetLowering::lowerFDIV_FAST(SDValue Op, SelectionDAG &DAG) const {
14059 SDNodeFlags Flags = Op->getFlags();
14060 SDLoc SL(Op);
14061 SDValue LHS = Op.getOperand(1);
14062 SDValue RHS = Op.getOperand(2);
14063
14064 // TODO: The combiner should probably handle elimination of redundant fabs.
14066 ? RHS
14067 : DAG.getNode(ISD::FABS, SL, MVT::f32, RHS, Flags);
14068
14069 const APFloat K0Val(0x1p+96f);
14070 const SDValue K0 = DAG.getConstantFP(K0Val, SL, MVT::f32);
14071
14072 const APFloat K1Val(0x1p-32f);
14073 const SDValue K1 = DAG.getConstantFP(K1Val, SL, MVT::f32);
14074
14075 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
14076
14077 EVT SetCCVT =
14078 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
14079
14080 SDValue r2 = DAG.getSetCC(SL, SetCCVT, r1, K0, ISD::SETOGT);
14081
14082 SDValue r3 = DAG.getNode(ISD::SELECT, SL, MVT::f32, r2, K1, One, Flags);
14083
14084 r1 = DAG.getNode(ISD::FMUL, SL, MVT::f32, RHS, r3, Flags);
14085
14086 // rcp does not support denormals.
14087 SDValue r0 = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, r1, Flags);
14088
14089 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f32, LHS, r0, Flags);
14090
14091 return DAG.getNode(ISD::FMUL, SL, MVT::f32, r3, Mul, Flags);
14092}
14093
14094// Returns immediate value for setting the F32 denorm mode when using the
14095// S_DENORM_MODE instruction.
14097 const SIMachineFunctionInfo *Info,
14098 const GCNSubtarget *ST) {
14099 assert(ST->hasDenormModeInst() && "Requires S_DENORM_MODE");
14100 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
14101 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
14102 return DAG.getTargetConstant(Mode, SDLoc(), MVT::i32);
14103}
14104
14105SDValue SITargetLowering::LowerFDIV32(SDValue Op, SelectionDAG &DAG) const {
14106 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
14107 return FastLowered;
14108
14109 // The selection matcher assumes anything with a chain selecting to a
14110 // mayRaiseFPException machine instruction. Since we're introducing a chain
14111 // here, we need to explicitly report nofpexcept for the regular fdiv
14112 // lowering.
14113 SDNodeFlags Flags = Op->getFlags();
14114 Flags.setNoFPExcept(true);
14115
14116 SDLoc SL(Op);
14117 SDValue LHS = Op.getOperand(0);
14118 SDValue RHS = Op.getOperand(1);
14119
14120 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
14121
14122 SDVTList ScaleVT = DAG.getVTList(MVT::f32, MVT::i1);
14123
14124 SDValue DenominatorScaled =
14125 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {RHS, RHS, LHS}, Flags);
14126 SDValue NumeratorScaled =
14127 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {LHS, RHS, LHS}, Flags);
14128
14129 // Denominator is scaled to not be denormal, so using rcp is ok.
14130 SDValue ApproxRcp =
14131 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
14132 SDValue NegDivScale0 =
14133 DAG.getNode(ISD::FNEG, SL, MVT::f32, DenominatorScaled, Flags);
14134
14135 using namespace AMDGPU::Hwreg;
14136 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
14137 const SDValue BitField = DAG.getTargetConstant(Denorm32Reg, SL, MVT::i32);
14138
14139 const MachineFunction &MF = DAG.getMachineFunction();
14140 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
14141 const DenormalMode DenormMode = Info->getMode().FP32Denormals;
14142
14143 const bool PreservesDenormals = DenormMode == DenormalMode::getIEEE();
14144 const bool HasDynamicDenormals =
14145 (DenormMode.Input == DenormalMode::Dynamic) ||
14146 (DenormMode.Output == DenormalMode::Dynamic);
14147
14148 SDValue SavedDenormMode;
14149
14150 if (!PreservesDenormals) {
14151 // Note we can't use the STRICT_FMA/STRICT_FMUL for the non-strict FDIV
14152 // lowering. The chain dependence is insufficient, and we need glue. We do
14153 // not need the glue variants in a strictfp function.
14154
14155 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
14156
14157 SDValue Glue = DAG.getEntryNode();
14158 if (HasDynamicDenormals) {
14159 SDNode *GetReg = DAG.getMachineNode(AMDGPU::S_GETREG_B32, SL,
14160 DAG.getVTList(MVT::i32, MVT::Glue),
14161 {BitField, Glue});
14162 SavedDenormMode = SDValue(GetReg, 0);
14163
14164 Glue = DAG.getMergeValues(
14165 {DAG.getEntryNode(), SDValue(GetReg, 0), SDValue(GetReg, 1)}, SL);
14166 }
14167
14168 SDNode *EnableDenorm;
14169 if (Subtarget->hasDenormModeInst()) {
14170 const SDValue EnableDenormValue =
14171 getSPDenormModeValue(FP_DENORM_FLUSH_NONE, DAG, Info, Subtarget);
14172
14173 EnableDenorm = DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
14174 EnableDenormValue)
14175 .getNode();
14176 } else {
14177 const SDValue EnableDenormValue =
14178 DAG.getConstant(FP_DENORM_FLUSH_NONE, SL, MVT::i32);
14179 EnableDenorm = DAG.getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
14180 {EnableDenormValue, BitField, Glue});
14181 }
14182
14183 SDValue Ops[3] = {NegDivScale0, SDValue(EnableDenorm, 0),
14184 SDValue(EnableDenorm, 1)};
14185
14186 NegDivScale0 = DAG.getMergeValues(Ops, SL);
14187 }
14188
14189 SDValue Fma0 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0,
14190 ApproxRcp, One, NegDivScale0, Flags);
14191
14192 SDValue Fma1 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma0, ApproxRcp,
14193 ApproxRcp, Fma0, Flags);
14194
14195 SDValue Mul = getFPBinOp(DAG, ISD::FMUL, SL, MVT::f32, NumeratorScaled, Fma1,
14196 Fma1, Flags);
14197
14198 SDValue Fma2 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Mul,
14199 NumeratorScaled, Mul, Flags);
14200
14201 SDValue Fma3 =
14202 getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma2, Fma1, Mul, Fma2, Flags);
14203
14204 SDValue Fma4 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Fma3,
14205 NumeratorScaled, Fma3, Flags);
14206
14207 if (!PreservesDenormals) {
14208 SDNode *DisableDenorm;
14209 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
14210 const SDValue DisableDenormValue = getSPDenormModeValue(
14211 FP_DENORM_FLUSH_IN_FLUSH_OUT, DAG, Info, Subtarget);
14212
14213 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
14214 DisableDenorm =
14215 DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
14216 Fma4.getValue(1), DisableDenormValue, Fma4.getValue(2))
14217 .getNode();
14218 } else {
14219 assert(HasDynamicDenormals == (bool)SavedDenormMode);
14220 const SDValue DisableDenormValue =
14221 HasDynamicDenormals
14222 ? SavedDenormMode
14223 : DAG.getConstant(FP_DENORM_FLUSH_IN_FLUSH_OUT, SL, MVT::i32);
14224
14225 DisableDenorm = DAG.getMachineNode(
14226 AMDGPU::S_SETREG_B32, SL, MVT::Other,
14227 {DisableDenormValue, BitField, Fma4.getValue(1), Fma4.getValue(2)});
14228 }
14229
14230 SDValue OutputChain = DAG.getNode(ISD::TokenFactor, SL, MVT::Other,
14231 SDValue(DisableDenorm, 0), DAG.getRoot());
14232 DAG.setRoot(OutputChain);
14233 }
14234
14235 SDValue Scale = NumeratorScaled.getValue(1);
14236 SDValue Fmas = DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f32,
14237 {Fma4, Fma1, Fma3, Scale}, Flags);
14238
14239 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas, RHS, LHS, Flags);
14240}
14241
14242SDValue SITargetLowering::LowerFDIV64(SDValue Op, SelectionDAG &DAG) const {
14243 if (SDValue FastLowered = lowerFastUnsafeFDIV64(Op, DAG))
14244 return FastLowered;
14245
14246 SDLoc SL(Op);
14247 SDValue X = Op.getOperand(0);
14248 SDValue Y = Op.getOperand(1);
14249
14250 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f64);
14251
14252 SDVTList ScaleVT = DAG.getVTList(MVT::f64, MVT::i1);
14253
14254 SDValue DivScale0 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, Y, Y, X);
14255
14256 SDValue NegDivScale0 = DAG.getNode(ISD::FNEG, SL, MVT::f64, DivScale0);
14257
14258 SDValue Rcp = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14259
14260 SDValue Fma0 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Rcp, One);
14261
14262 SDValue Fma1 = DAG.getNode(ISD::FMA, SL, MVT::f64, Rcp, Fma0, Rcp);
14263
14264 SDValue Fma2 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Fma1, One);
14265
14266 SDValue DivScale1 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, X, Y, X);
14267
14268 SDValue Fma3 = DAG.getNode(ISD::FMA, SL, MVT::f64, Fma1, Fma2, Fma1);
14269 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f64, DivScale1, Fma3);
14270
14271 SDValue Fma4 =
14272 DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Mul, DivScale1);
14273
14274 SDValue Scale;
14275
14276 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14277 // Workaround a hardware bug on SI where the condition output from div_scale
14278 // is not usable.
14279
14280 const SDValue Hi = DAG.getConstant(1, SL, MVT::i32);
14281
14282 // Figure out if the scale to use for div_fmas.
14283 SDValue NumBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, X);
14284 SDValue DenBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Y);
14285 SDValue Scale0BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale0);
14286 SDValue Scale1BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale1);
14287
14288 SDValue NumHi =
14289 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, NumBC, Hi);
14290 SDValue DenHi =
14291 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, DenBC, Hi);
14292
14293 SDValue Scale0Hi =
14294 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale0BC, Hi);
14295 SDValue Scale1Hi =
14296 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale1BC, Hi);
14297
14298 SDValue CmpDen = DAG.getSetCC(SL, MVT::i1, DenHi, Scale0Hi, ISD::SETEQ);
14299 SDValue CmpNum = DAG.getSetCC(SL, MVT::i1, NumHi, Scale1Hi, ISD::SETEQ);
14300 Scale = DAG.getNode(ISD::XOR, SL, MVT::i1, CmpNum, CmpDen);
14301 } else {
14302 Scale = DivScale1.getValue(1);
14303 }
14304
14305 SDValue Fmas =
14306 DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3, Mul, Scale);
14307
14308 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas, Y, X);
14309}
14310
14311SDValue SITargetLowering::LowerFDIV(SDValue Op, SelectionDAG &DAG) const {
14312 EVT VT = Op.getValueType();
14313
14314 if (VT == MVT::f32)
14315 return LowerFDIV32(Op, DAG);
14316
14317 if (VT == MVT::f64)
14318 return LowerFDIV64(Op, DAG);
14319
14320 if (VT == MVT::f16 || VT == MVT::bf16)
14321 return LowerFDIV16(Op, DAG);
14322
14323 llvm_unreachable("Unexpected type for fdiv");
14324}
14325
14326SDValue SITargetLowering::LowerFFREXP(SDValue Op, SelectionDAG &DAG) const {
14327 SDLoc dl(Op);
14328 SDValue Val = Op.getOperand(0);
14329 EVT VT = Val.getValueType();
14330 EVT ResultExpVT = Op->getValueType(1);
14331 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14332
14333 SDValue Mant = DAG.getNode(
14335 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_mant, dl, MVT::i32), Val);
14336
14337 SDValue Exp = DAG.getNode(
14338 ISD::INTRINSIC_WO_CHAIN, dl, InstrExpVT,
14339 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_exp, dl, MVT::i32), Val);
14340
14341 if (Subtarget->hasFractBug()) {
14342 SDValue Fabs = DAG.getNode(ISD::FABS, dl, VT, Val);
14343 SDValue Inf =
14345
14346 SDValue IsFinite = DAG.getSetCC(dl, MVT::i1, Fabs, Inf, ISD::SETOLT);
14347 SDValue Zero = DAG.getConstant(0, dl, InstrExpVT);
14348 Exp = DAG.getNode(ISD::SELECT, dl, InstrExpVT, IsFinite, Exp, Zero);
14349 Mant = DAG.getNode(ISD::SELECT, dl, VT, IsFinite, Mant, Val);
14350 }
14351
14352 SDValue CastExp = DAG.getSExtOrTrunc(Exp, dl, ResultExpVT);
14353 return DAG.getMergeValues({Mant, CastExp}, dl);
14354}
14355
14356SDValue SITargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const {
14357 SDLoc DL(Op);
14358 StoreSDNode *Store = cast<StoreSDNode>(Op);
14359 EVT VT = Store->getMemoryVT();
14360
14361 if (VT == MVT::i1) {
14362 return DAG.getTruncStore(
14363 Store->getChain(), DL,
14364 DAG.getSExtOrTrunc(Store->getValue(), DL, MVT::i32),
14365 Store->getBasePtr(), MVT::i1, Store->getMemOperand());
14366 }
14367
14368 assert(VT.isVector() &&
14369 Store->getValue().getValueType().getScalarType() == MVT::i32);
14370
14371 unsigned AS = Store->getAddressSpace();
14372 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14373 AS == AMDGPUAS::FLAT_ADDRESS &&
14374 Store->getAlign().value() < VT.getStoreSize() &&
14375 VT.getSizeInBits() > 32) {
14376 return SplitVectorStore(Op, DAG);
14377 }
14378
14380 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
14381 // If there is a possibility that flat instruction access scratch memory
14382 // then we need to use the same legalization rules we use for private.
14383 if (AS == AMDGPUAS::FLAT_ADDRESS &&
14384 !Subtarget->hasMultiDwordFlatScratchAddressing())
14385 AS = addressMayBeAccessedAsPrivate(Store->getMemOperand(), *MFI)
14388
14389 unsigned NumElements = VT.getVectorNumElements();
14391 if (NumElements > 4)
14392 return SplitVectorStore(Op, DAG);
14393 // v3 stores not supported on SI.
14394 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14395 return SplitVectorStore(Op, DAG);
14396
14398 VT, *Store->getMemOperand()))
14399 return expandUnalignedStore(Store, DAG);
14400
14401 return SDValue();
14402 }
14403 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
14404 switch (Subtarget->getMaxPrivateElementSize()) {
14405 case 4:
14406 return scalarizeVectorStore(Store, DAG);
14407 case 8:
14408 if (NumElements > 2)
14409 return SplitVectorStore(Op, DAG);
14410 return SDValue();
14411 case 16:
14412 if (NumElements > 4 ||
14413 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14414 return SplitVectorStore(Op, DAG);
14415 return SDValue();
14416 default:
14417 llvm_unreachable("unsupported private_element_size");
14418 }
14419 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
14420 unsigned Fast = 0;
14421 auto Flags = Store->getMemOperand()->getFlags();
14423 Store->getAlign(), Flags, &Fast) &&
14424 Fast > 1)
14425 return SDValue();
14426
14427 if (VT.isVector())
14428 return SplitVectorStore(Op, DAG);
14429
14430 return expandUnalignedStore(Store, DAG);
14431 }
14432
14433 // Probably an invalid store. If so we'll end up emitting a selection error.
14434 return SDValue();
14435}
14436
14437// Avoid the full correct expansion for f32 sqrt when promoting from f16.
14438SDValue SITargetLowering::lowerFSQRTF16(SDValue Op, SelectionDAG &DAG) const {
14439 SDLoc SL(Op);
14440 assert(!Subtarget->has16BitInsts());
14441 SDNodeFlags Flags = Op->getFlags();
14442 SDValue Ext =
14443 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op.getOperand(0), Flags);
14444
14445 SDValue SqrtID = DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, SL, MVT::i32);
14446 SDValue Sqrt =
14447 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::f32, SqrtID, Ext, Flags);
14448
14449 return DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Sqrt,
14450 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
14451}
14452
14453SDValue SITargetLowering::lowerFSQRTF32(SDValue Op, SelectionDAG &DAG) const {
14454 SDLoc DL(Op);
14455 SDNodeFlags Flags = Op->getFlags();
14456 MVT VT = Op.getValueType().getSimpleVT();
14457 const SDValue X = Op.getOperand(0);
14458
14459 if (allowApproxFunc(DAG, Flags)) {
14460 // Instruction is 1ulp but ignores denormals.
14461 return DAG.getNode(
14463 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32), X, Flags);
14464 }
14465
14466 SDValue ScaleThreshold = DAG.getConstantFP(0x1.0p-96f, DL, VT);
14467 SDValue NeedScale = DAG.getSetCC(DL, MVT::i1, X, ScaleThreshold, ISD::SETOLT);
14468
14469 SDValue ScaleUpFactor = DAG.getConstantFP(0x1.0p+32f, DL, VT);
14470
14471 SDValue ScaledX = DAG.getNode(ISD::FMUL, DL, VT, X, ScaleUpFactor, Flags);
14472
14473 SDValue SqrtX =
14474 DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledX, X, Flags);
14475
14476 SDValue SqrtS;
14477 if (needsDenormHandlingF32(DAG, X, Flags)) {
14478 SDValue SqrtID =
14479 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32);
14480 SqrtS = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, SqrtID, SqrtX, Flags);
14481
14482 SDValue SqrtSAsInt = DAG.getNode(ISD::BITCAST, DL, MVT::i32, SqrtS);
14483 SDValue SqrtSNextDownInt =
14484 DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14485 DAG.getAllOnesConstant(DL, MVT::i32));
14486 SDValue SqrtSNextDown = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextDownInt);
14487
14488 SDValue NegSqrtSNextDown =
14489 DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextDown, Flags);
14490
14491 SDValue SqrtVP =
14492 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
14493
14494 SDValue SqrtSNextUpInt = DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14495 DAG.getConstant(1, DL, MVT::i32));
14496 SDValue SqrtSNextUp = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextUpInt);
14497
14498 SDValue NegSqrtSNextUp = DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextUp, Flags);
14499 SDValue SqrtVS =
14500 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
14501
14502 SDValue Zero = DAG.getConstantFP(0.0f, DL, VT);
14503 SDValue SqrtVPLE0 = DAG.getSetCC(DL, MVT::i1, SqrtVP, Zero, ISD::SETOLE);
14504
14505 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPLE0, SqrtSNextDown, SqrtS,
14506 Flags);
14507
14508 SDValue SqrtVPVSGT0 = DAG.getSetCC(DL, MVT::i1, SqrtVS, Zero, ISD::SETOGT);
14509 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPVSGT0, SqrtSNextUp, SqrtS,
14510 Flags);
14511 } else {
14512 SDValue SqrtR = DAG.getNode(AMDGPUISD::RSQ, DL, VT, SqrtX, Flags);
14513
14514 SqrtS = DAG.getNode(ISD::FMUL, DL, VT, SqrtX, SqrtR, Flags);
14515
14516 SDValue Half = DAG.getConstantFP(0.5f, DL, VT);
14517 SDValue SqrtH = DAG.getNode(ISD::FMUL, DL, VT, SqrtR, Half, Flags);
14518 SDValue NegSqrtH = DAG.getNode(ISD::FNEG, DL, VT, SqrtH, Flags);
14519
14520 SDValue SqrtE = DAG.getNode(ISD::FMA, DL, VT, NegSqrtH, SqrtS, Half, Flags);
14521 SqrtH = DAG.getNode(ISD::FMA, DL, VT, SqrtH, SqrtE, SqrtH, Flags);
14522 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtS, SqrtE, SqrtS, Flags);
14523
14524 SDValue NegSqrtS = DAG.getNode(ISD::FNEG, DL, VT, SqrtS, Flags);
14525 SDValue SqrtD =
14526 DAG.getNode(ISD::FMA, DL, VT, NegSqrtS, SqrtS, SqrtX, Flags);
14527 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtD, SqrtH, SqrtS, Flags);
14528 }
14529
14530 SDValue ScaleDownFactor = DAG.getConstantFP(0x1.0p-16f, DL, VT);
14531
14532 SDValue ScaledDown =
14533 DAG.getNode(ISD::FMUL, DL, VT, SqrtS, ScaleDownFactor, Flags);
14534
14535 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledDown, SqrtS, Flags);
14536 SDValue IsZeroOrInf =
14537 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14538 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14539
14540 return DAG.getNode(ISD::SELECT, DL, VT, IsZeroOrInf, SqrtX, SqrtS, Flags);
14541}
14542
14543SDValue SITargetLowering::lowerFSQRTF64(SDValue Op, SelectionDAG &DAG) const {
14544 // For double type, the SQRT and RSQ instructions don't have required
14545 // precision, we apply Goldschmidt's algorithm to improve the result:
14546 //
14547 // y0 = rsq(x)
14548 // g0 = x * y0
14549 // h0 = 0.5 * y0
14550 //
14551 // r0 = 0.5 - h0 * g0
14552 // g1 = g0 * r0 + g0
14553 // h1 = h0 * r0 + h0
14554 //
14555 // r1 = 0.5 - h1 * g1 => d0 = x - g1 * g1
14556 // g2 = g1 * r1 + g1 g2 = d0 * h1 + g1
14557 // h2 = h1 * r1 + h1
14558 //
14559 // r2 = 0.5 - h2 * g2 => d1 = x - g2 * g2
14560 // g3 = g2 * r2 + g2 g3 = d1 * h1 + g2
14561 //
14562 // sqrt(x) = g3
14563
14564 SDNodeFlags Flags = Op->getFlags();
14565
14566 SDLoc DL(Op);
14567
14568 SDValue X = Op.getOperand(0);
14569 SDValue ZeroInt = DAG.getConstant(0, DL, MVT::i32);
14570
14571 SDValue SqrtX = X;
14572 SDValue Scaling;
14573 if (!Flags.hasApproximateFuncs()) {
14574 SDValue ScaleConstant = DAG.getConstantFP(0x1.0p-767, DL, MVT::f64);
14575 Scaling = DAG.getSetCC(DL, MVT::i1, X, ScaleConstant, ISD::SETOLT);
14576
14577 // Scale up input if it is too small.
14578 SDValue ScaleUpFactor = DAG.getConstant(256, DL, MVT::i32);
14579 SDValue ScaleUp =
14580 DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling, ScaleUpFactor, ZeroInt);
14581 SqrtX = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, X, ScaleUp, Flags);
14582 }
14583
14584 SDValue SqrtY = DAG.getNode(AMDGPUISD::RSQ, DL, MVT::f64, SqrtX);
14585
14586 SDValue SqrtS0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtX, SqrtY);
14587
14588 SDValue Half = DAG.getConstantFP(0.5, DL, MVT::f64);
14589 SDValue SqrtH0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtY, Half);
14590
14591 SDValue NegSqrtH0 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtH0);
14592 SDValue SqrtR0 = DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtH0, SqrtS0, Half);
14593
14594 SDValue SqrtH1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtH0, SqrtR0, SqrtH0);
14595
14596 SDValue SqrtS1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtS0, SqrtR0, SqrtS0);
14597
14598 SDValue NegSqrtS1 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS1);
14599 SDValue SqrtD0 =
14600 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS1, SqrtS1, SqrtX);
14601
14602 SDValue SqrtS2 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD0, SqrtH1, SqrtS1);
14603
14604 SDValue SqrtRet = SqrtS2;
14605 if (!Flags.hasApproximateFuncs()) {
14606 SDValue NegSqrtS2 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS2);
14607 SDValue SqrtD1 =
14608 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS2, SqrtS2, SqrtX);
14609
14610 SqrtRet = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD1, SqrtH1, SqrtS2);
14611
14612 SDValue ScaleDownFactor = DAG.getSignedConstant(-128, DL, MVT::i32);
14613 SDValue ScaleDown = DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling,
14614 ScaleDownFactor, ZeroInt);
14615 SqrtRet = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, SqrtRet, ScaleDown, Flags);
14616 }
14617
14618 // TODO: Check for DAZ and expand to subnormals
14619
14620 SDValue IsZeroOrInf;
14621 if (Flags.hasNoInfs()) {
14622 SDValue Zero = DAG.getConstantFP(0.0, DL, MVT::f64);
14623 IsZeroOrInf = DAG.getSetCC(DL, MVT::i1, SqrtX, Zero, ISD::SETOEQ);
14624 } else {
14625 IsZeroOrInf =
14626 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14627 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14628 }
14629
14630 // If x is +INF, +0, or -0, use its original value
14631 return DAG.getNode(ISD::SELECT, DL, MVT::f64, IsZeroOrInf, SqrtX, SqrtRet,
14632 Flags);
14633}
14634
14635SDValue SITargetLowering::LowerTrig(SDValue Op, SelectionDAG &DAG) const {
14636 SDLoc DL(Op);
14637 EVT VT = Op.getValueType();
14638 SDValue Arg = Op.getOperand(0);
14639 SDValue TrigVal;
14640
14641 // Propagate fast-math flags so that the multiply we introduce can be folded
14642 // if Arg is already the result of a multiply by constant.
14643 auto Flags = Op->getFlags();
14644
14645 // AMDGPUISD nodes of vector type must be unrolled here since
14646 // they will not be expanded elsewhere.
14647 auto UnrollIfVec = [&DAG](SDValue V) -> SDValue {
14648 if (!V.getValueType().isVector())
14649 return V;
14650
14651 return DAG.UnrollVectorOp(cast<SDNode>(V));
14652 };
14653
14654 SDValue OneOver2Pi = DAG.getConstantFP(0.5 * numbers::inv_pi, DL, VT);
14655
14656 if (Subtarget->hasTrigReducedRange()) {
14657 SDValue MulVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14658 TrigVal = UnrollIfVec(DAG.getNode(AMDGPUISD::FRACT, DL, VT, MulVal, Flags));
14659 } else {
14660 TrigVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14661 }
14662
14663 switch (Op.getOpcode()) {
14664 case ISD::FCOS:
14665 TrigVal = DAG.getNode(AMDGPUISD::COS_HW, SDLoc(Op), VT, TrigVal, Flags);
14666 break;
14667 case ISD::FSIN:
14668 TrigVal = DAG.getNode(AMDGPUISD::SIN_HW, SDLoc(Op), VT, TrigVal, Flags);
14669 break;
14670 default:
14671 llvm_unreachable("Wrong trig opcode");
14672 }
14673
14674 return UnrollIfVec(TrigVal);
14675}
14676
14677SDValue SITargetLowering::LowerATOMIC_CMP_SWAP(SDValue Op,
14678 SelectionDAG &DAG) const {
14679 AtomicSDNode *AtomicNode = cast<AtomicSDNode>(Op);
14680 assert(AtomicNode->isCompareAndSwap());
14681 unsigned AS = AtomicNode->getAddressSpace();
14682
14683 // No custom lowering required for local address space
14685 return Op;
14686
14687 // Non-local address space requires custom lowering for atomic compare
14688 // and swap; cmp and swap should be in a v2i32 or v2i64 in case of _X2
14689 SDLoc DL(Op);
14690 SDValue ChainIn = Op.getOperand(0);
14691 SDValue Addr = Op.getOperand(1);
14692 SDValue Old = Op.getOperand(2);
14693 SDValue New = Op.getOperand(3);
14694 EVT VT = Op.getValueType();
14695 MVT SimpleVT = VT.getSimpleVT();
14696 MVT VecType = MVT::getVectorVT(SimpleVT, 2);
14697
14698 SDValue NewOld = DAG.getBuildVector(VecType, DL, {New, Old});
14699 SDValue Ops[] = {ChainIn, Addr, NewOld};
14700
14701 return DAG.getMemIntrinsicNode(AMDGPUISD::ATOMIC_CMP_SWAP, DL,
14702 Op->getVTList(), Ops, VT,
14703 AtomicNode->getMemOperand());
14704}
14705
14706//===----------------------------------------------------------------------===//
14707// Custom DAG optimizations
14708//===----------------------------------------------------------------------===//
14709
14710SDValue
14711SITargetLowering::performUCharToFloatCombine(SDNode *N,
14712 DAGCombinerInfo &DCI) const {
14713 EVT VT = N->getValueType(0);
14714 EVT ScalarVT = VT.getScalarType();
14715 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14716 return SDValue();
14717
14718 SelectionDAG &DAG = DCI.DAG;
14719 SDLoc DL(N);
14720
14721 SDValue Src = N->getOperand(0);
14722 EVT SrcVT = Src.getValueType();
14723
14724 // TODO: We could try to match extracting the higher bytes, which would be
14725 // easier if i8 vectors weren't promoted to i32 vectors, particularly after
14726 // types are legalized. v4i8 -> v4f32 is probably the only case to worry
14727 // about in practice.
14728 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14729 if (DAG.MaskedValueIsZero(Src, APInt::getHighBitsSet(32, 24))) {
14730 SDValue Cvt = DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0, DL, MVT::f32, Src);
14731 DCI.AddToWorklist(Cvt.getNode());
14732
14733 // For the f16 case, fold to a cast to f32 and then cast back to f16.
14734 if (ScalarVT != MVT::f32) {
14735 Cvt = DAG.getNode(ISD::FP_ROUND, DL, VT, Cvt,
14736 DAG.getTargetConstant(0, DL, MVT::i32));
14737 }
14738 return Cvt;
14739 }
14740 }
14741
14742 return SDValue();
14743}
14744
14745SDValue SITargetLowering::performFCopySignCombine(SDNode *N,
14746 DAGCombinerInfo &DCI) const {
14747 SDValue MagnitudeOp = N->getOperand(0);
14748 SDValue SignOp = N->getOperand(1);
14749
14750 // The generic combine for fcopysign + fp cast is too conservative with
14751 // vectors, and also gets confused by the splitting we will perform here, so
14752 // peek through FP casts.
14753 if (SignOp.getOpcode() == ISD::FP_EXTEND ||
14754 SignOp.getOpcode() == ISD::FP_ROUND)
14755 SignOp = SignOp.getOperand(0);
14756
14757 SelectionDAG &DAG = DCI.DAG;
14758 SDLoc DL(N);
14759 EVT SignVT = SignOp.getValueType();
14760
14761 // f64 fcopysign is really an f32 copysign on the high bits, so replace the
14762 // lower half with a copy.
14763 // fcopysign f64:x, _:y -> x.lo32, (fcopysign (f32 x.hi32), _:y)
14764 EVT MagVT = MagnitudeOp.getValueType();
14765
14766 unsigned NumElts = MagVT.isVector() ? MagVT.getVectorNumElements() : 1;
14767
14768 if (MagVT.getScalarType() == MVT::f64) {
14769 EVT F32VT = MagVT.isVector()
14770 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14771 : MVT::v2f32;
14772
14773 SDValue MagAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, MagnitudeOp);
14774
14776 for (unsigned I = 0; I != NumElts; ++I) {
14777 SDValue MagLo =
14778 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14779 DAG.getConstant(2 * I, DL, MVT::i32));
14780 SDValue MagHi =
14781 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14782 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14783
14784 SDValue SignOpElt =
14785 MagVT.isVector()
14787 SignOp, DAG.getConstant(I, DL, MVT::i32))
14788 : SignOp;
14789
14790 SDValue HiOp =
14791 DAG.getNode(ISD::FCOPYSIGN, DL, MVT::f32, MagHi, SignOpElt);
14792
14793 SDValue Vector =
14794 DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v2f32, MagLo, HiOp);
14795
14796 SDValue NewElt = DAG.getNode(ISD::BITCAST, DL, MVT::f64, Vector);
14797 NewElts.push_back(NewElt);
14798 }
14799
14800 if (NewElts.size() == 1)
14801 return NewElts[0];
14802
14803 return DAG.getNode(ISD::BUILD_VECTOR, DL, MagVT, NewElts);
14804 }
14805
14806 if (SignVT.getScalarType() != MVT::f64)
14807 return SDValue();
14808
14809 // Reduce width of sign operand, we only need the highest bit.
14810 //
14811 // fcopysign f64:x, f64:y ->
14812 // fcopysign f64:x, (extract_vector_elt (bitcast f64:y to v2f32), 1)
14813 // TODO: In some cases it might make sense to go all the way to f16.
14814
14815 EVT F32VT = MagVT.isVector()
14816 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14817 : MVT::v2f32;
14818
14819 SDValue SignAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, SignOp);
14820
14821 SmallVector<SDValue, 8> F32Signs;
14822 for (unsigned I = 0; I != NumElts; ++I) {
14823 // Take sign from odd elements of cast vector
14824 SDValue SignAsF32 =
14825 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, SignAsVector,
14826 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14827 F32Signs.push_back(SignAsF32);
14828 }
14829
14830 SDValue NewSign =
14831 NumElts == 1
14832 ? F32Signs.back()
14834 EVT::getVectorVT(*DAG.getContext(), MVT::f32, NumElts),
14835 F32Signs);
14836
14837 return DAG.getNode(ISD::FCOPYSIGN, DL, N->getValueType(0), N->getOperand(0),
14838 NewSign);
14839}
14840
14841// (shl (add x, c1), c2) -> add (shl x, c2), (shl c1, c2)
14842// (shl (or x, c1), c2) -> add (shl x, c2), (shl c1, c2) iff x and c1 share no
14843// bits
14844
14845// This is a variant of
14846// (mul (add x, c1), c2) -> add (mul x, c2), (mul c1, c2),
14847//
14848// The normal DAG combiner will do this, but only if the add has one use since
14849// that would increase the number of instructions.
14850//
14851// This prevents us from seeing a constant offset that can be folded into a
14852// memory instruction's addressing mode. If we know the resulting add offset of
14853// a pointer can be folded into an addressing offset, we can replace the pointer
14854// operand with the add of new constant offset. This eliminates one of the uses,
14855// and may allow the remaining use to also be simplified.
14856//
14857SDValue SITargetLowering::performSHLPtrCombine(SDNode *N, unsigned AddrSpace,
14858 EVT MemVT,
14859 DAGCombinerInfo &DCI) const {
14860 SDValue N0 = N->getOperand(0);
14861 SDValue N1 = N->getOperand(1);
14862
14863 // We only do this to handle cases where it's profitable when there are
14864 // multiple uses of the add, so defer to the standard combine.
14865 if ((!N0->isAnyAdd() && N0.getOpcode() != ISD::OR) || N0->hasOneUse())
14866 return SDValue();
14867
14868 const ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(N1);
14869 if (!CN1)
14870 return SDValue();
14871
14872 const ConstantSDNode *CAdd = dyn_cast<ConstantSDNode>(N0.getOperand(1));
14873 if (!CAdd)
14874 return SDValue();
14875
14876 SelectionDAG &DAG = DCI.DAG;
14877
14878 if (N0->getOpcode() == ISD::OR &&
14879 !DAG.haveNoCommonBitsSet(N0.getOperand(0), N0.getOperand(1)))
14880 return SDValue();
14881
14882 // If the resulting offset is too large, we can't fold it into the
14883 // addressing mode offset.
14884 APInt Offset = CAdd->getAPIntValue() << CN1->getAPIntValue();
14885 Type *Ty = MemVT.getTypeForEVT(*DCI.DAG.getContext());
14886
14887 AddrMode AM;
14888 AM.HasBaseReg = true;
14889 AM.BaseOffs = Offset.getSExtValue();
14890 if (!isLegalAddressingMode(DCI.DAG.getDataLayout(), AM, Ty, AddrSpace))
14891 return SDValue();
14892
14893 SDLoc SL(N);
14894 EVT VT = N->getValueType(0);
14895
14896 SDValue ShlX = DAG.getNode(ISD::SHL, SL, VT, N0.getOperand(0), N1);
14897 SDValue COffset = DAG.getConstant(Offset, SL, VT);
14898
14899 SDNodeFlags Flags;
14900 Flags.setNoUnsignedWrap(
14901 N->getFlags().hasNoUnsignedWrap() &&
14902 (N0.getOpcode() == ISD::OR || N0->getFlags().hasNoUnsignedWrap()));
14903
14904 // Use ISD::ADD even if the original operation was ISD::PTRADD, since we can't
14905 // be sure that the new left operand is a proper base pointer.
14906 return DAG.getNode(ISD::ADD, SL, VT, ShlX, COffset, Flags);
14907}
14908
14909/// MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset
14910/// by the chain and intrinsic ID. Theoretically we would also need to check the
14911/// specific intrinsic, but they all place the pointer operand first.
14912static unsigned getBasePtrIndex(const MemSDNode *N) {
14913 switch (N->getOpcode()) {
14914 case ISD::STORE:
14917 return 2;
14918 default:
14919 return 1;
14920 }
14921}
14922
14923SDValue SITargetLowering::performMemSDNodeCombine(MemSDNode *N,
14924 DAGCombinerInfo &DCI) const {
14925 SelectionDAG &DAG = DCI.DAG;
14926
14927 unsigned PtrIdx = getBasePtrIndex(N);
14928 SDValue Ptr = N->getOperand(PtrIdx);
14929
14930 // TODO: We could also do this for multiplies.
14931 if (Ptr.getOpcode() == ISD::SHL) {
14932 SDValue NewPtr = performSHLPtrCombine(Ptr.getNode(), N->getAddressSpace(),
14933 N->getMemoryVT(), DCI);
14934 if (NewPtr) {
14935 SmallVector<SDValue, 8> NewOps(N->ops());
14936
14937 NewOps[PtrIdx] = NewPtr;
14938 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
14939 }
14940 }
14941
14942 return SDValue();
14943}
14944
14945static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val) {
14946 return (Opc == ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14947 (Opc == ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14948 (Opc == ISD::XOR && Val == 0);
14949}
14950
14951// Break up 64-bit bit operation of a constant into two 32-bit and/or/xor. This
14952// will typically happen anyway for a VALU 64-bit and. This exposes other 32-bit
14953// integer combine opportunities since most 64-bit operations are decomposed
14954// this way. TODO: We won't want this for SALU especially if it is an inline
14955// immediate.
14956SDValue SITargetLowering::splitBinaryBitConstantOp(
14957 DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS,
14958 const ConstantSDNode *CRHS) const {
14959 uint64_t Val = CRHS->getZExtValue();
14960 uint32_t ValLo = Lo_32(Val);
14961 uint32_t ValHi = Hi_32(Val);
14962 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
14963
14964 if ((bitOpWithConstantIsReducible(Opc, ValLo) ||
14966 (CRHS->hasOneUse() && !TII->isInlineConstant(CRHS->getAPIntValue()))) {
14967 // We have 64-bit scalar and/or/xor, but do not have vector forms.
14968 if (Subtarget->has64BitLiterals() && CRHS->hasOneUse() &&
14969 !CRHS->user_begin()->isDivergent())
14970 return SDValue();
14971
14972 // If we need to materialize a 64-bit immediate, it will be split up later
14973 // anyway. Avoid creating the harder to understand 64-bit immediate
14974 // materialization.
14975 return splitBinaryBitConstantOpImpl(DCI, SL, Opc, LHS, ValLo, ValHi);
14976 }
14977
14978 return SDValue();
14979}
14980
14982 if (V.getValueType() != MVT::i1)
14983 return false;
14984 switch (V.getOpcode()) {
14985 default:
14986 break;
14987 case ISD::SETCC:
14988 case ISD::IS_FPCLASS:
14989 case AMDGPUISD::FP_CLASS:
14990 return true;
14991 case ISD::AND:
14992 case ISD::OR:
14993 case ISD::XOR:
14994 return isBoolSGPR(V.getOperand(0)) && isBoolSGPR(V.getOperand(1));
14995 case ISD::SADDO:
14996 case ISD::UADDO:
14997 case ISD::SSUBO:
14998 case ISD::USUBO:
14999 case ISD::SMULO:
15000 case ISD::UMULO:
15001 return V.getResNo() == 1;
15003 unsigned IntrinsicID = V.getConstantOperandVal(0);
15004 switch (IntrinsicID) {
15005 case Intrinsic::amdgcn_is_shared:
15006 case Intrinsic::amdgcn_is_private:
15007 return true;
15008 default:
15009 return false;
15010 }
15011
15012 return false;
15013 }
15014 }
15015 return false;
15016}
15017
15018// If a constant has all zeroes or all ones within each byte return it.
15019// Otherwise return 0.
15021 // 0xff for any zero byte in the mask
15022 uint32_t ZeroByteMask = 0;
15023 if (!(C & 0x000000ff))
15024 ZeroByteMask |= 0x000000ff;
15025 if (!(C & 0x0000ff00))
15026 ZeroByteMask |= 0x0000ff00;
15027 if (!(C & 0x00ff0000))
15028 ZeroByteMask |= 0x00ff0000;
15029 if (!(C & 0xff000000))
15030 ZeroByteMask |= 0xff000000;
15031 uint32_t NonZeroByteMask = ~ZeroByteMask; // 0xff for any non-zero byte
15032 if ((NonZeroByteMask & C) != NonZeroByteMask)
15033 return 0; // Partial bytes selected.
15034 return C;
15035}
15036
15037// Check if a node selects whole bytes from its operand 0 starting at a byte
15038// boundary while masking the rest. Returns select mask as in the v_perm_b32
15039// or -1 if not succeeded.
15040// Note byte select encoding:
15041// value 0-3 selects corresponding source byte;
15042// value 0xc selects zero;
15043// value 0xff selects 0xff.
15045 assert(V.getValueSizeInBits() == 32);
15046
15047 if (V.getNumOperands() != 2)
15048 return ~0;
15049
15050 ConstantSDNode *N1 = dyn_cast<ConstantSDNode>(V.getOperand(1));
15051 if (!N1)
15052 return ~0;
15053
15054 uint32_t C = N1->getZExtValue();
15055
15056 switch (V.getOpcode()) {
15057 default:
15058 break;
15059 case ISD::AND:
15060 if (uint32_t ConstMask = getConstantPermuteMask(C))
15061 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
15062 break;
15063
15064 case ISD::OR:
15065 if (uint32_t ConstMask = getConstantPermuteMask(C))
15066 return (0x03020100 & ~ConstMask) | ConstMask;
15067 break;
15068
15069 case ISD::SHL:
15070 if (C % 8)
15071 return ~0;
15072
15073 return uint32_t((0x030201000c0c0c0cull << C) >> 32);
15074
15075 case ISD::SRL:
15076 if (C % 8)
15077 return ~0;
15078
15079 return uint32_t(0x0c0c0c0c03020100ull >> C);
15080 }
15081
15082 return ~0;
15083}
15084
15085SDValue SITargetLowering::performAndCombine(SDNode *N,
15086 DAGCombinerInfo &DCI) const {
15087 if (DCI.isBeforeLegalize())
15088 return SDValue();
15089
15090 SelectionDAG &DAG = DCI.DAG;
15091 EVT VT = N->getValueType(0);
15092 SDValue LHS = N->getOperand(0);
15093 SDValue RHS = N->getOperand(1);
15094
15095 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS);
15096 if (VT == MVT::i64 && CRHS) {
15097 if (SDValue Split =
15098 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::AND, LHS, CRHS))
15099 return Split;
15100 }
15101
15102 if (CRHS && VT == MVT::i32) {
15103 // and (srl x, c), mask => shl (bfe x, nb + c, mask >> nb), nb
15104 // nb = number of trailing zeroes in mask
15105 // It can be optimized out using SDWA for GFX8+ in the SDWA peephole pass,
15106 // given that we are selecting 8 or 16 bit fields starting at byte boundary.
15107 uint64_t Mask = CRHS->getZExtValue();
15108 unsigned Bits = llvm::popcount(Mask);
15109 if (getSubtarget()->hasSDWA() && LHS->getOpcode() == ISD::SRL &&
15110 (Bits == 8 || Bits == 16) && isShiftedMask_64(Mask) && !(Mask & 1)) {
15111 if (auto *CShift = dyn_cast<ConstantSDNode>(LHS->getOperand(1))) {
15112 unsigned Shift = CShift->getZExtValue();
15113 unsigned NB = CRHS->getAPIntValue().countr_zero();
15114 unsigned Offset = NB + Shift;
15115 if ((Offset & (Bits - 1)) == 0) { // Starts at a byte or word boundary.
15116 SDLoc SL(N);
15117 SDValue BFE =
15118 DAG.getNode(AMDGPUISD::BFE_U32, SL, MVT::i32, LHS->getOperand(0),
15119 DAG.getConstant(Offset, SL, MVT::i32),
15120 DAG.getConstant(Bits, SL, MVT::i32));
15121 EVT NarrowVT = EVT::getIntegerVT(*DAG.getContext(), Bits);
15122 SDValue Ext = DAG.getNode(ISD::AssertZext, SL, VT, BFE,
15123 DAG.getValueType(NarrowVT));
15124 SDValue Shl = DAG.getNode(ISD::SHL, SDLoc(LHS), VT, Ext,
15125 DAG.getConstant(NB, SDLoc(CRHS), MVT::i32));
15126 return Shl;
15127 }
15128 }
15129 }
15130
15131 // and (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
15132 if (LHS.hasOneUse() && LHS.getOpcode() == AMDGPUISD::PERM &&
15133 isa<ConstantSDNode>(LHS.getOperand(2))) {
15134 uint32_t Sel = getConstantPermuteMask(Mask);
15135 if (!Sel)
15136 return SDValue();
15137
15138 // Select 0xc for all zero bytes
15139 Sel = (LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
15140 SDLoc DL(N);
15141 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15142 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
15143 }
15144 }
15145
15146 // and (trunc (srl x, c)), mask => srl (trunc x), c
15147 // if mask keeps exactly the bits that srl leaves in the low half
15148 if (CRHS && VT == MVT::i16 && LHS.getOpcode() == ISD::TRUNCATE &&
15149 LHS.hasOneUse() && LHS.getOperand(0).getOpcode() == ISD::SRL) {
15150 auto *Shift = dyn_cast<ConstantSDNode>(LHS.getOperand(0).getOperand(1));
15151 if (Shift && Shift->getZExtValue() < 16 &&
15152 CRHS->getAPIntValue().isMask(16 - Shift->getZExtValue())) {
15153 SDLoc SL(N);
15154 SDValue Trunc =
15155 DAG.getNode(ISD::TRUNCATE, SL, VT, LHS.getOperand(0).getOperand(0));
15156 return DAG.getNode(
15157 ISD::SRL, SL, VT, Trunc,
15158 DAG.getShiftAmountConstant(Shift->getZExtValue(), VT, SL));
15159 }
15160 }
15161
15162 // (and (fcmp ord x, x), (fcmp une (fabs x), inf)) ->
15163 // fp_class x, ~(s_nan | q_nan | n_infinity | p_infinity)
15164 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == ISD::SETCC) {
15165 ISD::CondCode LCC = LHS.getOperandCondCode(2);
15166 ISD::CondCode RCC = RHS.getOperandCondCode(2);
15167
15168 SDValue X = LHS.getOperand(0);
15169 SDValue Y = RHS.getOperand(0);
15170 if (Y.getOpcode() != ISD::FABS || Y.getOperand(0) != X ||
15171 !isTypeLegal(X.getValueType()))
15172 return SDValue();
15173
15174 if (LCC == ISD::SETO) {
15175 if (X != LHS.getOperand(1))
15176 return SDValue();
15177
15178 if (RCC == ISD::SETUNE) {
15179 const ConstantFPSDNode *C1 =
15180 dyn_cast<ConstantFPSDNode>(RHS.getOperand(1));
15181 if (!C1 || !C1->isInfinity() || C1->isNegative())
15182 return SDValue();
15183
15184 const uint32_t Mask = SIInstrFlags::N_NORMAL |
15188
15189 static_assert(
15192 0x3ff) == Mask,
15193 "mask not equal");
15194
15195 SDLoc DL(N);
15196 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, X,
15197 DAG.getConstant(Mask, DL, MVT::i32));
15198 }
15199 }
15200 }
15201
15202 if (RHS.getOpcode() == ISD::SETCC && LHS.getOpcode() == AMDGPUISD::FP_CLASS)
15203 std::swap(LHS, RHS);
15204
15205 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15206 RHS.hasOneUse()) {
15207 ISD::CondCode LCC = LHS.getOperandCondCode(2);
15208 // and (fcmp seto), (fp_class x, mask) -> fp_class x, mask & ~(p_nan |
15209 // n_nan) and (fcmp setuo), (fp_class x, mask) -> fp_class x, mask & (p_nan
15210 // | n_nan)
15211 const ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
15212 if ((LCC == ISD::SETO || LCC == ISD::SETUO) && Mask &&
15213 (RHS.getOperand(0) == LHS.getOperand(0) &&
15214 LHS.getOperand(0) == LHS.getOperand(1))) {
15215 const unsigned OrdMask = SIInstrFlags::S_NAN | SIInstrFlags::Q_NAN;
15216 unsigned NewMask = LCC == ISD::SETO ? Mask->getZExtValue() & ~OrdMask
15217 : Mask->getZExtValue() & OrdMask;
15218
15219 SDLoc DL(N);
15220 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, RHS.getOperand(0),
15221 DAG.getConstant(NewMask, DL, MVT::i32));
15222 }
15223 }
15224
15225 if (VT == MVT::i32 && (RHS.getOpcode() == ISD::SIGN_EXTEND ||
15226 LHS.getOpcode() == ISD::SIGN_EXTEND)) {
15227 // and x, (sext cc from i1) => select cc, x, 0
15228 if (RHS.getOpcode() != ISD::SIGN_EXTEND)
15229 std::swap(LHS, RHS);
15230 if (isBoolSGPR(RHS.getOperand(0)))
15231 return DAG.getSelect(SDLoc(N), MVT::i32, RHS.getOperand(0), LHS,
15232 DAG.getConstant(0, SDLoc(N), MVT::i32));
15233 }
15234
15235 // and (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
15236 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
15237 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
15238 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15239 uint32_t LHSMask = getPermuteMask(LHS);
15240 uint32_t RHSMask = getPermuteMask(RHS);
15241 if (LHSMask != ~0u && RHSMask != ~0u) {
15242 // Canonicalize the expression in an attempt to have fewer unique masks
15243 // and therefore fewer registers used to hold the masks.
15244 if (LHSMask > RHSMask) {
15245 std::swap(LHSMask, RHSMask);
15246 std::swap(LHS, RHS);
15247 }
15248
15249 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15250 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15251 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15252 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15253
15254 // Check of we need to combine values from two sources within a byte.
15255 if (!(LHSUsedLanes & RHSUsedLanes) &&
15256 // If we select high and lower word keep it for SDWA.
15257 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15258 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15259 // Each byte in each mask is either selector mask 0-3, or has higher
15260 // bits set in either of masks, which can be 0xff for 0xff or 0x0c for
15261 // zero. If 0x0c is in either mask it shall always be 0x0c. Otherwise
15262 // mask which is not 0xff wins. By anding both masks we have a correct
15263 // result except that 0x0c shall be corrected to give 0x0c only.
15264 uint32_t Mask = LHSMask & RHSMask;
15265 for (unsigned I = 0; I < 32; I += 8) {
15266 uint32_t ByteSel = 0xff << I;
15267 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15268 Mask &= (0x0c << I) & 0xffffffff;
15269 }
15270
15271 // Add 4 to each active LHS lane. It will not affect any existing 0xff
15272 // or 0x0c.
15273 uint32_t Sel = Mask | (LHSUsedLanes & 0x04040404);
15274 SDLoc DL(N);
15275
15276 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15277 RHS.getOperand(0),
15278 DAG.getConstant(Sel, DL, MVT::i32));
15279 }
15280 }
15281 }
15282
15283 return SDValue();
15284}
15285
15286// A key component of v_perm is a mapping between byte position of the src
15287// operands, and the byte position of the dest. To provide such, we need: 1. the
15288// node that provides x byte of the dest of the OR, and 2. the byte of the node
15289// used to provide that x byte. calculateByteProvider finds which node provides
15290// a certain byte of the dest of the OR, and calculateSrcByte takes that node,
15291// and finds an ultimate src and byte position For example: The supported
15292// LoadCombine pattern for vector loads is as follows
15293// t1
15294// or
15295// / \
15296// t2 t3
15297// zext shl
15298// | | \
15299// t4 t5 16
15300// or anyext
15301// / \ |
15302// t6 t7 t8
15303// srl shl or
15304// / | / \ / \
15305// t9 t10 t11 t12 t13 t14
15306// trunc* 8 trunc* 8 and and
15307// | | / | | \
15308// t15 t16 t17 t18 t19 t20
15309// trunc* 255 srl -256
15310// | / \
15311// t15 t15 16
15312//
15313// *In this example, the truncs are from i32->i16
15314//
15315// calculateByteProvider would find t6, t7, t13, and t14 for bytes 0-3
15316// respectively. calculateSrcByte would find (given node) -> ultimate src &
15317// byteposition: t6 -> t15 & 1, t7 -> t16 & 0, t13 -> t15 & 0, t14 -> t15 & 3.
15318// After finding the mapping, we can combine the tree into vperm t15, t16,
15319// 0x05000407
15320
15321// Find the source and byte position from a node.
15322// \p DestByte is the byte position of the dest of the or that the src
15323// ultimately provides. \p SrcIndex is the byte of the src that maps to this
15324// dest of the or byte. \p Depth tracks how many recursive iterations we have
15325// performed.
15326static const std::optional<ByteProvider<SDValue>>
15327calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex = 0,
15328 unsigned Depth = 0) {
15329 // We may need to recursively traverse a series of SRLs
15330 if (Depth >= 6)
15331 return std::nullopt;
15332
15333 if (Op.getValueSizeInBits() < 8)
15334 return std::nullopt;
15335
15336 if (Op.getValueType().isVector())
15337 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15338
15339 switch (Op->getOpcode()) {
15340 case ISD::TRUNCATE: {
15341 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15342 }
15343
15344 case ISD::ANY_EXTEND:
15345 case ISD::SIGN_EXTEND:
15346 case ISD::ZERO_EXTEND:
15348 SDValue NarrowOp = Op->getOperand(0);
15349 auto NarrowVT = NarrowOp.getValueType();
15350 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG) {
15351 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15352 NarrowVT = VTSign->getVT();
15353 }
15354 if (!NarrowVT.isByteSized())
15355 return std::nullopt;
15356 uint64_t NarrowByteWidth = NarrowVT.getStoreSize();
15357
15358 if (SrcIndex >= NarrowByteWidth)
15359 return std::nullopt;
15360 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15361 }
15362
15363 case ISD::SRA:
15364 case ISD::SRL: {
15365 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15366 if (!ShiftOp)
15367 return std::nullopt;
15368
15369 uint64_t BitShift = ShiftOp->getZExtValue();
15370
15371 if (BitShift % 8 != 0)
15372 return std::nullopt;
15373
15374 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15375 if (NewSrcIndex >= Op.getScalarValueSizeInBits() / 8)
15376 return std::nullopt;
15377
15378 return calculateSrcByte(Op->getOperand(0), DestByte, NewSrcIndex,
15379 Depth + 1);
15380 }
15381
15382 default: {
15383 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15384 }
15385 }
15386 llvm_unreachable("fully handled switch");
15387}
15388
15389// For a byte position in the result of an Or, traverse the tree and find the
15390// node (and the byte of the node) which ultimately provides this {Or,
15391// BytePosition}. \p Op is the operand we are currently examining. \p Index is
15392// the byte position of the Op that corresponds with the originally requested
15393// byte of the Or \p Depth tracks how many recursive iterations we have
15394// performed. \p StartingIndex is the originally requested byte of the Or
15395static const std::optional<ByteProvider<SDValue>>
15396calculateByteProvider(const SDValue &Op, unsigned Index, unsigned Depth,
15397 unsigned StartingIndex = 0) {
15398 // Finding Src tree of RHS of or typically requires at least 1 additional
15399 // depth
15400 if (Depth > 6)
15401 return std::nullopt;
15402
15403 unsigned BitWidth = Op.getScalarValueSizeInBits();
15404 if (BitWidth % 8 != 0)
15405 return std::nullopt;
15406 if (Index > BitWidth / 8 - 1)
15407 return std::nullopt;
15408
15409 bool IsVec = Op.getValueType().isVector();
15410 switch (Op.getOpcode()) {
15411 case ISD::OR: {
15412 if (IsVec)
15413 return std::nullopt;
15414
15415 auto RHS = calculateByteProvider(Op.getOperand(1), Index, Depth + 1,
15416 StartingIndex);
15417 if (!RHS)
15418 return std::nullopt;
15419 auto LHS = calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15420 StartingIndex);
15421 if (!LHS)
15422 return std::nullopt;
15423 // A well formed Or will have two ByteProviders for each byte, one of which
15424 // is constant zero
15425 if (!LHS->isConstantZero() && !RHS->isConstantZero())
15426 return std::nullopt;
15427 if (!LHS || LHS->isConstantZero())
15428 return RHS;
15429 if (!RHS || RHS->isConstantZero())
15430 return LHS;
15431 return std::nullopt;
15432 }
15433
15434 case ISD::AND: {
15435 if (IsVec)
15436 return std::nullopt;
15437
15438 auto *BitMaskOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15439 if (!BitMaskOp)
15440 return std::nullopt;
15441
15442 uint32_t BitMask = BitMaskOp->getZExtValue();
15443 // Bits we expect for our StartingIndex
15444 uint32_t IndexMask = 0xFF << (Index * 8);
15445
15446 if ((IndexMask & BitMask) != IndexMask) {
15447 // If the result of the and partially provides the byte, then it
15448 // is not well formatted
15449 if (IndexMask & BitMask)
15450 return std::nullopt;
15452 }
15453
15454 return calculateSrcByte(Op->getOperand(0), StartingIndex, Index);
15455 }
15456
15457 case ISD::FSHR: {
15458 if (IsVec)
15459 return std::nullopt;
15460
15461 // fshr(X,Y,Z): (X << (BW - (Z % BW))) | (Y >> (Z % BW))
15462 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15463 if (!ShiftOp || Op.getValueType().isVector())
15464 return std::nullopt;
15465
15466 uint64_t BitsProvided = Op.getValueSizeInBits();
15467 if (BitsProvided % 8 != 0)
15468 return std::nullopt;
15469
15470 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15471 if (BitShift % 8)
15472 return std::nullopt;
15473
15474 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15475 uint64_t ByteShift = BitShift / 8;
15476
15477 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15478 uint64_t BytesProvided = BitsProvided / 8;
15479 SDValue NextOp = Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15480 NewIndex %= BytesProvided;
15481 return calculateByteProvider(NextOp, NewIndex, Depth + 1, StartingIndex);
15482 }
15483
15484 case ISD::SRA:
15485 case ISD::SRL: {
15486 if (IsVec)
15487 return std::nullopt;
15488
15489 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15490 if (!ShiftOp)
15491 return std::nullopt;
15492
15493 uint64_t BitShift = ShiftOp->getZExtValue();
15494 if (BitShift % 8)
15495 return std::nullopt;
15496
15497 auto BitsProvided = Op.getScalarValueSizeInBits();
15498 if (BitsProvided % 8 != 0)
15499 return std::nullopt;
15500
15501 uint64_t BytesProvided = BitsProvided / 8;
15502 uint64_t ByteShift = BitShift / 8;
15503 if (Index + ByteShift < BytesProvided)
15504 return calculateSrcByte(Op->getOperand(0), StartingIndex,
15505 Index + ByteShift);
15506 // SRA's out-of-range bytes are sign bits, not constant zero.
15507 if (Op.getOpcode() == ISD::SRA)
15508 return std::nullopt;
15510 }
15511
15512 case ISD::SHL: {
15513 if (IsVec)
15514 return std::nullopt;
15515
15516 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15517 if (!ShiftOp)
15518 return std::nullopt;
15519
15520 uint64_t BitShift = ShiftOp->getZExtValue();
15521 if (BitShift % 8 != 0)
15522 return std::nullopt;
15523 uint64_t ByteShift = BitShift / 8;
15524
15525 // If we are shifting by an amount greater than (or equal to)
15526 // the index we are trying to provide, then it provides 0s. If not,
15527 // then this bytes are not definitively 0s, and the corresponding byte
15528 // of interest is Index - ByteShift of the src
15529 return Index < ByteShift
15531 : calculateByteProvider(Op.getOperand(0), Index - ByteShift,
15532 Depth + 1, StartingIndex);
15533 }
15534 case ISD::ANY_EXTEND:
15535 case ISD::SIGN_EXTEND:
15536 case ISD::ZERO_EXTEND:
15538 case ISD::AssertZext:
15539 case ISD::AssertSext: {
15540 if (IsVec)
15541 return std::nullopt;
15542
15543 SDValue NarrowOp = Op->getOperand(0);
15544 unsigned NarrowBitWidth = NarrowOp.getValueSizeInBits();
15545 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG ||
15546 Op->getOpcode() == ISD::AssertZext ||
15547 Op->getOpcode() == ISD::AssertSext) {
15548 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15549 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15550 }
15551 if (NarrowBitWidth % 8 != 0)
15552 return std::nullopt;
15553 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15554
15555 if (Index >= NarrowByteWidth)
15556 return Op.getOpcode() == ISD::ZERO_EXTEND
15557 ? std::optional<ByteProvider<SDValue>>(
15559 : std::nullopt;
15560 return calculateByteProvider(NarrowOp, Index, Depth + 1, StartingIndex);
15561 }
15562
15563 case ISD::TRUNCATE: {
15564 if (IsVec)
15565 return std::nullopt;
15566
15567 uint64_t NarrowByteWidth = BitWidth / 8;
15568
15569 if (NarrowByteWidth >= Index) {
15570 return calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15571 StartingIndex);
15572 }
15573
15574 return std::nullopt;
15575 }
15576
15577 case ISD::CopyFromReg: {
15578 if (BitWidth / 8 > Index)
15579 return calculateSrcByte(Op, StartingIndex, Index);
15580
15581 return std::nullopt;
15582 }
15583
15584 case ISD::LOAD: {
15585 auto *L = cast<LoadSDNode>(Op.getNode());
15586
15587 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15588 if (NarrowBitWidth % 8 != 0)
15589 return std::nullopt;
15590 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15591
15592 // If the width of the load does not reach byte we are trying to provide for
15593 // and it is not a ZEXTLOAD, then the load does not provide for the byte in
15594 // question
15595 if (Index >= NarrowByteWidth) {
15596 return L->getExtensionType() == ISD::ZEXTLOAD
15597 ? std::optional<ByteProvider<SDValue>>(
15599 : std::nullopt;
15600 }
15601
15602 if (NarrowByteWidth > Index) {
15603 return calculateSrcByte(Op, StartingIndex, Index);
15604 }
15605
15606 return std::nullopt;
15607 }
15608
15609 case ISD::BSWAP: {
15610 if (IsVec)
15611 return std::nullopt;
15612
15613 return calculateByteProvider(Op->getOperand(0), BitWidth / 8 - Index - 1,
15614 Depth + 1, StartingIndex);
15615 }
15616
15618 auto *IdxOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15619 if (!IdxOp)
15620 return std::nullopt;
15621 auto VecIdx = IdxOp->getZExtValue();
15622 auto ScalarSize = Op.getScalarValueSizeInBits();
15623 if (ScalarSize < 32)
15624 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15625 return calculateSrcByte(ScalarSize >= 32 ? Op : Op.getOperand(0),
15626 StartingIndex, Index);
15627 }
15628
15629 case AMDGPUISD::PERM: {
15630 if (IsVec)
15631 return std::nullopt;
15632
15633 auto *PermMask = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15634 if (!PermMask)
15635 return std::nullopt;
15636
15637 auto IdxMask =
15638 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15639 if (IdxMask > 0x07 && IdxMask != 0x0c)
15640 return std::nullopt;
15641
15642 auto NextOp = Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15643 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15644
15645 return IdxMask != 0x0c ? calculateSrcByte(NextOp, StartingIndex, NextIndex)
15648 }
15649
15650 default: {
15651 return std::nullopt;
15652 }
15653 }
15654
15655 llvm_unreachable("fully handled switch");
15656}
15657
15658// Returns true if the Operand is a scalar and is 16 bits
15659static bool isExtendedFrom16Bits(SDValue &Operand) {
15660
15661 switch (Operand.getOpcode()) {
15662 case ISD::ANY_EXTEND:
15663 case ISD::SIGN_EXTEND:
15664 case ISD::ZERO_EXTEND: {
15665 auto OpVT = Operand.getOperand(0).getValueType();
15666 return !OpVT.isVector() && OpVT.getSizeInBits() == 16;
15667 }
15668 case ISD::LOAD: {
15669 LoadSDNode *L = cast<LoadSDNode>(Operand.getNode());
15670 auto ExtType = cast<LoadSDNode>(L)->getExtensionType();
15671 if (ExtType == ISD::ZEXTLOAD || ExtType == ISD::SEXTLOAD ||
15672 ExtType == ISD::EXTLOAD) {
15673 auto MemVT = L->getMemoryVT();
15674 return !MemVT.isVector() && MemVT.getSizeInBits() == 16;
15675 }
15676 return L->getMemoryVT().getSizeInBits() == 16;
15677 }
15678 default:
15679 return false;
15680 }
15681}
15682
15683// Returns true if the mask matches consecutive bytes, and the first byte
15684// begins at a power of 2 byte offset from 0th byte
15685static bool addresses16Bits(int Mask) {
15686 int Low8 = Mask & 0xff;
15687 int Hi8 = (Mask & 0xff00) >> 8;
15688
15689 assert(Low8 < 8 && Hi8 < 8);
15690 // Are the bytes contiguous in the order of increasing addresses.
15691 bool IsConsecutive = (Hi8 - Low8 == 1);
15692 // Is the first byte at location that is aligned for 16 bit instructions.
15693 // A counter example is taking 2 consecutive bytes starting at the 8th bit.
15694 // In this case, we still need code to extract the 16 bit operand, so it
15695 // is better to use i8 v_perm
15696 bool Is16Aligned = !(Low8 % 2);
15697
15698 return IsConsecutive && Is16Aligned;
15699}
15700
15701// Do not lower into v_perm if the operands are actually 16 bit
15702// and the selected bits (based on PermMask) correspond with two
15703// easily addressable 16 bit operands.
15705 SDValue &OtherOp) {
15706 int Low16 = PermMask & 0xffff;
15707 int Hi16 = (PermMask & 0xffff0000) >> 16;
15708
15709 auto TempOp = peekThroughBitcasts(Op);
15710 auto TempOtherOp = peekThroughBitcasts(OtherOp);
15711
15712 auto OpIs16Bit =
15713 TempOp.getValueSizeInBits() == 16 || isExtendedFrom16Bits(TempOp);
15714 if (!OpIs16Bit)
15715 return true;
15716
15717 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15718 isExtendedFrom16Bits(TempOtherOp);
15719 if (!OtherOpIs16Bit)
15720 return true;
15721
15722 // Do we cleanly address both
15723 return !addresses16Bits(Low16) || !addresses16Bits(Hi16);
15724}
15725
15727 unsigned DWordOffset) {
15728 SDValue Ret;
15729
15730 auto TypeSize = Src.getValueSizeInBits().getFixedValue();
15731 // ByteProvider must be at least 8 bits
15732 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15733
15734 if (TypeSize <= 32)
15735 return DAG.getBitcastedAnyExtOrTrunc(Src, SL, MVT::i32);
15736
15737 if (Src.getValueType().isVector()) {
15738 auto ScalarTySize = Src.getScalarValueSizeInBits();
15739 auto ScalarTy = Src.getValueType().getScalarType();
15740 if (ScalarTySize == 32) {
15741 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Src,
15742 DAG.getConstant(DWordOffset, SL, MVT::i32));
15743 }
15744 if (ScalarTySize > 32) {
15745 Ret = DAG.getNode(
15746 ISD::EXTRACT_VECTOR_ELT, SL, ScalarTy, Src,
15747 DAG.getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15748 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15749 if (ShiftVal)
15750 Ret = DAG.getNode(ISD::SRL, SL, Ret.getValueType(), Ret,
15751 DAG.getConstant(ShiftVal, SL, MVT::i32));
15752 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15753 }
15754
15755 assert(ScalarTySize < 32);
15756 if (TypeSize % 32 == 0) {
15757 assert(DWordOffset < TypeSize / 32);
15758 SDValue Cast = DAG.getBitcast(
15759 EVT::getVectorVT(*DAG.getContext(), MVT::i32, TypeSize / 32), Src);
15760 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Cast,
15761 DAG.getConstant(DWordOffset, SL, MVT::i32));
15762 }
15763
15764 auto NumElements = TypeSize / ScalarTySize;
15765 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15766 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15767 auto NumElementsIn32 = 32 / ScalarTySize;
15768 auto NumAvailElements = DWordOffset < Trunc32Elements
15769 ? NumElementsIn32
15770 : NumElements - NormalizedTrunc;
15771
15773 DAG.ExtractVectorElements(Src, VecSrcs, DWordOffset * NumElementsIn32,
15774 NumAvailElements);
15775
15776 Ret = DAG.getBuildVector(
15777 MVT::getVectorVT(MVT::getIntegerVT(ScalarTySize), NumAvailElements), SL,
15778 VecSrcs);
15779 return Ret = DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15780 }
15781
15782 /// Scalar Type
15783 auto ShiftVal = 32 * DWordOffset;
15784 Ret = DAG.getNode(ISD::SRL, SL, Src.getValueType(), Src,
15785 DAG.getConstant(ShiftVal, SL, MVT::i32));
15786 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15787}
15788
15790 SelectionDAG &DAG = DCI.DAG;
15791 [[maybe_unused]] EVT VT = N->getValueType(0);
15793
15794 // VT is known to be MVT::i32, so we need to provide 4 bytes.
15795 assert(VT == MVT::i32);
15796 for (int i = 0; i < 4; i++) {
15797 // Find the ByteProvider that provides the ith byte of the result of OR
15798 std::optional<ByteProvider<SDValue>> P =
15799 calculateByteProvider(SDValue(N, 0), i, 0, /*StartingIndex = */ i);
15800 // TODO support constantZero
15801 if (!P || P->isConstantZero())
15802 return SDValue();
15803
15804 PermNodes.push_back(*P);
15805 }
15806 if (PermNodes.size() != 4)
15807 return SDValue();
15808
15809 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15810 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15811 uint64_t PermMask = 0x00000000;
15812 for (size_t i = 0; i < PermNodes.size(); i++) {
15813 auto PermOp = PermNodes[i];
15814 // Since the mask is applied to Src1:Src2, Src1 bytes must be offset
15815 // by sizeof(Src2) = 4
15816 int SrcByteAdjust = 4;
15817
15818 // If the Src uses a byte from a different DWORD, then it corresponds
15819 // with a difference source
15820 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15821 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15822 if (SecondSrc)
15823 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15824 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15825 return SDValue();
15826
15827 // Set the index of the second distinct Src node
15828 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15829 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15830 SrcByteAdjust = 0;
15831 }
15832 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15834 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15835 }
15836 SDLoc DL(N);
15837 SDValue Op = *PermNodes[FirstSrc.first].Src;
15838 Op = getDWordFromOffset(DAG, DL, Op, FirstSrc.second);
15839 assert(Op.getValueSizeInBits() == 32);
15840
15841 // Check that we are not just extracting the bytes in order from an op
15842 if (!SecondSrc) {
15843 int Low16 = PermMask & 0xffff;
15844 int Hi16 = (PermMask & 0xffff0000) >> 16;
15845
15846 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15847 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15848
15849 // The perm op would really just produce Op. So combine into Op
15850 if (WellFormedLow && WellFormedHi)
15851 return DAG.getBitcast(MVT::getIntegerVT(32), Op);
15852 }
15853
15854 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src : Op;
15855
15856 if (SecondSrc) {
15857 OtherOp = getDWordFromOffset(DAG, DL, OtherOp, SecondSrc->second);
15858 assert(OtherOp.getValueSizeInBits() == 32);
15859 }
15860
15861 // Check that we haven't just recreated the same FSHR node.
15862 if (N->getOpcode() == ISD::FSHR &&
15863 (N->getOperand(0) == Op || N->getOperand(0) == OtherOp) &&
15864 (N->getOperand(1) == Op || N->getOperand(1) == OtherOp))
15865 return SDValue();
15866
15867 if (hasNon16BitAccesses(PermMask, Op, OtherOp)) {
15868
15869 assert(Op.getValueType().isByteSized() &&
15870 OtherOp.getValueType().isByteSized());
15871
15872 // If the ultimate src is less than 32 bits, then we will only be
15873 // using bytes 0: Op.getValueSizeInBytes() - 1 in the or.
15874 // CalculateByteProvider would not have returned Op as source if we
15875 // used a byte that is outside its ValueType. Thus, we are free to
15876 // ANY_EXTEND as the extended bits are dont-cares.
15877 Op = DAG.getBitcastedAnyExtOrTrunc(Op, DL, MVT::i32);
15878 OtherOp = DAG.getBitcastedAnyExtOrTrunc(OtherOp, DL, MVT::i32);
15879
15880 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op, OtherOp,
15881 DAG.getConstant(PermMask, DL, MVT::i32));
15882 }
15883 return SDValue();
15884}
15885
15886SDValue SITargetLowering::performOrCombine(SDNode *N,
15887 DAGCombinerInfo &DCI) const {
15888 SelectionDAG &DAG = DCI.DAG;
15889 SDValue LHS = N->getOperand(0);
15890 SDValue RHS = N->getOperand(1);
15891
15892 EVT VT = N->getValueType(0);
15893 if (VT == MVT::i1) {
15894 // or (fp_class x, c1), (fp_class x, c2) -> fp_class x, (c1 | c2)
15895 if (LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15896 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15897 SDValue Src = LHS.getOperand(0);
15898 if (Src != RHS.getOperand(0))
15899 return SDValue();
15900
15901 const ConstantSDNode *CLHS = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
15902 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
15903 if (!CLHS || !CRHS)
15904 return SDValue();
15905
15906 // Only 10 bits are used.
15907 static const uint32_t MaxMask = 0x3ff;
15908
15909 uint32_t NewMask =
15910 (CLHS->getZExtValue() | CRHS->getZExtValue()) & MaxMask;
15911 SDLoc DL(N);
15912 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, Src,
15913 DAG.getConstant(NewMask, DL, MVT::i32));
15914 }
15915
15916 return SDValue();
15917 }
15918
15919 // or (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
15921 LHS.getOpcode() == AMDGPUISD::PERM &&
15922 isa<ConstantSDNode>(LHS.getOperand(2))) {
15923 uint32_t Sel = getConstantPermuteMask(N->getConstantOperandVal(1));
15924 if (!Sel)
15925 return SDValue();
15926
15927 Sel |= LHS.getConstantOperandVal(2);
15928 SDLoc DL(N);
15929 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15930 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
15931 }
15932
15933 // or (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
15934 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
15935 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
15936 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15937
15938 // If all the uses of an or need to extract the individual elements, do not
15939 // attempt to lower into v_perm
15940 auto usesCombinedOperand = [](SDNode *OrUse) {
15941 // If we have any non-vectorized use, then it is a candidate for v_perm
15942 if (OrUse->getOpcode() != ISD::BITCAST ||
15943 !OrUse->getValueType(0).isVector())
15944 return true;
15945
15946 // If we have any non-vectorized use, then it is a candidate for v_perm
15947 for (auto *VUser : OrUse->users()) {
15948 if (!VUser->getValueType(0).isVector())
15949 return true;
15950
15951 // If the use of a vector is a store, then combining via a v_perm
15952 // is beneficial.
15953 // TODO -- whitelist more uses
15954 for (auto VectorwiseOp : {ISD::STORE, ISD::CopyToReg, ISD::CopyFromReg})
15955 if (VUser->getOpcode() == VectorwiseOp)
15956 return true;
15957 }
15958 return false;
15959 };
15960
15961 if (!any_of(N->users(), usesCombinedOperand))
15962 return SDValue();
15963
15964 uint32_t LHSMask = getPermuteMask(LHS);
15965 uint32_t RHSMask = getPermuteMask(RHS);
15966
15967 if (LHSMask != ~0u && RHSMask != ~0u) {
15968 // Canonicalize the expression in an attempt to have fewer unique masks
15969 // and therefore fewer registers used to hold the masks.
15970 if (LHSMask > RHSMask) {
15971 std::swap(LHSMask, RHSMask);
15972 std::swap(LHS, RHS);
15973 }
15974
15975 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15976 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15977 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15978 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15979
15980 // Check of we need to combine values from two sources within a byte.
15981 if (!(LHSUsedLanes & RHSUsedLanes) &&
15982 // If we select high and lower word keep it for SDWA.
15983 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15984 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15985 // Kill zero bytes selected by other mask. Zero value is 0xc.
15986 LHSMask &= ~RHSUsedLanes;
15987 RHSMask &= ~LHSUsedLanes;
15988 // Add 4 to each active LHS lane
15989 LHSMask |= LHSUsedLanes & 0x04040404;
15990 // Combine masks
15991 uint32_t Sel = LHSMask | RHSMask;
15992 SDLoc DL(N);
15993
15994 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15995 RHS.getOperand(0),
15996 DAG.getConstant(Sel, DL, MVT::i32));
15997 }
15998 }
15999 if (LHSMask == ~0u || RHSMask == ~0u) {
16000 if (SDValue Perm = matchPERM(N, DCI))
16001 return Perm;
16002 }
16003 }
16004
16005 // Detect identity v2i32 OR and replace with identity source node.
16006 // Specifically an Or that has operands constructed from the same source node
16007 // via extract_vector_elt and build_vector. I.E.
16008 // v2i32 or(
16009 // v2i32 build_vector(
16010 // i32 extract_elt(%IdentitySrc, 0),
16011 // i32 0
16012 // ),
16013 // v2i32 build_vector(
16014 // i32 0,
16015 // i32 extract_elt(%IdentitySrc, 1)
16016 // ) )
16017 // =>
16018 // v2i32 %IdentitySrc
16019
16020 if (VT == MVT::v2i32 && LHS->getOpcode() == ISD::BUILD_VECTOR &&
16021 RHS->getOpcode() == ISD::BUILD_VECTOR) {
16022
16023 ConstantSDNode *LC = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
16024 ConstantSDNode *RC = dyn_cast<ConstantSDNode>(RHS->getOperand(0));
16025
16026 // Test for and normalise build vectors.
16027 if (LC && RC && LC->getZExtValue() == 0 && RC->getZExtValue() == 0) {
16028
16029 // Get the extract_vector_element operands.
16030 SDValue LEVE = LHS->getOperand(0);
16031 SDValue REVE = RHS->getOperand(1);
16032
16033 if (LEVE->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
16035 // Check that different elements from the same vector are
16036 // extracted.
16037 if (LEVE->getOperand(0) == REVE->getOperand(0) &&
16038 LEVE->getOperand(1) != REVE->getOperand(1)) {
16039 SDValue IdentitySrc = LEVE.getOperand(0);
16040 return IdentitySrc;
16041 }
16042 }
16043 }
16044 }
16045
16046 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
16047 return SDValue();
16048
16049 // TODO: This could be a generic combine with a predicate for extracting the
16050 // high half of an integer being free.
16051
16052 // (or i64:x, (zero_extend i32:y)) ->
16053 // i64 (bitcast (v2i32 build_vector (or i32:y, lo_32(x)), hi_32(x)))
16054 if (LHS.getOpcode() == ISD::ZERO_EXTEND &&
16055 RHS.getOpcode() != ISD::ZERO_EXTEND)
16056 std::swap(LHS, RHS);
16057
16058 if (RHS.getOpcode() == ISD::ZERO_EXTEND) {
16059 SDValue ExtSrc = RHS.getOperand(0);
16060 EVT SrcVT = ExtSrc.getValueType();
16061 if (SrcVT == MVT::i32) {
16062 SDLoc SL(N);
16063 auto [LowLHS, HiBits] = split64BitValue(LHS, DAG);
16064 SDValue LowOr = DAG.getNode(ISD::OR, SL, MVT::i32, LowLHS, ExtSrc);
16065
16066 DCI.AddToWorklist(LowOr.getNode());
16067 DCI.AddToWorklist(HiBits.getNode());
16068
16069 SDValue Vec =
16070 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, LowOr, HiBits);
16071 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
16072 }
16073 }
16074
16075 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
16076 if (CRHS) {
16077 if (SDValue Split = splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::OR,
16078 N->getOperand(0), CRHS))
16079 return Split;
16080 }
16081
16082 return SDValue();
16083}
16084
16085SDValue SITargetLowering::performXorCombine(SDNode *N,
16086 DAGCombinerInfo &DCI) const {
16087 if (SDValue RV = reassociateScalarOps(N, DCI.DAG))
16088 return RV;
16089
16090 SDValue LHS = N->getOperand(0);
16091 SDValue RHS = N->getOperand(1);
16092
16093 const ConstantSDNode *CRHS = isConstOrConstSplat(RHS);
16094 SelectionDAG &DAG = DCI.DAG;
16095
16096 EVT VT = N->getValueType(0);
16097 if (CRHS && VT == MVT::i64) {
16098 if (SDValue Split =
16099 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::XOR, LHS, CRHS))
16100 return Split;
16101 }
16102
16103 // v2i32 (xor (vselect cc, x, y), K) ->
16104 // (v2i32 svelect cc, (xor x, K), (xor y, K)) This enables the xor to be
16105 // replaced with source modifiers when the select is lowered to CNDMASK.
16106 unsigned Opc = LHS.getOpcode();
16107 if (((Opc == ISD::VSELECT && VT == MVT::v2i32) ||
16108 (Opc == ISD::SELECT && VT == MVT::i64)) &&
16109 CRHS && CRHS->getAPIntValue().isSignMask()) {
16110 SDValue CC = LHS->getOperand(0);
16111 SDValue TRUE = LHS->getOperand(1);
16112 SDValue FALSE = LHS->getOperand(2);
16113 SDValue XTrue = DAG.getNode(ISD::XOR, SDLoc(N), VT, TRUE, RHS);
16114 SDValue XFalse = DAG.getNode(ISD::XOR, SDLoc(N), VT, FALSE, RHS);
16115 SDValue XSelect =
16116 DAG.getNode(ISD::VSELECT, SDLoc(N), VT, CC, XTrue, XFalse);
16117 return XSelect;
16118 }
16119
16120 // Make sure to apply the 64-bit constant splitting fold before trying to fold
16121 // fneg-like xors into 64-bit select.
16122 if (LHS.getOpcode() == ISD::SELECT && VT == MVT::i32) {
16123 // This looks like an fneg, try to fold as a source modifier.
16124 if (CRHS && CRHS->getAPIntValue().isSignMask() &&
16126 // xor (select c, a, b), 0x80000000 ->
16127 // bitcast (select c, (fneg (bitcast a)), (fneg (bitcast b)))
16128 SDLoc DL(N);
16129 SDValue CastLHS =
16130 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(1));
16131 SDValue CastRHS =
16132 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(2));
16133 SDValue FNegLHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastLHS);
16134 SDValue FNegRHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastRHS);
16135 SDValue NewSelect = DAG.getNode(ISD::SELECT, DL, MVT::f32,
16136 LHS->getOperand(0), FNegLHS, FNegRHS);
16137 return DAG.getNode(ISD::BITCAST, DL, VT, NewSelect);
16138 }
16139 }
16140
16141 return SDValue();
16142}
16143
16144SDValue
16145SITargetLowering::performZeroOrAnyExtendCombine(SDNode *N,
16146 DAGCombinerInfo &DCI) const {
16147 if (!Subtarget->has16BitInsts() ||
16148 DCI.getDAGCombineLevel() < AfterLegalizeTypes)
16149 return SDValue();
16150
16151 EVT VT = N->getValueType(0);
16152 if (VT != MVT::i32)
16153 return SDValue();
16154
16155 SDValue Src = N->getOperand(0);
16156 if (Src.getValueType() != MVT::i16)
16157 return SDValue();
16158
16159 if (!Src->hasOneUse())
16160 return SDValue();
16161
16162 if (SDValue Ext = performExtendTruncShiftCombine(N, DCI))
16163 return Ext;
16164
16165 // TODO: We bail out below if SrcOffset is not in the first dword (>= 4). It's
16166 // possible we're missing out on some combine opportunities, but we'd need to
16167 // weigh the cost of extracting the byte from the upper dwords.
16168
16169 std::optional<ByteProvider<SDValue>> BP0 =
16170 calculateByteProvider(SDValue(N, 0), 0, 0, 0);
16171 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
16172 return SDValue();
16173 SDValue V0 = *BP0->Src;
16174
16175 std::optional<ByteProvider<SDValue>> BP1 =
16176 calculateByteProvider(SDValue(N, 0), 1, 0, 1);
16177 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
16178 return SDValue();
16179
16180 SDValue V1 = *BP1->Src;
16181
16182 if (V0 == V1)
16183 return SDValue();
16184
16185 SelectionDAG &DAG = DCI.DAG;
16186 SDLoc DL(N);
16187 uint32_t PermMask = 0x0c0c0c0c;
16188 if (V0) {
16189 V0 = getDWordFromOffset(DAG, DL, V0, /*DWordOffset=*/0);
16190 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
16191 }
16192
16193 if (V1) {
16194 V1 = getDWordFromOffset(DAG, DL, V1, /*DWordOffset=*/0);
16195 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
16196 }
16197
16198 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, V0, V1,
16199 DAG.getConstant(PermMask, DL, MVT::i32));
16200}
16201
16202// zext (srl (trunc x), c) => and (srl x, c), lowbits
16203// aext (srl (trunc x), c) => and (srl x, c), lowbits
16204// sext (sra (trunc x), 8) => sext_inreg (srl x, 8), i8
16205SDValue
16206SITargetLowering::performExtendTruncShiftCombine(SDNode *N,
16207 DAGCombinerInfo &DCI) const {
16208 if (DCI.getDAGCombineLevel() < AfterLegalizeTypes)
16209 return SDValue();
16210
16211 const unsigned Opc = N->getOpcode();
16212 const bool IsSigned = Opc == ISD::SIGN_EXTEND;
16213 SDValue Src = N->getOperand(0);
16214 if (N->getValueType(0) != MVT::i32 || Src.getValueType() != MVT::i16 ||
16215 Src.getOpcode() != (IsSigned ? ISD::SRA : ISD::SRL) || !Src.hasOneUse() ||
16216 Src.getOperand(0).getOpcode() != ISD::TRUNCATE)
16217 return SDValue();
16218
16219 // A uniform i16 srl is promoted to i32 later and yields the same nodes.
16220 // Skip it so that the node order, and with it the schedule, stays the same.
16221 if (!IsSigned && !Src->isDivergent())
16222 return SDValue();
16223
16224 SDValue X = Src.getOperand(0).getOperand(0);
16225 auto *Shift = dyn_cast<ConstantSDNode>(Src.getOperand(1));
16226 if (X.getValueType() != MVT::i32 || !Shift || Shift->getZExtValue() == 0 ||
16227 Shift->getZExtValue() >= 16 || (IsSigned && Shift->getZExtValue() != 8))
16228 return SDValue();
16229
16230 SelectionDAG &DAG = DCI.DAG;
16231 SDLoc SL(N);
16232 const unsigned Width = 16 - Shift->getZExtValue();
16233 SDValue Srl = DAG.getNode(
16234 ISD::SRL, SL, MVT::i32, X,
16235 DAG.getShiftAmountConstant(Shift->getZExtValue(), MVT::i32, SL));
16236 if (IsSigned)
16237 return DAG.getNode(ISD::SIGN_EXTEND_INREG, SL, MVT::i32, Srl,
16238 DAG.getValueType(MVT::i8));
16239 return DAG.getNode(
16240 ISD::AND, SL, MVT::i32, Srl,
16241 DAG.getConstant(maskTrailingOnes<uint32_t>(Width), SL, MVT::i32));
16242}
16243
16244SDValue
16245SITargetLowering::performSignExtendInRegCombine(SDNode *N,
16246 DAGCombinerInfo &DCI) const {
16247 SDValue Src = N->getOperand(0);
16248 auto *VTSign = cast<VTSDNode>(N->getOperand(1));
16249
16250 // Combine s_buffer_load_u8 or s_buffer_load_u16 with sext and replace them
16251 // with s_buffer_load_i8 and s_buffer_load_i16 respectively.
16252 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
16253 VTSign->getVT() == MVT::i8) ||
16254 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
16255 VTSign->getVT() == MVT::i16))) {
16256 assert(Subtarget->hasScalarSubwordLoads() &&
16257 "s_buffer_load_{u8, i8} are supported "
16258 "in GFX12 (or newer) architectures.");
16259 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
16260 ? AMDGPUISD::SBUFFER_LOAD_BYTE
16261 : AMDGPUISD::SBUFFER_LOAD_SHORT;
16262 SDLoc DL(N);
16263 SDVTList ResList =
16264 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16265 SDValue Ops[] = {
16266 Src.getOperand(0), // Chain
16267 Src.getOperand(1), // source register
16268 Src.getOperand(2), // offset
16269 Src.getOperand(3) // cachePolicy
16270 };
16271 auto *M = cast<MemSDNode>(Src);
16272 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
16273 Opc, DL, ResList, Ops, M->getMemoryVT(), M->getMemOperand());
16274 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.getValue(1)}, DL);
16275 }
16276 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
16277 VTSign->getVT() == MVT::i8) ||
16278 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
16279 VTSign->getVT() == MVT::i16)) &&
16280 Src.hasOneUse()) {
16281 auto *M = cast<MemSDNode>(Src);
16282 SDValue Ops[] = {Src.getOperand(0), // Chain
16283 Src.getOperand(1), // rsrc
16284 Src.getOperand(2), // vindex
16285 Src.getOperand(3), // voffset
16286 Src.getOperand(4), // soffset
16287 Src.getOperand(5), // offset
16288 Src.getOperand(6), Src.getOperand(7)};
16289 // replace with BUFFER_LOAD_BYTE/SHORT
16290 SDVTList ResList =
16291 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
16292 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
16293 ? AMDGPUISD::BUFFER_LOAD_BYTE
16294 : AMDGPUISD::BUFFER_LOAD_SHORT;
16295 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
16296 Opc, SDLoc(N), ResList, Ops, M->getMemoryVT(), M->getMemOperand());
16297 return DCI.DAG.getMergeValues(
16298 {BufferLoadSignExt, BufferLoadSignExt.getValue(1)}, SDLoc(N));
16299 }
16300 return SDValue();
16301}
16302
16303SDValue SITargetLowering::performClassCombine(SDNode *N,
16304 DAGCombinerInfo &DCI) const {
16305 SelectionDAG &DAG = DCI.DAG;
16306 SDValue Mask = N->getOperand(1);
16307
16308 // fp_class x, 0 -> false
16309 if (isNullConstant(Mask))
16310 return DAG.getConstant(0, SDLoc(N), MVT::i1);
16311
16312 if (N->getOperand(0).isUndef())
16313 return DAG.getUNDEF(MVT::i1);
16314
16315 return SDValue();
16316}
16317
16318SDValue SITargetLowering::performRcpCombine(SDNode *N,
16319 DAGCombinerInfo &DCI) const {
16320 EVT VT = N->getValueType(0);
16321 SDValue N0 = N->getOperand(0);
16322
16323 if (N0.isUndef()) {
16324 return DCI.DAG.getConstantFP(APFloat::getQNaN(VT.getFltSemantics()),
16325 SDLoc(N), VT);
16326 }
16327
16328 // TODO: Could handle f32 + amdgcn.sqrt but probably never reaches here.
16329 if ((VT == MVT::f16 && N0.getOpcode() == ISD::FSQRT) &&
16330 N->getFlags().hasAllowContract() && N0->getFlags().hasAllowContract()) {
16331 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(N), VT, N0.getOperand(0),
16332 N->getFlags());
16333 }
16334
16336}
16337
16339 SDNodeFlags UserFlags,
16340 unsigned MaxDepth) const {
16341 EVT VT = Op.getValueType();
16342 assert(VT.isFloatingPoint() &&
16343 "expected a floating-point value to query canonicality of");
16344 return isCanonicalized(DAG, Op, VT.getScalarType(), UserFlags, MaxDepth);
16345}
16346
16348 EVT QueryVT, SDNodeFlags UserFlags,
16349 unsigned MaxDepth) const {
16350 assert(QueryVT.isFloatingPoint() && !QueryVT.isVector() &&
16351 "QueryVT must be a floating-point scalar type");
16352 EVT VT = Op.getValueType();
16353 if (VT.isFloatingPoint() && VT.getScalarType() != QueryVT)
16354 return false;
16355
16356 unsigned Opcode = Op.getOpcode();
16357 if (Opcode == ISD::FCANONICALIZE)
16358 return true;
16359
16360 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16361 const auto &F = CFP->getValueAPF();
16362 if (F.isNaN() && F.isSignaling())
16363 return false;
16364 if (!F.isDenormal())
16365 return true;
16366
16367 DenormalMode Mode =
16368 DAG.getMachineFunction().getDenormalMode(F.getSemantics());
16369 return Mode == DenormalMode::getIEEE();
16370 }
16371
16372 // If source is a result of another standard FP operation it is already in
16373 // canonical form.
16374 if (MaxDepth == 0)
16375 return false;
16376
16377 switch (Opcode) {
16378 // These will flush denorms if required.
16379 case ISD::FADD:
16380 case ISD::FSUB:
16381 case ISD::FMUL:
16382 case ISD::FCEIL:
16383 case ISD::FFLOOR:
16384 case ISD::FMA:
16385 case ISD::FMAD:
16386 case ISD::FSQRT:
16387 case ISD::FDIV:
16388 case ISD::FREM:
16389 case ISD::FP_ROUND:
16390 case ISD::FP_EXTEND:
16391 case ISD::FP16_TO_FP:
16392 case ISD::FP_TO_FP16:
16393 case ISD::BF16_TO_FP:
16394 case ISD::FP_TO_BF16:
16395 case ISD::FLDEXP:
16396 case AMDGPUISD::FMUL_LEGACY:
16397 case AMDGPUISD::FMAD_FTZ:
16398 case AMDGPUISD::RCP:
16399 case AMDGPUISD::RSQ:
16400 case AMDGPUISD::RSQ_CLAMP:
16401 case AMDGPUISD::RCP_LEGACY:
16402 case AMDGPUISD::RCP_IFLAG:
16403 case AMDGPUISD::LOG:
16404 case AMDGPUISD::EXP:
16405 case AMDGPUISD::DIV_SCALE:
16406 case AMDGPUISD::DIV_FMAS:
16407 case AMDGPUISD::DIV_FIXUP:
16408 case AMDGPUISD::FRACT:
16409 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16410 case AMDGPUISD::CVT_F32_UBYTE0:
16411 case AMDGPUISD::CVT_F32_UBYTE1:
16412 case AMDGPUISD::CVT_F32_UBYTE2:
16413 case AMDGPUISD::CVT_F32_UBYTE3:
16414 case AMDGPUISD::FP_TO_FP16:
16415 case AMDGPUISD::SIN_HW:
16416 case AMDGPUISD::COS_HW:
16417 return true;
16418
16419 // It can/will be lowered or combined as a bit operation.
16420 // Need to check their input recursively to handle.
16421 case ISD::FNEG:
16422 case ISD::FABS:
16423 case ISD::FCOPYSIGN:
16424 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16425 MaxDepth - 1);
16426
16427 case ISD::AND:
16428 if (Op.getValueType() == MVT::i32) {
16429 // Be careful as we only know it is a bitcast floating point type. It
16430 // could be f32, v2f16, we have no way of knowing. Luckily the constant
16431 // value that we optimize for, which comes up in fp32 to bf16 conversions,
16432 // is valid to optimize for all types.
16433 if (auto *RHS = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
16434 if (RHS->getZExtValue() == 0xffff0000) {
16435 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16436 MaxDepth - 1);
16437 }
16438 }
16439 }
16440 break;
16441
16442 case ISD::FSIN:
16443 case ISD::FCOS:
16444 case ISD::FSINCOS:
16445 return Op.getValueType().getScalarType() != MVT::f16;
16446
16447 case ISD::FMINNUM:
16448 case ISD::FMAXNUM:
16449 case ISD::FMINNUM_IEEE:
16450 case ISD::FMAXNUM_IEEE:
16451 case ISD::FMINIMUM:
16452 case ISD::FMAXIMUM:
16453 case ISD::FMINIMUMNUM:
16454 case ISD::FMAXIMUMNUM:
16455 case AMDGPUISD::CLAMP:
16456 case AMDGPUISD::FMED3:
16457 case AMDGPUISD::FMAX3:
16458 case AMDGPUISD::FMIN3:
16459 case AMDGPUISD::FMAXIMUM3:
16460 case AMDGPUISD::FMINIMUM3: {
16461 // FIXME: Shouldn't treat the generic operations different based these.
16462 // However, we aren't really required to flush the result from
16463 // minnum/maxnum..
16464
16465 // snans will be quieted, so we only need to worry about denormals.
16466 if (Subtarget->supportsMinMaxDenormModes() ||
16467 // FIXME: denormalsEnabledForType is broken for dynamic
16468 denormalsEnabledForType(DAG, Op.getValueType()))
16469 return true;
16470
16471 // Flushing may be required.
16472 // In pre-GFX9 targets V_MIN_F32 and others do not flush denorms. For such
16473 // targets need to check their input recursively.
16474
16475 // FIXME: Does this apply with clamp? It's implemented with max.
16476 for (unsigned I = 0, E = Op.getNumOperands(); I != E; ++I) {
16477 if (!isCanonicalized(DAG, Op.getOperand(I), QueryVT, UserFlags,
16478 MaxDepth - 1))
16479 return false;
16480 }
16481
16482 return true;
16483 }
16484 case ISD::SELECT: {
16485 return isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16486 MaxDepth - 1) &&
16487 isCanonicalized(DAG, Op.getOperand(2), QueryVT, UserFlags,
16488 MaxDepth - 1);
16489 }
16490 case ISD::BUILD_VECTOR: {
16491 for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
16492 SDValue SrcOp = Op.getOperand(i);
16493 if (!isCanonicalized(DAG, SrcOp, QueryVT, UserFlags, MaxDepth - 1))
16494 return false;
16495 }
16496
16497 return true;
16498 }
16501 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16502 MaxDepth - 1);
16503 }
16505 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16506 MaxDepth - 1) &&
16507 isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16508 MaxDepth - 1);
16509 }
16510 case ISD::POISON:
16511 return true;
16512 case ISD::UNDEF:
16513 // Could be anything.
16514 return false;
16515
16516 case ISD::BITCAST: {
16517 // Carry QueryVT through the bitcast unchanged. The top-of-function guard
16518 // rejects a source whose FP format differs from the consumed type, so a
16519 // value canonical in one FP format is not assumed canonical in another.
16520 SDValue Src = peekThroughBitcasts(Op.getOperand(0));
16521 return isCanonicalized(DAG, Src, QueryVT, UserFlags, MaxDepth - 1);
16522 }
16523 case ISD::TRUNCATE: {
16524 // Hack round the mess we make when legalizing extract_vector_elt
16525 if (Op.getValueType() == MVT::i16) {
16526 SDValue TruncSrc = Op.getOperand(0);
16527 if (TruncSrc.getValueType() == MVT::i32 &&
16528 TruncSrc.getOpcode() == ISD::BITCAST &&
16529 TruncSrc.getOperand(0).getValueType() == MVT::v2f16) {
16530 return isCanonicalized(DAG, TruncSrc.getOperand(0), QueryVT, UserFlags,
16531 MaxDepth - 1);
16532 }
16533 }
16534 return false;
16535 }
16537 unsigned IntrinsicID = Op.getConstantOperandVal(0);
16538 // TODO: Handle more intrinsics
16539 switch (IntrinsicID) {
16540 case Intrinsic::amdgcn_cvt_pkrtz:
16541 case Intrinsic::amdgcn_cubeid:
16542 case Intrinsic::amdgcn_frexp_mant:
16543 case Intrinsic::amdgcn_fdot2:
16544 case Intrinsic::amdgcn_rcp:
16545 case Intrinsic::amdgcn_rsq:
16546 case Intrinsic::amdgcn_rsq_clamp:
16547 case Intrinsic::amdgcn_rcp_legacy:
16548 case Intrinsic::amdgcn_rsq_legacy:
16549 case Intrinsic::amdgcn_trig_preop:
16550 case Intrinsic::amdgcn_tanh:
16551 case Intrinsic::amdgcn_log:
16552 case Intrinsic::amdgcn_exp2:
16553 case Intrinsic::amdgcn_sqrt:
16554 return true;
16555 default:
16556 break;
16557 }
16558
16559 break;
16560 }
16561 default:
16562 break;
16563 }
16564
16565 // FIXME: denormalsEnabledForType is broken for dynamic
16566 return denormalsEnabledForType(DAG, Op.getValueType()) &&
16567 (UserFlags.hasNoNaNs() || DAG.isKnownNeverSNaN(Op));
16568}
16569
16571 unsigned MaxDepth) const {
16572 const MachineRegisterInfo &MRI = MF.getRegInfo();
16573 MachineInstr *MI = MRI.getVRegDef(Reg);
16574 unsigned Opcode = MI->getOpcode();
16575
16576 if (Opcode == AMDGPU::G_FCANONICALIZE)
16577 return true;
16578
16579 std::optional<FPValueAndVReg> FCR;
16580 // Constant splat (can be padded with undef) or scalar constant.
16582 if (FCR->Value.isSignaling())
16583 return false;
16584 if (!FCR->Value.isDenormal())
16585 return true;
16586
16587 DenormalMode Mode = MF.getDenormalMode(FCR->Value.getSemantics());
16588 return Mode == DenormalMode::getIEEE();
16589 }
16590
16591 if (MaxDepth == 0)
16592 return false;
16593
16594 switch (Opcode) {
16595 case AMDGPU::G_FADD:
16596 case AMDGPU::G_FSUB:
16597 case AMDGPU::G_FMUL:
16598 case AMDGPU::G_FCEIL:
16599 case AMDGPU::G_FFLOOR:
16600 case AMDGPU::G_FRINT:
16601 case AMDGPU::G_FNEARBYINT:
16602 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16603 case AMDGPU::G_INTRINSIC_TRUNC:
16604 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16605 case AMDGPU::G_FMA:
16606 case AMDGPU::G_FMAD:
16607 case AMDGPU::G_FSQRT:
16608 case AMDGPU::G_FDIV:
16609 case AMDGPU::G_FREM:
16610 case AMDGPU::G_FPOW:
16611 case AMDGPU::G_FPEXT:
16612 case AMDGPU::G_FLOG:
16613 case AMDGPU::G_FLOG2:
16614 case AMDGPU::G_FLOG10:
16615 case AMDGPU::G_FPTRUNC:
16616 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16617 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16618 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16619 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16620 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16621 return true;
16622 case AMDGPU::G_FNEG:
16623 case AMDGPU::G_FABS:
16624 case AMDGPU::G_FCOPYSIGN:
16625 return isCanonicalized(MI->getOperand(1).getReg(), MF, MaxDepth - 1);
16626 case AMDGPU::G_FMINNUM:
16627 case AMDGPU::G_FMAXNUM:
16628 case AMDGPU::G_FMINNUM_IEEE:
16629 case AMDGPU::G_FMAXNUM_IEEE:
16630 case AMDGPU::G_FMINIMUM:
16631 case AMDGPU::G_FMAXIMUM:
16632 case AMDGPU::G_FMINIMUMNUM:
16633 case AMDGPU::G_FMAXIMUMNUM: {
16634 if (Subtarget->supportsMinMaxDenormModes() ||
16635 // FIXME: denormalsEnabledForType is broken for dynamic
16636 denormalsEnabledForType(MRI.getType(Reg), MF))
16637 return true;
16638
16639 [[fallthrough]];
16640 }
16641 case AMDGPU::G_BUILD_VECTOR:
16642 for (const MachineOperand &MO : llvm::drop_begin(MI->operands()))
16643 if (!isCanonicalized(MO.getReg(), MF, MaxDepth - 1))
16644 return false;
16645 return true;
16646 case AMDGPU::G_INTRINSIC:
16647 case AMDGPU::G_INTRINSIC_CONVERGENT:
16648 switch (cast<GIntrinsic>(MI)->getIntrinsicID()) {
16649 case Intrinsic::amdgcn_fmul_legacy:
16650 case Intrinsic::amdgcn_fmad_ftz:
16651 case Intrinsic::amdgcn_sqrt:
16652 case Intrinsic::amdgcn_fmed3:
16653 case Intrinsic::amdgcn_sin:
16654 case Intrinsic::amdgcn_cos:
16655 case Intrinsic::amdgcn_log:
16656 case Intrinsic::amdgcn_exp2:
16657 case Intrinsic::amdgcn_log_clamp:
16658 case Intrinsic::amdgcn_rcp:
16659 case Intrinsic::amdgcn_rcp_legacy:
16660 case Intrinsic::amdgcn_rsq:
16661 case Intrinsic::amdgcn_rsq_clamp:
16662 case Intrinsic::amdgcn_rsq_legacy:
16663 case Intrinsic::amdgcn_div_scale:
16664 case Intrinsic::amdgcn_div_fmas:
16665 case Intrinsic::amdgcn_div_fixup:
16666 case Intrinsic::amdgcn_fract:
16667 case Intrinsic::amdgcn_cvt_pkrtz:
16668 case Intrinsic::amdgcn_cubeid:
16669 case Intrinsic::amdgcn_cubema:
16670 case Intrinsic::amdgcn_cubesc:
16671 case Intrinsic::amdgcn_cubetc:
16672 case Intrinsic::amdgcn_frexp_mant:
16673 case Intrinsic::amdgcn_fdot2:
16674 case Intrinsic::amdgcn_trig_preop:
16675 case Intrinsic::amdgcn_tanh:
16676 return true;
16677 default:
16678 break;
16679 }
16680
16681 [[fallthrough]];
16682 default:
16683 return false;
16684 }
16685
16686 llvm_unreachable("invalid operation");
16687}
16688
16689// Constant fold canonicalize.
16690SDValue SITargetLowering::getCanonicalConstantFP(SelectionDAG &DAG,
16691 const SDLoc &SL, EVT VT,
16692 const APFloat &C) const {
16693 // Flush denormals to 0 if not enabled.
16694 if (C.isDenormal()) {
16695 DenormalMode Mode =
16696 DAG.getMachineFunction().getDenormalMode(C.getSemantics());
16697 if (Mode == DenormalMode::getPreserveSign()) {
16698 return DAG.getConstantFP(
16699 APFloat::getZero(C.getSemantics(), C.isNegative()), SL, VT);
16700 }
16701
16702 if (Mode != DenormalMode::getIEEE())
16703 return SDValue();
16704 }
16705
16706 if (C.isNaN()) {
16707 if (C.isSignaling()) {
16708 // Quiet a signaling NaN.
16709 return DAG.getConstantFP(C.makeQuiet(), SL, VT);
16710 }
16711 }
16712
16713 // Already canonical.
16714 return DAG.getConstantFP(C, SL, VT);
16715}
16716
16718 return Op.isUndef() || isa<ConstantFPSDNode>(Op);
16719}
16720
16721SDValue
16722SITargetLowering::performFCanonicalizeCombine(SDNode *N,
16723 DAGCombinerInfo &DCI) const {
16724 SelectionDAG &DAG = DCI.DAG;
16725 SDValue N0 = N->getOperand(0);
16726 EVT VT = N->getValueType(0);
16727
16728 // fcanonicalize undef -> qnan
16729 if (N0.isUndef()) {
16731 return DAG.getConstantFP(QNaN, SDLoc(N), VT);
16732 }
16733
16734 if (ConstantFPSDNode *CFP = isConstOrConstSplatFP(N0))
16735 return getCanonicalConstantFP(DAG, SDLoc(N), VT, CFP->getValueAPF());
16736
16737 // fcanonicalize (build_vector x, k) -> build_vector (fcanonicalize x),
16738 // (fcanonicalize k)
16739 //
16740 // fcanonicalize (build_vector x, undef) -> build_vector (fcanonicalize x), 0
16741
16742 // TODO: This could be better with wider vectors that will be split to v2f16,
16743 // and to consider uses since there aren't that many packed operations.
16744 if (N0.getOpcode() == ISD::BUILD_VECTOR && N0.getNumOperands() == 2 &&
16745 isTypeLegal(VT)) {
16746 SDLoc SL(N);
16747 SDValue NewElts[2];
16748 SDValue Lo = N0.getOperand(0);
16749 SDValue Hi = N0.getOperand(1);
16750 EVT EltVT = Lo.getValueType();
16751
16752 // Only apply this optimization if scalar canonicalize is legal for the
16753 // element type. Otherwise, scalarizing may require widening the scalar back
16754 // to a vector, adding overhead (e.g., bf16 has no scalar instructions).
16756 return SDValue();
16757
16759 for (unsigned I = 0; I != 2; ++I) {
16760 SDValue Op = N0.getOperand(I);
16761 if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16762 NewElts[I] =
16763 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16764 } else if (Op.isUndef()) {
16765 // Handled below based on what the other operand is.
16766 NewElts[I] = Op;
16767 } else {
16768 NewElts[I] = DAG.getNode(ISD::FCANONICALIZE, SL, EltVT, Op);
16769 }
16770 }
16771
16772 // If one half is undef, and one is constant, prefer a splat vector.
16773 // Otherwise, convert the undef to 0.0 since that's cheaper to use and may
16774 // be free with a packed operation.
16775 if (NewElts[0].isUndef()) {
16776 NewElts[0] = isa<ConstantFPSDNode>(NewElts[1])
16777 ? NewElts[1]
16778 : DAG.getConstantFP(0.0f, SL, EltVT);
16779 }
16780
16781 if (NewElts[1].isUndef()) {
16782 NewElts[1] = isa<ConstantFPSDNode>(NewElts[0])
16783 ? NewElts[0]
16784 : DAG.getConstantFP(0.0f, SL, EltVT);
16785 }
16786
16787 return DAG.getBuildVector(VT, SL, NewElts);
16788 }
16789 }
16790
16791 return SDValue();
16792}
16793
16794static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc) {
16795 switch (Opc) {
16796 case ISD::FMAXNUM:
16797 case ISD::FMAXNUM_IEEE:
16798 case ISD::FMAXIMUMNUM:
16799 return AMDGPUISD::FMAX3;
16800 case ISD::FMAXIMUM:
16801 return AMDGPUISD::FMAXIMUM3;
16802 case ISD::SMAX:
16803 return AMDGPUISD::SMAX3;
16804 case ISD::UMAX:
16805 return AMDGPUISD::UMAX3;
16806 case ISD::FMINNUM:
16807 case ISD::FMINNUM_IEEE:
16808 case ISD::FMINIMUMNUM:
16809 return AMDGPUISD::FMIN3;
16810 case ISD::FMINIMUM:
16811 return AMDGPUISD::FMINIMUM3;
16812 case ISD::SMIN:
16813 return AMDGPUISD::SMIN3;
16814 case ISD::UMIN:
16815 return AMDGPUISD::UMIN3;
16816 default:
16817 llvm_unreachable("Not a min/max opcode");
16818 }
16819}
16820
16821SDValue SITargetLowering::performIntMed3ImmCombine(SelectionDAG &DAG,
16822 const SDLoc &SL, SDValue Src,
16823 SDValue MinVal,
16824 SDValue MaxVal,
16825 bool Signed) const {
16826
16827 // med3 comes from
16828 // min(max(x, K0), K1), K0 < K1
16829 // max(min(x, K0), K1), K1 < K0
16830 //
16831 // "MinVal" and "MaxVal" respectively refer to the rhs of the
16832 // min/max op.
16833 ConstantSDNode *MinK = dyn_cast<ConstantSDNode>(MinVal);
16834 ConstantSDNode *MaxK = dyn_cast<ConstantSDNode>(MaxVal);
16835
16836 if (!MinK || !MaxK)
16837 return SDValue();
16838
16839 if (Signed) {
16840 if (MaxK->getAPIntValue().sge(MinK->getAPIntValue()))
16841 return SDValue();
16842 } else {
16843 if (MaxK->getAPIntValue().uge(MinK->getAPIntValue()))
16844 return SDValue();
16845 }
16846
16847 EVT VT = MinK->getValueType(0);
16848 unsigned Med3Opc = Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16849 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16850 return DAG.getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16851
16852 // Note: we could also extend to i32 and use i32 med3 if i16 med3 is
16853 // not available, but this is unlikely to be profitable as constants
16854 // will often need to be materialized & extended, especially on
16855 // pre-GFX10 where VOP3 instructions couldn't take literal operands.
16856 return SDValue();
16857}
16858
16861 return C;
16862
16864 if (ConstantFPSDNode *C = BV->getConstantFPSplatNode())
16865 return C;
16866 }
16867
16868 return nullptr;
16869}
16870
16871SDValue SITargetLowering::performFPMed3ImmCombine(SelectionDAG &DAG,
16872 const SDLoc &SL, SDValue Op0,
16873 SDValue Op1,
16874 bool IsKnownNoNaNs) const {
16875 ConstantFPSDNode *K1 = getSplatConstantFP(Op1);
16876 if (!K1)
16877 return SDValue();
16878
16879 ConstantFPSDNode *K0 = getSplatConstantFP(Op0.getOperand(1));
16880 if (!K0)
16881 return SDValue();
16882
16883 // Ordered >= (although NaN inputs should have folded away by now).
16884 if (K0->getValueAPF() > K1->getValueAPF())
16885 return SDValue();
16886
16887 // med3 with a nan input acts like
16888 // v_min_f32(v_min_f32(S0.f32, S1.f32), S2.f32)
16889 //
16890 // So the result depends on whether the IEEE mode bit is enabled or not with a
16891 // signaling nan input.
16892 // ieee=1
16893 // s0 snan: yields s2
16894 // s1 snan: yields s2
16895 // s2 snan: qnan
16896
16897 // s0 qnan: min(s1, s2)
16898 // s1 qnan: min(s0, s2)
16899 // s2 qnan: min(s0, s1)
16900
16901 // ieee=0
16902 // s0 snan: min(s1, s2)
16903 // s1 snan: min(s0, s2)
16904 // s2 snan: qnan
16905
16906 // s0 qnan: min(s1, s2)
16907 // s1 qnan: min(s0, s2)
16908 // s2 qnan: min(s0, s1)
16909 const MachineFunction &MF = DAG.getMachineFunction();
16910 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
16911
16912 // TODO: Check IEEE bit enabled. We can form fmed3 with IEEE=0 regardless of
16913 // whether the input is a signaling nan if op0 is fmaximum or fmaximumnum. We
16914 // can only form if op0 is fmaxnum_ieee if IEEE=1.
16915 EVT VT = Op0.getValueType();
16916 if (Info->getMode().DX10Clamp) {
16917 // If dx10_clamp is enabled, NaNs clamp to 0.0. This is the same as the
16918 // hardware fmed3 behavior converting to a min.
16919 // FIXME: Should this be allowing -0.0?
16920 if (K1->isOne() && K0->isPosZero())
16921 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Op0.getOperand(0));
16922 }
16923
16924 // med3 for f16 is only available on gfx9+, and not available for v2f16.
16925 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16926 // This isn't safe with signaling NaNs because in IEEE mode, min/max on a
16927 // signaling NaN gives a quiet NaN. The quiet NaN input to the min would
16928 // then give the other result, which is different from med3 with a NaN
16929 // input.
16930 SDValue Var = Op0.getOperand(0);
16931 if (!IsKnownNoNaNs && !DAG.isKnownNeverSNaN(Var))
16932 return SDValue();
16933
16934 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
16935
16936 if ((!K0->hasOneUse() || TII->isInlineConstant(K0->getValueAPF())) &&
16937 (!K1->hasOneUse() || TII->isInlineConstant(K1->getValueAPF()))) {
16938 return DAG.getNode(AMDGPUISD::FMED3, SL, K0->getValueType(0), Var,
16939 SDValue(K0, 0), SDValue(K1, 0));
16940 }
16941 }
16942
16943 return SDValue();
16944}
16945
16946/// \return true if the subtarget supports minimum3 and maximum3 with the given
16947/// base min/max opcode \p Opc for type \p VT.
16948static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc,
16949 EVT VT) {
16950 switch (Opc) {
16951 case ISD::FMINNUM:
16952 case ISD::FMAXNUM:
16953 case ISD::FMINNUM_IEEE:
16954 case ISD::FMAXNUM_IEEE:
16955 case ISD::FMINIMUMNUM:
16956 case ISD::FMAXIMUMNUM:
16957 case AMDGPUISD::FMIN_LEGACY:
16958 case AMDGPUISD::FMAX_LEGACY:
16959 return (VT == MVT::f32) || (VT == MVT::f16 && Subtarget.hasMin3Max3_16()) ||
16960 (VT == MVT::v2f16 && Subtarget.hasMin3Max3PKF16());
16961 case ISD::FMINIMUM:
16962 case ISD::FMAXIMUM:
16963 return (VT == MVT::f32 && Subtarget.hasMinimum3Maximum3F32()) ||
16964 (VT == MVT::f16 && Subtarget.hasMinimum3Maximum3F16()) ||
16965 (VT == MVT::v2f16 && Subtarget.hasMinimum3Maximum3PKF16());
16966 case ISD::SMAX:
16967 case ISD::SMIN:
16968 case ISD::UMAX:
16969 case ISD::UMIN:
16970 return (VT == MVT::i32) || (VT == MVT::i16 && Subtarget.hasMin3Max3_16());
16971 default:
16972 return false;
16973 }
16974
16975 llvm_unreachable("not a min/max opcode");
16976}
16977
16978SDValue SITargetLowering::performMinMaxCombine(SDNode *N,
16979 DAGCombinerInfo &DCI) const {
16980 SelectionDAG &DAG = DCI.DAG;
16981
16982 EVT VT = N->getValueType(0);
16983 unsigned Opc = N->getOpcode();
16984 SDValue Op0 = N->getOperand(0);
16985 SDValue Op1 = N->getOperand(1);
16986
16987 // Only do this if the inner op has one use since this will just increases
16988 // register pressure for no benefit.
16989
16990 if (supportsMin3Max3(*Subtarget, Opc, VT)) {
16991 auto IsTreeWithCombinableChildren = [Opc](SDValue Op) {
16992 return (Op.getOperand(0).getOpcode() == Opc &&
16993 Op.getOperand(0).hasOneUse()) ||
16994 (Op.getOperand(1).getOpcode() == Opc &&
16995 Op.getOperand(1).hasOneUse());
16996 };
16997
16998 bool CanTreeCombineApply = Op0.getOpcode() == Opc && Op0.hasOneUse() &&
16999 Op1.getOpcode() == Opc && Op1.hasOneUse();
17000 bool HasCombinableTreeChild =
17001 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
17002 IsTreeWithCombinableChildren(Op1));
17003
17004 // Tree reduction: when both operands are the same min/max op, restructure
17005 // to keep a 2-op node on top so higher tree levels can still combine.
17006 //
17007 // max(max(a, b), max(c, d)) -> max(max3(a, b, c), d)
17008 // min(min(a, b), min(c, d)) -> min(min3(a, b, c), d)
17009 //
17010 // Defer when either inner op is a tree node with combinable children.
17011 if (CanTreeCombineApply && !HasCombinableTreeChild) {
17012 SDLoc DL(N);
17013 SDValue Inner =
17015 Op0.getOperand(1), Op1.getOperand(0));
17016 return DAG.getNode(Opc, DL, VT, Inner, Op1.getOperand(1));
17017 }
17018
17019 // max(max(a, b), c) -> max3(a, b, c)
17020 // min(min(a, b), c) -> min3(a, b, c)
17021 // Deferred when Op0 is a tree node with combinable children.
17022 if (Op0.getOpcode() == Opc && Op0.hasOneUse() && !HasCombinableTreeChild) {
17023 SDLoc DL(N);
17024 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
17025 Op0.getOperand(0), Op0.getOperand(1), Op1);
17026 }
17027
17028 // Try commuted.
17029 // max(a, max(b, c)) -> max3(a, b, c)
17030 // min(a, min(b, c)) -> min3(a, b, c)
17031 // Deferred when Op1 is a tree node with combinable children.
17032 if (Op1.getOpcode() == Opc && Op1.hasOneUse() && !HasCombinableTreeChild) {
17033 SDLoc DL(N);
17034 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
17035 Op0, Op1.getOperand(0), Op1.getOperand(1));
17036 }
17037 }
17038
17039 // umin(sffbh(x), bitwidth) -> sffbh(x) if x is known to be not 0 or -1.
17040 SDValue FfbhSrc;
17041 uint64_t Clamp = 0;
17042 if (Opc == ISD::UMIN &&
17043 sd_match(Op0,
17045 sd_match(Op1, m_ConstInt(Clamp))) {
17046 unsigned BitWidth = FfbhSrc.getValueType().getScalarSizeInBits();
17047 if (Clamp >= BitWidth) {
17048 KnownBits Known = DAG.computeKnownBits(FfbhSrc);
17049 if (Known.isNonZero() && Known.Zero.getBoolValue())
17050 return Op0;
17051 }
17052 }
17053
17054 // min(max(x, K0), K1), K0 < K1 -> med3(x, K0, K1)
17055 // max(min(x, K0), K1), K1 < K0 -> med3(x, K1, K0)
17056 if (Opc == ISD::SMIN && Op0.getOpcode() == ISD::SMAX && Op0.hasOneUse()) {
17057 if (SDValue Med3 = performIntMed3ImmCombine(
17058 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), true))
17059 return Med3;
17060 }
17061 if (Opc == ISD::SMAX && Op0.getOpcode() == ISD::SMIN && Op0.hasOneUse()) {
17062 if (SDValue Med3 = performIntMed3ImmCombine(
17063 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, true))
17064 return Med3;
17065 }
17066
17067 if (Opc == ISD::UMIN && Op0.getOpcode() == ISD::UMAX && Op0.hasOneUse()) {
17068 if (SDValue Med3 = performIntMed3ImmCombine(
17069 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), false))
17070 return Med3;
17071 }
17072 if (Opc == ISD::UMAX && Op0.getOpcode() == ISD::UMIN && Op0.hasOneUse()) {
17073 if (SDValue Med3 = performIntMed3ImmCombine(
17074 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, false))
17075 return Med3;
17076 }
17077
17078 // if !is_snan(x):
17079 // fminnum(fmaxnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17080 // fminnum_ieee(fmaxnum_ieee(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17081 // fminnumnum(fmaxnumnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17082 // fmin_legacy(fmax_legacy(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
17083 if (((Opc == ISD::FMINNUM && Op0.getOpcode() == ISD::FMAXNUM) ||
17086 (Opc == AMDGPUISD::FMIN_LEGACY &&
17087 Op0.getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
17088 (VT == MVT::f32 || VT == MVT::f64 ||
17089 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
17090 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
17091 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
17092 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
17093 Op0.hasOneUse()) {
17094 if (SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(N), Op0, Op1,
17095 N->getFlags().hasNoNaNs()))
17096 return Res;
17097 }
17098
17099 // Prefer fminnum_ieee over fminimum. For gfx950, minimum/maximum are legal
17100 // for some types, but at a higher cost since it's implemented with a 3
17101 // operand form.
17102 const SDNodeFlags Flags = N->getFlags();
17103 if ((Opc == ISD::FMINIMUM || Opc == ISD::FMAXIMUM) && Flags.hasNoNaNs() &&
17104 !Subtarget->hasIEEEMinimumMaximumInsts() &&
17106 unsigned NewOpc =
17108 return DAG.getNode(NewOpc, SDLoc(N), VT, Op0, Op1, Flags);
17109 }
17110
17111 return SDValue();
17112}
17113
17117 // FIXME: Should this be allowing -0.0?
17118 return (CA->isPosZero() && CB->isOne()) ||
17119 (CA->isOne() && CB->isPosZero());
17120 }
17121 }
17122
17123 return false;
17124}
17125
17126// FIXME: Should only worry about snans for version with chain.
17127SDValue SITargetLowering::performFMed3Combine(SDNode *N,
17128 DAGCombinerInfo &DCI) const {
17129 EVT VT = N->getValueType(0);
17130 // v_med3_f32 and v_max_f32 behave identically wrt denorms, exceptions and
17131 // NaNs. With a NaN input, the order of the operands may change the result.
17132
17133 SelectionDAG &DAG = DCI.DAG;
17134 SDLoc SL(N);
17135
17136 SDValue Src0 = N->getOperand(0);
17137 SDValue Src1 = N->getOperand(1);
17138 SDValue Src2 = N->getOperand(2);
17139
17140 if (isClampZeroToOne(Src0, Src1)) {
17141 // const_a, const_b, x -> clamp is safe in all cases including signaling
17142 // nans.
17143 // FIXME: Should this be allowing -0.0?
17144 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
17145 }
17146
17147 const MachineFunction &MF = DAG.getMachineFunction();
17148 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
17149
17150 // FIXME: dx10_clamp behavior assumed in instcombine. Should we really bother
17151 // handling no dx10-clamp?
17152 if (Info->getMode().DX10Clamp) {
17153 // If NaNs is clamped to 0, we are free to reorder the inputs.
17154
17155 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
17156 std::swap(Src0, Src1);
17157
17158 if (isa<ConstantFPSDNode>(Src1) && !isa<ConstantFPSDNode>(Src2))
17159 std::swap(Src1, Src2);
17160
17161 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
17162 std::swap(Src0, Src1);
17163
17164 if (isClampZeroToOne(Src1, Src2))
17165 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
17166 }
17167
17168 return SDValue();
17169}
17170
17171SDValue SITargetLowering::performCvtPkRTZCombine(SDNode *N,
17172 DAGCombinerInfo &DCI) const {
17173 SDValue Src0 = N->getOperand(0);
17174 SDValue Src1 = N->getOperand(1);
17175 if (Src0.isUndef() && Src1.isUndef())
17176 return DCI.DAG.getUNDEF(N->getValueType(0));
17177 return SDValue();
17178}
17179
17180/// V_CVT_SCALEF32_* conversions to a narrow format only read the exponent
17181/// field of their f32 scale operand.
17182SDValue
17183SITargetLowering::performExponentOnlyScaleCombine(SDNode *N,
17184 DAGCombinerInfo &DCI) const {
17185 std::optional<unsigned> ScaleArgIdx =
17186 AMDGPU::getExponentOnlyScaleArgIdx(N->getConstantOperandVal(0));
17187 if (!ScaleArgIdx)
17188 return SDValue();
17189
17190 // Operand 0 is the intrinsic ID.
17191 unsigned OpIdx = *ScaleArgIdx + 1;
17192 SelectionDAG &DAG = DCI.DAG;
17193 SDValue Scale = N->getOperand(OpIdx);
17195
17196 if (SDValue DemandedScale =
17197 SimplifyMultipleUseDemandedBits(Scale, Demanded, DAG)) {
17198 SmallVector<SDValue> Ops(N->ops());
17199 Ops[OpIdx] = DemandedScale;
17200 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SDLoc(N), N->getVTList(), Ops);
17201 }
17202
17203 if (SimplifyDemandedBits(Scale, Demanded, DCI))
17204 return SDValue(N, 0);
17205
17206 return SDValue();
17207}
17208
17209// Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be
17210// expanded into a set of cmp/select instructions.
17212 unsigned NumElem,
17213 bool IsDivergentIdx,
17214 const GCNSubtarget *Subtarget) {
17216 return false;
17217
17218 unsigned VecSize = EltSize * NumElem;
17219
17220 // Sub-dword vectors of size 2 dword or less have better implementation.
17221 if (VecSize <= 64 && EltSize < 32)
17222 return false;
17223
17224 // Always expand the rest of sub-dword instructions, otherwise it will be
17225 // lowered via memory.
17226 if (EltSize < 32)
17227 return true;
17228
17229 // Always do this if var-idx is divergent, otherwise it will become a loop.
17230 if (IsDivergentIdx)
17231 return true;
17232
17233 // Large vectors would yield too many compares and v_cndmask_b32 instructions.
17234 unsigned NumInsts = NumElem /* Number of compares */ +
17235 ((EltSize + 31) / 32) * NumElem /* Number of cndmasks */;
17236
17237 // On some architectures (GFX9) movrel is not available and it's better
17238 // to expand.
17239 if (Subtarget->useVGPRIndexMode())
17240 return NumInsts <= 16;
17241
17242 // If movrel is available, use it instead of expanding for vector of 8
17243 // elements.
17244 if (Subtarget->hasMovrel())
17245 return NumInsts <= 15;
17246
17247 return true;
17248}
17249
17251 SDValue Idx = N->getOperand(N->getNumOperands() - 1);
17252 if (isa<ConstantSDNode>(Idx))
17253 return false;
17254
17255 SDValue Vec = N->getOperand(0);
17256 EVT VecVT = Vec.getValueType();
17257 EVT EltVT = VecVT.getVectorElementType();
17258 unsigned EltSize = EltVT.getSizeInBits();
17259 unsigned NumElem = VecVT.getVectorNumElements();
17260
17262 EltSize, NumElem, Idx->isDivergent(), getSubtarget());
17263}
17264
17265SDValue
17266SITargetLowering::performExtractVectorEltCombine(SDNode *N,
17267 DAGCombinerInfo &DCI) const {
17268 SDValue Vec = N->getOperand(0);
17269 SelectionDAG &DAG = DCI.DAG;
17270
17271 EVT VecVT = Vec.getValueType();
17272 EVT VecEltVT = VecVT.getVectorElementType();
17273 EVT ResVT = N->getValueType(0);
17274
17275 unsigned VecSize = VecVT.getSizeInBits();
17276 unsigned VecEltSize = VecEltVT.getSizeInBits();
17277
17278 if ((Vec.getOpcode() == ISD::FNEG || Vec.getOpcode() == ISD::FABS) &&
17280 SDLoc SL(N);
17281 SDValue Idx = N->getOperand(1);
17282 SDValue Elt =
17283 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec.getOperand(0), Idx);
17284 return DAG.getNode(Vec.getOpcode(), SL, ResVT, Elt);
17285 }
17286
17287 // (extract_vector_element (and {y0, y1}, (build_vector 0x1f, 0x1f)), index)
17288 // -> (and (extract_vector_element {y0, y1}, index), 0x1f)
17289 // There are optimisations to transform 64-bit shifts into 32-bit shifts
17290 // depending on the shift operand. See e.g. performSraCombine().
17291 // This combine ensures that the optimisation is compatible with v2i32
17292 // legalised AND.
17293 if (VecVT == MVT::v2i32 && Vec->getOpcode() == ISD::AND &&
17294 Vec->getOperand(1)->getOpcode() == ISD::BUILD_VECTOR) {
17295
17297 if (!C || C->getZExtValue() != 0x1f)
17298 return SDValue();
17299
17300 SDLoc SL(N);
17301 SDValue AndMask = DAG.getConstant(0x1f, SL, MVT::i32);
17302 SDValue EVE = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32,
17303 Vec->getOperand(0), N->getOperand(1));
17304 SDValue A = DAG.getNode(ISD::AND, SL, MVT::i32, EVE, AndMask);
17305 DAG.ReplaceAllUsesWith(N, A.getNode());
17306 }
17307
17308 // ScalarRes = EXTRACT_VECTOR_ELT ((vector-BINOP Vec1, Vec2), Idx)
17309 // =>
17310 // Vec1Elt = EXTRACT_VECTOR_ELT(Vec1, Idx)
17311 // Vec2Elt = EXTRACT_VECTOR_ELT(Vec2, Idx)
17312 // ScalarRes = scalar-BINOP Vec1Elt, Vec2Elt
17313 if (Vec.hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
17314 SDLoc SL(N);
17315 SDValue Idx = N->getOperand(1);
17316 unsigned Opc = Vec.getOpcode();
17317
17318 switch (Opc) {
17319 default:
17320 break;
17321 // TODO: Support other binary operations.
17322 case ISD::FADD:
17323 case ISD::FSUB:
17324 case ISD::FMUL:
17325 case ISD::ADD:
17326 case ISD::UMIN:
17327 case ISD::UMAX:
17328 case ISD::SMIN:
17329 case ISD::SMAX:
17330 case ISD::FMAXNUM:
17331 case ISD::FMINNUM:
17332 case ISD::FMAXNUM_IEEE:
17333 case ISD::FMINNUM_IEEE:
17334 case ISD::FMAXIMUM:
17335 case ISD::FMINIMUM: {
17336 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17337 Vec.getOperand(0), Idx);
17338 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17339 Vec.getOperand(1), Idx);
17340
17341 DCI.AddToWorklist(Elt0.getNode());
17342 DCI.AddToWorklist(Elt1.getNode());
17343 return DAG.getNode(Opc, SL, ResVT, Elt0, Elt1, Vec->getFlags());
17344 }
17345 }
17346 }
17347
17348 // EXTRACT_VECTOR_ELT (<n x e>, var-idx) => n x select (e, const-idx)
17350 SDLoc SL(N);
17351 SDValue Idx = N->getOperand(1);
17352 SDValue V;
17353 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17354 SDValue IC = DAG.getVectorIdxConstant(I, SL);
17355 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec, IC);
17356 if (I == 0)
17357 V = Elt;
17358 else
17359 V = DAG.getSelectCC(SL, Idx, IC, Elt, V, ISD::SETEQ);
17360 }
17361 return V;
17362 }
17363
17364 // EXTRACT_VECTOR_ELT (v2i32 bitcast (i64/f64:k), Idx)
17365 // =>
17366 // i32:Lo(k) if Idx == 0, or
17367 // i32:Hi(k) if Idx == 1
17368 auto *Idx = dyn_cast<ConstantSDNode>(N->getOperand(1));
17369 if (Vec.getOpcode() == ISD::BITCAST && VecVT == MVT::v2i32 && Idx) {
17370 SDLoc SL(N);
17371 SDValue PeekThrough = Vec.getOperand(0);
17372 auto *KImm = dyn_cast<ConstantSDNode>(PeekThrough);
17373 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17374 uint64_t KImmValue = KImm->getZExtValue();
17375 return DAG.getConstant(
17376 (KImmValue >> (32 * Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17377 }
17378 auto *KFPImm = dyn_cast<ConstantFPSDNode>(PeekThrough);
17379 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17380 uint64_t KFPImmValue =
17381 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17382 return DAG.getConstant((KFPImmValue >> (32 * Idx->getZExtValue())) &
17383 0xffffffff,
17384 SL, MVT::i32);
17385 }
17386 }
17387
17388 if (!DCI.isBeforeLegalize())
17389 return SDValue();
17390
17391 // Try to turn sub-dword accesses of vectors into accesses of the same 32-bit
17392 // elements. This exposes more load reduction opportunities by replacing
17393 // multiple small extract_vector_elements with a single 32-bit extract.
17394 if (isa<MemSDNode>(Vec) && VecEltSize <= 16 && VecEltVT.isByteSized() &&
17395 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17396 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VecVT);
17397
17398 unsigned BitIndex = Idx->getZExtValue() * VecEltSize;
17399 unsigned EltIdx = BitIndex / 32;
17400 unsigned LeftoverBitIdx = BitIndex % 32;
17401 SDLoc SL(N);
17402
17403 SDValue Cast = DAG.getNode(ISD::BITCAST, SL, NewVT, Vec);
17404 DCI.AddToWorklist(Cast.getNode());
17405
17406 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Cast,
17407 DAG.getConstant(EltIdx, SL, MVT::i32));
17408 DCI.AddToWorklist(Elt.getNode());
17409 SDValue Srl = DAG.getNode(ISD::SRL, SL, MVT::i32, Elt,
17410 DAG.getConstant(LeftoverBitIdx, SL, MVT::i32));
17411 DCI.AddToWorklist(Srl.getNode());
17412
17413 EVT VecEltAsIntVT = VecEltVT.changeTypeToInteger();
17414 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SL, VecEltAsIntVT, Srl);
17415 DCI.AddToWorklist(Trunc.getNode());
17416
17417 if (VecEltVT == ResVT) {
17418 return DAG.getNode(ISD::BITCAST, SL, VecEltVT, Trunc);
17419 }
17420
17421 assert(ResVT.isScalarInteger());
17422 return DAG.getAnyExtOrTrunc(Trunc, SL, ResVT);
17423 }
17424
17425 return SDValue();
17426}
17427
17428SDValue
17429SITargetLowering::performInsertVectorEltCombine(SDNode *N,
17430 DAGCombinerInfo &DCI) const {
17431 SDValue Vec = N->getOperand(0);
17432 SDValue Idx = N->getOperand(2);
17433 EVT VecVT = Vec.getValueType();
17434 EVT EltVT = VecVT.getVectorElementType();
17435
17436 // INSERT_VECTOR_ELT (<n x e>, var-idx)
17437 // => BUILD_VECTOR n x select (e, const-idx)
17438 // 16-bit elements are left to lowerINSERT_VECTOR_ELT, which is cheaper.
17440 (EltVT.getSizeInBits() == 16 &&
17442 return SDValue();
17443
17444 SelectionDAG &DAG = DCI.DAG;
17445 SDLoc SL(N);
17446 SDValue Ins = N->getOperand(1);
17447 EVT IdxVT = Idx.getValueType();
17448
17450 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17451 SDValue IC = DAG.getConstant(I, SL, IdxVT);
17452 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec, IC);
17453 SDValue V = DAG.getSelectCC(SL, Idx, IC, Ins, Elt, ISD::SETEQ);
17454 Ops.push_back(V);
17455 }
17456
17457 return DAG.getBuildVector(VecVT, SL, Ops);
17458}
17459
17460/// Return the source of an fp_extend from f16 to f32, or a converted FP
17461/// constant.
17463 if (Src.getOpcode() == ISD::FP_EXTEND &&
17464 Src.getOperand(0).getValueType() == MVT::f16) {
17465 return Src.getOperand(0);
17466 }
17467
17468 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Src)) {
17469 APFloat Val = CFP->getValueAPF();
17470 bool LosesInfo = true;
17472 if (!LosesInfo)
17473 return DAG.getConstantFP(Val, SDLoc(Src), MVT::f16);
17474 }
17475
17476 return SDValue();
17477}
17478
17479SDValue SITargetLowering::performFPRoundCombine(SDNode *N,
17480 DAGCombinerInfo &DCI) const {
17481 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17482 "combine only useful on gfx8");
17483
17484 SDValue TruncSrc = N->getOperand(0);
17485 EVT VT = N->getValueType(0);
17486 if (VT != MVT::f16)
17487 return SDValue();
17488
17489 if (TruncSrc.getOpcode() != AMDGPUISD::FMED3 ||
17490 TruncSrc.getValueType() != MVT::f32 || !TruncSrc.hasOneUse())
17491 return SDValue();
17492
17493 SelectionDAG &DAG = DCI.DAG;
17494 SDLoc SL(N);
17495
17496 // Optimize f16 fmed3 pattern performed on f32. On gfx8 there is no f16 fmed3,
17497 // and expanding it with min/max saves 1 instruction vs. casting to f32 and
17498 // casting back.
17499
17500 // fptrunc (f32 (fmed3 (fpext f16:a, fpext f16:b, fpext f16:c))) =>
17501 // fmin(fmax(a, b), fmax(fmin(a, b), c))
17502 SDValue A = strictFPExtFromF16(DAG, TruncSrc.getOperand(0));
17503 if (!A)
17504 return SDValue();
17505
17506 SDValue B = strictFPExtFromF16(DAG, TruncSrc.getOperand(1));
17507 if (!B)
17508 return SDValue();
17509
17510 SDValue C = strictFPExtFromF16(DAG, TruncSrc.getOperand(2));
17511 if (!C)
17512 return SDValue();
17513
17514 // This changes signaling nan behavior. If an input is a signaling nan, it
17515 // would have been quieted by the fpext originally. We don't care because
17516 // these are unconstrained ops. If we needed to insert quieting canonicalizes
17517 // we would be worse off than just doing the promotion.
17518 SDValue A1 = DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, A, B);
17519 SDValue B1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A, B);
17520 SDValue C1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A1, C);
17521 return DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, B1, C1);
17522}
17523
17524unsigned SITargetLowering::getFusedOpcode(const SelectionDAG &DAG,
17525 const SDNode *N0,
17526 const SDNode *N1) const {
17527 EVT VT = N0->getValueType(0);
17528
17529 // Only do this if we are not trying to support denormals. v_mad_f32 does not
17530 // support denormals ever.
17531 if (((VT == MVT::f32 &&
17533 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17536 return ISD::FMAD;
17537
17538 if (N0->getFlags().hasAllowContract() && N1->getFlags().hasAllowContract() &&
17540 return ISD::FMA;
17541 }
17542
17543 return 0;
17544}
17545
17546// For a reassociatable opcode perform:
17547// op x, (op y, z) -> op (op x, z), y, if x and z are uniform
17548SDValue SITargetLowering::reassociateScalarOps(SDNode *N,
17549 SelectionDAG &DAG) const {
17550 EVT VT = N->getValueType(0);
17551 if (VT != MVT::i32 && VT != MVT::i64)
17552 return SDValue();
17553
17554 if (DAG.isBaseWithConstantOffset(SDValue(N, 0)))
17555 return SDValue();
17556
17557 unsigned Opc = N->getOpcode();
17558 SDValue Op0 = N->getOperand(0);
17559 SDValue Op1 = N->getOperand(1);
17560
17561 if (!(Op0->isDivergent() ^ Op1->isDivergent()))
17562 return SDValue();
17563
17564 if (Op0->isDivergent())
17565 std::swap(Op0, Op1);
17566
17567 if (Op1.getOpcode() != Opc || !Op1.hasOneUse())
17568 return SDValue();
17569
17570 SDValue Op2 = Op1.getOperand(1);
17571 Op1 = Op1.getOperand(0);
17572 if (!(Op1->isDivergent() ^ Op2->isDivergent()))
17573 return SDValue();
17574
17575 if (Op1->isDivergent())
17576 std::swap(Op1, Op2);
17577
17578 SDLoc SL(N);
17579 SDValue Add1 = DAG.getNode(Opc, SL, VT, Op0, Op1);
17580 return DAG.getNode(Opc, SL, VT, Add1, Op2);
17581}
17582
17583static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT,
17584 SDValue N0, SDValue N1, SDValue N2, bool Signed) {
17586 SDVTList VTs = DAG.getVTList(MVT::i64, MVT::i1);
17587 SDValue Mad = DAG.getNode(MadOpc, SL, VTs, N0, N1, N2);
17588 return DAG.getNode(ISD::TRUNCATE, SL, VT, Mad);
17589}
17590
17591// Fold
17592// y = lshr i64 x, 32
17593// res = add (mul i64 y, Const), x where "Const" is a 64-bit constant
17594// with Const.hi == -1
17595// To
17596// res = mad_u64_u32 y.lo ,Const.lo, x.lo
17598 SDValue MulLHS, SDValue MulRHS,
17599 SDValue AddRHS) {
17600 if (MulRHS.getOpcode() == ISD::SRL)
17601 std::swap(MulLHS, MulRHS);
17602
17603 if (MulLHS.getValueType() != MVT::i64 || MulLHS.getOpcode() != ISD::SRL)
17604 return SDValue();
17605
17606 ConstantSDNode *ShiftVal = dyn_cast<ConstantSDNode>(MulLHS.getOperand(1));
17607 if (!ShiftVal || ShiftVal->getAsZExtVal() != 32 ||
17608 MulLHS.getOperand(0) != AddRHS)
17609 return SDValue();
17610
17612 if (!Const || Hi_32(Const->getZExtValue()) != uint32_t(-1))
17613 return SDValue();
17614
17615 SDValue ConstMul =
17616 DAG.getConstant(Lo_32(Const->getZExtValue()), SL, MVT::i32);
17617 return getMad64_32(DAG, SL, MVT::i64,
17618 DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS), ConstMul,
17619 DAG.getZeroExtendInReg(AddRHS, SL, MVT::i32), false);
17620}
17621
17622// Fold (add (mul x, y), z) --> (mad_[iu]64_[iu]32 x, y, z) plus high
17623// multiplies, if any.
17624//
17625// Full 64-bit multiplies that feed into an addition are lowered here instead
17626// of using the generic expansion. The generic expansion ends up with
17627// a tree of ADD nodes that prevents us from using the "add" part of the
17628// MAD instruction. The expansion produced here results in a chain of ADDs
17629// instead of a tree.
17630SDValue SITargetLowering::tryFoldToMad64_32(SDNode *N,
17631 DAGCombinerInfo &DCI) const {
17632 assert(N->isAnyAdd());
17633
17634 SelectionDAG &DAG = DCI.DAG;
17635 EVT VT = N->getValueType(0);
17636 SDLoc SL(N);
17637 SDValue LHS = N->getOperand(0);
17638 SDValue RHS = N->getOperand(1);
17639
17640 if (VT.isVector())
17641 return SDValue();
17642
17643 // S_MUL_HI_[IU]32 was added in gfx9, which allows us to keep the overall
17644 // result in scalar registers for uniform values.
17645 if (!N->isDivergent() && Subtarget->hasSMulHi())
17646 return SDValue();
17647
17648 unsigned NumBits = VT.getScalarSizeInBits();
17649 if (NumBits <= 32 || NumBits > 64)
17650 return SDValue();
17651
17652 if (LHS.getOpcode() != ISD::MUL) {
17653 assert(RHS.getOpcode() == ISD::MUL);
17654 std::swap(LHS, RHS);
17655 }
17656
17657 // Avoid the fold if it would unduly increase the number of multiplies due to
17658 // multiple uses, except on hardware with full-rate multiply-add (which is
17659 // part of full-rate 64-bit ops).
17660 if (!Subtarget->hasFullRate64Ops()) {
17661 unsigned NumUsers = 0;
17662 for (SDNode *User : LHS->users()) {
17663 // There is a use that does not feed into addition, so the multiply can't
17664 // be removed. We prefer MUL + ADD + ADDC over MAD + MUL.
17665 if (!User->isAnyAdd())
17666 return SDValue();
17667
17668 // We prefer 2xMAD over MUL + 2xADD + 2xADDC (code density), and prefer
17669 // MUL + 3xADD + 3xADDC over 3xMAD.
17670 ++NumUsers;
17671 if (NumUsers >= 3)
17672 return SDValue();
17673 }
17674 }
17675
17676 SDValue MulLHS = LHS.getOperand(0);
17677 SDValue MulRHS = LHS.getOperand(1);
17678 SDValue AddRHS = RHS;
17679
17680 if (SDValue FoldedMAD = tryFoldMADwithSRL(DAG, SL, MulLHS, MulRHS, AddRHS))
17681 return FoldedMAD;
17682
17683 // Always check whether operands are small unsigned values, since that
17684 // knowledge is useful in more cases. Check for small signed values only if
17685 // doing so can unlock a shorter code sequence.
17686 bool MulLHSUnsigned32 = numBitsUnsigned(MulLHS, DAG) <= 32;
17687 bool MulRHSUnsigned32 = numBitsUnsigned(MulRHS, DAG) <= 32;
17688
17689 bool MulSignedLo = false;
17690 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17691 MulSignedLo =
17692 numBitsSigned(MulLHS, DAG) <= 32 && numBitsSigned(MulRHS, DAG) <= 32;
17693 }
17694
17695 // The operands and final result all have the same number of bits. If
17696 // operands need to be extended, they can be extended with garbage. The
17697 // resulting garbage in the high bits of the mad_[iu]64_[iu]32 result is
17698 // truncated away in the end.
17699 if (VT != MVT::i64) {
17700 MulLHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulLHS);
17701 MulRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulRHS);
17702 AddRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, AddRHS);
17703 }
17704
17705 // The basic code generated is conceptually straightforward. Pseudo code:
17706 //
17707 // accum = mad_64_32 lhs.lo, rhs.lo, accum
17708 // accum.hi = add (mul lhs.hi, rhs.lo), accum.hi
17709 // accum.hi = add (mul lhs.lo, rhs.hi), accum.hi
17710 //
17711 // The second and third lines are optional, depending on whether the factors
17712 // are {sign,zero}-extended or not.
17713 //
17714 // The actual DAG is noisier than the pseudo code, but only due to
17715 // instructions that disassemble values into low and high parts, and
17716 // assemble the final result.
17717 SDValue One = DAG.getConstant(1, SL, MVT::i32);
17718
17719 auto MulLHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS);
17720 auto MulRHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulRHS);
17721 SDValue Accum =
17722 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17723
17724 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17725 auto [AccumLo, AccumHi] = DAG.SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17726
17727 if (!MulLHSUnsigned32) {
17728 auto MulLHSHi =
17729 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulLHS, One);
17730 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSHi, MulRHSLo);
17731 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17732 }
17733
17734 if (!MulRHSUnsigned32) {
17735 auto MulRHSHi =
17736 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulRHS, One);
17737 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSLo, MulRHSHi);
17738 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17739 }
17740
17741 Accum = DAG.getBuildVector(MVT::v2i32, SL, {AccumLo, AccumHi});
17742 Accum = DAG.getBitcast(MVT::i64, Accum);
17743 }
17744
17745 if (VT != MVT::i64)
17746 Accum = DAG.getNode(ISD::TRUNCATE, SL, VT, Accum);
17747 return Accum;
17748}
17749
17750SDValue
17751SITargetLowering::foldAddSub64WithZeroLowBitsTo32(SDNode *N,
17752 DAGCombinerInfo &DCI) const {
17753 SDValue RHS = N->getOperand(1);
17754 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
17755 if (!CRHS)
17756 return SDValue();
17757
17758 // TODO: Worth using computeKnownBits? Maybe expensive since it's so
17759 // common.
17760 uint64_t Val = CRHS->getZExtValue();
17761 if (countr_zero(Val) >= 32) {
17762 SelectionDAG &DAG = DCI.DAG;
17763 SDLoc SL(N);
17764 SDValue LHS = N->getOperand(0);
17765
17766 // Avoid carry machinery if we know the low half of the add does not
17767 // contribute to the final result.
17768 //
17769 // add i64:x, K if computeTrailingZeros(K) >= 32
17770 // => build_pair (add x.hi, K.hi), x.lo
17771
17772 // Breaking the 64-bit add here with this strange constant is unlikely
17773 // to interfere with addressing mode patterns.
17774
17775 SDValue Hi = getHiHalf64(LHS, DAG);
17776 SDValue ConstHi32 = DAG.getConstant(Hi_32(Val), SL, MVT::i32);
17777 unsigned Opcode = N->getOpcode();
17778 if (Opcode == ISD::PTRADD)
17779 Opcode = ISD::ADD;
17780 SDValue AddHi =
17781 DAG.getNode(Opcode, SL, MVT::i32, Hi, ConstHi32, N->getFlags());
17782
17783 SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
17784 return DAG.getNode(ISD::BUILD_PAIR, SL, MVT::i64, Lo, AddHi);
17785 }
17786
17787 return SDValue();
17788}
17789
17790// Collect the ultimate src of each of the mul node's operands, and confirm
17791// each operand is 8 bytes.
17792static std::optional<ByteProvider<SDValue>>
17793handleMulOperand(const SDValue &MulOperand) {
17794 auto Byte0 = calculateByteProvider(MulOperand, 0, 0);
17795 if (!Byte0 || Byte0->isConstantZero()) {
17796 return std::nullopt;
17797 }
17798 auto Byte1 = calculateByteProvider(MulOperand, 1, 0);
17799 if (Byte1 && !Byte1->isConstantZero()) {
17800 return std::nullopt;
17801 }
17802 return Byte0;
17803}
17804
17805static unsigned addPermMasks(unsigned First, unsigned Second) {
17806 unsigned FirstCs = First & 0x0c0c0c0c;
17807 unsigned SecondCs = Second & 0x0c0c0c0c;
17808 unsigned FirstNoCs = First & ~0x0c0c0c0c;
17809 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17810
17811 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17812 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17813 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17814 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17815
17816 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17817}
17818
17819struct DotSrc {
17821 int64_t PermMask;
17823};
17824
17828 SmallVectorImpl<DotSrc> &Src1s, int Step) {
17829
17830 assert(Src0.Src.has_value() && Src1.Src.has_value());
17831 // Src0s and Src1s are empty, just place arbitrarily.
17832 if (Step == 0) {
17833 Src0s.push_back({*Src0.Src, ((Src0.SrcOffset % 4) << 24) + 0x0c0c0c,
17834 Src0.SrcOffset / 4});
17835 Src1s.push_back({*Src1.Src, ((Src1.SrcOffset % 4) << 24) + 0x0c0c0c,
17836 Src1.SrcOffset / 4});
17837 return;
17838 }
17839
17840 for (int BPI = 0; BPI < 2; BPI++) {
17841 std::pair<ByteProvider<SDValue>, ByteProvider<SDValue>> BPP = {Src0, Src1};
17842 if (BPI == 1) {
17843 BPP = {Src1, Src0};
17844 }
17845 unsigned ZeroMask = 0x0c0c0c0c;
17846 unsigned FMask = 0xFF << (8 * (3 - Step));
17847
17848 unsigned FirstMask =
17849 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17850 unsigned SecondMask =
17851 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17852 // Attempt to find Src vector which contains our SDValue, if so, add our
17853 // perm mask to the existing one. If we are unable to find a match for the
17854 // first SDValue, attempt to find match for the second.
17855 int FirstGroup = -1;
17856 for (int I = 0; I < 2; I++) {
17857 SmallVectorImpl<DotSrc> &Srcs = I == 0 ? Src0s : Src1s;
17858 auto MatchesFirst = [&BPP](DotSrc &IterElt) {
17859 return IterElt.SrcOp == *BPP.first.Src &&
17860 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17861 };
17862
17863 auto *Match = llvm::find_if(Srcs, MatchesFirst);
17864 if (Match != Srcs.end()) {
17865 Match->PermMask = addPermMasks(FirstMask, Match->PermMask);
17866 FirstGroup = I;
17867 break;
17868 }
17869 }
17870 if (FirstGroup != -1) {
17871 SmallVectorImpl<DotSrc> &Srcs = FirstGroup == 1 ? Src0s : Src1s;
17872 auto MatchesSecond = [&BPP](DotSrc &IterElt) {
17873 return IterElt.SrcOp == *BPP.second.Src &&
17874 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17875 };
17876 auto *Match = llvm::find_if(Srcs, MatchesSecond);
17877 if (Match != Srcs.end()) {
17878 Match->PermMask = addPermMasks(SecondMask, Match->PermMask);
17879 } else
17880 Srcs.push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17881 return;
17882 }
17883 }
17884
17885 // If we have made it here, then we could not find a match in Src0s or Src1s
17886 // for either Src0 or Src1, so just place them arbitrarily.
17887
17888 unsigned ZeroMask = 0x0c0c0c0c;
17889 unsigned FMask = 0xFF << (8 * (3 - Step));
17890
17891 Src0s.push_back(
17892 {*Src0.Src,
17893 ((Src0.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17894 Src0.SrcOffset / 4});
17895 Src1s.push_back(
17896 {*Src1.Src,
17897 ((Src1.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17898 Src1.SrcOffset / 4});
17899}
17900
17902 SmallVectorImpl<DotSrc> &Srcs, bool IsSigned,
17903 bool IsAny) {
17904
17905 // If we just have one source, just permute it accordingly.
17906 if (Srcs.size() == 1) {
17907 auto *Elt = Srcs.begin();
17908 auto EltOp = getDWordFromOffset(DAG, SL, Elt->SrcOp, Elt->DWordOffset);
17909
17910 // v_perm will produce the original value
17911 if (Elt->PermMask == 0x3020100)
17912 return EltOp;
17913
17914 return DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17915 DAG.getConstant(Elt->PermMask, SL, MVT::i32));
17916 }
17917
17918 auto *FirstElt = Srcs.begin();
17919 auto *SecondElt = std::next(FirstElt);
17920
17922
17923 // If we have multiple sources in the chain, combine them via perms (using
17924 // calculated perm mask) and Ors.
17925 while (true) {
17926 auto FirstMask = FirstElt->PermMask;
17927 auto SecondMask = SecondElt->PermMask;
17928
17929 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17930 unsigned FirstPlusFour = FirstMask | 0x04040404;
17931 // 0x0c + 0x04 = 0x10, so anding with 0x0F will produced 0x00 for any
17932 // original 0x0C.
17933 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17934
17935 auto PermMask = addPermMasks(FirstMask, SecondMask);
17936 auto FirstVal =
17937 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17938 auto SecondVal =
17939 getDWordFromOffset(DAG, SL, SecondElt->SrcOp, SecondElt->DWordOffset);
17940
17941 Perms.push_back(DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, FirstVal,
17942 SecondVal,
17943 DAG.getConstant(PermMask, SL, MVT::i32)));
17944
17945 FirstElt = std::next(SecondElt);
17946 if (FirstElt == Srcs.end())
17947 break;
17948
17949 SecondElt = std::next(FirstElt);
17950 // If we only have a FirstElt, then just combine that into the cumulative
17951 // source node.
17952 if (SecondElt == Srcs.end()) {
17953 auto EltOp =
17954 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17955
17956 Perms.push_back(
17957 DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17958 DAG.getConstant(FirstElt->PermMask, SL, MVT::i32)));
17959 break;
17960 }
17961 }
17962
17963 assert(Perms.size() == 1 || Perms.size() == 2);
17964 return Perms.size() == 2
17965 ? DAG.getNode(ISD::OR, SL, MVT::i32, Perms[0], Perms[1])
17966 : Perms[0];
17967}
17968
17969static void fixMasks(SmallVectorImpl<DotSrc> &Srcs, unsigned ChainLength) {
17970 for (auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17971 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17972 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17973 EntryMask += ZeroMask;
17974 }
17975}
17976
17977static bool isMul(const SDValue Op) {
17978 auto Opcode = Op.getOpcode();
17979
17980 return (Opcode == ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17981 Opcode == AMDGPUISD::MUL_I24);
17982}
17983
17984static std::optional<bool>
17986 ByteProvider<SDValue> &Src1, const SDValue &S0Op,
17987 const SDValue &S1Op, const SelectionDAG &DAG) {
17988 // If we both ops are i8s (pre legalize-dag), then the signedness semantics
17989 // of the dot4 is irrelevant.
17990 if (S0Op.getValueSizeInBits() == 8 && S1Op.getValueSizeInBits() == 8)
17991 return false;
17992
17993 auto Known0 = DAG.computeKnownBits(S0Op, 0);
17994 bool S0IsUnsigned = Known0.countMinLeadingZeros() > 0;
17995 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17996 auto Known1 = DAG.computeKnownBits(S1Op, 0);
17997 bool S1IsUnsigned = Known1.countMinLeadingZeros() > 0;
17998 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
17999
18000 assert(!(S0IsUnsigned && S0IsSigned));
18001 assert(!(S1IsUnsigned && S1IsSigned));
18002
18003 // There are 9 possible permutations of
18004 // {S0IsUnsigned, S0IsSigned, S1IsUnsigned, S1IsSigned}
18005
18006 // In two permutations, the sign bits are known to be the same for both Ops,
18007 // so simply return Signed / Unsigned corresponding to the MSB
18008
18009 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
18010 return S0IsSigned;
18011
18012 // In another two permutations, the sign bits are known to be opposite. In
18013 // this case return std::nullopt to indicate a bad match.
18014
18015 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
18016 return std::nullopt;
18017
18018 // In the remaining five permutations, we don't know the value of the sign
18019 // bit for at least one Op. Since we have a valid ByteProvider, we know that
18020 // the upper bits must be extension bits. Thus, the only ways for the sign
18021 // bit to be unknown is if it was sign extended from unknown value, or if it
18022 // was any extended. In either case, it is correct to use the signed
18023 // version of the signedness semantics of dot4
18024
18025 // In two of such permutations, we known the sign bit is set for
18026 // one op, and the other is unknown. It is okay to used signed version of
18027 // dot4.
18028 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
18029 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
18030 return true;
18031
18032 // In one such permutation, we don't know either of the sign bits. It is okay
18033 // to used the signed version of dot4.
18034 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
18035 return true;
18036
18037 // In two of such permutations, we known the sign bit is unset for
18038 // one op, and the other is unknown. Return std::nullopt to indicate a
18039 // bad match.
18040 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
18041 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
18042 return std::nullopt;
18043
18044 llvm_unreachable("Fully covered condition");
18045}
18046
18047SDValue SITargetLowering::performAddCombine(SDNode *N,
18048 DAGCombinerInfo &DCI) const {
18049 SelectionDAG &DAG = DCI.DAG;
18050 EVT VT = N->getValueType(0);
18051 SDLoc SL(N);
18052 SDValue LHS = N->getOperand(0);
18053 SDValue RHS = N->getOperand(1);
18054
18055 if (LHS.getOpcode() == ISD::MUL || RHS.getOpcode() == ISD::MUL) {
18056 if (Subtarget->hasMad64_32()) {
18057 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
18058 return Folded;
18059 }
18060 }
18061
18062 if (SDValue V = reassociateScalarOps(N, DAG)) {
18063 return V;
18064 }
18065
18066 if (VT == MVT::i64) {
18067 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18068 return Folded;
18069 }
18070
18071 // dot4 produces a 32-bit result, so a wider VT can't be folded.
18072 if (!VT.isVector() && VT.getSizeInBits() <= 32 &&
18073 (isMul(LHS) || isMul(RHS)) && Subtarget->hasDot7Insts() &&
18074 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
18075 SDValue TempNode(N, 0);
18076 std::optional<bool> IsSigned;
18080
18081 // Match the v_dot4 tree, while collecting src nodes.
18082 int ChainLength = 0;
18083 for (int I = 0; I < 4; I++) {
18084 auto MulIdx = isMul(LHS) ? 0 : isMul(RHS) ? 1 : -1;
18085 if (MulIdx == -1)
18086 break;
18087 auto Src0 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(0));
18088 if (!Src0)
18089 break;
18090 auto Src1 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(1));
18091 if (!Src1)
18092 break;
18093
18094 auto IterIsSigned = checkDot4MulSignedness(
18095 TempNode->getOperand(MulIdx), *Src0, *Src1,
18096 TempNode->getOperand(MulIdx)->getOperand(0),
18097 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
18098 if (!IterIsSigned)
18099 break;
18100 if (!IsSigned)
18101 IsSigned = *IterIsSigned;
18102 if (*IterIsSigned != *IsSigned)
18103 break;
18104 placeSources(*Src0, *Src1, Src0s, Src1s, I);
18105 auto AddIdx = 1 - MulIdx;
18106 // Allow the special case where add (add (mul24, 0), mul24) became ->
18107 // add (mul24, mul24).
18108 if (I == 2 && isMul(TempNode->getOperand(AddIdx))) {
18109 Src2s.push_back(TempNode->getOperand(AddIdx));
18110 auto Src0 =
18111 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(0));
18112 if (!Src0)
18113 break;
18114 auto Src1 =
18115 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(1));
18116 if (!Src1)
18117 break;
18118 auto IterIsSigned = checkDot4MulSignedness(
18119 TempNode->getOperand(AddIdx), *Src0, *Src1,
18120 TempNode->getOperand(AddIdx)->getOperand(0),
18121 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
18122 if (!IterIsSigned)
18123 break;
18124 assert(IsSigned);
18125 if (*IterIsSigned != *IsSigned)
18126 break;
18127 placeSources(*Src0, *Src1, Src0s, Src1s, I + 1);
18128 Src2s.push_back(DAG.getConstant(0, SL, MVT::i32));
18129 ChainLength = I + 2;
18130 break;
18131 }
18132
18133 TempNode = TempNode->getOperand(AddIdx);
18134 Src2s.push_back(TempNode);
18135 ChainLength = I + 1;
18136 // The loop body treats TempNode's operands as addends.
18137 if (TempNode.getOpcode() != ISD::ADD)
18138 break;
18139 LHS = TempNode->getOperand(0);
18140 RHS = TempNode->getOperand(1);
18141 }
18142
18143 if (ChainLength < 2)
18144 return SDValue();
18145
18146 // Masks were constructed with assumption that we would find a chain of
18147 // length 4. If not, then we need to 0 out the MSB bits (via perm mask of
18148 // 0x0c) so they do not affect dot calculation.
18149 if (ChainLength < 4) {
18150 fixMasks(Src0s, ChainLength);
18151 fixMasks(Src1s, ChainLength);
18152 }
18153
18154 SDValue Src0, Src1;
18155
18156 // If we are just using a single source for both, and have permuted the
18157 // bytes consistently, we can just use the sources without permuting
18158 // (commutation).
18159 bool UseOriginalSrc = false;
18160 if (ChainLength == 4 && Src0s.size() == 1 && Src1s.size() == 1 &&
18161 Src0s.begin()->PermMask == Src1s.begin()->PermMask &&
18162 Src0s.begin()->SrcOp.getValueSizeInBits() >= 32 &&
18163 Src1s.begin()->SrcOp.getValueSizeInBits() >= 32) {
18164 SmallVector<unsigned, 4> SrcBytes;
18165 auto Src0Mask = Src0s.begin()->PermMask;
18166 SrcBytes.push_back(Src0Mask & 0xFF000000);
18167 bool UniqueEntries = true;
18168 for (auto I = 1; I < 4; I++) {
18169 auto NextByte = Src0Mask & (0xFF << ((3 - I) * 8));
18170
18171 if (is_contained(SrcBytes, NextByte)) {
18172 UniqueEntries = false;
18173 break;
18174 }
18175 SrcBytes.push_back(NextByte);
18176 }
18177
18178 if (UniqueEntries) {
18179 UseOriginalSrc = true;
18180
18181 auto *FirstElt = Src0s.begin();
18182 auto FirstEltOp =
18183 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
18184
18185 auto *SecondElt = Src1s.begin();
18186 auto SecondEltOp = getDWordFromOffset(DAG, SL, SecondElt->SrcOp,
18187 SecondElt->DWordOffset);
18188
18189 Src0 = DAG.getBitcastedAnyExtOrTrunc(FirstEltOp, SL,
18190 MVT::getIntegerVT(32));
18191 Src1 = DAG.getBitcastedAnyExtOrTrunc(SecondEltOp, SL,
18192 MVT::getIntegerVT(32));
18193 }
18194 }
18195
18196 if (!UseOriginalSrc) {
18197 Src0 = resolveSources(DAG, SL, Src0s, false, true);
18198 Src1 = resolveSources(DAG, SL, Src1s, false, true);
18199 }
18200
18201 assert(IsSigned);
18202 SDValue Src2 =
18203 DAG.getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
18204
18205 SDValue IID = DAG.getTargetConstant(*IsSigned ? Intrinsic::amdgcn_sdot4
18206 : Intrinsic::amdgcn_udot4,
18207 SL, MVT::i64);
18208
18209 assert(!VT.isVector());
18210 auto Dot = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32, IID, Src0,
18211 Src1, Src2, DAG.getTargetConstant(0, SL, MVT::i1));
18212
18213 return DAG.getExtOrTrunc(*IsSigned, Dot, SL, VT);
18214 }
18215
18216 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
18217 return SDValue();
18218
18219 // add x, zext (setcc) => uaddo_carry x, 0, setcc
18220 // add x, sext (setcc) => usubo_carry x, 0, setcc
18221 unsigned Opc = LHS.getOpcode();
18224 std::swap(RHS, LHS);
18225
18226 Opc = RHS.getOpcode();
18227 switch (Opc) {
18228 default:
18229 break;
18230 case ISD::ZERO_EXTEND:
18231 case ISD::SIGN_EXTEND:
18232 case ISD::ANY_EXTEND: {
18233 auto Cond = RHS.getOperand(0);
18234 // If this won't be a real VOPC output, we would still need to insert an
18235 // extra instruction anyway.
18236 if (!isBoolSGPR(Cond))
18237 break;
18238 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
18239 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
18241 return DAG.getNode(Opc, SL, VTList, Args);
18242 }
18243 case ISD::UADDO_CARRY: {
18244 // add x, (uaddo_carry y, 0, cc) => uaddo_carry x, y, cc
18245 if (!isNullConstant(RHS.getOperand(1)))
18246 break;
18247 SDValue Args[] = {LHS, RHS.getOperand(0), RHS.getOperand(2)};
18248 return DAG.getNode(ISD::UADDO_CARRY, SDLoc(N), RHS->getVTList(), Args);
18249 }
18250 }
18251 return SDValue();
18252}
18253
18254SDValue SITargetLowering::performPtrAddCombine(SDNode *N,
18255 DAGCombinerInfo &DCI) const {
18256 SelectionDAG &DAG = DCI.DAG;
18257 SDLoc DL(N);
18258 EVT VT = N->getValueType(0);
18259 SDValue N0 = N->getOperand(0);
18260 SDValue N1 = N->getOperand(1);
18261
18262 // The following folds transform PTRADDs into regular arithmetic in cases
18263 // where the PTRADD wouldn't be folded as an immediate offset into memory
18264 // instructions anyway. They are target-specific in that other targets might
18265 // prefer to not lose information about the pointer arithmetic.
18266
18267 // Fold (ptradd x, shl(0 - v, k)) -> sub(x, shl(v, k)).
18268 // Adapted from DAGCombiner::visitADDLikeCommutative.
18269 SDValue V, K;
18270 if (sd_match(N1, m_Shl(m_Neg(m_Value(V)), m_Value(K)))) {
18271 SDNodeFlags ShlFlags = N1->getFlags();
18272 // If the original shl is NUW and NSW, the first k+1 bits of 0-v are all 0,
18273 // so v is either 0 or the first k+1 bits of v are all 1 -> NSW can be
18274 // preserved.
18275 SDNodeFlags NewShlFlags =
18276 ShlFlags.hasNoUnsignedWrap() && ShlFlags.hasNoSignedWrap()
18278 : SDNodeFlags();
18279 SDValue Inner = DAG.getNode(ISD::SHL, DL, VT, V, K, NewShlFlags);
18280 DCI.AddToWorklist(Inner.getNode());
18281 return DAG.getNode(ISD::SUB, DL, VT, N0, Inner);
18282 }
18283
18284 // Fold into Mad64 if the right-hand side is a MUL. Analogous to a fold in
18285 // performAddCombine.
18286 if (N1.getOpcode() == ISD::MUL) {
18287 if (Subtarget->hasMad64_32()) {
18288 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
18289 return Folded;
18290 }
18291 }
18292
18293 // If the 32 low bits of the constant are all zero, there is nothing to fold
18294 // into an immediate offset, so it's better to eliminate the unnecessary
18295 // addition for the lower 32 bits than to preserve the PTRADD.
18296 // Analogous to a fold in performAddCombine.
18297 if (VT == MVT::i64) {
18298 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18299 return Folded;
18300 }
18301
18302 if (N1.getOpcode() != ISD::ADD || !N1.hasOneUse())
18303 return SDValue();
18304
18305 SDValue X = N0;
18306 SDValue Y = N1.getOperand(0);
18307 SDValue Z = N1.getOperand(1);
18308 bool YIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Y);
18309 bool ZIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Z);
18310
18311 if (!YIsConstant && !ZIsConstant && !X->isDivergent() &&
18312 Y->isDivergent() != Z->isDivergent()) {
18313 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, y), z) if x and
18314 // y are uniform and z isn't.
18315 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, z), y) if x and
18316 // z are uniform and y isn't.
18317 // The goal is to push uniform operands up in the computation, so that they
18318 // can be handled with scalar operations. We can't use reassociateScalarOps
18319 // for this since it requires two identical commutative operations to
18320 // reassociate.
18321 if (Y->isDivergent())
18322 std::swap(Y, Z);
18323 // If both additions in the original were NUW, reassociation preserves that.
18324 SDNodeFlags ReassocFlags =
18325 (N->getFlags() & N1->getFlags()) & SDNodeFlags::NoUnsignedWrap;
18326 SDValue UniformInner = DAG.getMemBasePlusOffset(X, Y, DL, ReassocFlags);
18327 DCI.AddToWorklist(UniformInner.getNode());
18328 return DAG.getMemBasePlusOffset(UniformInner, Z, DL, ReassocFlags);
18329 }
18330
18331 return SDValue();
18332}
18333
18334static bool isCtlzOpc(unsigned Opc) {
18335 return Opc == ISD::CTLZ || Opc == ISD::CTLZ_ZERO_POISON;
18336}
18337
18338SDValue SITargetLowering::performSubCombine(SDNode *N,
18339 DAGCombinerInfo &DCI) const {
18340 SelectionDAG &DAG = DCI.DAG;
18341 EVT VT = N->getValueType(0);
18342
18343 if (VT == MVT::i64) {
18344 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18345 return Folded;
18346 }
18347
18348 if (VT != MVT::i32)
18349 return SDValue();
18350
18351 SDLoc SL(N);
18352 SDValue LHS = N->getOperand(0);
18353 SDValue RHS = N->getOperand(1);
18354
18355 // sub x, zext (setcc) => usubo_carry x, 0, setcc
18356 // sub x, sext (setcc) => uaddo_carry x, 0, setcc
18357 unsigned Opc = RHS.getOpcode();
18358 switch (Opc) {
18359 default:
18360 break;
18361 case ISD::ZERO_EXTEND:
18362 case ISD::SIGN_EXTEND:
18363 case ISD::ANY_EXTEND: {
18364 auto Cond = RHS.getOperand(0);
18365 // If this won't be a real VOPC output, we would still need to insert an
18366 // extra instruction anyway.
18367 if (!isBoolSGPR(Cond))
18368 break;
18369 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
18370 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
18372 return DAG.getNode(Opc, SL, VTList, Args);
18373 }
18374 }
18375
18376 if (LHS.getOpcode() == ISD::USUBO_CARRY) {
18377 // sub (usubo_carry x, 0, cc), y => usubo_carry x, y, cc
18378 if (!isNullConstant(LHS.getOperand(1)))
18379 return SDValue();
18380 SDValue Args[] = {LHS.getOperand(0), RHS, LHS.getOperand(2)};
18381 return DAG.getNode(ISD::USUBO_CARRY, SDLoc(N), LHS->getVTList(), Args);
18382 }
18383
18384 // sub (ctlz (xor x, (sra x, 31))), 1 -> ctls x.
18385 if (isOneConstant(RHS) && isCtlzOpc(LHS.getOpcode())) {
18386 SDValue CtlzSrc = LHS.getOperand(0);
18387 // Check for xor x, (sra x, 31) pattern.
18388 if (CtlzSrc.getOpcode() == ISD::XOR) {
18389 SDValue X = CtlzSrc.getOperand(0);
18390 SDValue SignExt = CtlzSrc.getOperand(1);
18391 // Try both ordering of XOR operands.
18392 if (SignExt.getOpcode() != ISD::SRA)
18393 std::swap(X, SignExt);
18394 if (SignExt.getOpcode() == ISD::SRA && SignExt.getOperand(0) == X) {
18395 ConstantSDNode *ShiftAmt =
18397 unsigned BitWidth = X.getValueType().getScalarSizeInBits();
18398 if (ShiftAmt && ShiftAmt->getZExtValue() == BitWidth - 1)
18399 return DAG.getNode(ISD::CTLS, SL, VT, X);
18400 }
18401 }
18402 }
18403
18404 return SDValue();
18405}
18406
18407SDValue SITargetLowering::performFAddCombine(SDNode *N,
18408 DAGCombinerInfo &DCI) const {
18409 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18410 return SDValue();
18411
18412 SelectionDAG &DAG = DCI.DAG;
18413 EVT VT = N->getValueType(0);
18414
18415 SDLoc SL(N);
18416 SDValue LHS = N->getOperand(0);
18417 SDValue RHS = N->getOperand(1);
18418
18419 // These should really be instruction patterns, but writing patterns with
18420 // source modifiers is a pain.
18421
18422 // fadd (fadd (a, a), b) -> mad 2.0, a, b
18423 if (LHS.getOpcode() == ISD::FADD) {
18424 SDValue A = LHS.getOperand(0);
18425 if (A == LHS.getOperand(1)) {
18426 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18427 if (FusedOp != 0) {
18428 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18429 return DAG.getNode(FusedOp, SL, VT, A, Two, RHS);
18430 }
18431 }
18432 }
18433
18434 // fadd (b, fadd (a, a)) -> mad 2.0, a, b
18435 if (RHS.getOpcode() == ISD::FADD) {
18436 SDValue A = RHS.getOperand(0);
18437 if (A == RHS.getOperand(1)) {
18438 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18439 if (FusedOp != 0) {
18440 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18441 return DAG.getNode(FusedOp, SL, VT, A, Two, LHS);
18442 }
18443 }
18444 }
18445
18446 return SDValue();
18447}
18448
18449SDValue SITargetLowering::performFSubCombine(SDNode *N,
18450 DAGCombinerInfo &DCI) const {
18451 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18452 return SDValue();
18453
18454 SelectionDAG &DAG = DCI.DAG;
18455 SDLoc SL(N);
18456 EVT VT = N->getValueType(0);
18457 assert(!VT.isVector());
18458
18459 // Try to get the fneg to fold into the source modifier. This undoes generic
18460 // DAG combines and folds them into the mad.
18461 //
18462 // Only do this if we are not trying to support denormals. v_mad_f32 does
18463 // not support denormals ever.
18464 SDValue LHS = N->getOperand(0);
18465 SDValue RHS = N->getOperand(1);
18466 if (LHS.getOpcode() == ISD::FADD) {
18467 // (fsub (fadd a, a), c) -> mad 2.0, a, (fneg c)
18468 SDValue A = LHS.getOperand(0);
18469 if (A == LHS.getOperand(1)) {
18470 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18471 if (FusedOp != 0) {
18472 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18473 SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
18474
18475 return DAG.getNode(FusedOp, SL, VT, A, Two, NegRHS);
18476 }
18477 }
18478 }
18479
18480 if (RHS.getOpcode() == ISD::FADD) {
18481 // (fsub c, (fadd a, a)) -> mad -2.0, a, c
18482
18483 SDValue A = RHS.getOperand(0);
18484 if (A == RHS.getOperand(1)) {
18485 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18486 if (FusedOp != 0) {
18487 const SDValue NegTwo = DAG.getConstantFP(-2.0, SL, VT);
18488 return DAG.getNode(FusedOp, SL, VT, A, NegTwo, LHS);
18489 }
18490 }
18491 }
18492
18493 return SDValue();
18494}
18495
18496SDValue SITargetLowering::performFDivCombine(SDNode *N,
18497 DAGCombinerInfo &DCI) const {
18498 SelectionDAG &DAG = DCI.DAG;
18499 SDLoc SL(N);
18500 EVT VT = N->getValueType(0);
18501
18502 if (VT != MVT::f16 && VT != MVT::bf16)
18503 return SDValue();
18504
18505 SDValue LHS = N->getOperand(0);
18506 SDValue RHS = N->getOperand(1);
18507
18508 SDNodeFlags Flags = N->getFlags();
18509 SDNodeFlags RHSFlags = RHS->getFlags();
18510 if (!Flags.hasAllowContract() || !RHSFlags.hasAllowContract() ||
18511 !RHS->hasOneUse())
18512 return SDValue();
18513
18514 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
18515 bool IsNegative = false;
18516 if (CLHS->isOne() || (IsNegative = CLHS->isMinusOne())) {
18517 // fdiv contract 1.0, (sqrt contract x) -> rsq
18518 // fdiv contract -1.0, (sqrt contract x) -> fneg(rsq)
18519 if (RHS.getOpcode() == ISD::FSQRT) {
18520 // TODO: Or in RHS flags, somehow missing from SDNodeFlags
18521 SDValue SqrtOp = RHS.getOperand(0);
18522 SDValue Rsq;
18523 if (isOperationLegal(ISD::FSQRT, VT)) {
18524 // fsqrt legality correlates to rsq availability of the same type.
18525 Rsq = DAG.getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18526 } else if (VT == MVT::f16) {
18527 // Targets without 16-bit instructions (gfx6/gfx7) have no f16 rsq,
18528 // but v_rsq_f32 is more than accurate enough for f16. Unlike bf16,
18529 // every f16 value (including denormals) extends to a normal f32, and
18530 // an f16 rsq result is never denormal, so the f32 reciprocal square
18531 // root needs no denormal handling. Compute it in f32 and round back.
18532 SDValue Ext =
18533 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, SqrtOp, Flags);
18534 SDValue F32Rsq =
18535 DAG.getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18536 Rsq = DAG.getNode(ISD::FP_ROUND, SL, VT, F32Rsq,
18537 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
18538 } else {
18539 // bf16 shares f32's exponent range, so bf16 denormals would extend to
18540 // f32 denormals that v_rsq_f32 does not handle. Leave it expanded.
18541 return SDValue();
18542 }
18543 return IsNegative ? DAG.getNode(ISD::FNEG, SL, VT, Rsq, Flags) : Rsq;
18544 }
18545 }
18546 }
18547
18548 return SDValue();
18549}
18550
18551SDValue SITargetLowering::performFMulCombine(SDNode *N,
18552 DAGCombinerInfo &DCI) const {
18553 SelectionDAG &DAG = DCI.DAG;
18554 EVT VT = N->getValueType(0);
18555 EVT ScalarVT = VT.getScalarType();
18556 EVT IntVT = VT.changeElementType(*DAG.getContext(), MVT::i32);
18557
18558 if (!N->isDivergent() && getSubtarget()->hasSALUFloatInsts() &&
18559 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18560 // Prefer to use s_mul_f16/f32 instead of v_ldexp_f16/f32.
18561 return SDValue();
18562 }
18563
18564 SDValue LHS = N->getOperand(0);
18565 SDValue RHS = N->getOperand(1);
18566
18567 // It is cheaper to realize i32 inline constants as compared against
18568 // materializing f16 or f64 (or even non-inline f32) values,
18569 // possible via ldexp usage, as shown below :
18570 //
18571 // Given : A = 2^a & B = 2^b ; where a and b are integers.
18572 // fmul x, (select y, A, B) -> ldexp( x, (select i32 y, a, b) )
18573 // fmul x, (select y, -A, -B) -> ldexp( (fneg x), (select i32 y, a, b) )
18574 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18575 (RHS.hasOneUse() && RHS.getOpcode() == ISD::SELECT)) {
18576 const ConstantFPSDNode *TrueNode = isConstOrConstSplatFP(RHS.getOperand(1));
18577 if (!TrueNode)
18578 return SDValue();
18579 const ConstantFPSDNode *FalseNode =
18580 isConstOrConstSplatFP(RHS.getOperand(2));
18581 if (!FalseNode)
18582 return SDValue();
18583
18584 if (TrueNode->isNegative() != FalseNode->isNegative())
18585 return SDValue();
18586
18587 // For f32, only non-inline constants should be transformed.
18588 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
18589 if (ScalarVT == MVT::f32 &&
18590 TII->isInlineConstant(TrueNode->getValueAPF()) &&
18591 TII->isInlineConstant(FalseNode->getValueAPF()))
18592 return SDValue();
18593
18594 int TrueNodeExpVal = TrueNode->getValueAPF().getExactLog2Abs();
18595 if (TrueNodeExpVal == INT_MIN)
18596 return SDValue();
18597 int FalseNodeExpVal = FalseNode->getValueAPF().getExactLog2Abs();
18598 if (FalseNodeExpVal == INT_MIN)
18599 return SDValue();
18600
18601 SDLoc SL(N);
18602 SDValue SelectNode =
18603 DAG.getNode(ISD::SELECT, SL, IntVT, RHS.getOperand(0),
18604 DAG.getSignedConstant(TrueNodeExpVal, SL, IntVT),
18605 DAG.getSignedConstant(FalseNodeExpVal, SL, IntVT));
18606
18607 LHS = TrueNode->isNegative()
18608 ? DAG.getNode(ISD::FNEG, SL, VT, LHS, LHS->getFlags())
18609 : LHS;
18610
18611 return DAG.getNode(ISD::FLDEXP, SL, VT, LHS, SelectNode, N->getFlags());
18612 }
18613
18614 return SDValue();
18615}
18616
18617SDValue SITargetLowering::performFMACombine(SDNode *N,
18618 DAGCombinerInfo &DCI) const {
18619 SelectionDAG &DAG = DCI.DAG;
18620 EVT VT = N->getValueType(0);
18621 SDLoc SL(N);
18622
18623 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18624 return SDValue();
18625
18626 // FMA((F32)S0.x, (F32)S1. x, FMA((F32)S0.y, (F32)S1.y, (F32)z)) ->
18627 // FDOT2((V2F16)S0, (V2F16)S1, (F32)z))
18628 SDValue Op1 = N->getOperand(0);
18629 SDValue Op2 = N->getOperand(1);
18630 SDValue FMA = N->getOperand(2);
18631
18632 if (FMA.getOpcode() != ISD::FMA || Op1.getOpcode() != ISD::FP_EXTEND ||
18633 Op2.getOpcode() != ISD::FP_EXTEND)
18634 return SDValue();
18635
18636 // The fdot2 fold (fma_mix -> dot2) is only safe when both instructions agree
18637 // on how f16 subnormal inputs are handled. However, if both FMAs carry afn
18638 // the caller accepts approximate results, so any subnormal flushing
18639 // introduced by dot2 is acceptable regardless of mode.
18640 //
18641 // gfx90a (CDNA2) is the sole exception (dot2UnconditionalFlush): v_dot2c
18642 // unconditionally flushes f16 subnormal inputs to zero regardless of MODE,
18643 // while v_fma_mix_f32 preserves them when ieee=1 (the default compute kernel
18644 // mode). The fold is safe only when f32 denorm = PreserveSign, which implies
18645 // ieee=0 so both flush.
18646 //
18647 // All other GPUs: v_dot2 does NOT flush f16 subnormal inputs. v_fma_mix_f32
18648 // flushes them only when f32 denorm = PreserveSign. The fold is safe only
18649 // when f32 denorm is IEEE (both preserve the subnormal). Dynamic mode is
18650 // also rejected since the runtime value is unknown.
18651 bool AllowInaccuracy = N->getFlags().hasApproximateFuncs() &&
18652 FMA->getFlags().hasApproximateFuncs();
18653 if (!AllowInaccuracy) {
18654 const MachineFunction &MF = DAG.getMachineFunction();
18655 DenormalMode Mode = MF.getDenormalMode(APFloat::IEEEsingle());
18656 if (Subtarget->dot2UnconditionalFlush()) {
18657 // gfx90a: fold safe only when f32 denorm flushes.
18659 return SDValue();
18660 } else {
18661 // All other GPUs: fold safe only when f32 denorm is IEEE.
18662 if (Mode != DenormalMode::getIEEE())
18663 return SDValue();
18664 }
18665 }
18666
18667 // fp-contract allows reassociating the fma tree into a dot product.
18668 if (N->getFlags().hasAllowContract() && FMA->getFlags().hasAllowContract()) {
18669 Op1 = Op1.getOperand(0);
18670 Op2 = Op2.getOperand(0);
18671 if (Op1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18673 return SDValue();
18674
18675 SDValue Vec1 = Op1.getOperand(0);
18676 SDValue Idx1 = Op1.getOperand(1);
18677 SDValue Vec2 = Op2.getOperand(0);
18678
18679 SDValue FMAOp1 = FMA.getOperand(0);
18680 SDValue FMAOp2 = FMA.getOperand(1);
18681 SDValue FMAAcc = FMA.getOperand(2);
18682
18683 if (FMAOp1.getOpcode() != ISD::FP_EXTEND ||
18684 FMAOp2.getOpcode() != ISD::FP_EXTEND)
18685 return SDValue();
18686
18687 FMAOp1 = FMAOp1.getOperand(0);
18688 FMAOp2 = FMAOp2.getOperand(0);
18689 if (FMAOp1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18691 return SDValue();
18692
18693 SDValue Vec3 = FMAOp1.getOperand(0);
18694 SDValue Vec4 = FMAOp2.getOperand(0);
18695 SDValue Idx2 = FMAOp1.getOperand(1);
18696
18697 if (Idx1 != Op2.getOperand(1) || Idx2 != FMAOp2.getOperand(1))
18698 return SDValue();
18699
18700 if (!isa<ConstantSDNode>(Idx1) || !isa<ConstantSDNode>(Idx2) ||
18701 Idx1 == Idx2)
18702 return SDValue();
18703
18704 if (Vec1 == Vec2 || Vec3 == Vec4)
18705 return SDValue();
18706
18707 if (Vec1.getValueType() != MVT::v2f16 || Vec2.getValueType() != MVT::v2f16)
18708 return SDValue();
18709
18710 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18711 return DAG.getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18712 DAG.getTargetConstant(0, SL, MVT::i1));
18713 }
18714 }
18715 return SDValue();
18716}
18717
18718// Given a double-precision ordered or unordered comparison, return the
18719// condition code for an equivalent integral comparison of the operands' upper
18720// 32 bits, or `SETCC_INVALID` if not possible.
18721// For simplicity, no simplification occurs if the operands are not both known
18722// to have sign bit zero.
18723//
18724// EQ/NE:
18725// If LHS.lo32 == RHS.lo32:
18726// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18727// If LHS.lo32 != RHS.lo32:
18728// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18729// The reduction is not possible if operands may be +0 and -0.
18730// For ordered eq / unordered ne, at most one operand may be NaN.
18731// For unordered eq / ordered ne, neither operand can be NaN.
18732//
18733// LT/GE:
18734// If LHS.lo32 >= RHS.lo32 (unsigned):
18735// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18736// If LHS.lo32 < RHS.lo32 (unsigned):
18737// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18738// The reduction is only supported if both operands are nonnegative.
18739// For ordered lt / unordered ge, the RHS cannot be NaN.
18740// For unordered lt / ordered ge, neither operand can be NaN.
18741//
18742// LE/GT:
18743// If LHS.lo32 > RHS.lo32 (unsigned):
18744// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18745// If LHS.lo32 <= RHS.lo32 (unsigned):
18746// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18747// The reduction is only supported if both operands are nonnegative.
18748// For unordered le / ordered gt, the LHS cannot be NaN.
18749// For ordered le / unordered gt, neither operand can be NaN.
18751 const SDValue LHS,
18752 const SDValue RHS,
18753 const SelectionDAG &DAG) {
18754 EVT VT = LHS.getValueType();
18755 assert(VT == MVT::f64 && "Incorrect operand type!");
18756
18757 const KnownBits RHSBits = DAG.computeKnownBits(RHS);
18758 // Bail if RHS sign bit is not known to be zero.
18759 if (!RHSBits.Zero.isSignBitSet())
18760 return ISD::SETCC_INVALID;
18761
18762 const KnownBits RHSKnownLo32 = RHSBits.trunc(32);
18763 const KnownFPClass RHSFPClass =
18765 const bool RHSMaybeNaN = !RHSFPClass.isKnownNeverNaN();
18766
18767 const KnownBits LHSBits = DAG.computeKnownBits(LHS);
18768 const KnownBits LHSKnownLo32 = LHSBits.trunc(32);
18769 const KnownFPClass LHSFPClass =
18771 const bool LHSMaybeNaN = !LHSFPClass.isKnownNeverNaN();
18772
18773 // Bail if LHS sign bit is not known to be zero.
18774 if (!LHSBits.Zero.isSignBitSet())
18775 return ISD::SETCC_INVALID;
18776
18777 switch (CC) {
18778 default:
18779 break;
18780 case ISD::SETEQ:
18781 case ISD::SETOEQ:
18782 case ISD::SETUEQ:
18783 case ISD::SETONE:
18784 case ISD::SETUNE: {
18785 // OEQ should be false if either operand is NaN, so it suffices that at
18786 // least one operand is not NaN.
18787 if (CC == ISD::SETOEQ && LHSMaybeNaN && RHSMaybeNaN)
18788 break;
18789 // UEQ should be true if either operand is NaN, but this cannot be checked
18790 // on underlying bits.
18791 if (CC == ISD::SETUEQ && (LHSMaybeNaN || RHSMaybeNaN))
18792 break;
18793 // ONE should be false if either operand is NaN, but this cannot be
18794 // checked on underlying bits.
18795 if (CC == ISD::SETONE && (LHSMaybeNaN || RHSMaybeNaN))
18796 break;
18797 // UNE should be true if either operand is NaN, so it suffices that they
18798 // are not both NaN.
18799 if (CC == ISD::SETUNE && LHSMaybeNaN && RHSMaybeNaN)
18800 break;
18801
18802 const std::optional<bool> KnownEq =
18803 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18804
18805 if (!KnownEq)
18806 break;
18807
18808 if (*KnownEq)
18809 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18810 ? ISD::SETEQ
18811 : ISD::SETNE;
18812
18813 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18815 : ISD::SETTRUE;
18816 }
18817 case ISD::SETLT:
18818 case ISD::SETOLT:
18819 case ISD::SETULT:
18820 case ISD::SETGE:
18821 case ISD::SETOGE:
18822 case ISD::SETUGE: {
18823 // OLT should be false if either operand is NaN.
18824 // Since NaNs have maximum exponent and nonzero mantissa, false positives
18825 // are only possible if the RHS is NaN. (No issue with RHS == +inf since
18826 // the inequality is strict)
18827 if (CC == ISD::SETOLT && RHSMaybeNaN)
18828 break;
18829 // ULT should be true if either operand is NaN, but this cannot be ensured
18830 // with a truncated comparison.
18831 if (CC == ISD::SETULT && (LHSMaybeNaN || RHSMaybeNaN))
18832 break;
18833 // OGE should be false if either operand is NaN, but this cannot be
18834 // ensured with a truncated comparison.
18835 if (CC == ISD::SETOGE && (LHSMaybeNaN || RHSMaybeNaN))
18836 break;
18837 // UGE should be true if either operand is NaN.
18838 // False negatives are only possible if the RHS is NaN.
18839 // (No issue with RHS == +inf since the inequality is inclusive)
18840 if (CC == ISD::SETUGE && RHSMaybeNaN)
18841 break;
18842
18843 const std::optional<bool> KnownUge =
18844 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
18845
18846 if (!KnownUge)
18847 break;
18848
18849 if (*KnownUge) {
18850 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
18851 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18852 ? ISD::SETLT
18853 : ISD::SETGE;
18854 }
18855 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
18856 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18857 ? ISD::SETLE
18858 : ISD::SETGT;
18859 }
18860 case ISD::SETLE:
18861 case ISD::SETOLE:
18862 case ISD::SETULE:
18863 case ISD::SETGT:
18864 case ISD::SETOGT:
18865 case ISD::SETUGT: {
18866 // OLE should be false if either operand is NaN, but this cannot be
18867 // ensured with a truncated comparison.
18868 if (CC == ISD::SETOLE && (LHSMaybeNaN || RHSMaybeNaN))
18869 break;
18870 // ULE should be true if either operand is NaN.
18871 // False negatives are only possible if the LHS is NaN.
18872 // (No issue with LHS == +inf since the inequality is inclusive)
18873 if (CC == ISD::SETULE && LHSMaybeNaN)
18874 break;
18875 // OGT should be false if either operand is NaN.
18876 // False positives are only possible if the LHS is NaN.
18877 // (No issue with LHS == +inf since the inequality is strict)
18878 if (CC == ISD::SETOGT && LHSMaybeNaN)
18879 break;
18880 // UGT should be true if either operand is NaN, but this cannot be ensured
18881 // with a truncated comparison.
18882 if (CC == ISD::SETUGT && (LHSMaybeNaN || RHSMaybeNaN))
18883 break;
18884
18885 const std::optional<bool> KnownUle =
18886 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
18887
18888 if (!KnownUle)
18889 break;
18890
18891 if (*KnownUle) {
18892 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
18893 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18894 ? ISD::SETLE
18895 : ISD::SETGT;
18896 }
18897 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
18898 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18899 ? ISD::SETLT
18900 : ISD::SETGE;
18901 }
18902 }
18903
18904 return ISD::SETCC_INVALID;
18905}
18906
18907SDValue SITargetLowering::performSetCCCombine(SDNode *N,
18908 DAGCombinerInfo &DCI) const {
18909 SelectionDAG &DAG = DCI.DAG;
18910 SDLoc SL(N);
18911
18912 SDValue LHS = N->getOperand(0);
18913 SDValue RHS = N->getOperand(1);
18914 EVT VT = LHS.getValueType();
18915 ISD::CondCode CC = N->getOperandCondCode(2);
18916
18917 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
18918 if (!CRHS) {
18920 if (CRHS) {
18921 std::swap(LHS, RHS);
18923 }
18924 }
18925
18926 if (CRHS) {
18927 if (VT == MVT::i32 && LHS.getOpcode() == ISD::SIGN_EXTEND &&
18928 isBoolSGPR(LHS.getOperand(0))) {
18929 // setcc (sext from i1 cc), -1, ne|sgt|ult) => not cc => xor cc, -1
18930 // setcc (sext from i1 cc), -1, eq|sle|uge) => cc
18931 // setcc (sext from i1 cc), 0, eq|sge|ule) => not cc => xor cc, -1
18932 // setcc (sext from i1 cc), 0, ne|ugt|slt) => cc
18933 if ((CRHS->isAllOnes() &&
18934 (CC == ISD::SETNE || CC == ISD::SETGT || CC == ISD::SETULT)) ||
18935 (CRHS->isZero() &&
18936 (CC == ISD::SETEQ || CC == ISD::SETGE || CC == ISD::SETULE)))
18937 return DAG.getNode(ISD::XOR, SL, MVT::i1, LHS.getOperand(0),
18938 DAG.getAllOnesConstant(SL, MVT::i1));
18939 if ((CRHS->isAllOnes() &&
18940 (CC == ISD::SETEQ || CC == ISD::SETLE || CC == ISD::SETUGE)) ||
18941 (CRHS->isZero() &&
18942 (CC == ISD::SETNE || CC == ISD::SETUGT || CC == ISD::SETLT)))
18943 return LHS.getOperand(0);
18944 }
18945
18946 const APInt &CRHSVal = CRHS->getAPIntValue();
18947 if ((CC == ISD::SETEQ || CC == ISD::SETNE) &&
18948 LHS.getOpcode() == ISD::SELECT &&
18949 isa<ConstantSDNode>(LHS.getOperand(1)) &&
18950 isa<ConstantSDNode>(LHS.getOperand(2)) &&
18951 isBoolSGPR(LHS.getOperand(0))) {
18952 // Given CT != FT:
18953 // setcc (select cc, CT, CF), CF, eq => xor cc, -1
18954 // setcc (select cc, CT, CF), CF, ne => cc
18955 // setcc (select cc, CT, CF), CT, ne => xor cc, -1
18956 // setcc (select cc, CT, CF), CT, eq => cc
18957 const APInt &CT = LHS.getConstantOperandAPInt(1);
18958 const APInt &CF = LHS.getConstantOperandAPInt(2);
18959
18960 if (CT != CF) {
18961 if ((CF == CRHSVal && CC == ISD::SETEQ) ||
18962 (CT == CRHSVal && CC == ISD::SETNE))
18963 return DAG.getNOT(SL, LHS.getOperand(0), MVT::i1);
18964 if ((CF == CRHSVal && CC == ISD::SETNE) ||
18965 (CT == CRHSVal && CC == ISD::SETEQ))
18966 return LHS.getOperand(0);
18967 }
18968 }
18969 }
18970
18971 // Truncate 64-bit setcc to only test upper or lower 32-bits.
18972 if (VT == MVT::i64) {
18973 const KnownBits LHSKnown = DAG.computeKnownBits(LHS);
18974 const KnownBits RHSKnown = DAG.computeKnownBits(RHS);
18975 const KnownBits LHSKnownLo32 = LHSKnown.trunc(32);
18976 const KnownBits RHSKnownLo32 = RHSKnown.trunc(32);
18977 // Truncate 64-bit setcc to test only upper 32-bits of its operands in the
18978 // following cases where information about the lower 32-bits of its operands
18979 // is known:
18980 //
18981 // If LHS.lo32 == RHS.lo32:
18982 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18983 // If LHS.lo32 != RHS.lo32:
18984 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18985 // If LHS.lo32 >= RHS.lo32 (unsigned):
18986 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18987 // If LHS.lo32 > RHS.lo32 (unsigned):
18988 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18989 // If LHS.lo32 <= RHS.lo32 (unsigned):
18990 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18991 // If LHS.lo32 < RHS.lo32 (unsigned):
18992 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18993
18994 // NewCC is valid iff we can truncate the setcc to only test the upper 32
18995 // bits
18997
18998 switch (CC) {
18999 default:
19000 llvm_unreachable("Unexpected condition code for integer setcc");
19001 break;
19002 case ISD::SETEQ: {
19003 const std::optional<bool> KnownEq =
19004 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
19005 if (KnownEq)
19006 NewCC = *KnownEq ? ISD::SETEQ : ISD::SETFALSE;
19007
19008 break;
19009 }
19010 case ISD::SETNE: {
19011 const std::optional<bool> KnownEq =
19012 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
19013 if (KnownEq)
19014 NewCC = *KnownEq ? ISD::SETNE : ISD::SETTRUE;
19015
19016 break;
19017 }
19018 case ISD::SETULT:
19019 case ISD::SETUGE:
19020 case ISD::SETLT:
19021 case ISD::SETGE: {
19022 const std::optional<bool> KnownUge =
19023 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
19024 if (KnownUge) {
19025 if (*KnownUge) {
19026 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
19027 NewCC = CC;
19028 } else {
19029 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
19030 NewCC = CC == ISD::SETULT ? ISD::SETULE
19032 : CC == ISD::SETLT ? ISD::SETLE
19033 : ISD::SETGT;
19034 }
19035 }
19036 break;
19037 }
19038 case ISD::SETULE:
19039 case ISD::SETUGT:
19040 case ISD::SETLE:
19041 case ISD::SETGT: {
19042 const std::optional<bool> KnownUle =
19043 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
19044 if (KnownUle) {
19045 if (*KnownUle) {
19046 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
19047 NewCC = CC;
19048 } else {
19049 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
19050 NewCC = CC == ISD::SETULE ? ISD::SETULT
19052 : CC == ISD::SETLE ? ISD::SETLT
19053 : ISD::SETGE;
19054 }
19055 }
19056 break;
19057 }
19058 }
19059
19060 if (NewCC != ISD::SETCC_INVALID)
19061 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
19062 getHiHalf64(RHS, DAG), NewCC);
19063
19064 // Truncate 64-bit setcc to test only lower 32-bits when upper 32-bits are
19065 // known equal.
19066 const KnownBits LHSKnownHi32 = LHSKnown.extractBits(32, 32);
19067 const KnownBits RHSKnownHi32 = RHSKnown.extractBits(32, 32);
19068 const std::optional<bool> KnownEq =
19069 KnownBits::eq(LHSKnownHi32, RHSKnownHi32);
19070
19071 if (KnownEq == true) {
19072 // For signed comparisons, convert to unsigned since upper halves match
19074
19075 SDValue LHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
19076 SDValue RHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, RHS);
19077 return DAG.getSetCC(SL, N->getValueType(0), LHSLo, RHSLo, NewCC);
19078 }
19079 }
19080
19081 // Eliminate setcc by using carryout from add/sub instruction
19082
19083 // LHS = ADD i64 RHS, Z LHSlo = UADDO i32 RHSlo, Zlo
19084 // setcc LHS ult RHS -> LHSHi = UADDO_CARRY i32 RHShi, Zhi
19085 // similarly for subtraction
19086
19087 // LHS = ADD i64 Y, 1 LHSlo = UADDO i32 Ylo, 1
19088 // setcc LHS eq 0 -> LHSHi = UADDO_CARRY i32 Yhi, 0
19089
19090 if (VT == MVT::i64 && ((CC == ISD::SETULT &&
19092 (CC == ISD::SETUGT &&
19094 (CC == ISD::SETEQ && CRHS && CRHS->isZero() &&
19095 sd_match(LHS, m_Add(m_Value(), m_One()))))) {
19096 bool IsAdd = LHS.getOpcode() == ISD::ADD;
19097
19098 SDValue Op0 = LHS.getOperand(0);
19099 SDValue Op1 = LHS.getOperand(1);
19100
19101 SDValue Op0Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op0);
19102 SDValue Op1Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op1);
19103
19104 SDValue Op0Hi = getHiHalf64(Op0, DAG);
19105 SDValue Op1Hi = getHiHalf64(Op1, DAG);
19106
19107 SDValue NodeLo =
19108 DAG.getNode(IsAdd ? ISD::UADDO : ISD::USUBO, SL,
19109 DAG.getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
19110
19111 SDValue CarryInHi = NodeLo.getValue(1);
19112 SDValue NodeHi = DAG.getNode(IsAdd ? ISD::UADDO_CARRY : ISD::USUBO_CARRY,
19113 SL, DAG.getVTList(MVT::i32, MVT::i1),
19114 {Op0Hi, Op1Hi, CarryInHi});
19115
19116 SDValue ResultLo = NodeLo.getValue(0);
19117 SDValue ResultHi = NodeHi.getValue(0);
19118
19119 SDValue JoinedResult =
19120 DAG.getBuildVector(MVT::v2i32, SL, {ResultLo, ResultHi});
19121
19122 SDValue Result = DAG.getNode(ISD::BITCAST, SL, VT, JoinedResult);
19123 SDValue Overflow = NodeHi.getValue(1);
19124 DCI.CombineTo(LHS.getNode(), Result);
19125 return Overflow;
19126 }
19127
19128 if (VT != MVT::f32 && VT != MVT::f64 &&
19129 (!Subtarget->has16BitInsts() || VT != MVT::f16))
19130 return SDValue();
19131
19132 // Match isinf/isfinite pattern
19133 // (fcmp oeq (fabs x), inf) -> (fp_class x, (p_infinity | n_infinity))
19134 // (fcmp one (fabs x), inf) -> (fp_class x,
19135 // (p_normal | n_normal | p_subnormal | n_subnormal | p_zero | n_zero)
19136 if ((CC == ISD::SETOEQ || CC == ISD::SETONE) &&
19137 LHS.getOpcode() == ISD::FABS) {
19138 const ConstantFPSDNode *CRHS = dyn_cast<ConstantFPSDNode>(RHS);
19139 if (!CRHS)
19140 return SDValue();
19141
19142 const APFloat &APF = CRHS->getValueAPF();
19143 if (APF.isInfinity() && !APF.isNegative()) {
19144 const unsigned IsInfMask =
19146 const unsigned IsFiniteMask =
19150 unsigned Mask = CC == ISD::SETOEQ ? IsInfMask : IsFiniteMask;
19151 return DAG.getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1, LHS.getOperand(0),
19152 DAG.getConstant(Mask, SL, MVT::i32));
19153 }
19154 }
19155
19156 if (VT == MVT::f64) {
19158 if (HiHalfCC != ISD::SETCC_INVALID)
19159 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
19160 getHiHalf64(RHS, DAG), HiHalfCC);
19161 }
19162
19163 return SDValue();
19164}
19165
19166SDValue
19167SITargetLowering::performCvtF32UByteNCombine(SDNode *N,
19168 DAGCombinerInfo &DCI) const {
19169 SelectionDAG &DAG = DCI.DAG;
19170 SDLoc SL(N);
19171 unsigned Offset = N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
19172
19173 SDValue Src = N->getOperand(0);
19174 SDValue Shift = N->getOperand(0);
19175
19176 // TODO: Extend type shouldn't matter (assuming legal types).
19177 if (Shift.getOpcode() == ISD::ZERO_EXTEND)
19178 Shift = Shift.getOperand(0);
19179
19180 if (Shift.getOpcode() == ISD::SRL || Shift.getOpcode() == ISD::SHL) {
19181 // cvt_f32_ubyte1 (shl x, 8) -> cvt_f32_ubyte0 x
19182 // cvt_f32_ubyte3 (shl x, 16) -> cvt_f32_ubyte1 x
19183 // cvt_f32_ubyte0 (srl x, 16) -> cvt_f32_ubyte2 x
19184 // cvt_f32_ubyte1 (srl x, 16) -> cvt_f32_ubyte3 x
19185 // cvt_f32_ubyte0 (srl x, 8) -> cvt_f32_ubyte1 x
19186 if (auto *C = dyn_cast<ConstantSDNode>(Shift.getOperand(1))) {
19187 SDValue Shifted = DAG.getZExtOrTrunc(
19188 Shift.getOperand(0), SDLoc(Shift.getOperand(0)), MVT::i32);
19189
19190 unsigned ShiftOffset = 8 * Offset;
19191 if (Shift.getOpcode() == ISD::SHL)
19192 ShiftOffset -= C->getZExtValue();
19193 else
19194 ShiftOffset += C->getZExtValue();
19195
19196 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
19197 return DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
19198 MVT::f32, Shifted);
19199 }
19200 }
19201 }
19202
19204 APInt DemandedBits = APInt::getBitsSet(32, 8 * Offset, 8 * Offset + 8);
19205 if (TLI.SimplifyDemandedBits(Src, DemandedBits, DCI)) {
19206 // We simplified Src. If this node is not dead, visit it again so it is
19207 // folded properly.
19208 if (N->getOpcode() != ISD::DELETED_NODE)
19209 DCI.AddToWorklist(N);
19210 return SDValue(N, 0);
19211 }
19212
19213 // Handle (or x, (srl y, 8)) pattern when known bits are zero.
19214 if (SDValue DemandedSrc =
19215 TLI.SimplifyMultipleUseDemandedBits(Src, DemandedBits, DAG))
19216 return DAG.getNode(N->getOpcode(), SL, MVT::f32, DemandedSrc);
19217
19218 return SDValue();
19219}
19220
19221SDValue SITargetLowering::performClampCombine(SDNode *N,
19222 DAGCombinerInfo &DCI) const {
19223 ConstantFPSDNode *CSrc = dyn_cast<ConstantFPSDNode>(N->getOperand(0));
19224 if (!CSrc)
19225 return SDValue();
19226
19227 const MachineFunction &MF = DCI.DAG.getMachineFunction();
19228 const APFloat &F = CSrc->getValueAPF();
19229 APFloat Zero = APFloat::getZero(F.getSemantics());
19230 if (F < Zero ||
19231 (F.isNaN() && MF.getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
19232 return DCI.DAG.getConstantFP(Zero, SDLoc(N), N->getValueType(0));
19233 }
19234
19235 APFloat One = APFloat::getOne(F.getSemantics());
19236 if (F > One)
19237 return DCI.DAG.getConstantFP(One, SDLoc(N), N->getValueType(0));
19238
19239 return getCanonicalConstantFP(DCI.DAG, SDLoc(N), N->getValueType(0), F);
19240}
19241
19242// Check if V is the exponent result of a frexp operation. Returns the frexp
19243// input via FrexpInput if matched. We only match the exponent (not mantissa)
19244// because V_FREXP_MANT returns its input for Inf/NaN, not zero.
19245static bool isFrexpExp(SDValue V, SDValue &FrexpInput) {
19246 // ISD::FFREXP returns {mant, exp} - only match if using the exp result
19247 // (result number 1).
19248 if (V.getOpcode() == ISD::FFREXP && V.getResNo() == 1) {
19249 FrexpInput = V.getOperand(0);
19250 return true;
19251 }
19253 m_Value(FrexpInput))))
19254 return true;
19255 return false;
19256}
19257
19258SDValue
19259SITargetLowering::performFrexpSelectCombine(SDNode *N,
19260 DAGCombinerInfo &DCI) const {
19261 // This optimization only applies when the hardware handles inf/nan correctly.
19262 if (Subtarget->hasFractBug())
19263 return SDValue();
19264
19265 SDValue Cond = N->getOperand(0);
19266 SDValue TrueVal = N->getOperand(1);
19267 SDValue FalseVal = N->getOperand(2);
19268
19269 // Identify which operand is the frexp result and which is the zero constant.
19270 // Pattern 1: select cond, 0, frexp_result (cond true -> return 0)
19271 // Pattern 2: select cond, frexp_result, 0 (cond false -> return 0)
19272 SDValue FrexpVal;
19273 SDValue ZeroVal;
19274 bool CondSelectsZero; // If true, condition=true selects zero
19275
19276 // Check if FrexpVal comes from ISD::FFREXP (exponent result only) or
19277 // amdgcn_frexp_exp intrinsic.
19278 SDValue FrexpInput;
19279 if (isFrexpExp(FalseVal, FrexpInput)) {
19280 FrexpVal = FalseVal;
19281 ZeroVal = TrueVal;
19282 CondSelectsZero = true;
19283 } else if (isFrexpExp(TrueVal, FrexpInput)) {
19284 FrexpVal = TrueVal;
19285 ZeroVal = FalseVal;
19286 CondSelectsZero = false;
19287 } else {
19288 return SDValue();
19289 }
19290
19291 // frexp_exp returns integer, so check for integer zero.
19292 if (!isNullConstant(ZeroVal))
19293 return SDValue();
19294
19295 // The frexp intrinsics ignore sign, so we can strip sign ops when comparing.
19296 SDValue FrexpInputStripped = peekFPSignOps(FrexpInput);
19297
19298 bool IsNonFiniteTest = false;
19299
19300 // Handle SETCC conditions for inf/nan tests.
19301 // The canonical form of these checks is fcmp + fabs.
19302 if (Cond.getOpcode() == ISD::SETCC) {
19303 ISD::CondCode CC = Cond.getOperandCondCode(2);
19304 SDValue CondLHS = Cond.getOperand(0);
19305 SDValue CondRHS = Cond.getOperand(1);
19306
19307 // Check if LHS is fabs(FrexpInput) - required for infinity comparisons.
19308 SDValue FAbsInput;
19309 bool LHSIsFabs = sd_match(CondLHS, m_FAbs(m_Value(FAbsInput)));
19310 bool LHSMatchesFrexp =
19311 (CondLHS == FrexpInput) ||
19312 (LHSIsFabs && peekFPSignOps(FAbsInput) == FrexpInputStripped) ||
19313 (peekFPSignOps(CondLHS) == FrexpInputStripped);
19314 bool RHSMatchesFrexp = (CondRHS == FrexpInput) ||
19315 (peekFPSignOps(CondRHS) == FrexpInputStripped);
19316
19317 if (CC == ISD::SETUO) {
19318 // fcmp uno x, y - true if either x or y is NaN
19319 // We can only fold if the non-frexp operand is known to never be NaN,
19320 // otherwise the comparison could be true due to the other operand.
19321 // Special case: fcmp uno x, x (same operand) is a valid NaN test.
19322 SelectionDAG &DAG = DCI.DAG;
19323 if (LHSMatchesFrexp &&
19324 (CondLHS == CondRHS || DAG.isKnownNeverNaN(CondRHS)))
19325 IsNonFiniteTest = CondSelectsZero;
19326 else if (RHSMatchesFrexp && DAG.isKnownNeverNaN(CondLHS))
19327 IsNonFiniteTest = CondSelectsZero;
19328 } else if ((CC == ISD::SETOEQ || CC == ISD::SETUEQ) && LHSMatchesFrexp &&
19329 LHSIsFabs &&
19330 sd_match(CondRHS,
19332 CondRHS.getValueType().getFltSemantics())))) {
19333 // fcmp oeq/ueq fabs(x), +inf - true if x is inf (or inf/nan for ueq)
19334 IsNonFiniteTest = CondSelectsZero;
19335 } else if ((CC == ISD::SETONE || CC == ISD::SETUNE) && LHSMatchesFrexp &&
19336 LHSIsFabs &&
19337 sd_match(CondRHS,
19339 CondRHS.getValueType().getFltSemantics())))) {
19340 // fcmp one/une fabs(x), +inf - true if x is NOT inf
19341 IsNonFiniteTest = !CondSelectsZero;
19342 } else if (CC == ISD::SETO) {
19343 // fcmp ord x, y - true if both are NOT NaN
19344 // We can only fold if the non-frexp operand is known to never be NaN,
19345 // otherwise the comparison could be false due to the other operand.
19346 // Special case: fcmp ord x, x (same operand) is a valid not-NaN test.
19347 SelectionDAG &DAG = DCI.DAG;
19348 if (LHSMatchesFrexp &&
19349 (CondLHS == CondRHS || DAG.isKnownNeverNaN(CondRHS)))
19350 IsNonFiniteTest = !CondSelectsZero;
19351 else if (RHSMatchesFrexp && DAG.isKnownNeverNaN(CondLHS))
19352 IsNonFiniteTest = !CondSelectsZero;
19353 }
19354 }
19355
19356 if (!IsNonFiniteTest)
19357 return SDValue();
19358
19359 // The select can be eliminated - just return the frexp result directly.
19360 return FrexpVal;
19361}
19362
19363SDValue SITargetLowering::performSelectCombine(SDNode *N,
19364 DAGCombinerInfo &DCI) const {
19365
19366 // Try to fold CMP + SELECT patterns with shared constants (both FP and
19367 // integer).
19368 // Detect when CMP and SELECT use the same constant and fold them to avoid
19369 // loading the constant twice. Specifically handles patterns like:
19370 // %cmp = icmp eq i32 %val, 4242
19371 // %sel = select i1 %cmp, i32 4242, i32 %other
19372 // It can be optimized to reuse %val instead of 4242 in select.
19373 SDValue Cond = N->getOperand(0);
19374 SDValue TrueVal = N->getOperand(1);
19375 SDValue FalseVal = N->getOperand(2);
19376
19377 // Check if condition is a comparison.
19378 if (Cond.getOpcode() != ISD::SETCC)
19379 return SDValue();
19380
19381 SDValue LHS = Cond.getOperand(0);
19382 SDValue RHS = Cond.getOperand(1);
19383 ISD::CondCode CC = Cond.getOperandCondCode(2);
19384
19385 bool isFloatingPoint = LHS.getValueType().isFloatingPoint();
19386 bool isInteger = LHS.getValueType().isInteger();
19387
19388 // Handle simple floating-point and integer types only.
19389 if (!isFloatingPoint && !isInteger)
19390 return SDValue();
19391
19392 // Bare SETEQ/SETNE is the builder's NaN-impossible downgrade.
19393 bool isEquality = CC == ISD::SETEQ || (isFloatingPoint && CC == ISD::SETOEQ);
19394 bool isNonEquality =
19395 CC == ISD::SETNE || (isFloatingPoint && CC == ISD::SETONE);
19396 if (!isEquality && !isNonEquality)
19397 return SDValue();
19398
19399 SDValue ArgVal, ConstVal;
19400 if ((isFloatingPoint && isa<ConstantFPSDNode>(RHS)) ||
19401 (isInteger && isa<ConstantSDNode>(RHS))) {
19402 ConstVal = RHS;
19403 ArgVal = LHS;
19404 } else if ((isFloatingPoint && isa<ConstantFPSDNode>(LHS)) ||
19405 (isInteger && isa<ConstantSDNode>(LHS))) {
19406 ConstVal = LHS;
19407 ArgVal = RHS;
19408 } else {
19409 return SDValue();
19410 }
19411
19412 // Skip optimization for inlinable immediates.
19413 if (isFloatingPoint) {
19414 const APFloat &Val = cast<ConstantFPSDNode>(ConstVal)->getValueAPF();
19415 if (!Val.isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
19416 return SDValue();
19417 } else {
19418 const std::optional<int64_t> Val =
19419 cast<ConstantSDNode>(ConstVal)->getAPIntValue().trySExtValue();
19420 if (Val && AMDGPU::isInlinableIntLiteral(*Val))
19421 return SDValue();
19422 }
19423
19424 // For equality and non-equality comparisons, patterns:
19425 // select (setcc x, const), const, y -> select (setcc x, const), x, y
19426 // select (setccinv x, const), y, const -> select (setccinv x, const), y, x
19427 if (!(isEquality && TrueVal == ConstVal) &&
19428 !(isNonEquality && FalseVal == ConstVal))
19429 return SDValue();
19430
19431 // SETONE's false arm is also taken for NaN ArgVal, so require NaN excluded.
19432 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
19433 !Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
19434 return SDValue();
19435
19436 SDValue SelectLHS = (isEquality && TrueVal == ConstVal) ? ArgVal : TrueVal;
19437 SDValue SelectRHS =
19438 (isNonEquality && FalseVal == ConstVal) ? ArgVal : FalseVal;
19439 return DCI.DAG.getNode(ISD::SELECT, SDLoc(N), N->getValueType(0), Cond,
19440 SelectLHS, SelectRHS);
19441}
19442
19444 DAGCombinerInfo &DCI) const {
19445 switch (N->getOpcode()) {
19446 case ISD::ABS:
19447 if (SDValue Res = promoteUniformUnaryOpToI32(SDValue(N, 0), DCI))
19448 return Res;
19449 break;
19450 case ISD::ADD:
19451 case ISD::SUB:
19452 case ISD::SHL:
19453 case ISD::SRL:
19454 case ISD::SRA:
19455 case ISD::AND:
19456 case ISD::OR:
19457 case ISD::XOR:
19458 case ISD::MUL:
19459 case ISD::SETCC:
19460 case ISD::SELECT:
19461 case ISD::SMIN:
19462 case ISD::SMAX:
19463 case ISD::UMIN:
19464 case ISD::UMAX:
19465 case ISD::USUBSAT:
19466 case ISD::UADDSAT:
19467 if (auto Res = promoteUniformOpToI32(SDValue(N, 0), DCI))
19468 return Res;
19469 break;
19470 default:
19471 break;
19472 }
19473
19474 if (getTargetMachine().getOptLevel() == CodeGenOptLevel::None)
19475 return SDValue();
19476
19477 switch (N->getOpcode()) {
19478 case ISD::ADD:
19479 return performAddCombine(N, DCI);
19480 case ISD::PTRADD:
19481 return performPtrAddCombine(N, DCI);
19482 case ISD::SUB:
19483 return performSubCombine(N, DCI);
19484 case ISD::FADD:
19485 return performFAddCombine(N, DCI);
19486 case ISD::FSUB:
19487 return performFSubCombine(N, DCI);
19488 case ISD::FDIV:
19489 return performFDivCombine(N, DCI);
19490 case ISD::FMUL:
19491 return performFMulCombine(N, DCI);
19492 case ISD::SETCC:
19493 return performSetCCCombine(N, DCI);
19494 case ISD::SELECT:
19495 if (auto Res = performFrexpSelectCombine(N, DCI))
19496 return Res;
19497 if (auto Res = performSelectCombine(N, DCI))
19498 return Res;
19499 break;
19500 case ISD::FMAXNUM:
19501 case ISD::FMINNUM:
19502 case ISD::FMAXNUM_IEEE:
19503 case ISD::FMINNUM_IEEE:
19504 case ISD::FMAXIMUM:
19505 case ISD::FMINIMUM:
19506 case ISD::FMAXIMUMNUM:
19507 case ISD::FMINIMUMNUM:
19508 case ISD::SMAX:
19509 case ISD::SMIN:
19510 case ISD::UMAX:
19511 case ISD::UMIN:
19512 case AMDGPUISD::FMIN_LEGACY:
19513 case AMDGPUISD::FMAX_LEGACY:
19514 return performMinMaxCombine(N, DCI);
19515 case ISD::FMA:
19516 return performFMACombine(N, DCI);
19517 case ISD::AND:
19518 return performAndCombine(N, DCI);
19519 case ISD::OR:
19520 return performOrCombine(N, DCI);
19521 case ISD::FSHR: {
19523 if (N->getValueType(0) == MVT::i32 && N->isDivergent() &&
19524 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19525 return matchPERM(N, DCI);
19526 }
19527 break;
19528 }
19529 case ISD::XOR:
19530 return performXorCombine(N, DCI);
19531 case ISD::ANY_EXTEND:
19532 case ISD::ZERO_EXTEND:
19533 return performZeroOrAnyExtendCombine(N, DCI);
19534 case ISD::SIGN_EXTEND:
19535 return performExtendTruncShiftCombine(N, DCI);
19537 return performSignExtendInRegCombine(N, DCI);
19538 case AMDGPUISD::FP_CLASS:
19539 return performClassCombine(N, DCI);
19540 case ISD::FCANONICALIZE:
19541 return performFCanonicalizeCombine(N, DCI);
19542 case AMDGPUISD::RCP:
19543 return performRcpCombine(N, DCI);
19544 case ISD::FLDEXP:
19545 case AMDGPUISD::FRACT:
19546 case AMDGPUISD::RSQ:
19547 case AMDGPUISD::RCP_LEGACY:
19548 case AMDGPUISD::RCP_IFLAG:
19549 case AMDGPUISD::RSQ_CLAMP: {
19550 // FIXME: This is probably wrong. If src is an sNaN, it won't be quieted
19551 SDValue Src = N->getOperand(0);
19552 if (Src.isUndef())
19553 return Src;
19554 break;
19555 }
19556 case ISD::SINT_TO_FP:
19557 case ISD::UINT_TO_FP:
19558 return performUCharToFloatCombine(N, DCI);
19559 case ISD::FCOPYSIGN:
19560 return performFCopySignCombine(N, DCI);
19561 case AMDGPUISD::CVT_F32_UBYTE0:
19562 case AMDGPUISD::CVT_F32_UBYTE1:
19563 case AMDGPUISD::CVT_F32_UBYTE2:
19564 case AMDGPUISD::CVT_F32_UBYTE3:
19565 return performCvtF32UByteNCombine(N, DCI);
19566 case AMDGPUISD::FMED3:
19567 return performFMed3Combine(N, DCI);
19568 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19569 return performCvtPkRTZCombine(N, DCI);
19571 if (SDValue Res = performExponentOnlyScaleCombine(N, DCI))
19572 return Res;
19573 break;
19574 case AMDGPUISD::CLAMP:
19575 return performClampCombine(N, DCI);
19576 case ISD::SCALAR_TO_VECTOR: {
19577 SelectionDAG &DAG = DCI.DAG;
19578 EVT VT = N->getValueType(0);
19579
19580 // v2i16 (scalar_to_vector i16:x) -> v2i16 (bitcast (any_extend i16:x))
19581 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19582 SDLoc SL(N);
19583 SDValue Src = N->getOperand(0);
19584 EVT EltVT = Src.getValueType();
19585 if (EltVT != MVT::i16)
19586 Src = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
19587
19588 SDValue Ext = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Src);
19589 return DAG.getNode(ISD::BITCAST, SL, VT, Ext);
19590 }
19591
19592 break;
19593 }
19595 return performExtractVectorEltCombine(N, DCI);
19597 return performInsertVectorEltCombine(N, DCI);
19598 case ISD::FP_ROUND:
19599 return performFPRoundCombine(N, DCI);
19600 case ISD::LOAD: {
19601 if (SDValue Widened = widenLoad(cast<LoadSDNode>(N), DCI))
19602 return Widened;
19603 [[fallthrough]];
19604 }
19605 default: {
19606 if (!DCI.isBeforeLegalize()) {
19607 if (MemSDNode *MemNode = dyn_cast<MemSDNode>(N))
19608 return performMemSDNodeCombine(MemNode, DCI);
19609 }
19610
19611 break;
19612 }
19613 }
19614
19616}
19617
19618/// Helper function for adjustWritemask
19619static unsigned SubIdx2Lane(unsigned Idx) {
19620 switch (Idx) {
19621 default:
19622 return ~0u;
19623 case AMDGPU::sub0:
19624 return 0;
19625 case AMDGPU::sub1:
19626 return 1;
19627 case AMDGPU::sub2:
19628 return 2;
19629 case AMDGPU::sub3:
19630 return 3;
19631 case AMDGPU::sub4:
19632 return 4; // Possible with TFE/LWE
19633 }
19634}
19635
19636/// Adjust the writemask of MIMG, VIMAGE or VSAMPLE instructions
19637SDNode *SITargetLowering::adjustWritemask(MachineSDNode *&Node,
19638 SelectionDAG &DAG) const {
19639 unsigned Opcode = Node->getMachineOpcode();
19640
19641 // Subtract 1 because the vdata output is not a MachineSDNode operand.
19642 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19643 if (D16Idx >= 0 && Node->getConstantOperandVal(D16Idx))
19644 return Node; // not implemented for D16
19645
19646 SDNode *Users[5] = {nullptr};
19647 unsigned Lane = 0;
19648 unsigned DmaskIdx =
19649 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19650 unsigned OldDmask = Node->getConstantOperandVal(DmaskIdx);
19651 unsigned NewDmask = 0;
19652 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19653 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19654 bool UsesTFC = (int(TFEIdx) >= 0 && Node->getConstantOperandVal(TFEIdx)) ||
19655 (int(LWEIdx) >= 0 && Node->getConstantOperandVal(LWEIdx));
19656 unsigned TFCLane = 0;
19657 bool HasChain = Node->getNumValues() > 1;
19658
19659 if (OldDmask == 0) {
19660 // These are folded out, but on the chance it happens don't assert.
19661 return Node;
19662 }
19663
19664 unsigned OldBitsSet = llvm::popcount(OldDmask);
19665 // Work out which is the TFE/LWE lane if that is enabled.
19666 if (UsesTFC) {
19667 TFCLane = OldBitsSet;
19668 }
19669
19670 // Try to figure out the used register components
19671 for (SDUse &Use : Node->uses()) {
19672
19673 // Don't look at users of the chain.
19674 if (Use.getResNo() != 0)
19675 continue;
19676
19677 SDNode *User = Use.getUser();
19678
19679 // Abort if we can't understand the usage
19680 if (!User->isMachineOpcode() ||
19681 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19682 return Node;
19683
19684 // Lane means which subreg of %vgpra_vgprb_vgprc_vgprd is used.
19685 // Note that subregs are packed, i.e. Lane==0 is the first bit set
19686 // in OldDmask, so it can be any of X,Y,Z,W; Lane==1 is the second bit
19687 // set, etc.
19688 Lane = SubIdx2Lane(User->getConstantOperandVal(1));
19689 if (Lane == ~0u)
19690 return Node;
19691
19692 // Check if the use is for the TFE/LWE generated result at VGPRn+1.
19693 if (UsesTFC && Lane == TFCLane) {
19694 Users[Lane] = User;
19695 } else {
19696 // Set which texture component corresponds to the lane.
19697 unsigned Comp;
19698 for (unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19699 Comp = llvm::countr_zero(Dmask);
19700 Dmask &= ~(1 << Comp);
19701 }
19702
19703 // Abort if we have more than one user per component.
19704 if (Users[Lane])
19705 return Node;
19706
19707 Users[Lane] = User;
19708 NewDmask |= 1 << Comp;
19709 }
19710 }
19711
19712 // Don't allow 0 dmask, as hardware assumes one channel enabled.
19713 bool NoChannels = !NewDmask;
19714 if (NoChannels) {
19715 if (!UsesTFC) {
19716 // No uses of the result and not using TFC. Then do nothing.
19717 return Node;
19718 }
19719 // If the original dmask has one channel - then nothing to do
19720 if (OldBitsSet == 1)
19721 return Node;
19722 // Use an arbitrary dmask - required for the instruction to work
19723 NewDmask = 1;
19724 }
19725 // Abort if there's no change
19726 if (NewDmask == OldDmask)
19727 return Node;
19728
19729 unsigned BitsSet = llvm::popcount(NewDmask);
19730
19731 // Check for TFE or LWE - increase the number of channels by one to account
19732 // for the extra return value
19733 // This will need adjustment for D16 if this is also included in
19734 // adjustWriteMask (this function) but at present D16 are excluded.
19735 unsigned NewChannels = BitsSet + UsesTFC;
19736
19737 int NewOpcode =
19738 AMDGPU::getMaskedMIMGOp(Node->getMachineOpcode(), NewChannels);
19739 assert(NewOpcode != -1 &&
19740 NewOpcode != static_cast<int>(Node->getMachineOpcode()) &&
19741 "failed to find equivalent MIMG op");
19742
19743 // Adjust the writemask in the node
19745 llvm::append_range(Ops, Node->ops().take_front(DmaskIdx));
19746 Ops.push_back(DAG.getTargetConstant(NewDmask, SDLoc(Node), MVT::i32));
19747 llvm::append_range(Ops, Node->ops().drop_front(DmaskIdx + 1));
19748
19749 MVT SVT = Node->getValueType(0).getVectorElementType().getSimpleVT();
19750
19751 MVT ResultVT = NewChannels == 1
19752 ? SVT
19753 : MVT::getVectorVT(SVT, NewChannels == 3 ? 4
19754 : NewChannels == 5 ? 8
19755 : NewChannels);
19756 SDVTList NewVTList =
19757 HasChain ? DAG.getVTList(ResultVT, MVT::Other) : DAG.getVTList(ResultVT);
19758
19759 MachineSDNode *NewNode =
19760 DAG.getMachineNode(NewOpcode, SDLoc(Node), NewVTList, Ops);
19761
19762 if (HasChain) {
19763 // Update chain.
19764 DAG.setNodeMemRefs(NewNode, Node->memoperands());
19765 DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), SDValue(NewNode, 1));
19766 }
19767
19768 if (NewChannels == 1) {
19769 assert(Node->hasNUsesOfValue(1, 0));
19770 SDNode *Copy =
19771 DAG.getMachineNode(TargetOpcode::COPY, SDLoc(Node),
19772 Users[Lane]->getValueType(0), SDValue(NewNode, 0));
19773 DAG.ReplaceAllUsesWith(Users[Lane], Copy);
19774 return nullptr;
19775 }
19776
19777 // Update the users of the node with the new indices
19778 for (unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19779 SDNode *User = Users[i];
19780 if (!User) {
19781 // Handle the special case of NoChannels. We set NewDmask to 1 above, but
19782 // Users[0] is still nullptr because channel 0 doesn't really have a use.
19783 if (i || !NoChannels)
19784 continue;
19785 } else {
19786 SDValue Op = DAG.getTargetConstant(Idx, SDLoc(User), MVT::i32);
19787 SDNode *NewUser = DAG.UpdateNodeOperands(User, SDValue(NewNode, 0), Op);
19788 if (NewUser != User) {
19789 DAG.ReplaceAllUsesWith(SDValue(User, 0), SDValue(NewUser, 0));
19790 DAG.RemoveDeadNode(User);
19791 }
19792 }
19793
19794 switch (Idx) {
19795 default:
19796 break;
19797 case AMDGPU::sub0:
19798 Idx = AMDGPU::sub1;
19799 break;
19800 case AMDGPU::sub1:
19801 Idx = AMDGPU::sub2;
19802 break;
19803 case AMDGPU::sub2:
19804 Idx = AMDGPU::sub3;
19805 break;
19806 case AMDGPU::sub3:
19807 Idx = AMDGPU::sub4;
19808 break;
19809 }
19810 }
19811
19812 DAG.RemoveDeadNode(Node);
19813 return nullptr;
19814}
19815
19817 if (Op.getOpcode() == ISD::AssertZext)
19818 Op = Op.getOperand(0);
19819
19820 return isa<FrameIndexSDNode>(Op);
19821}
19822
19823/// Legalize target independent instructions (e.g. INSERT_SUBREG)
19824/// with frame index operands.
19825/// LLVM assumes that inputs are to these instructions are registers.
19826SDNode *
19828 SelectionDAG &DAG) const {
19829 if (Node->getOpcode() == ISD::CopyToReg) {
19830 RegisterSDNode *DestReg = cast<RegisterSDNode>(Node->getOperand(1));
19831 SDValue SrcVal = Node->getOperand(2);
19832
19833 // Insert a copy to a VReg_1 virtual register so LowerI1Copies doesn't have
19834 // to try understanding copies to physical registers.
19835 if (SrcVal.getValueType() == MVT::i1 && DestReg->getReg().isPhysical()) {
19836 SDLoc SL(Node);
19838 SDValue VReg = DAG.getRegister(
19839 MRI.createVirtualRegister(&AMDGPU::VReg_1RegClass), MVT::i1);
19840
19841 SDNode *Glued = Node->getGluedNode();
19842 SDValue ToVReg = DAG.getCopyToReg(
19843 Node->getOperand(0), SL, VReg, SrcVal,
19844 SDValue(Glued, Glued ? Glued->getNumValues() - 1 : 0));
19845 SDValue ToResultReg = DAG.getCopyToReg(ToVReg, SL, SDValue(DestReg, 0),
19846 VReg, ToVReg.getValue(1));
19847 DAG.ReplaceAllUsesWith(Node, ToResultReg.getNode());
19848 DAG.RemoveDeadNode(Node);
19849 return ToResultReg.getNode();
19850 }
19851 }
19852
19854 for (unsigned i = 0; i < Node->getNumOperands(); ++i) {
19855 if (!isFrameIndexOp(Node->getOperand(i))) {
19856 Ops.push_back(Node->getOperand(i));
19857 continue;
19858 }
19859
19860 SDLoc DL(Node);
19861 Ops.push_back(SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL,
19862 Node->getOperand(i).getValueType(),
19863 Node->getOperand(i)),
19864 0));
19865 }
19866
19867 return DAG.UpdateNodeOperands(Node, Ops);
19868}
19869
19870/// Fold the instructions after selecting them.
19871/// Returns null if users were already updated.
19873 SelectionDAG &DAG) const {
19875 unsigned Opcode = Node->getMachineOpcode();
19876
19877 if (TII->isImage(Opcode) && !TII->get(Opcode).mayStore() &&
19878 !TII->isGather4(Opcode) &&
19879 AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::dmask)) {
19880 return adjustWritemask(Node, DAG);
19881 }
19882
19883 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19885 return Node;
19886 }
19887
19888 switch (Opcode) {
19889 case AMDGPU::V_DIV_SCALE_F32_e64:
19890 case AMDGPU::V_DIV_SCALE_F64_e64: {
19891 // Satisfy the operand register constraint when one of the inputs is
19892 // undefined. Ordinarily each undef value will have its own implicit_def of
19893 // a vreg, so force these to use a single register.
19894 SDValue Src0 = Node->getOperand(1);
19895 SDValue Src1 = Node->getOperand(3);
19896 SDValue Src2 = Node->getOperand(5);
19897
19898 if ((Src0.isMachineOpcode() &&
19899 Src0.getMachineOpcode() != AMDGPU::IMPLICIT_DEF) &&
19900 (Src0 == Src1 || Src0 == Src2))
19901 break;
19902
19903 MVT VT = Src0.getValueType().getSimpleVT();
19904 const TargetRegisterClass *RC =
19905 getRegClassFor(VT, Src0.getNode()->isDivergent());
19906
19908 SDValue UndefReg = DAG.getRegister(MRI.createVirtualRegister(RC), VT);
19909
19910 SDValue ImpDef = DAG.getCopyToReg(DAG.getEntryNode(), SDLoc(Node), UndefReg,
19911 Src0, SDValue());
19912
19913 // src0 must be the same register as src1 or src2, even if the value is
19914 // undefined, so make sure we don't violate this constraint.
19915 if (Src0.isMachineOpcode() &&
19916 Src0.getMachineOpcode() == AMDGPU::IMPLICIT_DEF) {
19917 if (Src1.isMachineOpcode() &&
19918 Src1.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19919 Src0 = Src1;
19920 else if (Src2.isMachineOpcode() &&
19921 Src2.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19922 Src0 = Src2;
19923 else {
19924 assert(Src1.getMachineOpcode() == AMDGPU::IMPLICIT_DEF);
19925 Src0 = UndefReg;
19926 Src1 = UndefReg;
19927 }
19928 } else
19929 break;
19930
19932 Ops[1] = Src0;
19933 Ops[3] = Src1;
19934 Ops[5] = Src2;
19935 Ops.push_back(ImpDef.getValue(1));
19936 return DAG.getMachineNode(Opcode, SDLoc(Node), Node->getVTList(), Ops);
19937 }
19938 default:
19939 break;
19940 }
19941
19942 return Node;
19943}
19944
19945// Any MIMG instructions that use tfe or lwe require an initialization of the
19946// result register that will be written in the case of a memory access failure.
19947// The required code is also added to tie this init code to the result of the
19948// img instruction.
19951 const SIRegisterInfo &TRI = TII->getRegisterInfo();
19952 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
19953 MachineBasicBlock &MBB = *MI.getParent();
19954
19955 int DstIdx =
19956 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
19957 unsigned InitIdx = 0;
19958
19959 if (TII->isImage(MI)) {
19960 MachineOperand *TFE = TII->getNamedOperand(MI, AMDGPU::OpName::tfe);
19961 MachineOperand *LWE = TII->getNamedOperand(MI, AMDGPU::OpName::lwe);
19962 MachineOperand *D16 = TII->getNamedOperand(MI, AMDGPU::OpName::d16);
19963
19964 if (!TFE && !LWE) // intersect_ray
19965 return;
19966
19967 unsigned TFEVal = TFE ? TFE->getImm() : 0;
19968 unsigned LWEVal = LWE ? LWE->getImm() : 0;
19969 unsigned D16Val = D16 ? D16->getImm() : 0;
19970
19971 if (!TFEVal && !LWEVal)
19972 return;
19973
19974 // At least one of TFE or LWE are non-zero
19975 // We have to insert a suitable initialization of the result value and
19976 // tie this to the dest of the image instruction.
19977
19978 // Calculate which dword we have to initialize to 0.
19979 MachineOperand *MO_Dmask = TII->getNamedOperand(MI, AMDGPU::OpName::dmask);
19980
19981 // check that dmask operand is found.
19982 assert(MO_Dmask && "Expected dmask operand in instruction");
19983
19984 unsigned dmask = MO_Dmask->getImm();
19985 // Determine the number of active lanes taking into account the
19986 // Gather4 special case
19987 unsigned ActiveLanes = TII->isGather4(MI) ? 4 : llvm::popcount(dmask);
19988
19989 bool Packed = !Subtarget->hasUnpackedD16VMem();
19990
19991 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19992
19993 // Abandon attempt if the dst size isn't large enough
19994 // - this is in fact an error but this is picked up elsewhere and
19995 // reported correctly.
19996 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
19997
19998 uint32_t DstSize = TRI.getRegSizeInBits(*DstRC) / 32;
19999 if (DstSize < InitIdx)
20000 return;
20001 } else if (TII->isMUBUF(MI) && AMDGPU::getMUBUFTfe(MI.getOpcode())) {
20002 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
20003 InitIdx = TRI.getRegSizeInBits(*DstRC) / 32;
20004 } else {
20005 return;
20006 }
20007
20008 const DebugLoc &DL = MI.getDebugLoc();
20009
20010 // Create a register for the initialization value.
20011 Register PrevDst = MRI.cloneVirtualRegister(MI.getOperand(DstIdx).getReg());
20012 unsigned NewDst = 0; // Final initialized value will be in here
20013
20014 // If PRTStrictNull feature is enabled (the default) then initialize
20015 // all the result registers to 0, otherwise just the error indication
20016 // register (VGPRn+1)
20017 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
20018 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
20019
20020 BuildMI(MBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), PrevDst);
20021 for (; SizeLeft; SizeLeft--, CurrIdx++) {
20022 NewDst = MRI.createVirtualRegister(TII->getOpRegClass(MI, DstIdx));
20023 // Initialize dword
20024 Register SubReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
20025 // clang-format off
20026 BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), SubReg)
20027 .addImm(0);
20028 // clang-format on
20029 // Insert into the super-reg
20030 BuildMI(MBB, MI, DL, TII->get(TargetOpcode::INSERT_SUBREG), NewDst)
20031 .addReg(PrevDst)
20032 .addReg(SubReg)
20034
20035 PrevDst = NewDst;
20036 }
20037
20038 // Add as an implicit operand
20039 MI.addOperand(MachineOperand::CreateReg(NewDst, false, true));
20040
20041 // Tie the just added implicit operand to the dst
20042 MI.tieOperands(DstIdx, MI.getNumOperands() - 1);
20043}
20044
20045/// Assign the register class depending on the number of
20046/// bits set in the writemask
20048 SDNode *Node) const {
20050
20051 MachineFunction *MF = MI.getMF();
20053
20054 if (TII->isVOP3(MI.getOpcode())) {
20055 // Make sure constant bus requirements are respected.
20056 TII->legalizeOperandsVOP3(MRI, MI);
20057
20058 if (TII->isMAI(MI)) {
20059 // The ordinary src0, src1, src2 were legalized above.
20060 //
20061 // We have to also legalize the appended v_mfma_ld_scale_b32 operands,
20062 // as a separate instruction.
20063 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
20064 AMDGPU::OpName::scale_src0);
20065 if (Src0Idx != -1) {
20066 int Src1Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
20067 AMDGPU::OpName::scale_src1);
20068 if (TII->usesConstantBus(MRI, MI, Src0Idx) &&
20069 TII->usesConstantBus(MRI, MI, Src1Idx))
20070 TII->legalizeOpWithMove(MI, Src1Idx);
20071 }
20072 }
20073
20074 return;
20075 }
20076
20077 if (TII->isImage(MI))
20078 TII->enforceOperandRCAlignment(MI, AMDGPU::OpName::vaddr);
20079}
20080
20082 uint64_t Val) {
20083 SDValue K = DAG.getTargetConstant(Val, DL, MVT::i32);
20084 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, K), 0);
20085}
20086
20088 const SDLoc &DL,
20089 SDValue Ptr) const {
20091
20092 // Build the half of the subregister with the constants before building the
20093 // full 128-bit register. If we are building multiple resource descriptors,
20094 // this will allow CSEing of the 2-component register.
20095 const SDValue Ops0[] = {
20096 DAG.getTargetConstant(AMDGPU::SGPR_64RegClassID, DL, MVT::i32),
20097 buildSMovImm32(DAG, DL, 0),
20098 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
20099 buildSMovImm32(DAG, DL, TII->getDefaultRsrcDataFormat() >> 32),
20100 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32)};
20101
20102 SDValue SubRegHi = SDValue(
20103 DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v2i32, Ops0), 0);
20104
20105 // Combine the constants and the pointer.
20106 const SDValue Ops1[] = {
20107 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32), Ptr,
20108 DAG.getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32), SubRegHi,
20109 DAG.getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32)};
20110
20111 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops1);
20112}
20113
20114/// Return a resource descriptor with the 'Add TID' bit enabled
20115/// The TID (Thread ID) is multiplied by the stride value (bits [61:48]
20116/// of the resource descriptor) to create an offset, which is added to
20117/// the resource pointer.
20119 SDValue Ptr, uint32_t RsrcDword1,
20120 uint64_t RsrcDword2And3) const {
20121 SDValue PtrLo = DAG.getTargetExtractSubreg(AMDGPU::sub0, DL, MVT::i32, Ptr);
20122 SDValue PtrHi = DAG.getTargetExtractSubreg(AMDGPU::sub1, DL, MVT::i32, Ptr);
20123 if (RsrcDword1) {
20124 PtrHi = DAG.getNode(ISD::OR, DL, MVT::i32, PtrHi,
20125 DAG.getConstant(RsrcDword1, DL, MVT::i32));
20126 }
20127
20128 SDValue DataLo =
20129 buildSMovImm32(DAG, DL, RsrcDword2And3 & UINT64_C(0xFFFFFFFF));
20130 SDValue DataHi = buildSMovImm32(DAG, DL, RsrcDword2And3 >> 32);
20131
20132 const SDValue Ops[] = {
20133 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32),
20134 PtrLo,
20135 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
20136 PtrHi,
20137 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32),
20138 DataLo,
20139 DAG.getTargetConstant(AMDGPU::sub2, DL, MVT::i32),
20140 DataHi,
20141 DAG.getTargetConstant(AMDGPU::sub3, DL, MVT::i32)};
20142
20143 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops);
20144}
20145
20146//===----------------------------------------------------------------------===//
20147// SI Inline Assembly Support
20148//===----------------------------------------------------------------------===//
20149
20150std::pair<unsigned, const TargetRegisterClass *>
20152 StringRef Constraint,
20153 MVT VT) const {
20154 const SIRegisterInfo *TRI = static_cast<const SIRegisterInfo *>(TRI_);
20155
20156 const TargetRegisterClass *RC = nullptr;
20157 if (Constraint.size() == 1) {
20158 // Check if we cannot determine the bit size of the given value type. This
20159 // can happen, for example, in this situation where we have an empty struct
20160 // (size 0): `call void asm "", "v"({} poison)`-
20161 if (VT == MVT::Other)
20162 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20163 const unsigned BitWidth = VT.getSizeInBits();
20164 switch (Constraint[0]) {
20165 default:
20166 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20167 case 's':
20168 case 'r':
20169 switch (BitWidth) {
20170 case 16:
20171 RC = &AMDGPU::SReg_32RegClass;
20172 break;
20173 case 64:
20174 RC = &AMDGPU::SGPR_64RegClass;
20175 break;
20176 default:
20178 if (!RC)
20179 return std::pair(0U, nullptr);
20180 break;
20181 }
20182 break;
20183 case 'v':
20184 switch (BitWidth) {
20185 case 1:
20186 return std::pair(0U, nullptr);
20187 case 16:
20188 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
20189 : &AMDGPU::VGPR_32_Lo256RegClass;
20190 break;
20191 default:
20192 RC = Subtarget->hasVGPRMSBs()
20193 ? TRI->getAlignedLo256VGPRClassForBitWidth(BitWidth)
20194 : TRI->getVGPRClassForBitWidth(BitWidth);
20195 if (!RC)
20196 return std::pair(0U, nullptr);
20197 break;
20198 }
20199 break;
20200 case 'a':
20201 if (!Subtarget->hasMAIInsts())
20202 break;
20203 switch (BitWidth) {
20204 case 1:
20205 return std::pair(0U, nullptr);
20206 case 16:
20207 RC = &AMDGPU::AGPR_32RegClass;
20208 break;
20209 default:
20210 RC = TRI->getAGPRClassForBitWidth(BitWidth);
20211 if (!RC)
20212 return std::pair(0U, nullptr);
20213 break;
20214 }
20215 break;
20216 }
20217 } else if (Constraint == "VA" && Subtarget->hasGFX90AInsts()) {
20218 const unsigned BitWidth = VT.getSizeInBits();
20219 switch (BitWidth) {
20220 case 16:
20221 RC = &AMDGPU::AV_32RegClass;
20222 break;
20223 default:
20224 RC = TRI->getVectorSuperClassForBitWidth(BitWidth);
20225 if (!RC)
20226 return std::pair(0U, nullptr);
20227 break;
20228 }
20229 }
20230
20231 // We actually support i128, i16 and f16 as inline parameters
20232 // even if they are not reported as legal
20233 if (RC && (isTypeLegal(VT) || VT.SimpleTy == MVT::i128 ||
20234 VT.SimpleTy == MVT::i16 || VT.SimpleTy == MVT::f16))
20235 return std::pair(0U, RC);
20236
20237 auto [Kind, Idx, NumRegs] = AMDGPU::parseAsmConstraintPhysReg(Constraint);
20238 if (Kind != '\0') {
20239 if (Kind == 'v') {
20240 RC = &AMDGPU::VGPR_32_Lo256RegClass;
20241 } else if (Kind == 's') {
20242 RC = &AMDGPU::SGPR_32RegClass;
20243 } else if (Kind == 'a') {
20244 RC = &AMDGPU::AGPR_32RegClass;
20245 }
20246
20247 if (RC) {
20248 if (NumRegs > 1) {
20249 if (Idx >= RC->getNumRegs() || Idx + NumRegs - 1 >= RC->getNumRegs())
20250 return std::pair(0U, nullptr);
20251
20252 uint32_t Width = NumRegs * 32;
20253 // Prohibit constraints for register ranges with a width that does not
20254 // match the required type.
20255 if (VT.SimpleTy != MVT::Other && Width != VT.getSizeInBits())
20256 return std::pair(0U, nullptr);
20257
20258 MCRegister Reg = RC->getRegister(Idx);
20260 RC = TRI->getVGPRClassForBitWidth(Width);
20261 else if (SIRegisterInfo::isSGPRClass(RC))
20262 RC = TRI->getSGPRClassForBitWidth(Width);
20263 else if (SIRegisterInfo::isAGPRClass(RC))
20264 RC = TRI->getAGPRClassForBitWidth(Width);
20265 if (RC) {
20266 Reg = TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
20267 if (!Reg) {
20268 // The register class does not contain the requested register,
20269 // e.g., because it is an SGPR pair that would violate alignment
20270 // requirements.
20271 return std::pair(0U, nullptr);
20272 }
20273 return std::pair(Reg, RC);
20274 }
20275 }
20276
20277 // Reject types that do not fit a single 32-bit register: any scalar wider
20278 // than 32 bits, or a vector that is not exactly 32 bits.
20279 if (VT.SimpleTy != MVT::Other &&
20280 (VT.getSizeInBits() > 32 ||
20281 (VT.isVector() && VT.getSizeInBits() != 32)))
20282 return std::pair(0U, nullptr);
20283 if (RC && Idx < RC->getNumRegs())
20284 return std::pair(RC->getRegister(Idx), RC);
20285 return std::pair(0U, nullptr);
20286 }
20287 }
20288
20289 auto Ret = TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
20290 if (Ret.first) {
20291 Ret.second = TRI->getPhysRegBaseClass(Ret.first);
20292 if (!Subtarget->useRealTrue16Insts() &&
20293 TRI->getRegSizeInBits(*Ret.second) == 16)
20294 return std::pair(0U, nullptr);
20295 }
20296
20297 return Ret;
20298}
20299
20300static bool isImmConstraint(StringRef Constraint) {
20301 if (Constraint.size() == 1) {
20302 switch (Constraint[0]) {
20303 default:
20304 break;
20305 case 'I':
20306 case 'J':
20307 case 'A':
20308 case 'B':
20309 case 'C':
20310 return true;
20311 }
20312 } else if (Constraint == "DA" || Constraint == "DB") {
20313 return true;
20314 }
20315 return false;
20316}
20317
20320 if (Constraint.size() == 1) {
20321 switch (Constraint[0]) {
20322 default:
20323 break;
20324 case 's':
20325 case 'v':
20326 case 'a':
20327 return C_RegisterClass;
20328 }
20329 } else if (Constraint.size() == 2) {
20330 if (Constraint == "VA")
20331 return C_RegisterClass;
20332 }
20333 if (isImmConstraint(Constraint)) {
20334 return C_Other;
20335 }
20336 return TargetLowering::getConstraintType(Constraint);
20337}
20338
20339static uint64_t clearUnusedBits(uint64_t Val, unsigned Size) {
20341 Val = Val & maskTrailingOnes<uint64_t>(Size);
20342 }
20343 return Val;
20344}
20345
20347 StringRef Constraint,
20348 std::vector<SDValue> &Ops,
20349 SelectionDAG &DAG) const {
20350 if (isImmConstraint(Constraint)) {
20351 uint64_t Val;
20352 if (getAsmOperandConstVal(Op, Val) &&
20353 checkAsmConstraintVal(Op, Constraint, Val)) {
20354 Val = clearUnusedBits(Val, Op.getScalarValueSizeInBits());
20355 Ops.push_back(DAG.getTargetConstant(Val, SDLoc(Op), MVT::i64));
20356 }
20357 } else {
20359 }
20360}
20361
20363 unsigned Size = Op.getScalarValueSizeInBits();
20364 if (Size > 64)
20365 return false;
20366
20367 if (Size == 16 && !Subtarget->has16BitInsts())
20368 return false;
20369
20371 Val = C->getSExtValue();
20372 return true;
20373 }
20375 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
20376 return true;
20377 }
20379 if (Size != 16 || Op.getNumOperands() != 2)
20380 return false;
20381 if (Op.getOperand(0).isUndef() || Op.getOperand(1).isUndef())
20382 return false;
20383 if (ConstantSDNode *C = V->getConstantSplatNode()) {
20384 Val = C->getSExtValue();
20385 return true;
20386 }
20387 if (ConstantFPSDNode *C = V->getConstantFPSplatNode()) {
20388 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
20389 return true;
20390 }
20391 }
20392
20393 return false;
20394}
20395
20397 uint64_t Val) const {
20398 if (Constraint.size() == 1) {
20399 switch (Constraint[0]) {
20400 case 'I':
20402 case 'J':
20403 return isInt<16>(Val);
20404 case 'A':
20405 return checkAsmConstraintValA(Op, Val);
20406 case 'B':
20407 return isInt<32>(Val);
20408 case 'C':
20409 return isUInt<32>(clearUnusedBits(Val, Op.getScalarValueSizeInBits())) ||
20411 default:
20412 break;
20413 }
20414 } else if (Constraint.size() == 2) {
20415 if (Constraint == "DA") {
20416 int64_t HiBits = static_cast<int32_t>(Val >> 32);
20417 int64_t LoBits = static_cast<int32_t>(Val);
20418 return checkAsmConstraintValA(Op, HiBits, 32) &&
20419 checkAsmConstraintValA(Op, LoBits, 32);
20420 }
20421 if (Constraint == "DB") {
20422 return true;
20423 }
20424 }
20425 llvm_unreachable("Invalid asm constraint");
20426}
20427
20429 unsigned MaxSize) const {
20430 unsigned Size = std::min<unsigned>(Op.getScalarValueSizeInBits(), MaxSize);
20431 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
20432 if (Size == 16) {
20433 MVT VT = Op.getSimpleValueType();
20434 switch (VT.SimpleTy) {
20435 default:
20436 return false;
20437 case MVT::i16:
20438 return AMDGPU::isInlinableLiteralI16(Val, HasInv2Pi);
20439 case MVT::f16:
20440 return AMDGPU::isInlinableLiteralFP16(Val, HasInv2Pi);
20441 case MVT::bf16:
20442 return AMDGPU::isInlinableLiteralBF16(Val, HasInv2Pi);
20443 case MVT::v2i16:
20444 return AMDGPU::getInlineEncodingV2I16(Val).has_value();
20445 case MVT::v2f16:
20446 return AMDGPU::getInlineEncodingV2F16(Val).has_value();
20447 case MVT::v2bf16:
20448 return AMDGPU::getInlineEncodingV2BF16(Val).has_value();
20449 }
20450 }
20451 if ((Size == 32 && AMDGPU::isInlinableLiteral32(Val, HasInv2Pi)) ||
20452 (Size == 64 && AMDGPU::isInlinableLiteral64(Val, HasInv2Pi)))
20453 return true;
20454 return false;
20455}
20456
20457static int getAlignedAGPRClassID(unsigned UnalignedClassID) {
20458 switch (UnalignedClassID) {
20459 case AMDGPU::VReg_64RegClassID:
20460 return AMDGPU::VReg_64_Align2RegClassID;
20461 case AMDGPU::VReg_96RegClassID:
20462 return AMDGPU::VReg_96_Align2RegClassID;
20463 case AMDGPU::VReg_128RegClassID:
20464 return AMDGPU::VReg_128_Align2RegClassID;
20465 case AMDGPU::VReg_160RegClassID:
20466 return AMDGPU::VReg_160_Align2RegClassID;
20467 case AMDGPU::VReg_192RegClassID:
20468 return AMDGPU::VReg_192_Align2RegClassID;
20469 case AMDGPU::VReg_224RegClassID:
20470 return AMDGPU::VReg_224_Align2RegClassID;
20471 case AMDGPU::VReg_256RegClassID:
20472 return AMDGPU::VReg_256_Align2RegClassID;
20473 case AMDGPU::VReg_288RegClassID:
20474 return AMDGPU::VReg_288_Align2RegClassID;
20475 case AMDGPU::VReg_320RegClassID:
20476 return AMDGPU::VReg_320_Align2RegClassID;
20477 case AMDGPU::VReg_352RegClassID:
20478 return AMDGPU::VReg_352_Align2RegClassID;
20479 case AMDGPU::VReg_384RegClassID:
20480 return AMDGPU::VReg_384_Align2RegClassID;
20481 case AMDGPU::VReg_512RegClassID:
20482 return AMDGPU::VReg_512_Align2RegClassID;
20483 case AMDGPU::VReg_1024RegClassID:
20484 return AMDGPU::VReg_1024_Align2RegClassID;
20485 case AMDGPU::AReg_64RegClassID:
20486 return AMDGPU::AReg_64_Align2RegClassID;
20487 case AMDGPU::AReg_96RegClassID:
20488 return AMDGPU::AReg_96_Align2RegClassID;
20489 case AMDGPU::AReg_128RegClassID:
20490 return AMDGPU::AReg_128_Align2RegClassID;
20491 case AMDGPU::AReg_160RegClassID:
20492 return AMDGPU::AReg_160_Align2RegClassID;
20493 case AMDGPU::AReg_192RegClassID:
20494 return AMDGPU::AReg_192_Align2RegClassID;
20495 case AMDGPU::AReg_256RegClassID:
20496 return AMDGPU::AReg_256_Align2RegClassID;
20497 case AMDGPU::AReg_512RegClassID:
20498 return AMDGPU::AReg_512_Align2RegClassID;
20499 case AMDGPU::AReg_1024RegClassID:
20500 return AMDGPU::AReg_1024_Align2RegClassID;
20501 default:
20502 return -1;
20503 }
20504}
20505
20506// Figure out which registers should be reserved for stack access. Only after
20507// the function is legalized do we know all of the non-spill stack objects or if
20508// calls are present.
20512 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
20513 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20514 const SIInstrInfo *TII = ST.getInstrInfo();
20515
20516 if (Info->isEntryFunction()) {
20517 // Callable functions have fixed registers used for stack access.
20519 }
20520
20521 // TODO: Move this logic to getReservedRegs()
20522 // Reserve the SGPR(s) to save/restore EXEC for WWM spill/copy handling.
20523 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20524 Register SReg = ST.isWave32()
20525 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20526 : TRI->getAlignedHighSGPRForRC(MF, /*Align=*/2,
20527 &AMDGPU::SGPR_64RegClass);
20528 Info->setSGPRForEXECCopy(SReg);
20529
20530 assert(!TRI->isSubRegister(Info->getScratchRSrcReg(),
20531 Info->getStackPtrOffsetReg()));
20532 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20533 MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20534
20535 // We need to worry about replacing the default register with itself in case
20536 // of MIR testcases missing the MFI.
20537 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20538 MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20539
20540 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20541 MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());
20542
20543 Info->limitOccupancy(MF);
20544
20545 if (ST.isWave32() && !MF.empty()) {
20546 for (auto &MBB : MF) {
20547 for (auto &MI : MBB) {
20548 TII->fixImplicitOperands(MI);
20549 }
20550 }
20551 }
20552
20553 // FIXME: This is a hack to fixup AGPR classes to use the properly aligned
20554 // classes if required. Ideally the register class constraints would differ
20555 // per-subtarget, but there's no easy way to achieve that right now. This is
20556 // not a problem for VGPRs because the correctly aligned VGPR class is implied
20557 // from using them as the register class for legal types.
20558 if (ST.needsAlignedVGPRs()) {
20559 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
20560 const Register Reg = Register::index2VirtReg(I);
20561 const TargetRegisterClass *RC = MRI.getRegClassOrNull(Reg);
20562 if (!RC)
20563 continue;
20564 int NewClassID = getAlignedAGPRClassID(RC->getID());
20565 if (NewClassID != -1)
20566 MRI.setRegClass(Reg, TRI->getRegClass(NewClassID));
20567 }
20568 }
20569
20571}
20572
20575 const APInt &DemandedElts,
20576 const SelectionDAG &DAG,
20577 unsigned Depth) const {
20578 Known.resetAll();
20579 unsigned Opc = Op.getOpcode();
20580 switch (Opc) {
20582 unsigned IID = Op.getConstantOperandVal(0);
20583 switch (IID) {
20584 case Intrinsic::amdgcn_mbcnt_lo:
20585 case Intrinsic::amdgcn_mbcnt_hi: {
20586 const GCNSubtarget &ST =
20588 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20589 // most 31 + src1.
20590 Known.Zero.setBitsFrom(
20591 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20592 KnownBits Known2 = DAG.computeKnownBits(Op.getOperand(2), Depth + 1);
20593 Known = KnownBits::add(Known, Known2);
20594 return;
20595 }
20596 }
20597 break;
20598 }
20599 }
20601 Op, Known, DemandedElts, DAG, Depth);
20602}
20603
20605 KnownBits &Known, const MachineFunction &MF, Align Alignment) const {
20607
20608 // Set the high bits to zero based on the maximum allowed scratch size per
20609 // wave. We can't use vaddr in MUBUF instructions if we don't know the address
20610 // calculation won't overflow, so assume the sign bit is never set.
20611 Known.Zero.setHighBits(getSubtarget()->getKnownHighZeroBitsForFrameIndex());
20612}
20613
20616 unsigned Dim) {
20617 unsigned MaxValue =
20618 ST.getMaxWorkitemID(VT.getMachineFunction().getFunction(), Dim);
20619 Known.Zero.setHighBits(llvm::countl_zero(MaxValue));
20620}
20621
20623 KnownBits &Known, const APInt &DemandedElts,
20624 unsigned BFEWidth, bool SExt, unsigned Depth) {
20626 const MachineOperand &Src1 = MI.getOperand(2);
20627
20628 unsigned Src1Cst = 0;
20629 if (Src1.isImm()) {
20630 Src1Cst = Src1.getImm();
20631 } else if (Src1.isReg()) {
20632 auto Cst = getIConstantVRegValWithLookThrough(Src1.getReg(), MRI);
20633 if (!Cst)
20634 return;
20635 Src1Cst = Cst->Value.getZExtValue();
20636 } else {
20637 return;
20638 }
20639
20640 // Offset is at bits [4:0] for 32 bit, [5:0] for 64 bit.
20641 // Width is always [22:16].
20642 const unsigned Offset =
20643 Src1Cst & maskTrailingOnes<unsigned>((BFEWidth == 32) ? 5 : 6);
20644 const unsigned Width = (Src1Cst >> 16) & maskTrailingOnes<unsigned>(6);
20645
20646 if (Width >= BFEWidth) // Ill-formed.
20647 return;
20648
20649 VT.computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
20650 Depth + 1);
20651
20652 Known = Known.extractBits(Width, Offset);
20653
20654 if (SExt)
20655 Known = Known.sext(BFEWidth);
20656 else
20657 Known = Known.zext(BFEWidth);
20658}
20659
20662 const APInt &DemandedElts, const MachineRegisterInfo &MRI,
20663 unsigned Depth) const {
20664 Known.resetAll();
20665 const MachineInstr *MI = MRI.getVRegDef(R);
20666 switch (MI->getOpcode()) {
20667 case AMDGPU::S_BFE_I32:
20668 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20669 /*SExt=*/true, Depth);
20670 case AMDGPU::S_BFE_U32:
20671 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20672 /*SExt=*/false, Depth);
20673 case AMDGPU::S_BFE_I64:
20674 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20675 /*SExt=*/true, Depth);
20676 case AMDGPU::S_BFE_U64:
20677 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20678 /*SExt=*/false, Depth);
20679 case AMDGPU::G_INTRINSIC:
20680 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20681 Intrinsic::ID IID = cast<GIntrinsic>(MI)->getIntrinsicID();
20682 switch (IID) {
20683 case Intrinsic::amdgcn_workitem_id_x:
20685 break;
20686 case Intrinsic::amdgcn_workitem_id_y:
20688 break;
20689 case Intrinsic::amdgcn_workitem_id_z:
20691 break;
20692 case Intrinsic::amdgcn_mbcnt_lo:
20693 case Intrinsic::amdgcn_mbcnt_hi: {
20694 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20695 // most 31 + src1.
20696 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20697 ? getSubtarget()->getWavefrontSizeLog2()
20698 : 5);
20699 KnownBits Known2;
20700 VT.computeKnownBitsImpl(MI->getOperand(3).getReg(), Known2, DemandedElts,
20701 Depth + 1);
20702 Known = KnownBits::add(Known, Known2);
20703 break;
20704 }
20705 case Intrinsic::amdgcn_groupstaticsize: {
20706 // We can report everything over the maximum size as 0. We can't report
20707 // based on the actual size because we don't know if it's accurate or not
20708 // at any given point.
20709 Known.Zero.setHighBits(
20710 llvm::countl_zero(getSubtarget()->getAddressableLocalMemorySize()));
20711 break;
20712 }
20713 case Intrinsic::amdgcn_readfirstlane:
20714 case Intrinsic::amdgcn_readlane: {
20715 // Result is the data operand's value from some lane.
20716 VT.computeKnownBitsImpl(MI->getOperand(2).getReg(), Known, DemandedElts,
20717 Depth + 1);
20718 break;
20719 }
20720 case Intrinsic::amdgcn_mul_u24:
20721 case Intrinsic::amdgcn_mul_i24: {
20722 Register LHS = MI->getOperand(2).getReg();
20723 Register RHS = MI->getOperand(3).getReg();
20724
20725 KnownBits RHSKnown;
20726 VT.computeKnownBitsImpl(RHS, RHSKnown, DemandedElts, Depth + 1);
20727 if (RHSKnown.isUnknown())
20728 break;
20729
20730 KnownBits LHSKnown;
20731 VT.computeKnownBitsImpl(LHS, LHSKnown, DemandedElts, Depth + 1);
20732 if (LHSKnown.isUnknown())
20733 break;
20734
20735 bool SelfMultiply =
20736 LHS == RHS && isGuaranteedNotToBeUndef(LHS, MRI, Depth + 1);
20737 Known = computeKnownBitsForMul24(LHSKnown, RHSKnown, Known.getBitWidth(),
20738 IID == Intrinsic::amdgcn_mul_i24,
20739 SelfMultiply);
20740 break;
20741 }
20742 }
20743 break;
20744 }
20745 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20746 Known.Zero.setHighBits(24);
20747 break;
20748 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20749 Known.Zero.setHighBits(16);
20750 break;
20751 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20752 // G_AMDGPU_COPY_SCC_VCC converts a uniform boolean in VCC to SGPR s32,
20753 // producing exactly 0 or 1.
20754 Known.Zero.setHighBits(Known.getBitWidth() - 1);
20755 break;
20756 case AMDGPU::G_AMDGPU_SMED3:
20757 case AMDGPU::G_AMDGPU_UMED3: {
20758 auto [Dst, Src0, Src1, Src2] = MI->getFirst4Regs();
20759
20760 KnownBits Known2;
20761 VT.computeKnownBitsImpl(Src2, Known2, DemandedElts, Depth + 1);
20762 if (Known2.isUnknown())
20763 break;
20764
20765 KnownBits Known1;
20766 VT.computeKnownBitsImpl(Src1, Known1, DemandedElts, Depth + 1);
20767 if (Known1.isUnknown())
20768 break;
20769
20770 KnownBits Known0;
20771 VT.computeKnownBitsImpl(Src0, Known0, DemandedElts, Depth + 1);
20772 if (Known0.isUnknown())
20773 break;
20774
20775 // TODO: Handle LeadZero/LeadOne from UMIN/UMAX handling.
20776 Known.Zero = Known0.Zero & Known1.Zero & Known2.Zero;
20777 Known.One = Known0.One & Known1.One & Known2.One;
20778 break;
20779 }
20780 }
20781}
20782
20785 unsigned Depth) const {
20786 const MachineInstr *MI = MRI.getVRegDef(R);
20787 if (auto *GI = dyn_cast<GIntrinsic>(MI)) {
20788 // FIXME: Can this move to generic code? What about the case where the call
20789 // site specifies a lower alignment?
20790 Intrinsic::ID IID = GI->getIntrinsicID();
20792 AttributeList Attrs =
20793 Intrinsic::getAttributes(Ctx, IID, Intrinsic::getType(Ctx, IID));
20794 if (MaybeAlign RetAlign = Attrs.getRetAlignment())
20795 return *RetAlign;
20796 }
20797 return Align(1);
20798}
20799
20801 MachineLoop *ML, const MachineBasicBlock *BlockToAlign) const {
20803 const Align CacheLineAlign = Align(64);
20804
20805 // GFX950: Prevent an 8-byte instruction at the block being aligned from being
20806 // split by the 32-byte instruction fetch window boundary. This avoids a
20807 // significant fetch delay after a backward branch. We use 32-byte alignment
20808 // with max padding of 4 bytes (one s_nop), see
20809 // getMaxPermittedBytesForAlignment().
20810 if (ML && !DisableLoopAlignment &&
20811 getSubtarget()->hasLoopHeadInstSplitSensitivity()) {
20812 // Loop rotation can make the backedge destination a block other than the
20813 // LoopInfo header, so prefer the block the caller is actually aligning.
20814 if (!BlockToAlign)
20815 BlockToAlign = ML->getHeader();
20816 // Respect user-specified or previously set alignment.
20817 if (BlockToAlign->getAlignment() != PrefAlign)
20818 return BlockToAlign->getAlignment();
20819 if (needsFetchWindowAlignment(*BlockToAlign))
20820 return Align(32);
20821 }
20822
20823 // Pre-GFX10 target did not benefit from loop alignment
20824 if (!ML || DisableLoopAlignment || !getSubtarget()->hasInstPrefetch() ||
20825 getSubtarget()->hasInstFwdPrefetchBug())
20826 return PrefAlign;
20827
20828 // On GFX10 I$ is 4 x 64 bytes cache lines.
20829 // By default prefetcher keeps one cache line behind and reads two ahead.
20830 // We can modify it with S_INST_PREFETCH for larger loops to have two lines
20831 // behind and one ahead.
20832 // Therefor we can benefit from aligning loop headers if loop fits 192 bytes.
20833 // If loop fits 64 bytes it always spans no more than two cache lines and
20834 // does not need an alignment.
20835 // Else if loop is less or equal 128 bytes we do not need to modify prefetch,
20836 // Else if loop is less or equal 192 bytes we need two lines behind.
20837
20839 const MachineBasicBlock *Header = ML->getHeader();
20840 if (Header->getAlignment() != PrefAlign)
20841 return Header->getAlignment(); // Already processed.
20842
20843 unsigned LoopSize = 0;
20844 for (const MachineBasicBlock *MBB : ML->blocks()) {
20845 // If inner loop block is aligned assume in average half of the alignment
20846 // size to be added as nops.
20847 if (MBB != Header)
20848 LoopSize += MBB->getAlignment().value() / 2;
20849
20850 for (const MachineInstr &MI : *MBB) {
20851 LoopSize += TII->getInstSizeInBytes(MI);
20852 if (LoopSize > 192)
20853 return PrefAlign;
20854 }
20855 }
20856
20857 if (LoopSize <= 64)
20858 return PrefAlign;
20859
20860 if (LoopSize <= 128)
20861 return CacheLineAlign;
20862
20863 // If any of parent loops is surrounded by prefetch instructions do not
20864 // insert new for inner loop, which would reset parent's settings.
20865 for (MachineLoop *P = ML->getParentLoop(); P; P = P->getParentLoop()) {
20866 if (MachineBasicBlock *Exit = P->getExitBlock()) {
20867 auto I = Exit->getFirstNonDebugInstr();
20868 if (I != Exit->end() && I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20869 return CacheLineAlign;
20870 }
20871 }
20872
20873 MachineBasicBlock *Pre = ML->getLoopPreheader();
20874 MachineBasicBlock *Exit = ML->getExitBlock();
20875
20876 if (Pre && Exit) {
20877 auto PreTerm = Pre->getFirstTerminator();
20878 if (PreTerm == Pre->begin() ||
20879 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20880 BuildMI(*Pre, PreTerm, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20881 .addImm(1); // prefetch 2 lines behind PC
20882
20883 auto ExitHead = Exit->getFirstNonDebugInstr();
20884 if (ExitHead == Exit->end() ||
20885 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20886 BuildMI(*Exit, ExitHead, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20887 .addImm(2); // prefetch 1 line behind PC
20888 }
20889
20890 return CacheLineAlign;
20891}
20892
20894 MachineBasicBlock *MBB) const {
20895 // GFX950: Limit padding to 4 bytes (one s_nop) for blocks where an 8-byte
20896 // instruction could be split by the 32-byte fetch window boundary.
20897 // See getPrefLoopAlignment() for context.
20898 if (needsFetchWindowAlignment(*MBB))
20899 return 4;
20901}
20902
20903bool SITargetLowering::needsFetchWindowAlignment(
20904 const MachineBasicBlock &MBB) const {
20905 if (!getSubtarget()->hasLoopHeadInstSplitSensitivity())
20906 return false;
20908 for (const MachineInstr &MI : MBB) {
20909 if (MI.isMetaInstruction())
20910 continue;
20911 // Instructions larger than 4 bytes can be split by a 32-byte boundary.
20912 return TII->getInstSizeInBytes(MI) > 4;
20913 }
20914 return false;
20915}
20916
20917[[maybe_unused]]
20918static bool isCopyFromRegOfInlineAsm(const SDNode *N) {
20919 assert(N->getOpcode() == ISD::CopyFromReg);
20920 do {
20921 // Follow the chain until we find an INLINEASM node.
20922 N = N->getOperand(0).getNode();
20923 if (N->getOpcode() == ISD::INLINEASM || N->getOpcode() == ISD::INLINEASM_BR)
20924 return true;
20925 } while (N->getOpcode() == ISD::CopyFromReg);
20926 return false;
20927}
20928
20931 UniformityInfo *UA) const {
20932 switch (N->getOpcode()) {
20933 case ISD::CopyFromReg: {
20934 const RegisterSDNode *R = cast<RegisterSDNode>(N->getOperand(1));
20935 const MachineRegisterInfo &MRI = FLI->MF->getRegInfo();
20936 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20937 Register Reg = R->getReg();
20938
20939 // FIXME: Why does this need to consider isLiveIn?
20940 if (Reg.isPhysical() || MRI.isLiveIn(Reg))
20941 return !TRI->isSGPRReg(MRI, Reg);
20942
20943 if (const Value *V = FLI->getValueFromVirtualReg(R->getReg()))
20944 return UA->isDivergentAtDef(V);
20945
20947 return !TRI->isSGPRReg(MRI, Reg);
20948 }
20949 case ISD::LOAD: {
20950 const LoadSDNode *L = cast<LoadSDNode>(N);
20951 unsigned AS = L->getAddressSpace();
20952 // A flat load may access private memory.
20954 }
20955 case ISD::CALLSEQ_END:
20956 return true;
20958 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(0));
20960 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(1));
20961 case AMDGPUISD::ATOMIC_CMP_SWAP:
20962 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20963 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20964 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20965 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20966 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20967 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20968 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20969 case AMDGPUISD::BUFFER_ATOMIC_AND:
20970 case AMDGPUISD::BUFFER_ATOMIC_OR:
20971 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20972 case AMDGPUISD::BUFFER_ATOMIC_INC:
20973 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20974 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20975 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20976 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20977 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20978 // Target-specific read-modify-write atomics are sources of divergence.
20979 return true;
20980 default:
20981 if (auto *A = dyn_cast<AtomicSDNode>(N)) {
20982 // Generic read-modify-write atomics are sources of divergence.
20983 return A->readMem() && A->writeMem();
20984 }
20985 return false;
20986 }
20987}
20988
20990 EVT VT) const {
20991 switch (VT.getScalarType().getSimpleVT().SimpleTy) {
20992 case MVT::f32:
20994 case MVT::f64:
20995 case MVT::f16:
20997 default:
20998 return false;
20999 }
21000}
21001
21003 LLT Ty, const MachineFunction &MF) const {
21004 switch (Ty.getScalarSizeInBits()) {
21005 case 32:
21006 return !denormalModeIsFlushAllF32(MF);
21007 case 64:
21008 case 16:
21009 return !denormalModeIsFlushAllF64F16(MF);
21010 default:
21011 return false;
21012 }
21013}
21014
21016 const APInt &DemandedElts,
21017 const SelectionDAG &DAG,
21018 bool SNaN,
21019 unsigned Depth) const {
21020 if (Op.getOpcode() == AMDGPUISD::CLAMP) {
21021 const MachineFunction &MF = DAG.getMachineFunction();
21023
21024 if (Info->getMode().DX10Clamp)
21025 return true; // Clamped to 0.
21026 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);
21027 }
21028
21030 DAG, SNaN, Depth);
21031}
21032
21033namespace {
21034
21035/// Why a floating-point atomic instruction which may flush denormals is
21036/// acceptable.
21037enum class AtomicFlushDenormalReason {
21038 Native,
21039 IEEE,
21040 IgnoreDenormalMode,
21041 FunctionFlushesDenormals
21042};
21043
21044/// Why a native floating-point atomic instruction is acceptable for a global
21045/// memory address.
21046enum class GlobalFPAtomicLegality {
21047 Illegal,
21048 AgentScopeFineGrainedRemoteMemory,
21049 EmulatedSystemScope,
21050 NoRemoteMemory,
21051 NoFineGrainedMemory
21052};
21053
21054} // end anonymous namespace
21055
21056// On older subtargets, global FP atomic instructions have a hardcoded FP mode
21057// and do not support FP32 denormals, and only support v2f16/f64 denormals.
21058static AtomicFlushDenormalReason
21060 if (RMW->hasMetadata(LLVMContext::MD_atomic_ignore_denormal_mode))
21061 return AtomicFlushDenormalReason::IgnoreDenormalMode;
21062
21063 const fltSemantics &Flt = RMW->getType()->getScalarType()->getFltSemantics();
21064 auto DenormMode = RMW->getFunction()->getDenormalMode(Flt);
21065 return DenormMode == DenormalMode::getPreserveSign()
21066 ? AtomicFlushDenormalReason::FunctionFlushesDenormals
21067 : AtomicFlushDenormalReason::IEEE;
21068}
21069
21070static OptimizationRemark
21072 GlobalFPAtomicLegality MemLegality,
21073 AtomicFlushDenormalReason DenormReason) {
21074 LLVMContext &Ctx = RMW->getContext();
21075 StringRef MemScope = Ctx.getSyncScopeName(RMW->getSyncScopeID()).value_or("");
21076 if (MemScope.empty())
21077 MemScope = "system";
21078
21079 OptimizationRemark R(DEBUG_TYPE, "Passed", RMW);
21080 R << "hardware instruction generated for atomic "
21081 << ore::NV("Operation", RMW->getOperationName(RMW->getOperation()))
21082 << " at " << ore::NV("SyncScope", MemScope) << " scope since ";
21083
21084 switch (MemLegality) {
21085 case GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory:
21086 R << "fine-grained remote memory atomics work below system scope";
21087 break;
21088 case GlobalFPAtomicLegality::EmulatedSystemScope:
21089 R << "system scope atomics are emulated in hardware";
21090 break;
21091 case GlobalFPAtomicLegality::NoRemoteMemory:
21092 R << "memory is not remote (!amdgpu.no.remote.memory)";
21093 break;
21094 case GlobalFPAtomicLegality::NoFineGrainedMemory:
21095 R << "memory is not fine-grained (!amdgpu.no.fine.grained.memory)";
21096 break;
21097 case GlobalFPAtomicLegality::Illegal:
21098 llvm_unreachable("remark for illegal atomic");
21099 }
21100
21101 switch (DenormReason) {
21102 case AtomicFlushDenormalReason::Native:
21103 break;
21104 case AtomicFlushDenormalReason::IgnoreDenormalMode:
21105 R << ", and denormals may be flushed (!atomic.ignore.denormal.mode)";
21106 break;
21107 case AtomicFlushDenormalReason::FunctionFlushesDenormals:
21108 R << ", and the floating-point environment flushes denormals";
21109 break;
21110 case AtomicFlushDenormalReason::IEEE:
21111 llvm_unreachable("remark for illegal atomic");
21112 }
21113
21114 return R;
21115}
21116
21117static bool isV2F16OrV2BF16(Type *Ty) {
21118 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
21119 Type *EltTy = VT->getElementType();
21120 return VT->getNumElements() == 2 &&
21121 (EltTy->isHalfTy() || EltTy->isBFloatTy());
21122 }
21123
21124 return false;
21125}
21126
21127static bool isV2F16(Type *Ty) {
21129 return VT && VT->getNumElements() == 2 && VT->getElementType()->isHalfTy();
21130}
21131
21132static bool isV2BF16(Type *Ty) {
21134 return VT && VT->getNumElements() == 2 && VT->getElementType()->isBFloatTy();
21135}
21136
21137/// \return true if atomicrmw integer ops work for the type.
21138static bool isAtomicRMWLegalIntTy(Type *Ty) {
21139 if (auto *IT = dyn_cast<IntegerType>(Ty)) {
21140 unsigned BW = IT->getBitWidth();
21141 return BW == 32 || BW == 64;
21142 }
21143
21144 return false;
21145}
21146
21147/// \return true if this atomicrmw xchg type can be selected.
21148static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW) {
21149 Type *Ty = RMW->getType();
21150 if (isAtomicRMWLegalIntTy(Ty))
21151 return true;
21152
21153 if (PointerType *PT = dyn_cast<PointerType>(Ty)) {
21154 const DataLayout &DL = RMW->getFunction()->getDataLayout();
21155 unsigned BW = DL.getPointerSizeInBits(PT->getAddressSpace());
21156 return BW == 32 || BW == 64;
21157 }
21158
21159 if (Ty->isFloatTy() || Ty->isDoubleTy())
21160 return true;
21161
21163 return VT->getNumElements() == 2 &&
21164 VT->getElementType()->getPrimitiveSizeInBits() == 16;
21165 }
21166
21167 return false;
21168}
21169
21170/// \returns whether it's valid to emit a native instruction for \p RMW, and
21171/// why, based on the properties of the target memory.
21172static GlobalFPAtomicLegality
21174 const AtomicRMWInst *RMW, bool HasSystemScope) {
21175 // The remote/fine-grained access logic is different from the integer
21176 // atomics. Without AgentScopeFineGrainedRemoteMemoryAtomics support,
21177 // fine-grained access does not work, even for a device local allocation.
21178 //
21179 // With AgentScopeFineGrainedRemoteMemoryAtomics, system scoped device local
21180 // allocations work.
21181 if (HasSystemScope) {
21182 if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
21183 RMW->hasMetadata("amdgpu.no.remote.memory"))
21184 return GlobalFPAtomicLegality::NoRemoteMemory;
21185 if (Subtarget.hasEmulatedSystemScopeAtomics())
21186 return GlobalFPAtomicLegality::EmulatedSystemScope;
21187 } else if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
21188 return GlobalFPAtomicLegality::AgentScopeFineGrainedRemoteMemory;
21189
21190 return RMW->hasMetadata("amdgpu.no.fine.grained.memory")
21191 ? GlobalFPAtomicLegality::NoFineGrainedMemory
21192 : GlobalFPAtomicLegality::Illegal;
21193}
21194
21195/// \return Action to perform on AtomicRMWInsts for integer operations.
21202
21203/// Return if a flat address space atomicrmw can access private memory.
21205 const MDNode *MD = I->getMetadata(LLVMContext::MD_noalias_addrspace);
21206 return !MD ||
21208}
21209
21212 // For GAS, lower to flat atomic.
21213 return STI.hasGloballyAddressableScratch()
21216}
21217
21220 unsigned AS = RMW->getPointerAddressSpace();
21221 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
21223
21224 // 64-bit flat atomics that dynamically reside in private memory will silently
21225 // be dropped.
21226 //
21227 // Note that we will emit a new copy of the original atomic in the expansion,
21228 // which will be incrementally relegalized.
21229 const DataLayout &DL = RMW->getFunction()->getDataLayout();
21230 if (AS == AMDGPUAS::FLAT_ADDRESS &&
21231 DL.getTypeSizeInBits(RMW->getType()) == 64 &&
21234
21235 GlobalFPAtomicLegality MemLegality = GlobalFPAtomicLegality::Illegal;
21236 AtomicFlushDenormalReason DenormReason = AtomicFlushDenormalReason::Native;
21237 auto ReportHWInst = [&](TargetLowering::AtomicExpansionKind Kind) {
21239 ORE.emit([&]() {
21240 return emitAtomicRMWLegalRemark(RMW, MemLegality, DenormReason);
21241 });
21242 return Kind;
21243 };
21244
21245 auto SSID = RMW->getSyncScopeID();
21246 bool HasSystemScope =
21247 SSID == SyncScope::System ||
21249 getTargetMachine().getTargetTriple(), AtomicScope::System,
21250 /*OneAddressSpace=*/true));
21251
21252 auto Op = RMW->getOperation();
21253 switch (Op) {
21255 // PCIe supports add and xchg for system atomics.
21256 return isAtomicRMWLegalXChgTy(RMW)
21259 case AtomicRMWInst::Add:
21260 // PCIe supports add and xchg for system atomics.
21262 case AtomicRMWInst::Sub:
21263 case AtomicRMWInst::And:
21264 case AtomicRMWInst::Or:
21265 case AtomicRMWInst::Xor:
21266 case AtomicRMWInst::Max:
21267 case AtomicRMWInst::Min:
21274 if (Op == AtomicRMWInst::USubCond && !Subtarget->hasCondSubInsts())
21276 if (Op == AtomicRMWInst::USubSat) {
21277 // The global and buffer forms predate the LDS and flat ones.
21278 if (!Subtarget->hasSubClampInsts() ||
21279 (AS == AMDGPUAS::LOCAL_ADDRESS &&
21280 !Subtarget->hasAtomicDsCondSubClampInsts()) ||
21281 (AS == AMDGPUAS::FLAT_ADDRESS &&
21282 !Subtarget->hasAtomicCondSubClampFlatInsts()))
21284 }
21286 auto *IT = dyn_cast<IntegerType>(RMW->getType());
21287 if (!IT || IT->getBitWidth() != 32)
21289 }
21290
21293 if (Subtarget->hasEmulatedSystemScopeAtomics())
21295
21296 // On most subtargets, for atomicrmw operations other than add/xchg,
21297 // whether or not the instructions will behave correctly depends on where
21298 // the address physically resides and what interconnect is used in the
21299 // system configuration. On some some targets the instruction will nop,
21300 // and in others synchronization will only occur at degraded device scope.
21301 //
21302 // If the allocation is known local to the device, the instructions should
21303 // work correctly.
21304 if (RMW->hasMetadata("amdgpu.no.remote.memory"))
21306
21307 // If fine-grained remote memory works at device scope, we don't need to
21308 // do anything.
21309 if (!HasSystemScope &&
21310 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
21312
21313 // If we are targeting a remote allocated address, it depends what kind of
21314 // allocation the address belongs to.
21315 //
21316 // If the allocation is fine-grained (in host memory, or in PCIe peer
21317 // device memory), the operation will fail depending on the target.
21318 //
21319 // Note fine-grained host memory access does work on APUs or if XGMI is
21320 // used, but we do not know if we are targeting an APU or the system
21321 // configuration from the ISA version/target-cpu.
21322 if (RMW->hasMetadata("amdgpu.no.fine.grained.memory"))
21324
21327 // Atomic sub/or/xor do not work over PCI express, but atomic add
21328 // does. InstCombine transforms these with 0 to or, so undo that.
21329 // Sub-word types are not selectable and take the cmpxchg expansion.
21330 if (const Constant *ConstVal = dyn_cast<Constant>(RMW->getValOperand());
21331 ConstVal && ConstVal->isNullValue() &&
21334 }
21335
21336 // If the allocation could be in remote, fine-grained memory, the rmw
21337 // instructions may fail. cmpxchg should work, so emit that. On some
21338 // system configurations, PCIe atomics aren't supported so cmpxchg won't
21339 // even work, so you're out of luck anyway.
21340
21341 // In summary:
21342 //
21343 // Cases that may fail:
21344 // - fine-grained pinned host memory
21345 // - fine-grained migratable host memory
21346 // - fine-grained PCIe peer device
21347 //
21348 // Cases that should work, but may be treated overly conservatively.
21349 // - fine-grained host memory on an APU
21350 // - fine-grained XGMI peer device
21352 }
21353
21355 }
21356 case AtomicRMWInst::FAdd: {
21357 Type *Ty = RMW->getType();
21358
21359 // TODO: Handle REGION_ADDRESS
21360 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
21361 // DS F32 FP atomics do respect the denormal mode, but the rounding mode
21362 // is fixed to round-to-nearest-even.
21363 //
21364 // F64 / PK_F16 / PK_BF16 never flush and are also fixed to
21365 // round-to-nearest-even.
21366 //
21367 // We ignore the rounding mode problem, even in strictfp. The C++ standard
21368 // suggests it is OK if the floating-point mode may not match the calling
21369 // thread.
21370 if (Ty->isFloatTy()) {
21371 return Subtarget->hasLDSFPAtomicAddF32() ? AtomicExpansionKind::None
21373 }
21374
21375 if (Ty->isDoubleTy()) {
21376 // Ignores denormal mode, but we don't consider flushing mandatory.
21377 return Subtarget->hasLdsAtomicAddF64() ? AtomicExpansionKind::None
21379 }
21380
21381 if (Subtarget->hasAtomicDsPkAdd16Insts() && isV2F16OrV2BF16(Ty))
21383
21385 }
21386
21387 // LDS atomics respect the denormal mode from the mode register.
21388 //
21389 // Traditionally f32 global/buffer memory atomics would unconditionally
21390 // flush denormals, but newer targets do not flush. f64/f16/bf16 cases never
21391 // flush.
21392 //
21393 // On targets with flat atomic fadd, denormals would flush depending on
21394 // whether the target address resides in LDS or global memory. We consider
21395 // this flat-maybe-flush as will-flush.
21396 if (Ty->isFloatTy() &&
21397 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport()) {
21398 DenormReason = getAtomicFlushDenormalReason(RMW);
21399 if (DenormReason == AtomicFlushDenormalReason::IEEE)
21401 }
21402
21403 MemLegality =
21404 getGlobalMemoryFPAtomicLegality(*Subtarget, RMW, HasSystemScope);
21405 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21406 if (AS == AMDGPUAS::FLAT_ADDRESS) {
21407 // gfx942, gfx12
21408 if (Subtarget->hasAtomicFlatPkAdd16Insts() && isV2F16OrV2BF16(Ty))
21409 return ReportHWInst(AtomicExpansionKind::None);
21410 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS)) {
21411 // gfx90a, gfx942, gfx12
21412 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
21413 return ReportHWInst(AtomicExpansionKind::None);
21414
21415 // gfx942, gfx12
21416 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() && isV2BF16(Ty))
21417 return ReportHWInst(AtomicExpansionKind::None);
21418 } else if (AS == AMDGPUAS::BUFFER_FAT_POINTER) {
21419 // gfx90a, gfx942, gfx12
21420 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
21421 return ReportHWInst(AtomicExpansionKind::None);
21422
21423 // While gfx90a/gfx942 supports v2bf16 for global/flat, it does not for
21424 // buffer. gfx12 does have the buffer version.
21425 if (Subtarget->hasAtomicBufferPkAddBF16Inst() && isV2BF16(Ty))
21426 return ReportHWInst(AtomicExpansionKind::None);
21427 }
21428
21429 // global and flat atomic fadd f64: gfx90a, gfx942.
21430 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
21431 return ReportHWInst(AtomicExpansionKind::None);
21432
21433 if (AS != AMDGPUAS::FLAT_ADDRESS) {
21434 if (Ty->isFloatTy()) {
21435 // global/buffer atomic fadd f32 no-rtn: gfx908, gfx90a, gfx942,
21436 // gfx11+.
21437 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21438 return ReportHWInst(AtomicExpansionKind::None);
21439 // global/buffer atomic fadd f32 rtn: gfx90a, gfx942, gfx11+.
21440 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21441 return ReportHWInst(AtomicExpansionKind::None);
21442 } else {
21443 // gfx908
21444 if (RMW->use_empty() &&
21445 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
21446 isV2F16(Ty))
21447 return ReportHWInst(AtomicExpansionKind::None);
21448 }
21449 }
21450
21451 // flat atomic fadd f32: gfx942, gfx11+.
21452 if (AS == AMDGPUAS::FLAT_ADDRESS && Ty->isFloatTy()) {
21453 if (Subtarget->hasFlatAtomicFaddF32Inst())
21454 return ReportHWInst(AtomicExpansionKind::None);
21455
21456 // If it is in flat address space, and the type is float, we will try to
21457 // expand it, if the target supports global and lds atomic fadd. The
21458 // reason we need that is, in the expansion, we emit the check of
21459 // address space. If it is in global address space, we emit the global
21460 // atomic fadd; if it is in shared address space, we emit the LDS atomic
21461 // fadd.
21462 if (Subtarget->hasLDSFPAtomicAddF32()) {
21463 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
21465 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
21467 }
21468 }
21469 }
21470
21472 }
21474 case AtomicRMWInst::FMax: {
21475 Type *Ty = RMW->getType();
21476
21477 // LDS float and double fmin/fmax were always supported.
21478 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
21479 return Ty->isFloatTy() || Ty->isDoubleTy() ? AtomicExpansionKind::None
21481 }
21482
21483 MemLegality =
21484 getGlobalMemoryFPAtomicLegality(*Subtarget, RMW, HasSystemScope);
21485 if (MemLegality != GlobalFPAtomicLegality::Illegal) {
21486 // For flat and global cases:
21487 // float, double in gfx7. Manual claims denormal support.
21488 // Removed in gfx8.
21489 // float, double restored in gfx10.
21490 // double removed again in gfx11, so only f32 for gfx11/gfx12.
21491 //
21492 // For gfx9, gfx90a and gfx942 support f64 for global (same as fadd), but
21493 // no f32.
21494 if (AS == AMDGPUAS::FLAT_ADDRESS) {
21495 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
21496 return ReportHWInst(AtomicExpansionKind::None);
21497 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
21498 return ReportHWInst(AtomicExpansionKind::None);
21499 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS) ||
21501 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
21502 return ReportHWInst(AtomicExpansionKind::None);
21503 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
21504 return ReportHWInst(AtomicExpansionKind::None);
21505 }
21506 }
21507
21509 }
21512 default:
21514 }
21515
21516 llvm_unreachable("covered atomicrmw op switch");
21517}
21518
21525
21532
21535 const AtomicCmpXchgInst *CmpX) const {
21536 unsigned AddrSpace = CmpX->getPointerAddressSpace();
21537 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS)
21539
21540 if (AddrSpace != AMDGPUAS::FLAT_ADDRESS || !flatInstrMayAccessPrivate(CmpX))
21542
21543 const DataLayout &DL = CmpX->getDataLayout();
21544
21545 Type *ValTy = CmpX->getNewValOperand()->getType();
21546
21547 // If a 64-bit flat atomic may alias private, we need to avoid using the
21548 // atomic in the private case.
21549 return DL.getTypeSizeInBits(ValTy) == 64 ? AtomicExpansionKind::CustomExpand
21551}
21552
21553const TargetRegisterClass *
21554SITargetLowering::getRegClassFor(MVT VT, bool isDivergent) const {
21556 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
21557 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
21558 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
21559 : &AMDGPU::SReg_32RegClass;
21560 if (!TRI->isSGPRClass(RC) && !isDivergent)
21561 return TRI->getEquivalentSGPRClass(RC);
21562 if (TRI->isSGPRClass(RC) && isDivergent) {
21563 if (Subtarget->hasGFX90AInsts())
21564 return TRI->getEquivalentAVClass(RC);
21565 return TRI->getEquivalentVGPRClass(RC);
21566 }
21567
21568 return RC;
21569}
21570
21571// FIXME: This is a workaround for DivergenceAnalysis not understanding always
21572// uniform values (as produced by the mask results of control flow intrinsics)
21573// used outside of divergent blocks. The phi users need to also be treated as
21574// always uniform.
21575//
21576// FIXME: DA is no longer in-use. Does this still apply to UniformityAnalysis?
21578 unsigned WaveSize) {
21579 // FIXME: We assume we never cast the mask results of a control flow
21580 // intrinsic.
21581 // Early exit if the type won't be consistent as a compile time hack.
21582 IntegerType *IT = dyn_cast<IntegerType>(V->getType());
21583 if (!IT || IT->getBitWidth() != WaveSize)
21584 return false;
21585
21586 if (!isa<Instruction>(V))
21587 return false;
21588 if (!Visited.insert(V).second)
21589 return false;
21590 bool Result = false;
21591 for (const auto *U : V->users()) {
21593 if (V == U->getOperand(1)) {
21594 switch (Intrinsic->getIntrinsicID()) {
21595 default:
21596 Result = false;
21597 break;
21598 case Intrinsic::amdgcn_if_break:
21599 case Intrinsic::amdgcn_if:
21600 case Intrinsic::amdgcn_else:
21601 Result = true;
21602 break;
21603 }
21604 }
21605 if (V == U->getOperand(0)) {
21606 switch (Intrinsic->getIntrinsicID()) {
21607 default:
21608 Result = false;
21609 break;
21610 case Intrinsic::amdgcn_end_cf:
21611 case Intrinsic::amdgcn_loop:
21612 Result = true;
21613 break;
21614 }
21615 }
21616 } else {
21617 Result = hasCFUser(U, Visited, WaveSize);
21618 }
21619 if (Result)
21620 break;
21621 }
21622 return Result;
21623}
21624
21626 const Value *V) const {
21627 if (const CallInst *CI = dyn_cast<CallInst>(V)) {
21628 if (CI->isInlineAsm()) {
21629 // FIXME: This cannot give a correct answer. This should only trigger in
21630 // the case where inline asm returns mixed SGPR and VGPR results, used
21631 // outside the defining block. We don't have a specific result to
21632 // consider, so this assumes if any value is SGPR, the overall register
21633 // also needs to be SGPR.
21634 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
21636 MF.getDataLayout(), Subtarget->getRegisterInfo(), *CI);
21637 for (auto &TC : TargetConstraints) {
21638 if (TC.Type == InlineAsm::isOutput) {
21640 const TargetRegisterClass *RC =
21641 getRegForInlineAsmConstraint(SIRI, TC.ConstraintCode,
21642 TC.ConstraintVT)
21643 .second;
21644 if (RC && SIRI->isSGPRClass(RC))
21645 return true;
21646 }
21647 }
21648 }
21649 }
21651 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21652}
21653
21655 for (SDUse &Use : N->uses()) {
21657 if (getBasePtrIndex(M) == Use.getOperandNo())
21658 return true;
21659 }
21660 }
21661 return false;
21662}
21663
21665 SDValue N1) const {
21666 if (!N0.hasOneUse())
21667 return false;
21668 // Take care of the opportunity to keep N0 uniform
21669 if (N0->isDivergent() || !N1->isDivergent())
21670 return true;
21671 // Check if we have a good chance to form the memory access pattern with the
21672 // base and offset
21673 return (DAG.isBaseWithConstantOffset(N0) &&
21675}
21676
21678 Register N0, Register N1) const {
21679 return MRI.hasOneNonDBGUse(N0); // FIXME: handle regbanks
21680}
21681
21684 // Propagate metadata set by AMDGPUAnnotateUniformValues to the MMO of a load.
21686 if (I.getMetadata("amdgpu.noclobber"))
21687 Flags |= MONoClobber;
21688 if (I.getMetadata("amdgpu.last.use"))
21689 Flags |= MOLastUse;
21690 if (MDNode *N = I.getMetadata("amdgpu.cfs")) {
21691 const ConstantAsMetadata *CAM = cast<ConstantAsMetadata>(N->getOperand(0));
21693 unsigned CFS = CI->getZExtValue() & AMDGPU::CPol::CFS_MASK;
21694 static_assert((MOCFSB0 << 1) == MOCFSB1,
21695 "MOCFSB0 and MOCFSB1 are not adjacent bits");
21696 Flags |= static_cast<MachineMemOperand::Flags>(CFS * MOCFSB0);
21697 }
21698 return Flags;
21699}
21700
21702 Instruction *AI) const {
21703 // Given: atomicrmw fadd ptr %addr, float %val ordering
21704 //
21705 // With this expansion we produce the following code:
21706 // [...]
21707 // %is.shared = call i1 @llvm.amdgcn.is.shared(ptr %addr)
21708 // br i1 %is.shared, label %atomicrmw.shared, label %atomicrmw.check.private
21709 //
21710 // atomicrmw.shared:
21711 // %cast.shared = addrspacecast ptr %addr to ptr addrspace(3)
21712 // %loaded.shared = atomicrmw fadd ptr addrspace(3) %cast.shared,
21713 // float %val ordering
21714 // br label %atomicrmw.phi
21715 //
21716 // atomicrmw.check.private:
21717 // %is.private = call i1 @llvm.amdgcn.is.private(ptr %int8ptr)
21718 // br i1 %is.private, label %atomicrmw.private, label %atomicrmw.global
21719 //
21720 // atomicrmw.private:
21721 // %cast.private = addrspacecast ptr %addr to ptr addrspace(5)
21722 // %loaded.private = load float, ptr addrspace(5) %cast.private
21723 // %val.new = fadd float %loaded.private, %val
21724 // store float %val.new, ptr addrspace(5) %cast.private
21725 // br label %atomicrmw.phi
21726 //
21727 // atomicrmw.global:
21728 // %cast.global = addrspacecast ptr %addr to ptr addrspace(1)
21729 // %loaded.global = atomicrmw fadd ptr addrspace(1) %cast.global,
21730 // float %val ordering
21731 // br label %atomicrmw.phi
21732 //
21733 // atomicrmw.phi:
21734 // %loaded.phi = phi float [ %loaded.shared, %atomicrmw.shared ],
21735 // [ %loaded.private, %atomicrmw.private ],
21736 // [ %loaded.global, %atomicrmw.global ]
21737 // br label %atomicrmw.end
21738 //
21739 // atomicrmw.end:
21740 // [...]
21741 //
21742 //
21743 // For 64-bit atomics which may reside in private memory, we perform a simpler
21744 // version that only inserts the private check, and uses the flat operation.
21745
21746 IRBuilder<> Builder(AI);
21747 LLVMContext &Ctx = Builder.getContext();
21748
21749 auto *RMW = dyn_cast<AtomicRMWInst>(AI);
21750 const unsigned PtrOpIdx = RMW ? AtomicRMWInst::getPointerOperandIndex()
21752 Value *Addr = AI->getOperand(PtrOpIdx);
21753
21754 /// TODO: Only need to check private, then emit flat-known-not private (no
21755 /// need for shared block, or cast to global).
21757
21758 Align Alignment;
21759 if (RMW)
21760 Alignment = RMW->getAlign();
21761 else if (CX)
21762 Alignment = CX->getAlign();
21763 else
21764 llvm_unreachable("unhandled atomic operation");
21765
21766 // FullFlatEmulation is true if we need to issue the private, shared, and
21767 // global cases.
21768 //
21769 // If this is false, we are only dealing with the flat-targeting-private case,
21770 // where we only insert a check for private and still use the flat instruction
21771 // for global and shared.
21772
21773 bool FullFlatEmulation =
21774 RMW && RMW->getOperation() == AtomicRMWInst::FAdd &&
21775 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21776 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21777 RMW->getType()->isDoubleTy()));
21778
21779 // If the return value isn't used, do not introduce a false use in the phi.
21780 bool ReturnValueIsUsed = !AI->use_empty();
21781
21782 BasicBlock *BB = Builder.GetInsertBlock();
21783 Function *F = BB->getParent();
21784 BasicBlock *ExitBB =
21785 BB->splitBasicBlock(Builder.GetInsertPoint(), "atomicrmw.end");
21786 BasicBlock *SharedBB = nullptr;
21787
21788 BasicBlock *CheckPrivateBB = BB;
21789 if (FullFlatEmulation) {
21790 SharedBB = BasicBlock::Create(Ctx, "atomicrmw.shared", F, ExitBB);
21791 CheckPrivateBB =
21792 BasicBlock::Create(Ctx, "atomicrmw.check.private", F, ExitBB);
21793 }
21794
21795 BasicBlock *PrivateBB =
21796 BasicBlock::Create(Ctx, "atomicrmw.private", F, ExitBB);
21797 BasicBlock *GlobalBB = BasicBlock::Create(Ctx, "atomicrmw.global", F, ExitBB);
21798 BasicBlock *PhiBB = BasicBlock::Create(Ctx, "atomicrmw.phi", F, ExitBB);
21799
21800 std::prev(BB->end())->eraseFromParent();
21801 Builder.SetInsertPoint(BB);
21802
21803 Value *LoadedShared = nullptr;
21804 if (FullFlatEmulation) {
21805 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21806 {Addr}, nullptr, "is.shared");
21807 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21808 Builder.SetInsertPoint(SharedBB);
21809 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21811
21812 Instruction *Clone = AI->clone();
21813 Clone->insertInto(SharedBB, SharedBB->end());
21814 Clone->getOperandUse(PtrOpIdx).set(CastToLocal);
21815 LoadedShared = Clone;
21816
21817 Builder.CreateBr(PhiBB);
21818 Builder.SetInsertPoint(CheckPrivateBB);
21819 }
21820
21821 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21822 {Addr}, nullptr, "is.private");
21823 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21824
21825 Builder.SetInsertPoint(PrivateBB);
21826
21827 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21829
21830 Value *LoadedPrivate;
21831 if (RMW) {
21832 LoadedPrivate = Builder.CreateAlignedLoad(
21833 RMW->getType(), CastToPrivate, RMW->getAlign(), RMW->isVolatile(),
21834 "loaded.private");
21835
21836 Value *NewVal = buildAtomicRMWValue(RMW->getOperation(), Builder,
21837 LoadedPrivate, RMW->getValOperand());
21838
21839 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign(),
21840 RMW->isVolatile());
21841 } else {
21842 auto [ResultLoad, Equal] = buildCmpXchgValue(
21843 Builder, CastToPrivate, CX->getCompareOperand(), CX->getNewValOperand(),
21844 CX->getAlign(), CX->isVolatile());
21845
21846 Value *Insert = Builder.CreateInsertValue(PoisonValue::get(CX->getType()),
21847 ResultLoad, 0);
21848 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21849 }
21850
21851 Builder.CreateBr(PhiBB);
21852
21853 Builder.SetInsertPoint(GlobalBB);
21854
21855 // Continue using a flat instruction if we only emitted the check for private.
21856 Instruction *LoadedGlobal = AI;
21857 if (FullFlatEmulation) {
21858 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21860 AI->getOperandUse(PtrOpIdx).set(CastToGlobal);
21861 }
21862
21863 AI->removeFromParent();
21864 AI->insertInto(GlobalBB, GlobalBB->end());
21865
21866 // The new atomicrmw may go through another round of legalization later.
21867 if (!FullFlatEmulation) {
21868 // We inserted the runtime check already, make sure we do not try to
21869 // re-expand this.
21870 // TODO: Should union with any existing metadata.
21871 MDBuilder MDB(F->getContext());
21872 MDNode *RangeNotPrivate =
21875 LoadedGlobal->setMetadata(LLVMContext::MD_noalias_addrspace,
21876 RangeNotPrivate);
21877 }
21878
21879 Builder.CreateBr(PhiBB);
21880
21881 Builder.SetInsertPoint(PhiBB);
21882
21883 if (ReturnValueIsUsed) {
21884 PHINode *Loaded = Builder.CreatePHI(AI->getType(), 3);
21885 AI->replaceAllUsesWith(Loaded);
21886 if (FullFlatEmulation)
21887 Loaded->addIncoming(LoadedShared, SharedBB);
21888 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21889 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21890 Loaded->takeName(AI);
21891 }
21892
21893 Builder.CreateBr(ExitBB);
21894}
21895
21897 unsigned PtrOpIdx) {
21898 Value *PtrOp = I->getOperand(PtrOpIdx);
21901
21902 Type *FlatPtr = PointerType::get(I->getContext(), AMDGPUAS::FLAT_ADDRESS);
21903 Value *ASCast = CastInst::CreatePointerCast(PtrOp, FlatPtr, "scratch.ascast",
21904 I->getIterator());
21905 I->setOperand(PtrOpIdx, ASCast);
21906}
21907
21910
21913
21916 if (const auto *ConstVal = dyn_cast<Constant>(AI->getValOperand());
21917 ConstVal && ConstVal->isNullValue() &&
21919 // atomicrmw or %ptr, 0 -> atomicrmw add %ptr, 0
21921
21922 // We may still need the private-alias-flat handling below.
21923
21924 // TODO: Skip this for cases where we cannot access remote memory.
21925 }
21926 }
21927
21928 // The non-flat expansions should only perform the de-canonicalization of
21929 // identity values.
21931 return;
21932
21934}
21935
21942
21946
21948 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21949}
21950
21952 if (SI->getPointerAddressSpace() == AMDGPUAS::PRIVATE_ADDRESS)
21953 return convertScratchAtomicToFlatAtomic(SI, SI->getPointerOperandIndex());
21954
21956 "Expand Atomic Store only handles SCRATCH -> FLAT conversion");
21957}
static bool isMul(MachineInstr *MI)
unsigned NumParts
return SDValue()
static unsigned getIntrinsicID(const SDNode *N)
const AArch64Subtarget & Subtarget
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
static constexpr std::pair< ImplicitArgumentMask, StringLiteral > ImplicitAttrs[]
static bool allUsesHaveSourceMods(MachineInstr &MI, MachineRegisterInfo &MRI, unsigned CostThreshold=4)
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
uint64_t uint64_t
uint64_t Imm
static bool isCtlzOpc(unsigned Opc)
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isNoUnsignedWrap(MachineInstr *Addr)
static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE, bool &IsTexFail)
static bool isAsyncLDSDMA(Intrinsic::ID Intr)
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
Function Alias Analysis Results
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
@ DEFAULT
Default weight is used in cases when there is no dedicated execution weight set.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< SDByteProvider > calculateByteProvider(SDValue Op, unsigned Index, unsigned Depth, std::optional< uint64_t > VectorIndex, unsigned StartingIndex=0, MutableArrayRef< uint8_t > ByteMask={})
dxil translate DXIL Translate Metadata
static bool isSigned(unsigned Opcode)
Utilities for dealing with flags related to floating point properties and mode controls.
AMD GCN specific subclass of TargetSubtarget.
Provides analysis for querying information about KnownBits during GISel passes.
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
iv Induction Variable Users
Definition IVUsers.cpp:48
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RegName(no)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Contains matchers for matching SSA Machine Instructions.
static bool isUndef(const MachineInstr &MI)
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
uint64_t IntrinsicInst * II
#define P(N)
if(PassOpts->AAPipeline)
static constexpr MCPhysReg SPReg
MachineBasicBlock * Folded
SmallVector< MachineOperand, 4 > Cond
int64_t C1
RISCVCC::CondCode CC
MachineRegisterInfo & MRI
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
Contains matchers for matching SelectionDAG nodes and values.
static void r0(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:39
static void r3(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:57
static void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:51
static void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:45
#define FP_DENORM_FLUSH_NONE
Definition SIDefines.h:1516
#define FP_DENORM_FLUSH_IN_FLUSH_OUT
Definition SIDefines.h:1513
SI Fold Operands
static void reservePrivateMemoryRegs(const TargetMachine &TM, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info)
static SDValue adjustLoadValueTypeImpl(SDValue Result, EVT LoadVT, const SDLoc &DL, SelectionDAG &DAG, bool Unpacked)
static MachineBasicBlock * emitIndirectSrc(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static bool denormalModeIsFlushAllF64F16(const MachineFunction &MF)
static bool isAtomicRMWLegalIntTy(Type *Ty)
static void knownBitsForWorkitemID(const GCNSubtarget &ST, GISelValueTracking &VT, KnownBits &Known, unsigned Dim)
static bool flatInstrMayAccessPrivate(const Instruction *I)
Return if a flat address space atomicrmw can access private memory.
static std::pair< unsigned, int > computeIndirectRegAndOffset(const SIRegisterInfo &TRI, const TargetRegisterClass *SuperRC, unsigned VecReg, int Offset)
static bool denormalModeIsFlushAllF32(const MachineFunction &MF)
static bool addresses16Bits(int Mask)
static MachineBasicBlock * expand64BitScalarArithmetic(MachineInstr &MI, MachineBasicBlock *BB)
static bool isClampZeroToOne(SDValue A, SDValue B)
static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc, EVT VT)
static AtomicFlushDenormalReason getAtomicFlushDenormalReason(const AtomicRMWInst *RMW)
static unsigned findFirstFreeSGPR(CCState &CCInfo)
static uint32_t getPermuteMask(SDValue V)
static SDValue lowerLaneOp(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static int getAlignedAGPRClassID(unsigned UnalignedClassID)
static void processPSInputArgs(SmallVectorImpl< ISD::InputArg > &Splits, CallingConv::ID CallConv, ArrayRef< ISD::InputArg > Ins, BitVector &Skipped, FunctionType *FType, SIMachineFunctionInfo *Info)
static SDValue selectSOffset(SDValue SOffset, SelectionDAG &DAG, const GCNSubtarget *Subtarget)
static SDValue getLoadExtOrTrunc(SelectionDAG &DAG, ISD::LoadExtType ExtType, SDValue Op, const SDLoc &SL, EVT VT)
static std::tuple< unsigned, unsigned > getDPPOpcForWaveReduction(unsigned Opc, const GCNSubtarget &ST)
static void fixMasks(SmallVectorImpl< DotSrc > &Srcs, unsigned ChainLength)
static bool is32bitWaveReduceOperation(unsigned Opc)
static TargetLowering::AtomicExpansionKind atomicSupportedIfLegalIntType(const AtomicRMWInst *RMW)
static SDValue strictFPExtFromF16(SelectionDAG &DAG, SDValue Src)
Return the source of an fp_extend from f16 to f32, or a converted FP constant.
static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW)
static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val)
static void convertScratchAtomicToFlatAtomic(Instruction *I, unsigned PtrOpIdx)
static bool isCopyFromRegOfInlineAsm(const SDNode *N)
static bool elementPairIsOddToEven(ArrayRef< int > Mask, int Elt)
static SDValue lowerBFEIntrinsic(SDValue Op, SelectionDAG &DAG, Intrinsic::ID IntrinsicID)
static cl::opt< bool > DisableLoopAlignment("amdgpu-disable-loop-alignment", cl::desc("Do not align and prefetch loops"), cl::init(false))
static SDValue getDWordFromOffset(SelectionDAG &DAG, SDLoc SL, SDValue Src, unsigned DWordOffset)
static MachineBasicBlock::iterator loadM0FromVGPR(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineInstr &MI, unsigned InitResultReg, unsigned PhiReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static bool isFloatingPointWaveReduceOperation(unsigned Opc)
static bool isImmConstraint(StringRef Constraint)
static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT, SDValue Src, int ExtraElts)
static bool hasCFUser(const Value *V, SmallPtrSet< const Value *, 16 > &Visited, unsigned WaveSize)
static std::pair< Register, Register > ExtractSubRegs(MachineInstr &MI, MachineOperand &Op, const TargetRegisterClass *SrcRC, const GCNSubtarget &ST, MachineRegisterInfo &MRI)
static unsigned SubIdx2Lane(unsigned Idx)
Helper function for adjustWritemask.
static TargetLowering::AtomicExpansionKind getPrivateAtomicExpansionKind(const GCNSubtarget &STI)
static bool addressMayBeAccessedAsPrivate(const MachineMemOperand *MMO, const SIMachineFunctionInfo &Info)
static MachineBasicBlock * lowerWaveReduce(MachineInstr &MI, MachineBasicBlock &BB, const GCNSubtarget &ST, unsigned Opc)
static bool elementPairIsContiguous(ArrayRef< int > Mask, int Elt)
static bool isV2BF16(Type *Ty)
static bool isFrexpExp(SDValue V, SDValue &FrexpInput)
static ArgDescriptor allocateSGPR32InputImpl(CCState &CCInfo, const TargetRegisterClass *RC, unsigned NumArgRegs)
static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue N0, SDValue N1, SDValue N2, bool Signed)
static SDValue resolveSources(SelectionDAG &DAG, SDLoc SL, SmallVectorImpl< DotSrc > &Srcs, bool IsSigned, bool IsAny)
static bool hasNon16BitAccesses(uint64_t PermMask, SDValue &Op, SDValue &OtherOp)
static SDValue lowerWaveShuffle(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue diagnoseUnsupportedImage(SelectionDAG &DAG, SDValue Op, ArrayRef< EVT > ResultTypes, const SDLoc &DL, const Twine &Msg)
Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and return poison values of Resul...
static void placeSources(ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, SmallVectorImpl< DotSrc > &Src0s, SmallVectorImpl< DotSrc > &Src1s, int Step)
static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx)
static EVT memVTFromLoadIntrReturn(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static MachineBasicBlock::iterator emitLoadM0FromVGPRLoop(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB, const DebugLoc &DL, const MachineOperand &Idx, unsigned InitReg, unsigned ResultReg, unsigned PhiReg, unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static SDValue matchPERM(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isFrameIndexOp(SDValue Op)
static ConstantFPSDNode * getSplatConstantFP(SDValue Op)
static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg)
static void knownBitsForSBFE(const MachineInstr &MI, GISelValueTracking &VT, KnownBits &Known, const APInt &DemandedElts, unsigned BFEWidth, bool SExt, unsigned Depth)
static bool isExtendedFrom16Bits(SDValue &Operand)
static std::optional< bool > checkDot4MulSignedness(const SDValue &N, ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, const SDValue &S0Op, const SDValue &S1Op, const SelectionDAG &DAG)
static bool vectorEltWillFoldAway(SDValue Op)
static SDValue getSPDenormModeValue(uint32_t SPDenormMode, SelectionDAG &DAG, const SIMachineFunctionInfo *Info, const GCNSubtarget *ST)
static uint32_t getConstantPermuteMask(uint32_t C)
static AtomicOrdering parseAtomicOrderingCABIArg(const CallBase &CI, unsigned ArgIdx)
static MachineBasicBlock * emitIndirectDst(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static void setM0ToIndexFromSGPR(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static DenormalFPEnv getDenormalFPEnv(const MachineFunction &MF)
static std::pair< MachineBasicBlock *, MachineBasicBlock * > splitBlockForLoop(MachineInstr &MI, MachineBasicBlock &MBB, bool InstInLoop)
static unsigned getBasePtrIndex(const MemSDNode *N)
MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset by the chain and intrinsi...
static void allocateFixedSGPRInputImpl(CCState &CCInfo, const TargetRegisterClass *RC, MCRegister Reg)
static SDValue constructRetValue(SelectionDAG &DAG, MachineSDNode *Result, ArrayRef< EVT > ResultTypes, bool IsTexFail, bool Unpacked, bool IsD16, int DMaskPop, int NumVDataDwords, bool IsAtomicPacked16Bit, const SDLoc &DL)
static std::pair< SDValue, SDValue > splitTFEValueAndStatus(SDValue Op, EVT VT, const SDLoc &DL, SelectionDAG &DAG)
static std::optional< ByteProvider< SDValue > > handleMulOperand(const SDValue &MulOperand)
static ISD::CondCode tryReduceF64CompareToHiHalf(const ISD::CondCode CC, const SDValue LHS, const SDValue RHS, const SelectionDAG &DAG)
static Register getIndirectSGPRIdx(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static SDValue emitNonHSAIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static EVT memVTFromLoadIntrData(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc)
static unsigned getExtOpcodeForPromotedOp(SDValue Op)
static void expand64BitV_CNDMASK(MachineInstr &MI, MachineBasicBlock *BB)
static GlobalFPAtomicLegality getGlobalMemoryFPAtomicLegality(const GCNSubtarget &Subtarget, const AtomicRMWInst *RMW, bool HasSystemScope)
static SDValue lowerBALLOTIntrinsic(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue buildSMovImm32(SelectionDAG &DAG, const SDLoc &DL, uint64_t Val)
static SDValue tryFoldMADwithSRL(SelectionDAG &DAG, const SDLoc &SL, SDValue MulLHS, SDValue MulRHS, SDValue AddRHS)
static unsigned getIntrMemWidth(unsigned IntrID)
static SDValue getBuildDwordsVector(SelectionDAG &DAG, SDLoc DL, ArrayRef< SDValue > Elts)
static SDNode * findUser(SDValue Value, unsigned Opcode)
Helper function for LowerBRCOND.
static unsigned addPermMasks(unsigned First, unsigned Second)
static uint64_t clearUnusedBits(uint64_t Val, unsigned Size)
static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue C, SDValue GlueChain, SDNodeFlags Flags)
static bool isV2F16OrV2BF16(Type *Ty)
static OptimizationRemark emitAtomicRMWLegalRemark(const AtomicRMWInst *RMW, GlobalFPAtomicLegality MemLegality, AtomicFlushDenormalReason DenormReason)
static SDValue emitRemovedIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue GlueChain, SDNodeFlags Flags)
static SDValue buildPCRelGlobalAddress(SelectionDAG &DAG, const GlobalValue *GV, const SDLoc &DL, int64_t Offset, EVT PtrVT, unsigned GAFlags=SIInstrInfo::MO_NONE)
static cl::opt< bool > UseDivergentRegisterIndexing("amdgpu-use-divergent-register-indexing", cl::Hidden, cl::desc("Use indirect register addressing for divergent indexes"), cl::init(false))
static const std::optional< ByteProvider< SDValue > > calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex=0, unsigned Depth=0)
static bool isV2F16(Type *Ty)
static void initializeM0ToZeroForClusterLoad(SDValue Op, SelectionDAG &DAG, SDLoc DL)
static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg)
static uint64_t getIdentityValueForWaveReduction(unsigned Opc)
SI DAG Lowering interface definition.
Interface definition for SIRegisterInfo.
const char * Msg
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
static unsigned getScalarSizeInBits(Type *Ty)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
LLVM IR instance of the generic uniformity analysis.
static constexpr int Concat[]
Value * RHS
Value * LHS
The Input class is used to parse a yaml document into in-memory structs and vectors.
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
static std::optional< uint32_t > get32BitAbsoluteAddress(const GlobalValue &GV, unsigned AS)
static unsigned numBitsSigned(SDValue Op, SelectionDAG &DAG)
SDValue SplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Split a vector load into 2 loads of half the vector.
void analyzeFormalArgumentsCompute(CCState &State, const SmallVectorImpl< ISD::InputArg > &Ins) const
The SelectionDAGBuilder will automatically promote function arguments with illegal types.
SDValue LowerF64ToF16Safe(SDValue Src, const SDLoc &DL, SelectionDAG &DAG) const
SDValue storeStackInputValue(SelectionDAG &DAG, const SDLoc &SL, SDValue Chain, SDValue ArgVal, int64_t Offset) const
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue splitBinaryBitConstantOpImpl(DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS, uint32_t ValLo, uint32_t ValHi) const
Split the 64-bit value LHS into two 32-bit components, and perform the binary operation Opc to it wit...
SDValue lowerUnhandledCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals, StringRef Reason) const
virtual SDValue LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI, SDValue Op, SelectionDAG &DAG) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
SDValue addTokenForArgument(SDValue Chain, SelectionDAG &DAG, MachineFrameInfo &MFI, int ClobberedFI) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
static bool needsDenormHandlingF32(const SelectionDAG &DAG, SDValue Src, SDNodeFlags Flags)
uint32_t getImplicitParameterOffset(const MachineFunction &MF, const ImplicitParameter Param) const
Helper function that returns the byte offset of the given type of implicit parameter.
SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const
static KnownBits computeKnownBitsForMul24(const KnownBits &LHSKnown, const KnownBits &RHSKnown, unsigned BitWidth, bool IsSigned, bool SelfMultiply)
SDValue loadInputValue(SelectionDAG &DAG, const TargetRegisterClass *RC, EVT VT, const SDLoc &SL, const ArgDescriptor &Arg) const
AMDGPUTargetLowering(const TargetMachine &TM, const TargetSubtargetInfo &STI, const AMDGPUSubtarget &AMDGPUSTI)
static EVT getEquivalentMemType(LLVMContext &Context, EVT VT)
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
SDValue CreateLiveInRegister(SelectionDAG &DAG, const TargetRegisterClass *RC, Register Reg, EVT VT, const SDLoc &SL, bool RawReg=false) const
Helper function that adds Reg to the LiveIn list of the DAG's MachineFunction.
SDValue SplitVectorStore(SDValue Op, SelectionDAG &DAG) const
Split a vector store into 2 stores of half the vector.
std::pair< SDValue, SDValue > split64BitValue(SDValue Op, SelectionDAG &DAG) const
Return 64-bit value Op as two 32-bit integers.
static CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg)
static CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg)
Selects the correct CCAssignFn for a given CallingConvention value.
static unsigned numBitsUnsigned(SDValue Op, SelectionDAG &DAG)
static bool allowApproxFunc(const SelectionDAG &DAG, SDNodeFlags Flags)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
SDValue performRcpCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const
static bool shouldFoldFNegIntoSrc(SDNode *FNeg, SDValue FNegSrc)
bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const override
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue WidenOrSplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Widen a suitably aligned v3 load.
SDValue getHiHalf64(SDValue Op, SelectionDAG &DAG) const
bool isNoopAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const LaneMaskConstants & get(const GCNSubtarget &ST)
static const fltSemantics & IEEEsingle()
Definition APFloat.h:304
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:361
static const fltSemantics & IEEEhalf()
Definition APFloat.h:302
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
Definition APFloat.h:1224
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:6045
LLVM_READONLY int getExactLog2Abs() const
Definition APFloat.h:1654
bool isNegative() const
Definition APFloat.h:1583
bool isNormal() const
Definition APFloat.h:1587
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
Definition APFloat.h:1192
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
Definition APFloat.h:1242
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition APFloat.h:1202
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition APFloat.h:1183
bool isInfinity() const
Definition APFloat.h:1580
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1057
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
Definition APInt.h:202
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
Definition APInt.h:254
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:376
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
Definition APInt.h:462
unsigned countr_zero() const
Count the number of trailing zero bits.
Definition APInt.h:1659
bool isOneBitSet(unsigned BitNo) const
Determine if this APInt Value only has the specified bit set.
Definition APInt.h:362
bool isMask(unsigned numBits) const
Definition APInt.h:484
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
Definition APInt.h:337
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition APInt.h:292
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
Definition APInt.h:1241
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
Definition APInt.h:1225
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Check if an argument has a given attribute.
Definition Function.cpp:332
const Function * getParent() const
Definition Argument.h:44
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
An instruction that atomically checks whether a specified value is in a memory location,...
bool isVolatile() const
Return true if this is a cmpxchg from a volatile memory location.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
static unsigned getPointerOperandIndex()
an instruction that atomically reads a memory location, combines it with another value,...
static unsigned getPointerOperandIndex()
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ Add
*p = old + v
@ FAdd
*p = old + v
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ Sub
*p = old - v
@ And
*p = old & v
@ Xor
*p = old ^ v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ FSub
*p = old - v
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
@ Nand
*p = ~(old & v)
void setOperation(BinOp Operation)
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
static LLVM_ABI StringRef getOperationName(BinOp Op)
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
bool isCompareAndSwap() const
Returns true if this SDNode represents cmpxchg atomic operation, false otherwise.
This class holds the attributes for a particular argument, parameter, function, or return value.
Definition Attributes.h:406
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator end()
Definition BasicBlock.h:453
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
A "pseudo-class" with methods for operating on BUILD_VECTORs.
Represents known origin of an individual byte in combine pattern.
static ByteProvider getConstantZero()
static ByteProvider getSrc(std::optional< ISelOp > Val, int64_t ByteOffset, int64_t VectorOffset)
CCState - This class holds information needed while lowering arguments and return values.
MachineFunction & getMachineFunction() const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
LLVM_ABI void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
bool isAllocated(MCRegister Reg) const
isAllocated - Return true if the specified register (or an alias) is allocated.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
bool isTailCall() const
static LLVM_ABI CastInst * CreatePointerCast(Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction.
Constant * getValue() const
Definition Metadata.h:556
const APFloat & getValueAPF() const
bool isPosZero() const
Return true if the value is positive zero.
bool isOne() const
Returns true if this value is exactly +1.0.
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isNegative() const
Return true if the value is negative.
This is the shared class of boolean and integer constants.
Definition Constants.h:87
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition Constants.h:219
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
Definition Constant.h:44
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
bool isBigEndian() const
Definition DataLayout.h:218
A debug info location.
Definition DebugLoc.h:126
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:306
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Register DemoteRegister
DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg allocated to hold a pointer to ...
LLVM_ABI const Value * getValueFromVirtualReg(Register Vreg)
This method is called from TargetLowerinInfo::isSDNodeSourceOfDivergence to get the Value correspondi...
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:212
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Definition Function.cpp:356
iterator_range< arg_iterator > args()
Definition Function.h:877
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:273
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:352
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
Definition Function.cpp:807
size_t arg_size() const
Definition Function.h:886
Argument * getArg(unsigned i) const
Definition Function.h:871
const SIInstrInfo * getInstrInfo() const override
bool hasMadF16() const
unsigned getInstCacheLineSize() const
Instruction cache line size in bytes (64 for pre-GFX11, 128 for GFX11+).
const SIRegisterInfo * getRegisterInfo() const override
unsigned getMaxPrivateElementSize(bool ForBufferRSrc=false) const
bool hasPrivateSegmentBuffer() const
const MachineFunction & getMachineFunction() const
void computeKnownBitsImpl(Register R, KnownBits &Known, const APInt &DemandedElts, unsigned Depth=0)
Evaluate a known-bits query with an explicit worklist instead of recursive descent.
bool isDivergentAtDef(ConstValueRefT V) const
Whether V is divergent at its definition.
LLVM_ABI unsigned getAddressSpace() const
const GlobalValue * getGlobal() const
bool hasExternalLinkage() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Definition Globals.cpp:205
Type * getValueType() const
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2947
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
bool isKnownNeverNaN() const
Return true if it's known this can never be a nan.
static LLVM_ABI KnownFPClass bitcast(const fltSemantics &FltSemantics, const KnownBits &Bits)
Report known values for a bitcast into a float with provided semantics.
constexpr unsigned getScalarSizeInBits() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
static LLT integer(unsigned SizeInBits)
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI SyncScope::ID getOrInsertSyncScopeID(StringRef SSN)
getOrInsertSyncScopeID - Maps synchronization scope name to synchronization scope ID.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
static unsigned getPointerOperandIndex()
This class is used to represent ISD::LOAD nodes.
bool hasValue() const
TypeSize getValue() const
Describe properties that are true of each instruction in the target description file.
unsigned getID() const
getID() - Return the register class ID number.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
iterator begin() const
begin/end - Return all of the registers in this class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
LLVM_ABI MDNode * createRange(const APInt &Lo, const APInt &Hi)
Return metadata describing the range [Lo, Hi).
Definition MDBuilder.cpp:92
Metadata node.
Definition Metadata.h:1081
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1437
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
Machine Value Type.
SimpleValueType SimpleTy
uint64_t getScalarSizeInBits() const
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
static auto all_valuetypes()
SimpleValueType Iteration.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
Align getAlignment() const
Return alignment of the basic block.
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
bool hasCalls() const
Return true if the current function has any function calls.
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
bool hasStackObjects() const
Return true if there are any stack objects in this function.
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static MachineOperand CreateImm(int64_t Val)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
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...
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
EVT getMemoryVT() const
Return the type of the in-memory value.
bool onlyWritesMemory() const
Whether this function only (at most) writes memory.
Definition ModRef.h:252
bool doesNotAccessMemory() const
Whether this function accesses no memory.
Definition ModRef.h:246
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
Definition ModRef.h:249
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition Module.h:328
The optimization diagnostic interface.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Diagnostic information for applied optimization remarks.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
Definition Type.cpp:887
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition Register.h:72
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool isDivergent() const
bool hasOneUse() const
Return true if there is exactly one use of this node.
value_iterator value_end() const
ISD::CondCode getOperandCondCode(unsigned Num) const
Helper method returns the CondCode of a CondCodeSDNode.
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
op_iterator op_end() const
bool isAnyAdd() const
Returns true if the node type is ADD or PTRADD.
value_iterator value_begin() const
op_iterator op_begin() const
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isUndef() const
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
const AMDGPUGWSResourcePseudoSourceValue * getGWSPSV(const AMDGPUTargetMachine &TM)
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static unsigned getSubRegFromChannel(uint64_t Channel, uint64_t NumRegs=1)
static bool isVGPRClass(const TargetRegisterClass *RC)
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
bool isTypeDesirableForOp(unsigned Op, EVT VT) const override
Return true if the target has native support for the specified value type and it is 'desirable' to us...
SDNode * PostISelFolding(MachineSDNode *N, SelectionDAG &DAG) const override
Fold the instructions after selecting them.
SDValue splitTernaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachineSDNode * wrapAddr64Rsrc(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr) const
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool requiresUniformRegister(MachineFunction &MF, const Value *V) const override
Allows target to decide about the register class of the specific value that is live outside the defin...
bool isFMADLegal(const SelectionDAG &DAG, const SDNode *N) const override
Returns true if be combined with to form an ISD::FMAD.
AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void bundleInstWithWaitcnt(MachineInstr &MI) const
Insert MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
SDValue lowerROTR(SDValue Op, SelectionDAG &DAG) const
MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override
Return the type to use for a scalar shift opcode, given the shifted amount type.
SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
MVT getPointerTy(const DataLayout &DL, unsigned AS) const override
Map address space 7 to MVT::amdgpuBufferFatPointer because that's its in-memory representation.
bool denormalsEnabledForType(const SelectionDAG &DAG, EVT VT) const
void insertCopiesSplitCSR(MachineBasicBlock *Entry, const SmallVectorImpl< MachineBasicBlock * > &Exits) const override
Insert explicit copies in entry and exit blocks.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
SDNode * legalizeTargetIndependentNode(SDNode *Node, SelectionDAG &DAG) const
Legalize target independent instructions (e.g.
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
SDValue lowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const
const GCNSubtarget * getSubtarget() const
bool enableAggressiveFMAFusion(EVT VT) const override
Return true if target always benefits from combining into FMA for a given value type.
bool shouldEmitGOTReloc(const GlobalValue *GV) const
SDValue splitUnaryVectorOp(SDValue Op, SelectionDAG &DAG) const
SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool isCanonicalized(SelectionDAG &DAG, SDValue Op, SDNodeFlags UserFlags={}, unsigned MaxDepth=5) const
void allocateSpecialInputSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocateLDSKernelId(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const
bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const override
void allocateHSAUserSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent) const override
Return the register class that should be used for the specified value type.
void AddMemOpInit(MachineInstr &MI) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
bool isLegalGlobalAddressingMode(const AddrMode &AM) const
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
void emitExpandAtomicStore(StoreInst *SI) const override
Perform a atomic store using a target-specific way.
AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
Align computeKnownAlignForTargetInstr(GISelValueTracking &Analysis, Register R, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine the known alignment for the pointer value R.
bool getAsmOperandConstVal(SDValue Op, uint64_t &Val) const
bool isShuffleMaskLegal(ArrayRef< int >, EVT) const override
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
void emitExpandAtomicLoad(LoadInst *LI) const override
Perform a atomic load using a target-specific way.
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const override
Determine known bits of a pointer to a known valid stack object.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
LLT getPreferredShiftAmountTy(LLT Ty) const override
Return the preferred type to use for a shift opcode, given the shifted amount type is ShiftValueTy.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
Align getPrefLoopAlignment(MachineLoop *ML, const MachineBasicBlock *BlockToAlign) const override
Return the preferred loop alignment.
SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const override
True if target has some particular form of dealing with pointer arithmetic semantics for pointers wit...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &, const CallBase &, MachineFunction &MF, unsigned IntrinsicID) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
void allocateSpecialInputVGPRsFixed(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments in fixed registers.
MachineBasicBlock * emitGWSMemViolTestLoop(MachineInstr &MI, MachineBasicBlock *BB) const
bool getAddrModeArguments(const IntrinsicInst *I, SmallVectorImpl< Value * > &Ops, Type *&AccessTy) const override
CodeGenPrepare sinks address calculations into the same BB as Load/Store instructions reading the add...
bool checkAsmConstraintValA(SDValue Op, uint64_t Val, unsigned MaxSize=64) const
bool shouldEmitFixup(const GlobalValue *GV) const
MachineBasicBlock * splitKillBlock(MachineInstr &MI, MachineBasicBlock *BB) const
void emitExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) const override
Perform a cmpxchg expansion using a target-specific method.
bool canTransformPtrArithOutOfBounds(const Function &F, EVT PtrVT) const override
True if the target allows transformations of in-bounds pointer arithmetic that cause out-of-bounds in...
bool hasMemSDNodeUser(SDNode *N) const
bool isSDNodeSourceOfDivergence(const SDNode *N, FunctionLoweringInfo *FLI, UniformityInfo *UA) const override
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
bool isEligibleForTailCallOptimization(SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SmallVectorImpl< ISD::InputArg > &Ins, SelectionDAG &DAG) const
bool isMemOpHasNoClobberedMemOperand(const SDNode *N) const
bool isLegalFlatAddressingMode(const AddrMode &AM, unsigned AddrSpace) const
SDValue LowerCallResult(SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals, bool isThisReturn, SDValue ThisVal) const
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode, EVT DestVT, EVT SrcVT) const override
Return true if an fpext operation input to an Opcode operation is free (for instance,...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
Assign the register class depending on the number of bits set in the writemask.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
static bool isNonGlobalAddrSpace(unsigned AS)
void emitExpandAtomicAddrSpacePredicate(Instruction *AI) const
MachineSDNode * buildRSRC(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr, uint32_t RsrcDword1, uint64_t RsrcDword2And3) const
Return a resource descriptor with the 'Add TID' bit enabled The TID (Thread ID) is multiplied by the ...
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain targets require unusual breakdowns of certain types.
bool mayBeEmittedAsTailCall(const CallInst *) const override
Return true if the target may be able emit the call instruction as a tail call.
void passSpecialInputs(CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info, SmallVectorImpl< std::pair< unsigned, SDValue > > &RegsToPass, SmallVectorImpl< SDValue > &MemOpChains, SDValue Chain) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool checkAsmConstraintVal(SDValue Op, StringRef Constraint, uint64_t Val) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
static bool shouldExpandVectorDynExt(unsigned EltSize, unsigned NumElem, bool IsDivergentIdx, const GCNSubtarget *Subtarget)
Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be expanded into a set of cmp...
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool supportSplitCSR(MachineFunction *MF) const override
Return true if the target supports that a subset of CSRs for the given machine function is handled ex...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
bool allowsMisalignedMemoryAccesses(LLT Ty, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const override
LLT handling variant.
bool canMergeStoresTo(unsigned AS, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const
SITargetLowering(const TargetMachine &tm, const GCNSubtarget &STI)
void computeKnownBitsForTargetInstr(GISelValueTracking &Analysis, Register R, KnownBits &Known, const APInt &DemandedElts, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool isFreeAddrSpaceCast(const DataLayout &DL, unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g.
bool shouldEmitPCReloc(const GlobalValue *GV) const
bool isUniformLoad(const LoadSDNode *Load) const
AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
void initializeSplitCSR(MachineBasicBlock *Entry) const override
Perform necessary initialization to handle a subset of CSRs explicitly via copies.
void allocateSpecialEntryInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocatePreloadKernArgSGPRs(CCState &CCInfo, SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< ISD::InputArg > &Ins, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue copyToM0(SelectionDAG &DAG, SDValue Chain, const SDLoc &DL, SDValue V) const
SDValue splitBinaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
MVT getPointerMemTy(const DataLayout &DL, unsigned AS) const override
Similarly, the in-memory representation of a p7 is {p8, i32}, aka v8i32 when padding is added.
void allocateSystemSGPRs(CCState &CCInfo, MachineFunction &MF, SIMachineFunctionInfo &Info, CallingConv::ID CallConv, bool IsShader) const
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const override
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT, unsigned Opcode)
Convert Op, which must be of integer type, to the integer type VT, by either any/sign/zero-extending ...
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
bool isKnownNeverSNaN(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
const TargetSubtargetInfo & getSubtarget() const
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI bool isConstantIntBuildVectorOrConstantInt(SDValue N, bool AllowOpaques=true) const
Test whether the given value is a constant int or similar node.
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
LLVM_ABI SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS, const SDNodeFlags Flags=SDNodeFlags())
Return an AddrSpaceCastSDNode.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI bool SignBitIsZeroFP(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero, for a floating-point value.
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO)
Gets a node for an atomic op, produces result (if relevant) and chain and takes 2 operands.
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by first bitcasting (from potentia...
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
const TargetMachine & getTarget() const
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getErrorMergeValues(ArrayRef< EVT > ResultTypes, SDValue Chain, const SDLoc &dl)
Return poison values for each of ResultTypes, substituting Chain for any result of type MVT::Other,...
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
const SDValue & setRoot(SDValue N)
Set the current root tag of the SelectionDAG.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
int getMaskElt(unsigned Idx) const
ArrayRef< int > getMask() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition SmallSet.h:176
bool empty() const
Definition SmallSet.h:169
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Information about stack frame layout on the target.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
TargetInstrInfo - Interface to description of machine instruction set.
Type * Ty
Same as OrigTy, or partially legalized for soft float libcalls.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual Align getPrefLoopAlignment(MachineLoop *ML=nullptr, const MachineBasicBlock *BlockToAlign=nullptr) const
Return the preferred loop alignment.
virtual unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setHasExtractBitsInsn(bool hasExtractInsn=true)
Tells the code generator that the target has BitExtract instructions.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS=0) const
Return the in-memory pointer type for the given address space, defaults to the pointer type from the ...
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
std::vector< AsmOperandInfo > AsmOperandInfoVector
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminimumnum/fmaximumnum into multiple comparison with selects.
virtual bool isTypeDesirableForOp(unsigned, EVT VT) const
Return true if the target has native support for the specified value type and it is 'desirable' to us...
virtual void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const
Determine known bits of a pointer to a known valid stack object.
std::pair< SDValue, SDValue > scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Turn load of vector type into a load of the individual elements.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
TargetLowering(const TargetLowering &)=delete
virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
virtual AsmOperandInfoVector ParseConstraints(const DataLayout &DL, const TargetRegisterInfo *TRI, const CallBase &Call) const
Split up the constraint string from the inline assembly value into the specific constraints and their...
SDValue expandRoundInexactToOdd(EVT ResultVT, SDValue Op, const SDLoc &DL, SelectionDAG &DAG) const
Truncate Op to ResultVT.
virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, SelectionDAG *DAG=nullptr) const
Determines the constraint code and constraint type to use for the specific AsmOperandInfo,...
SDValue annotateStackObjectPointer(SDValue Ptr, SelectionDAG &DAG, const SDLoc &DL, Align Alignment) const
Annotate a stack object pointer with known-bits assertions.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs.
Primary interface to the complete machine description for the target machine.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
const Triple & getTargetTriple() const
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
TargetOptions Options
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
OSType getOS() const
Get the parsed operating system type of this triple.
Definition Triple.h:524
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:352
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition Type.h:147
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:363
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition Type.h:144
bool isFunctionTy() const
True if this is an instance of FunctionType.
Definition Type.h:268
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
LLVM_ABI const fltSemantics & getFltSemantics() const
Definition Type.cpp:96
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Definition Use.cpp:35
LLVM_ABI void set(Value *Val)
Definition Value.h:876
User * getUser() const
Returns the User that contains this Use.
Definition Use.h:61
const Use & getOperandUse(unsigned i) const
Definition User.h:220
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
bool hasOneUse() const
Return true if there is exactly one use of this value.
Definition Value.h:441
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:549
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:260
iterator_range< user_iterator > users()
Definition Value.h:428
bool use_empty() const
Definition Value.h:348
iterator_range< use_iterator > uses()
Definition Value.h:382
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:201
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
Definition TypeSize.h:177
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
self_iterator getIterator()
Definition ilist_node.h:123
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ BARRIER
Address space for modeling barrier IDs as addresses.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ STREAMOUT_REGISTER
Internal address spaces. Can be freely renumbered.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char NumVGPRs[]
Key for Kernel::CodeProps::Metadata::mNumVGPRs.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
APInt getExponentOnlyScaleDemandedBits()
LLVM_READONLY const MIMGG16MappingInfo * getMIMGG16MappingInfo(unsigned G)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isShader(CallingConv::ID CC)
bool shouldEmitConstantsToTextSection(const Triple &TT)
bool isFlatGlobalAddrSpace(unsigned AS)
const uint64_t FltRoundToHWConversionTable
bool isGFX12Plus(const MCSubtargetInfo &STI)
unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler)
std::optional< unsigned > getExponentOnlyScaleArgIdx(unsigned IntrID)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
bool isGFX13(const MCSubtargetInfo &STI)
bool hasValueInRangeLikeMetadata(const MDNode &MD, int64_t Val)
Checks if Val is inside MD, a !range-like metadata.
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READNONE constexpr bool mayTailCallThisCC(CallingConv::ID CC)
Return true if we might ever do TCO for calls with this calling convention.
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool getMUBUFTfe(unsigned Opc)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi, bool *IsBF16)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
bool isGFX11Plus(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
std::tuple< char, unsigned, unsigned > parseAsmConstraintPhysReg(StringRef Constraint)
Returns a valid charcode or 0 in the first entry if this is a valid physical register constraint.
bool isGFX10Plus(const MCSubtargetInfo &STI)
bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale, unsigned BFmt, unsigned BScale)
bool isUniformMMO(const MachineMemOperand *MMO)
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
uint32_t decodeFltRoundToHWConversionTable(uint32_t FltRounds)
Read the hardware rounding mode equivalent of a AMDGPUFltRounds value.
bool isExtendedGlobalAddrSpace(unsigned AS)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
unsigned getBarrierMemberCountBitMask(const IsaVersion &Version)
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
unsigned getSyntheticApertureNumber(unsigned AS)
LLVM_READNONE constexpr bool isChainCC(CallingConv::ID CC)
int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels)
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool canGuaranteeTCO(CallingConv::ID CC)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
const RsrcIntrinsic * lookupRsrcIntrinsic(unsigned Intr)
const uint64_t FltRoundConversionTable
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ MaxID
The highest possible ID. Must be some 2^k - 1.
@ AMDGPU_Gfx
Used for AMD graphics targets.
@ AMDGPU_CS_ChainPreserve
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:845
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:263
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
Definition ISDOpcodes.h:47
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:238
@ SET_FPENV
Sets the current floating-point environment.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:277
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:605
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:805
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
Definition ISDOpcodes.h:527
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:879
@ ATOMIC_LOAD_USUB_COND
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:523
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition ISDOpcodes.h:222
@ GlobalAddress
Definition ISDOpcodes.h:90
@ ATOMIC_CMP_SWAP_WITH_SUCCESS
Val, Success, OUTCHAIN = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) N.b.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:906
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:589
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:420
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:765
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition ISDOpcodes.h:256
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ ATOMIC_LOAD_USUB_SAT
@ CTLZ_ZERO_POISON
Definition ISDOpcodes.h:814
@ SET_ROUNDING
Set rounding mode.
@ CONVERGENCECTRL_GLUE
This does not correspond to any convergence control intrinsic.
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:870
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:675
@ READSTEADYCOUNTER
READSTEADYCOUNTER - This corresponds to the readfixedcounter intrinsic.
@ BR
Control flow instructions. These all have token chains.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
Definition ISDOpcodes.h:355
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:546
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
Definition ISDOpcodes.h:553
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:377
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:822
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:235
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
Definition ISDOpcodes.h:249
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
Definition ISDOpcodes.h:232
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:351
@ CTLS
Count leading redundant sign bits.
Definition ISDOpcodes.h:818
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
Definition ISDOpcodes.h:996
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:714
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:787
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:659
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:619
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Same as FMINNUM/FMAXNUM, except that a signaling NaN operand deterministi...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:581
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition ISDOpcodes.h:226
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:876
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:837
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Same semantics as the llvm.minnum/maxnum intrinsics.
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:359
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:914
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:745
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:831
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:331
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ ATOMIC_LOAD_UDEC_WRAP
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:505
@ FMINIMUM
FMINIMUM/FMAXIMUM - Same semantics as the llvm.minimum/maximum intrinsics.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:952
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:510
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:757
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:207
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:570
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:55
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
Definition ISDOpcodes.h:813
@ ExternalSymbol
Definition ISDOpcodes.h:95
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:985
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
Definition ISDOpcodes.h:124
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
Definition ISDOpcodes.h:971
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:882
@ BRCOND
BRCOND - Conditional branch.
@ CONVERT_TO_ARBITRARY_FP
CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary floating-point format,...
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
Definition ISDOpcodes.h:859
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:64
@ ATOMIC_LOAD_UINC_WRAP
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:539
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:368
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - Same semantics as the llvm.minimumnum/maximumnum intrinsics.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:215
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:561
CondCode getUnsignedSetCC(CondCode Code)
Convert a signed integer condition code to unsigned.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI AttributeSet getFnAttributes(LLVMContext &C, ID id)
Return the function attributes for an intrinsic.
LLVM_ABI StringRef getBaseName(ID id)
Return the LLVM name for an intrinsic, without encoded types for overloading, such as "llvm....
LLVM_ABI AttributeList getAttributes(LLVMContext &C, ID id, FunctionType *FT)
Return the attributes for an intrinsic.
LLVM_ABI FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > OverloadTys={})
Return the function type for an intrinsic.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
specific_fpval m_SpecificFP(double V)
Match a specific floating point value or vector with all elements equal to the value.
auto m_Value()
Match an arbitrary value and ignore it.
auto m_FAbs(const Opnd0 &Op0)
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
auto m_IntrinsicWOChain(const OpndPreds &...Opnds)
bool sd_match(SDValue N, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
Offsets
Offsets in bytes from the start of the input buffer.
@ System
Synchronized with respect to all concurrently executing threads.
Definition LLVMContext.h:66
initializer< Ty > init(const Ty &Val)
constexpr double inv_pi
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Offset
Definition DWP.cpp:577
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
Definition STLExtras.h:856
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Done
Definition Threading.h:60
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
Definition MathExtras.h:224
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:325
SDValue peekFPSignOps(SDValue Val)
Strip fabs/fneg/fcopysign from a value to get the underlying source.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
static const MachineMemOperand::Flags MOCFSB1
Definition SIInstrInfo.h:71
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:546
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
Definition ModRef.h:356
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
LLVM_ABI bool isGuaranteedNotToBeUndef(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Returns true if V cannot be undef, but may be poison.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
Definition MathExtras.h:380
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
Definition MathExtras.h:274
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
Definition MathExtras.h:352
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
Definition SIInstrInfo.h:45
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
AtomicOrderingCABI
Atomic ordering for C11 / C++11's memory models.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition bit.h:263
bool isBoolSGPR(SDValue V)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
Definition SIInstrInfo.h:53
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI Value * buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Val)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ AfterLegalizeDAG
Definition DAGCombine.h:19
@ AfterLegalizeVectorOps
Definition DAGCombine.h:18
@ AfterLegalizeTypes
Definition DAGCombine.h:17
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
@ Add
Sum of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ NearestTiesToEven
roundTiesToEven.
unsigned M0(unsigned Val)
Definition VE.h:393
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
Definition MathExtras.h:233
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI std::pair< Value *, Value * > buildCmpXchgValue(IRBuilderBase &Builder, Value *Ptr, Value *Cmp, Value *Val, Align Alignment, bool IsVolatile=false)
Emit IR to implement the given cmpxchg operation on values in registers, returning the new value.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition Utils.cpp:436
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
std::optional< StringRef > getAtomicScopeIRString(const Triple &T, AtomicScope S, bool IsSingleAddressSpace=false)
Returns the LLVM IR syncscope string that T uses to spell S.
Definition AtomicScope.h:34
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:49
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
Definition SIInstrInfo.h:68
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:206
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
constexpr RegState getUndefRegState(bool B)
@ Custom
The result value requires a custom uniformity check.
Definition Uniformity.h:31
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
int64_t DWordOffset
int64_t PermMask
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(PreloadedValue Value) const
static MCRegister getPrivateSegmentBufferReg(CallingConv::ID CC)
Returns the register a non-entry function with calling convention CC expects the private segment buff...
static const AMDGPUFunctionArgInfo FixedABIFunctionInfo
static constexpr uint64_t encode(Fields... Values)
static std::tuple< typename Fields::ValueType... > decode(uint64_t Encoded)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
MCRegister getRegister() const
static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask)
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
Helper struct shared between Function Specialization and SCCP Solver.
Definition SCCPSolver.h:42
Represents the full denormal controls for a function, including the default mode and the f32 specific...
Represent subnormal handling kind for floating point instruction inputs and outputs.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
Extended Value Type.
Definition ValueTypes.h:35
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition ValueTypes.h:433
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:160
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:70
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
Definition ValueTypes.h:144
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
Definition ValueTypes.h:338
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:170
ElementCount getVectorElementCount() const
Definition ValueTypes.h:388
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:411
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:281
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:423
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:516
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
Definition ValueTypes.h:450
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:354
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition ValueTypes.h:61
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
Definition ValueTypes.h:419
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:191
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:361
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:366
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
Definition ValueTypes.h:136
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
Definition ValueTypes.h:196
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
Definition ValueTypes.h:180
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:374
unsigned getPointerAddrSpace() const
unsigned getByValSize() const
Align getNonZeroMemAlign() const
InputArg - This struct carries flags and type information about a single incoming (formal) argument o...
MVT VT
Legalized type of this argument part.
unsigned getOrigArgIndex() const
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
static LLVM_ABI std::optional< bool > eq(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_EQ result.
bool isUnknown() const
Returns true if we don't know any bits.
Definition KnownBits.h:64
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
Definition KnownBits.h:165
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
Definition KnownBits.h:361
KnownBits extractBits(unsigned NumBits, unsigned BitPosition) const
Return a subset of the known bits from [bitPosition,bitPosition+numBits).
Definition KnownBits.h:239
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
Definition KnownBits.h:262
static LLVM_ABI std::optional< bool > ule(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_ULE result.
static LLVM_ABI std::optional< bool > uge(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_UGE result.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:111
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoUnsignedWrap() const
bool hasAllowContract() const
bool hasNoSignedWrap() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
unsigned int NumVTs
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
std::optional< unsigned > fallbackAddressSpace
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs