LLVM 24.0.0git
SIISelLowering.cpp
Go to the documentation of this file.
1//===-- SIISelLowering.cpp - SI DAG Lowering Implementation ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// Custom DAG lowering for SI
11//
12//===----------------------------------------------------------------------===//
13
14#include "SIISelLowering.h"
15#include "AMDGPU.h"
16#include "AMDGPUInstrInfo.h"
17#include "AMDGPULaneMaskUtils.h"
18#include "AMDGPUMemoryUtils.h"
20#include "AMDGPUTargetMachine.h"
21#include "GCNSubtarget.h"
24#include "SIRegisterInfo.h"
25#include "llvm/ADT/APFloat.h"
26#include "llvm/ADT/APInt.h"
28#include "llvm/ADT/Statistic.h"
43#include "llvm/IR/IRBuilder.h"
45#include "llvm/IR/IntrinsicsAMDGPU.h"
46#include "llvm/IR/IntrinsicsR600.h"
47#include "llvm/IR/MDBuilder.h"
50#include "llvm/Support/ModRef.h"
53#include <optional>
54
55using namespace llvm;
56using namespace llvm::SDPatternMatch;
57
58#define DEBUG_TYPE "si-lower"
59
60STATISTIC(NumTailCalls, "Number of tail calls");
61
62static cl::opt<bool>
63 DisableLoopAlignment("amdgpu-disable-loop-alignment",
64 cl::desc("Do not align and prefetch loops"),
65 cl::init(false));
66
68 "amdgpu-use-divergent-register-indexing", cl::Hidden,
69 cl::desc("Use indirect register addressing for divergent indexes"),
70 cl::init(false));
71
73 return MF.getInfo<SIMachineFunctionInfo>()->getMode().getDenormalFPEnv();
74}
75
80
85
86static unsigned findFirstFreeSGPR(CCState &CCInfo) {
87 unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs();
88 for (unsigned Reg = 0; Reg < NumSGPRs; ++Reg) {
89 if (!CCInfo.isAllocated(AMDGPU::SGPR0 + Reg)) {
90 return AMDGPU::SGPR0 + Reg;
91 }
92 }
93 llvm_unreachable("Cannot allocate sgpr");
94}
95
97 const GCNSubtarget &STI)
98 : AMDGPUTargetLowering(TM, STI, STI), Subtarget(&STI) {
99 addRegisterClass(MVT::i1, &AMDGPU::VReg_1RegClass);
100 addRegisterClass(MVT::i64, &AMDGPU::SReg_64RegClass);
101
102 addRegisterClass(MVT::i32, &AMDGPU::SReg_32RegClass);
103
104 const SIRegisterInfo *TRI = STI.getRegisterInfo();
105 const TargetRegisterClass *V32RegClass =
106 TRI->getDefaultVectorSuperClassForBitWidth(32);
107 addRegisterClass(MVT::f32, V32RegClass);
108
109 addRegisterClass(MVT::v2i32, &AMDGPU::SReg_64RegClass);
110
111 const TargetRegisterClass *V64RegClass =
112 TRI->getDefaultVectorSuperClassForBitWidth(64);
113
114 addRegisterClass(MVT::f64, V64RegClass);
115 addRegisterClass(MVT::v2f32, V64RegClass);
116 addRegisterClass(MVT::Untyped, V64RegClass);
117
118 addRegisterClass(MVT::v3i32, &AMDGPU::SGPR_96RegClass);
119 addRegisterClass(MVT::v3f32, TRI->getDefaultVectorSuperClassForBitWidth(96));
120
121 addRegisterClass(MVT::v2i64, &AMDGPU::SGPR_128RegClass);
122 addRegisterClass(MVT::v2f64, &AMDGPU::SGPR_128RegClass);
123
124 addRegisterClass(MVT::v4i32, &AMDGPU::SGPR_128RegClass);
125 addRegisterClass(MVT::v4f32, TRI->getDefaultVectorSuperClassForBitWidth(128));
126
127 addRegisterClass(MVT::v5i32, &AMDGPU::SGPR_160RegClass);
128 addRegisterClass(MVT::v5f32, TRI->getDefaultVectorSuperClassForBitWidth(160));
129
130 addRegisterClass(MVT::v6i32, &AMDGPU::SGPR_192RegClass);
131 addRegisterClass(MVT::v6f32, TRI->getDefaultVectorSuperClassForBitWidth(192));
132
133 addRegisterClass(MVT::v3i64, &AMDGPU::SGPR_192RegClass);
134 addRegisterClass(MVT::v3f64, TRI->getDefaultVectorSuperClassForBitWidth(192));
135
136 addRegisterClass(MVT::v7i32, &AMDGPU::SGPR_224RegClass);
137 addRegisterClass(MVT::v7f32, TRI->getDefaultVectorSuperClassForBitWidth(224));
138
139 addRegisterClass(MVT::v8i32, &AMDGPU::SGPR_256RegClass);
140 addRegisterClass(MVT::v8f32, TRI->getDefaultVectorSuperClassForBitWidth(256));
141
142 addRegisterClass(MVT::v4i64, &AMDGPU::SGPR_256RegClass);
143 addRegisterClass(MVT::v4f64, TRI->getDefaultVectorSuperClassForBitWidth(256));
144
145 addRegisterClass(MVT::v9i32, &AMDGPU::SGPR_288RegClass);
146 addRegisterClass(MVT::v9f32, TRI->getDefaultVectorSuperClassForBitWidth(288));
147
148 addRegisterClass(MVT::v10i32, &AMDGPU::SGPR_320RegClass);
149 addRegisterClass(MVT::v10f32,
150 TRI->getDefaultVectorSuperClassForBitWidth(320));
151
152 addRegisterClass(MVT::v11i32, &AMDGPU::SGPR_352RegClass);
153 addRegisterClass(MVT::v11f32,
154 TRI->getDefaultVectorSuperClassForBitWidth(352));
155
156 addRegisterClass(MVT::v12i32, &AMDGPU::SGPR_384RegClass);
157 addRegisterClass(MVT::v12f32,
158 TRI->getDefaultVectorSuperClassForBitWidth(384));
159
160 addRegisterClass(MVT::v16i32, &AMDGPU::SGPR_512RegClass);
161 addRegisterClass(MVT::v16f32,
162 TRI->getDefaultVectorSuperClassForBitWidth(512));
163
164 addRegisterClass(MVT::v8i64, &AMDGPU::SGPR_512RegClass);
165 addRegisterClass(MVT::v8f64, TRI->getDefaultVectorSuperClassForBitWidth(512));
166
167 addRegisterClass(MVT::v16i64, &AMDGPU::SGPR_1024RegClass);
168 addRegisterClass(MVT::v16f64,
169 TRI->getDefaultVectorSuperClassForBitWidth(1024));
170
171 if (Subtarget->has16BitInsts()) {
172 if (Subtarget->useRealTrue16Insts()) {
173 addRegisterClass(MVT::i16, &AMDGPU::VGPR_16RegClass);
174 addRegisterClass(MVT::f16, &AMDGPU::VGPR_16RegClass);
175 addRegisterClass(MVT::bf16, &AMDGPU::VGPR_16RegClass);
176 } else {
177 addRegisterClass(MVT::i16, &AMDGPU::SReg_32RegClass);
178 addRegisterClass(MVT::f16, &AMDGPU::SReg_32RegClass);
179 addRegisterClass(MVT::bf16, &AMDGPU::SReg_32RegClass);
180 }
181
182 // Unless there are also VOP3P operations, not operations are really legal.
183 addRegisterClass(MVT::v2i16, &AMDGPU::SReg_32RegClass);
184 addRegisterClass(MVT::v2f16, &AMDGPU::SReg_32RegClass);
185 addRegisterClass(MVT::v2bf16, &AMDGPU::SReg_32RegClass);
186 addRegisterClass(MVT::v4i16, &AMDGPU::SReg_64RegClass);
187 addRegisterClass(MVT::v4f16, &AMDGPU::SReg_64RegClass);
188 addRegisterClass(MVT::v4bf16, &AMDGPU::SReg_64RegClass);
189 addRegisterClass(MVT::v8i16, &AMDGPU::SGPR_128RegClass);
190 addRegisterClass(MVT::v8f16, &AMDGPU::SGPR_128RegClass);
191 addRegisterClass(MVT::v8bf16, &AMDGPU::SGPR_128RegClass);
192 addRegisterClass(MVT::v16i16, &AMDGPU::SGPR_256RegClass);
193 addRegisterClass(MVT::v16f16, &AMDGPU::SGPR_256RegClass);
194 addRegisterClass(MVT::v16bf16, &AMDGPU::SGPR_256RegClass);
195 addRegisterClass(MVT::v32i16, &AMDGPU::SGPR_512RegClass);
196 addRegisterClass(MVT::v32f16, &AMDGPU::SGPR_512RegClass);
197 addRegisterClass(MVT::v32bf16, &AMDGPU::SGPR_512RegClass);
198 }
199
200 addRegisterClass(MVT::v32i32, &AMDGPU::VReg_1024RegClass);
201 addRegisterClass(MVT::v32f32,
202 TRI->getDefaultVectorSuperClassForBitWidth(1024));
203
204 computeRegisterProperties(Subtarget->getRegisterInfo());
205
208
209 // The boolean content concept here is too inflexible. Compares only ever
210 // really produce a 1-bit result. Any copy/extend from these will turn into a
211 // select, and zext/1 or sext/-1 are equally cheap. Arbitrarily choose 0/1, as
212 // it's what most targets use.
215
216 // We need to custom lower vector stores from local memory
218 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
219 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
220 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
221 MVT::i1, MVT::v32i32},
222 Custom);
223
225 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
226 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
227 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32,
228 MVT::i1, MVT::v32i32},
229 Custom);
230
231 if (isTypeLegal(MVT::bf16)) {
232 for (unsigned Opc :
241 ISD::SETCC}) {
242 setOperationAction(Opc, MVT::bf16, Promote);
243 }
244
245 // Only targets with packed bf16 instructions, e.g. gfx13.
246 if (Subtarget->hasBF16PackedInsts()) {
247 // Don't use Expand for fsub - the DAG combiner will undo fadd+fneg back
248 // to fsub, causing a libcall (which doesn't exist for bf16). Instead,
249 // directly expand to widened v2bf16 operations.
251 // Promote scalar operations to a v2bf16 operation with an unused high
252 // lane.
253 for (unsigned Opc : {ISD::FADD, ISD::FMUL, ISD::FMA, ISD::FMAXNUM,
255 AddPromotedToType(Opc, MVT::bf16, MVT::v2bf16);
256 }
257
259
261 AddPromotedToType(ISD::SELECT, MVT::bf16, MVT::i16);
262
266
267 // We only need to custom lower because we can't specify an action for bf16
268 // sources.
271 }
272
273 setTruncStoreAction(MVT::v2i32, MVT::v2i16, Expand);
274 setTruncStoreAction(MVT::v3i32, MVT::v3i16, Expand);
275 setTruncStoreAction(MVT::v4i32, MVT::v4i16, Expand);
276 setTruncStoreAction(MVT::v8i32, MVT::v8i16, Expand);
277 setTruncStoreAction(MVT::v16i32, MVT::v16i16, Expand);
278 setTruncStoreAction(MVT::v32i32, MVT::v32i16, Expand);
279 setTruncStoreAction(MVT::v2i32, MVT::v2i8, Expand);
280 setTruncStoreAction(MVT::v4i32, MVT::v4i8, Expand);
281 setTruncStoreAction(MVT::v8i32, MVT::v8i8, Expand);
282 setTruncStoreAction(MVT::v16i32, MVT::v16i8, Expand);
283 setTruncStoreAction(MVT::v32i32, MVT::v32i8, Expand);
284 setTruncStoreAction(MVT::v2i16, MVT::v2i8, Expand);
285 setTruncStoreAction(MVT::v4i16, MVT::v4i8, Expand);
286 setTruncStoreAction(MVT::v8i16, MVT::v8i8, Expand);
287 setTruncStoreAction(MVT::v16i16, MVT::v16i8, Expand);
288 setTruncStoreAction(MVT::v32i16, MVT::v32i8, Expand);
289
290 setTruncStoreAction(MVT::v3i64, MVT::v3i16, Expand);
291 setTruncStoreAction(MVT::v3i64, MVT::v3i32, Expand);
292 setTruncStoreAction(MVT::v4i64, MVT::v4i8, Expand);
293 setTruncStoreAction(MVT::v8i64, MVT::v8i8, Expand);
294 setTruncStoreAction(MVT::v8i64, MVT::v8i16, Expand);
295 setTruncStoreAction(MVT::v8i64, MVT::v8i32, Expand);
296 setTruncStoreAction(MVT::v16i64, MVT::v16i32, Expand);
297
298 setOperationAction(ISD::GlobalAddress, {MVT::i32, MVT::i64}, Custom);
299 setOperationAction(ISD::BlockAddress, {MVT::i32, MVT::i64}, Custom);
300 setOperationAction(ISD::ExternalSymbol, {MVT::i32, MVT::i64}, Custom);
301
305 AddPromotedToType(ISD::SELECT, MVT::f64, MVT::i64);
306
307 setOperationAction(ISD::FSQRT, {MVT::f32, MVT::f64}, Custom);
308
310 {MVT::f32, MVT::i32, MVT::i64, MVT::f64, MVT::i1}, Expand);
311
313 setOperationAction(ISD::SETCC, {MVT::v2i1, MVT::v4i1}, Expand);
314 AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32);
315
317 {MVT::v2i32, MVT::v3i32, MVT::v4i32, MVT::v5i32,
318 MVT::v6i32, MVT::v7i32, MVT::v8i32, MVT::v9i32,
319 MVT::v10i32, MVT::v11i32, MVT::v12i32, MVT::v16i32},
320 Expand);
322 {MVT::v2f32, MVT::v3f32, MVT::v4f32, MVT::v5f32,
323 MVT::v6f32, MVT::v7f32, MVT::v8f32, MVT::v9f32,
324 MVT::v10f32, MVT::v11f32, MVT::v12f32, MVT::v16f32},
325 Expand);
326
328 {MVT::v2i1, MVT::v4i1, MVT::v2i8, MVT::v4i8, MVT::v2i16,
329 MVT::v3i16, MVT::v4i16, MVT::Other},
330 Custom);
331
334 {MVT::i1, MVT::i32, MVT::i64, MVT::f32, MVT::f64}, Expand);
335
338
341
343 Expand);
344
346
347 // We only support LOAD/STORE and vector manipulation ops for vectors
348 // with > 4 elements.
349 for (MVT VT :
350 {MVT::v8i32, MVT::v8f32, MVT::v9i32, MVT::v9f32, MVT::v10i32,
351 MVT::v10f32, MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32,
352 MVT::v16i32, MVT::v16f32, MVT::v2i64, MVT::v2f64, MVT::v4i16,
353 MVT::v4f16, MVT::v4bf16, MVT::v3i64, MVT::v3f64, MVT::v6i32,
354 MVT::v6f32, MVT::v4i64, MVT::v4f64, MVT::v8i64, MVT::v8f64,
355 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
356 MVT::v16bf16, MVT::v16i64, MVT::v16f64, MVT::v32i32, MVT::v32f32,
357 MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
358 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
359 switch (Op) {
360 case ISD::LOAD:
361 case ISD::STORE:
363 case ISD::BITCAST:
364 case ISD::UNDEF:
365 case ISD::POISON:
369 case ISD::IS_FPCLASS:
370 break;
375 break;
376 default:
378 break;
379 }
380 }
381 }
382
384
385 // TODO: For dynamic 64-bit vector inserts/extracts, should emit a pseudo that
386 // is expanded to avoid having two separate loops in case the index is a VGPR.
387
388 // Most operations are naturally 32-bit vector operations. We only support
389 // load and store of i64 vectors, so promote v2i64 vector operations to v4i32.
390 for (MVT Vec64 : {MVT::v2i64, MVT::v2f64}) {
392 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v4i32);
393
395 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v4i32);
396
398 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v4i32);
399
401 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v4i32);
402 }
403
404 for (MVT Vec64 : {MVT::v3i64, MVT::v3f64}) {
406 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v6i32);
407
409 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v6i32);
410
412 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v6i32);
413
415 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v6i32);
416 }
417
418 for (MVT Vec64 : {MVT::v4i64, MVT::v4f64}) {
420 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v8i32);
421
423 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v8i32);
424
426 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v8i32);
427
429 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v8i32);
430 }
431
432 for (MVT Vec64 : {MVT::v8i64, MVT::v8f64}) {
434 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v16i32);
435
437 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v16i32);
438
440 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v16i32);
441
443 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v16i32);
444 }
445
446 for (MVT Vec64 : {MVT::v16i64, MVT::v16f64}) {
448 AddPromotedToType(ISD::BUILD_VECTOR, Vec64, MVT::v32i32);
449
451 AddPromotedToType(ISD::EXTRACT_VECTOR_ELT, Vec64, MVT::v32i32);
452
454 AddPromotedToType(ISD::INSERT_VECTOR_ELT, Vec64, MVT::v32i32);
455
457 AddPromotedToType(ISD::SCALAR_TO_VECTOR, Vec64, MVT::v32i32);
458 }
459
461 {MVT::v4i32, MVT::v4f32, MVT::v8i32, MVT::v8f32,
462 MVT::v16i32, MVT::v16f32, MVT::v32i32, MVT::v32f32},
463 Custom);
464
465 if (Subtarget->hasPkMovB32()) {
466 // TODO: 16-bit element vectors should be legal with even aligned elements.
467 // TODO: Can be legal with wider source types than the result with
468 // subregister extracts.
469 setOperationAction(ISD::VECTOR_SHUFFLE, {MVT::v2i32, MVT::v2f32}, Legal);
470 }
471
473 // Prevent SELECT v2i32 from being implemented with the above bitwise ops and
474 // instead lower to cndmask in SITargetLowering::LowerSELECT().
476 // Enable MatchRotate to produce ISD::ROTR, which is later transformed to
477 // alignbit.
478 setOperationAction(ISD::ROTR, MVT::v2i32, Custom);
479
480 setOperationAction(ISD::BUILD_VECTOR, {MVT::v4f16, MVT::v4i16, MVT::v4bf16},
481 Custom);
482
483 // Avoid stack access for these.
484 // TODO: Generalize to more vector types.
486 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v2i8, MVT::v4i8,
487 MVT::v8i8, MVT::v4i16, MVT::v4f16, MVT::v4bf16},
488 Custom);
489
490 // Deal with vec3 vector operations when widened to vec4.
492 {MVT::v3i32, MVT::v3f32, MVT::v4i32, MVT::v4f32}, Custom);
493
494 // Deal with vec5/6/7 vector operations when widened to vec8.
496 {MVT::v5i32, MVT::v5f32, MVT::v6i32, MVT::v6f32,
497 MVT::v7i32, MVT::v7f32, MVT::v8i32, MVT::v8f32,
498 MVT::v9i32, MVT::v9f32, MVT::v10i32, MVT::v10f32,
499 MVT::v11i32, MVT::v11f32, MVT::v12i32, MVT::v12f32},
500 Custom);
501
502 // BUFFER/FLAT_ATOMIC_CMP_SWAP on GCN GPUs needs input marshalling,
503 // and output demarshalling
504 setOperationAction(ISD::ATOMIC_CMP_SWAP, {MVT::i32, MVT::i64}, Custom);
505
506 // We can't return success/failure, only the old value,
507 // let LLVM add the comparison
509 Expand);
510
511 setOperationAction(ISD::ADDRSPACECAST, {MVT::i32, MVT::i64}, Custom);
512
513 setOperationAction(ISD::BITREVERSE, {MVT::i32, MVT::i64}, Legal);
514
515 // FIXME: This should be narrowed to i32, but that only happens if i64 is
516 // illegal.
517 // FIXME: Should lower sub-i32 bswaps to bit-ops without v_perm_b32.
518 setOperationAction(ISD::BSWAP, {MVT::i64, MVT::i32}, Legal);
519
520 // On SI this is s_memtime and s_memrealtime on VI.
522
523 if (Subtarget->hasSMemRealTime() ||
524 Subtarget->getGeneration() >= AMDGPUSubtarget::GFX11)
527
528 if (Subtarget->has16BitInsts()) {
531 setOperationAction(ISD::IS_FPCLASS, {MVT::f16, MVT::f32, MVT::f64}, Legal);
534 } else {
536 }
537
538 if (Subtarget->hasMadMacF32Insts())
540
544
545 // We only really have 32-bit BFE instructions (and 16-bit on VI).
546 //
547 // On SI+ there are 64-bit BFEs, but they are scalar only and there isn't any
548 // effort to match them now. We want this to be false for i64 cases when the
549 // extraction isn't restricted to the upper or lower half. Ideally we would
550 // have some pass reduce 64-bit extracts to 32-bit if possible. Extracts that
551 // span the midpoint are probably relatively rare, so don't worry about them
552 // for now.
554
555 // Clamp modifier on add/sub
556 if (Subtarget->hasIntClamp())
558
559 if (Subtarget->hasAddNoCarryInsts())
560 setOperationAction({ISD::SADDSAT, ISD::SSUBSAT}, {MVT::i16, MVT::i32},
561 Legal);
562
565 {MVT::f32, MVT::f64}, Custom);
566
567 // These are really only legal for ieee_mode functions. We should be avoiding
568 // them for functions that don't have ieee_mode enabled, so just say they are
569 // legal.
571 {MVT::f32, MVT::f64}, Legal);
572
573 if (Subtarget->haveRoundOpsF64())
575 Legal);
576 else
578 MVT::f64, Custom);
579
581 setOperationAction({ISD::FLDEXP, ISD::STRICT_FLDEXP}, {MVT::f32, MVT::f64},
582 Legal);
583 setOperationAction(ISD::FFREXP, {MVT::f32, MVT::f64}, Custom);
584
587
588 setOperationAction(ISD::BF16_TO_FP, {MVT::i16, MVT::f32, MVT::f64}, Expand);
589 setOperationAction(ISD::FP_TO_BF16, {MVT::i16, MVT::f32, MVT::f64}, Expand);
590
592 Custom);
594 Custom);
596 Custom);
597
598 // Custom lower these because we can't specify a rule based on an illegal
599 // source bf16.
602
603 if (Subtarget->has16BitInsts()) {
606 MVT::i16, Legal);
607
608 AddPromotedToType(ISD::SIGN_EXTEND, MVT::i16, MVT::i32);
609
611 MVT::i16, Expand);
612
616 ISD::CTPOP},
617 MVT::i16, Promote);
618
620
621 setTruncStoreAction(MVT::i64, MVT::i16, Expand);
622
624 AddPromotedToType(ISD::FP16_TO_FP, MVT::i16, MVT::i32);
626 AddPromotedToType(ISD::FP_TO_FP16, MVT::i16, MVT::i32);
627
632
634
635 // F16 - Constant Actions.
638
639 // F16 - Load/Store Actions.
641 AddPromotedToType(ISD::LOAD, MVT::f16, MVT::i16);
643 AddPromotedToType(ISD::STORE, MVT::f16, MVT::i16);
644
645 // BF16 - Load/Store Actions.
647 AddPromotedToType(ISD::LOAD, MVT::bf16, MVT::i16);
649 AddPromotedToType(ISD::STORE, MVT::bf16, MVT::i16);
650
651 // F16 - VOP1 Actions.
654 MVT::f16, Custom);
655
656 // BF16 - VOP1 Actions.
657 if (Subtarget->hasBF16TransInsts())
659
660 // F16 - VOP2 Actions.
661 setOperationAction({ISD::BR_CC, ISD::SELECT_CC}, {MVT::f16, MVT::bf16},
662 Expand);
666
667 // F16 - VOP3 Actions.
669 if (STI.hasMadF16())
671
672 for (MVT VT :
673 {MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::v4i16, MVT::v4f16,
674 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16,
675 MVT::v16f16, MVT::v16bf16, MVT::v32i16, MVT::v32f16}) {
676 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) {
677 switch (Op) {
678 case ISD::LOAD:
679 case ISD::STORE:
681 case ISD::BITCAST:
682 case ISD::UNDEF:
683 case ISD::POISON:
688 case ISD::IS_FPCLASS:
689 break;
692 case ISD::FSIN:
693 case ISD::FCOS:
695 break;
696 default:
698 break;
699 }
700 }
701 }
702
703 // v_perm_b32 can handle either of these.
704 setOperationAction(ISD::BSWAP, {MVT::i16, MVT::v2i16}, Legal);
706
707 // Legalize vector types for sat conversions to select v_cvt_pk_[iu]16_f32.
708 if (Subtarget->hasVCvtPkIU16F32())
711 {MVT::v2i16, MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16},
712 Custom);
713
714 // XXX - Do these do anything? Vector constants turn into build_vector.
715 setOperationAction(ISD::Constant, {MVT::v2i16, MVT::v2f16}, Legal);
716
718 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Legal);
719
721 AddPromotedToType(ISD::STORE, MVT::v2i16, MVT::i32);
723 AddPromotedToType(ISD::STORE, MVT::v2f16, MVT::i32);
724
726 AddPromotedToType(ISD::LOAD, MVT::v2i16, MVT::i32);
728 AddPromotedToType(ISD::LOAD, MVT::v2f16, MVT::i32);
729
731 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v2i16, MVT::i32);
733 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v2f16, MVT::i32);
734
736 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v2i16, MVT::i32);
738 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v2f16, MVT::i32);
739
740 setOperationAction(ISD::AND, MVT::v2i16, Promote);
741 AddPromotedToType(ISD::AND, MVT::v2i16, MVT::i32);
742 setOperationAction(ISD::OR, MVT::v2i16, Promote);
743 AddPromotedToType(ISD::OR, MVT::v2i16, MVT::i32);
744 setOperationAction(ISD::XOR, MVT::v2i16, Promote);
745 AddPromotedToType(ISD::XOR, MVT::v2i16, MVT::i32);
746
748 AddPromotedToType(ISD::LOAD, MVT::v4i16, MVT::v2i32);
750 AddPromotedToType(ISD::LOAD, MVT::v4f16, MVT::v2i32);
751 setOperationAction(ISD::LOAD, MVT::v4bf16, Promote);
752 AddPromotedToType(ISD::LOAD, MVT::v4bf16, MVT::v2i32);
753
755 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v4i16, MVT::i64);
757 AddPromotedToType(ISD::ATOMIC_LOAD, MVT::v4f16, MVT::i64);
758
760 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v4i16, MVT::i64);
762 AddPromotedToType(ISD::ATOMIC_STORE, MVT::v4f16, MVT::i64);
763
765 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
767 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
769 AddPromotedToType(ISD::STORE, MVT::v4bf16, MVT::v2i32);
770
772 AddPromotedToType(ISD::LOAD, MVT::v8i16, MVT::v4i32);
774 AddPromotedToType(ISD::LOAD, MVT::v8f16, MVT::v4i32);
775 setOperationAction(ISD::LOAD, MVT::v8bf16, Promote);
776 AddPromotedToType(ISD::LOAD, MVT::v8bf16, MVT::v4i32);
777
779 AddPromotedToType(ISD::STORE, MVT::v4i16, MVT::v2i32);
781 AddPromotedToType(ISD::STORE, MVT::v4f16, MVT::v2i32);
782
784 AddPromotedToType(ISD::STORE, MVT::v8i16, MVT::v4i32);
786 AddPromotedToType(ISD::STORE, MVT::v8f16, MVT::v4i32);
788 AddPromotedToType(ISD::STORE, MVT::v8bf16, MVT::v4i32);
789
790 setOperationAction(ISD::LOAD, MVT::v16i16, Promote);
791 AddPromotedToType(ISD::LOAD, MVT::v16i16, MVT::v8i32);
792 setOperationAction(ISD::LOAD, MVT::v16f16, Promote);
793 AddPromotedToType(ISD::LOAD, MVT::v16f16, MVT::v8i32);
794 setOperationAction(ISD::LOAD, MVT::v16bf16, Promote);
795 AddPromotedToType(ISD::LOAD, MVT::v16bf16, MVT::v8i32);
796
798 AddPromotedToType(ISD::STORE, MVT::v16i16, MVT::v8i32);
800 AddPromotedToType(ISD::STORE, MVT::v16f16, MVT::v8i32);
801 setOperationAction(ISD::STORE, MVT::v16bf16, Promote);
802 AddPromotedToType(ISD::STORE, MVT::v16bf16, MVT::v8i32);
803
804 setOperationAction(ISD::LOAD, MVT::v32i16, Promote);
805 AddPromotedToType(ISD::LOAD, MVT::v32i16, MVT::v16i32);
806 setOperationAction(ISD::LOAD, MVT::v32f16, Promote);
807 AddPromotedToType(ISD::LOAD, MVT::v32f16, MVT::v16i32);
808 setOperationAction(ISD::LOAD, MVT::v32bf16, Promote);
809 AddPromotedToType(ISD::LOAD, MVT::v32bf16, MVT::v16i32);
810
812 AddPromotedToType(ISD::STORE, MVT::v32i16, MVT::v16i32);
814 AddPromotedToType(ISD::STORE, MVT::v32f16, MVT::v16i32);
815 setOperationAction(ISD::STORE, MVT::v32bf16, Promote);
816 AddPromotedToType(ISD::STORE, MVT::v32bf16, MVT::v16i32);
817
819 MVT::v2i32, Expand);
821
823 MVT::v4i32, Expand);
824
826 MVT::v8i32, Expand);
827
828 setOperationAction(ISD::BUILD_VECTOR, {MVT::v2i16, MVT::v2f16, MVT::v2bf16},
829 Subtarget->hasVOP3PInsts() ? Legal : Custom);
830
831 setOperationAction(ISD::FNEG, {MVT::v2f16, MVT::v2bf16}, Legal);
832 // This isn't really legal, but this avoids the legalizer unrolling it (and
833 // allows matching fneg (fabs x) patterns)
834 setOperationAction(ISD::FABS, {MVT::v2f16, MVT::v2bf16}, Legal);
835
836 // Can do this in one BFI plus a constant materialize.
838 {MVT::v2f16, MVT::v2bf16, MVT::v4f16, MVT::v4bf16,
839 MVT::v8f16, MVT::v8bf16, MVT::v16f16, MVT::v16bf16,
840 MVT::v32f16, MVT::v32bf16},
841 Custom);
842
845 MVT::f16, Custom);
847
850 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
851 Custom);
852
854 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
855 Expand);
856
857 for (MVT Vec16 :
858 {MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::v16i16, MVT::v16f16,
859 MVT::v16bf16, MVT::v32i16, MVT::v32f16, MVT::v32bf16}) {
862 Vec16, Custom);
864 }
865 }
866
867 if (Subtarget->hasVOP3PInsts()) {
871 MVT::v2i16, Legal);
872
876 MVT::v2f16, Legal);
877
879 {MVT::v2i16, MVT::v2f16, MVT::v2bf16}, Custom);
880
882 {MVT::v4f16, MVT::v4i16, MVT::v4bf16, MVT::v8f16,
883 MVT::v8i16, MVT::v8bf16, MVT::v16f16, MVT::v16i16,
884 MVT::v16bf16, MVT::v32f16, MVT::v32i16, MVT::v32bf16},
885 Custom);
886
887 for (MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v16i16, MVT::v32i16})
888 // Split vector operations.
893 VT, Custom);
894
895 for (MVT VT : {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16})
896 // Split vector operations.
899 VT, Custom);
900
903 {MVT::v2f16, MVT::v4f16}, Custom);
904
905 setOperationAction(ISD::FEXP, MVT::v2f16, Custom);
906 setOperationAction(ISD::SELECT, {MVT::v4i16, MVT::v4f16, MVT::v4bf16},
907 Custom);
908
909 if (Subtarget->hasBF16PackedInsts()) {
912 MVT::v2bf16, Legal);
913
914 for (MVT VT : {MVT::v4bf16, MVT::v8bf16, MVT::v16bf16, MVT::v32bf16})
915 // Split vector operations.
918 VT, Custom);
919 }
920
921 if (Subtarget->hasAnyPackedFP32Ops()) {
923 MVT::v2f32, Legal);
925 {MVT::v4f32, MVT::v8f32, MVT::v16f32, MVT::v32f32},
926 Custom);
927 }
928 if (Subtarget->hasAnyPackedFP64Ops()) {
932 MVT::v2f64, Legal);
935 MVT::v2f64, Custom);
940 {MVT::v4f64, MVT::v8f64, MVT::v16f64, MVT::v32f64}, Custom);
941 }
942
943 if (Subtarget->hasAnyPackedU64Ops()) {
945 MVT::v2i64, Legal);
947 {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
948 Custom);
949 }
950 }
951
953
954 if (Subtarget->has16BitInsts()) {
956 AddPromotedToType(ISD::SELECT, MVT::v2i16, MVT::i32);
958 AddPromotedToType(ISD::SELECT, MVT::v2f16, MVT::i32);
960 AddPromotedToType(ISD::SELECT, MVT::v2bf16, MVT::i32);
961 } else {
962 // Legalization hack.
963 setOperationAction(ISD::SELECT, {MVT::v2i16, MVT::v2f16}, Custom);
964
966 }
967
969 {MVT::v4i16, MVT::v4f16, MVT::v4bf16, MVT::v2i8, MVT::v4i8,
970 MVT::v8i8, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
971 MVT::v16i16, MVT::v16f16, MVT::v16bf16, MVT::v32i16,
972 MVT::v32f16, MVT::v32bf16},
973 Custom);
974
976
977 if (Subtarget->hasVMulU64Inst())
979 else if (Subtarget->hasScalarSMulU64())
981
982 if (Subtarget->hasMad64_32())
984
985 if (Subtarget->hasSafeSmemPrefetch() || Subtarget->hasVmemPrefInsts())
987
988 if (Subtarget->hasIEEEMinimumMaximumInsts()) {
990 {MVT::f16, MVT::f32, MVT::f64, MVT::v2f16}, Legal);
991 } else {
992 // FIXME: For nnan fmaximum, emit the fmaximum3 instead of fmaxnum
993 if (Subtarget->hasMinimum3Maximum3F32())
995
996 if (Subtarget->hasMinimum3Maximum3PKF16()) {
998
999 // If only the vector form is available, we need to widen to a vector.
1000 if (!Subtarget->hasMinimum3Maximum3F16())
1002 MVT::v2f16);
1003 }
1004 }
1005
1006 if (Subtarget->hasVOP3PInsts()) {
1007 // We want to break these into v2f16 pieces, not scalarize.
1009 {MVT::v4f16, MVT::v8f16, MVT::v16f16, MVT::v32f16},
1010 Custom);
1011 }
1012
1013 if (Subtarget->hasMinMaxI64Insts())
1015 Legal);
1016
1018 {MVT::Other, MVT::f32, MVT::v4f32, MVT::i16, MVT::f16,
1019 MVT::bf16, MVT::v2i16, MVT::v2f16, MVT::v2bf16, MVT::i128,
1020 MVT::i8},
1021 Custom);
1022
1024 {MVT::v2f16, MVT::v2i16, MVT::v2bf16, MVT::v3f16,
1025 MVT::v3i16, MVT::v4f16, MVT::v4i16, MVT::v4bf16,
1026 MVT::v8i16, MVT::v8f16, MVT::v8bf16, MVT::Other, MVT::f16,
1027 MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1028 Custom);
1029
1031 {MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
1032 MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
1033 MVT::v4bf16, MVT::v8i16, MVT::v8f16, MVT::v8bf16,
1034 MVT::f16, MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
1035 Custom);
1036
1042
1043 // TODO: Could move this to custom lowering, could benefit from combines on
1044 // extract of relevant bits.
1046
1048
1049 if (Subtarget->hasBF16ConversionInsts()) {
1051 {MVT::bf16, MVT::v2bf16}, Custom);
1053 }
1054
1055 if (Subtarget->hasBF16TransInsts()) {
1057 }
1058
1059 if (Subtarget->hasOCPFP8ConversionInsts()) {
1060 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f32, MVT::v2f32},
1061 Custom);
1063
1064 // i8 result promotes to i16, wider vectors split down to v2i8, and v2i8 is
1065 // handled in ReplaceNodeResults before the legalizer splits it per lane.
1066 setOperationAction(ISD::CONVERT_TO_ARBITRARY_FP, {MVT::i16, MVT::v2i8},
1067 Custom);
1068 }
1069
1070 if (Subtarget->hasFP8F16ConversionInsts()) {
1071 setOperationAction(ISD::CONVERT_FROM_ARBITRARY_FP, {MVT::f16, MVT::v2f16},
1072 Custom);
1073 }
1074
1075 if (Subtarget->hasCvtPkF16F32Inst()) {
1077 {MVT::v2f16, MVT::v4f16, MVT::v8f16, MVT::v16f16},
1078 Custom);
1079 }
1080
1083 ISD::SUB,
1084 ISD::MUL,
1085 ISD::FADD,
1086 ISD::FSUB,
1087 ISD::FDIV,
1088 ISD::FMUL,
1097 ISD::FMA,
1098 ISD::ABS,
1099 ISD::SMIN,
1100 ISD::SMAX,
1101 ISD::UMIN,
1102 ISD::UMAX,
1103 ISD::SETCC,
1105 ISD::SMIN,
1106 ISD::SMAX,
1107 ISD::UMIN,
1108 ISD::UMAX,
1110 ISD::AND,
1111 ISD::OR,
1112 ISD::XOR,
1113 ISD::SHL,
1114 ISD::SRL,
1115 ISD::SRA,
1116 ISD::FSHR,
1127
1128 if (Subtarget->has16BitInsts() && !Subtarget->hasMed3_16())
1130
1131 // All memory operations. Some folding on the pointer operand is done to help
1132 // matching the constant offsets in the addressing modes.
1134 ISD::STORE,
1159
1160 // FIXME: In other contexts we pretend this is a per-function property.
1162
1164}
1165
1166const GCNSubtarget *SITargetLowering::getSubtarget() const { return Subtarget; }
1167
1169 static const MCPhysReg RCRegs[] = {AMDGPU::MODE};
1170 return RCRegs;
1171}
1172
1173//===----------------------------------------------------------------------===//
1174// TargetLowering queries
1175//===----------------------------------------------------------------------===//
1176
1177// v_mad_mix* support a conversion from f16 to f32.
1178//
1179// There is only one special case when denormals are enabled we don't currently,
1180// where this is OK to use.
1181bool SITargetLowering::isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode,
1182 EVT DestVT, EVT SrcVT) const {
1183 return DestVT.getScalarType() == MVT::f32 &&
1184 ((((Opcode == ISD::FMAD && Subtarget->hasMadMixInsts()) ||
1185 (Opcode == ISD::FMA && Subtarget->hasFmaMixInsts())) &&
1186 SrcVT.getScalarType() == MVT::f16) ||
1187 (Opcode == ISD::FMA && Subtarget->hasFmaMixBF16Insts() &&
1188 SrcVT.getScalarType() == MVT::bf16)) &&
1189 // TODO: This probably only requires no input flushing?
1191}
1192
1194 LLT DestTy, LLT SrcTy) const {
1195 return ((Opcode == TargetOpcode::G_FMAD && Subtarget->hasMadMixInsts()) ||
1196 (Opcode == TargetOpcode::G_FMA && Subtarget->hasFmaMixInsts())) &&
1197 DestTy.getScalarSizeInBits() == 32 &&
1198 SrcTy.getScalarSizeInBits() == 16 &&
1199 // TODO: This probably only requires no input flushing?
1200 denormalModeIsFlushAllF32(*MI.getMF());
1201}
1202
1204 // SI has some legal vector types, but no legal vector operations. Say no
1205 // shuffles are legal in order to prefer scalarizing some vector operations.
1206 return false;
1207}
1208
1210 CallingConv::ID CC,
1211 EVT VT) const {
1213 return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
1214
1215 if (VT.isVector()) {
1216 EVT ScalarVT = VT.getScalarType();
1217 unsigned Size = ScalarVT.getSizeInBits();
1218 if (Size == 16) {
1219 return Subtarget->has16BitInsts()
1220 ? MVT::getVectorVT(ScalarVT.getSimpleVT(), 2)
1221 : MVT::i32;
1222 }
1223
1224 if (Size < 16)
1225 return Subtarget->has16BitInsts() ? MVT::i16 : MVT::i32;
1226 return Size == 32 ? ScalarVT.getSimpleVT() : MVT::i32;
1227 }
1228
1229 if (!Subtarget->has16BitInsts() && VT.getSizeInBits() == 16)
1230 return MVT::i32;
1231
1232 if (VT.getSizeInBits() > 32)
1233 return MVT::i32;
1234
1235 return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
1236}
1237
1239 CallingConv::ID CC,
1240 EVT VT) const {
1242 return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
1243
1244 if (VT.isVector()) {
1245 unsigned NumElts = VT.getVectorNumElements();
1246 EVT ScalarVT = VT.getScalarType();
1247 unsigned Size = ScalarVT.getSizeInBits();
1248
1249 // FIXME: Should probably promote 8-bit vectors to i16.
1250 if (Size == 16)
1251 return (NumElts + 1) / 2;
1252
1253 if (Size <= 32)
1254 return NumElts;
1255
1256 if (Size > 32)
1257 return NumElts * ((Size + 31) / 32);
1258 } else if (VT.getSizeInBits() > 32)
1259 return (VT.getSizeInBits() + 31) / 32;
1260
1261 return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
1262}
1263
1265 LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT,
1266 unsigned &NumIntermediates, MVT &RegisterVT) const {
1267 if (CC != CallingConv::AMDGPU_KERNEL && VT.isVector()) {
1268 unsigned NumElts = VT.getVectorNumElements();
1269 EVT ScalarVT = VT.getScalarType();
1270 unsigned Size = ScalarVT.getSizeInBits();
1271 // FIXME: We should fix the ABI to be the same on targets without 16-bit
1272 // support, but unless we can properly handle 3-vectors, it will be still be
1273 // inconsistent.
1274 if (Size == 16) {
1275 MVT SimpleIntermediateVT =
1277 IntermediateVT = SimpleIntermediateVT;
1278 RegisterVT = Subtarget->has16BitInsts() ? SimpleIntermediateVT : MVT::i32;
1279 NumIntermediates = (NumElts + 1) / 2;
1280 return (NumElts + 1) / 2;
1281 }
1282
1283 if (Size == 32) {
1284 RegisterVT = ScalarVT.getSimpleVT();
1285 IntermediateVT = RegisterVT;
1286 NumIntermediates = NumElts;
1287 return NumIntermediates;
1288 }
1289
1290 if (Size < 16 && Subtarget->has16BitInsts()) {
1291 // FIXME: Should probably form v2i16 pieces
1292 RegisterVT = MVT::i16;
1293 IntermediateVT = ScalarVT;
1294 NumIntermediates = NumElts;
1295 return NumIntermediates;
1296 }
1297
1298 if (Size != 16 && Size <= 32) {
1299 RegisterVT = MVT::i32;
1300 IntermediateVT = ScalarVT;
1301 NumIntermediates = NumElts;
1302 return NumIntermediates;
1303 }
1304
1305 if (Size > 32) {
1306 RegisterVT = MVT::i32;
1307 IntermediateVT = RegisterVT;
1308 NumIntermediates = NumElts * ((Size + 31) / 32);
1309 return NumIntermediates;
1310 }
1311 }
1312
1314 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
1315}
1316
1318 const DataLayout &DL, Type *Ty,
1319 unsigned MaxNumLanes) {
1320 assert(MaxNumLanes != 0);
1321
1322 LLVMContext &Ctx = Ty->getContext();
1323 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1324 unsigned NumElts = std::min(MaxNumLanes, VT->getNumElements());
1325 return EVT::getVectorVT(Ctx, TLI.getValueType(DL, VT->getElementType()),
1326 NumElts);
1327 }
1328
1329 return TLI.getValueType(DL, Ty);
1330}
1331
1332// Peek through TFE struct returns to only use the data size.
1334 const DataLayout &DL, Type *Ty,
1335 unsigned MaxNumLanes) {
1336 auto *ST = dyn_cast<StructType>(Ty);
1337 if (!ST)
1338 return memVTFromLoadIntrData(TLI, DL, Ty, MaxNumLanes);
1339
1340 // TFE intrinsics return an aggregate type.
1341 assert(ST->getNumContainedTypes() == 2 &&
1342 ST->getContainedType(1)->isIntegerTy(32));
1343 return memVTFromLoadIntrData(TLI, DL, ST->getContainedType(0), MaxNumLanes);
1344}
1345
1346/// Map address space 7 to MVT::amdgpuBufferFatPointer because that's its
1347/// in-memory representation. This return value is a custom type because there
1348/// is no MVT::i160 and adding one breaks integer promotion logic. While this
1349/// could cause issues during codegen, these address space 7 pointers will be
1350/// rewritten away by then. Therefore, we can return MVT::amdgpuBufferFatPointer
1351/// in order to allow pre-codegen passes that query TargetTransformInfo, often
1352/// for cost modeling, to work. (This also sets us up decently for doing the
1353/// buffer lowering in GlobalISel if SelectionDAG ever goes away.)
1355 if (AMDGPUAS::BUFFER_FAT_POINTER == AS && DL.getPointerSizeInBits(AS) == 160)
1356 return MVT::amdgpuBufferFatPointer;
1358 DL.getPointerSizeInBits(AS) == 192)
1359 return MVT::amdgpuBufferStridedPointer;
1361}
1362/// Similarly, the in-memory representation of a p7 is {p8, i32}, aka
1363/// v8i32 when padding is added.
1364/// The in-memory representation of a p9 is {p8, i32, i32}, which is
1365/// also v8i32 with padding.
1367 if ((AMDGPUAS::BUFFER_FAT_POINTER == AS &&
1368 DL.getPointerSizeInBits(AS) == 160) ||
1370 DL.getPointerSizeInBits(AS) == 192))
1371 return MVT::v8i32;
1373}
1374
1375static unsigned getIntrMemWidth(unsigned IntrID) {
1376 switch (IntrID) {
1377 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1378 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1379 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1380 return 8;
1381 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1382 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1383 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1384 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1385 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1386 case Intrinsic::amdgcn_flat_load_monitor_b32:
1387 case Intrinsic::amdgcn_global_load_monitor_b32:
1388 return 32;
1389 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1390 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1391 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1392 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1393 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1394 case Intrinsic::amdgcn_flat_load_monitor_b64:
1395 case Intrinsic::amdgcn_global_load_monitor_b64:
1396 return 64;
1397 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1398 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1399 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1400 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
1401 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B:
1402 case Intrinsic::amdgcn_flat_load_monitor_b128:
1403 case Intrinsic::amdgcn_global_load_monitor_b128:
1404 return 128;
1405 default:
1406 llvm_unreachable("Unknown width");
1407 }
1408}
1409
1411 unsigned ArgIdx) {
1412 Value *OrderingArg = CI.getArgOperand(ArgIdx);
1413 unsigned Ord = cast<ConstantInt>(OrderingArg)->getZExtValue();
1414 switch (AtomicOrderingCABI(Ord)) {
1417 break;
1420 break;
1423 break;
1424 default:
1426 }
1427}
1428
1429static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx) {
1430 MDNode *ScopeMD = cast<MDNode>(
1431 cast<MetadataAsValue>(CI.getArgOperand(ArgIdx))->getMetadata());
1432 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1433 return CI.getContext().getOrInsertSyncScopeID(Scope);
1434}
1435
1437 const CallBase &CI,
1438 MachineFunction &MF,
1439 unsigned IntrID) const {
1441 if (CI.hasMetadata(LLVMContext::MD_invariant_load))
1443 if (CI.hasMetadata(LLVMContext::MD_nontemporal))
1445 Flags |= getTargetMMOFlags(CI);
1446
1447 if (const AMDGPU::RsrcIntrinsic *RsrcIntr =
1449 AttributeSet Attr =
1451 MemoryEffects ME = Attr.getMemoryEffects();
1452 if (ME.doesNotAccessMemory())
1453 return;
1454
1455 bool IsSPrefetch = IntrID == Intrinsic::amdgcn_s_buffer_prefetch_data;
1456 if (!IsSPrefetch) {
1457 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1458 if (Aux->getZExtValue() & AMDGPU::CPol::VOLATILE)
1460 }
1461
1463
1464 IntrinsicInfo Info;
1465 // TODO: Should images get their own address space?
1467
1468 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = nullptr;
1469 if (RsrcIntr->IsImage) {
1470 const AMDGPU::ImageDimIntrinsicInfo *Intr =
1472 BaseOpcode = AMDGPU::getMIMGBaseOpcodeInfo(Intr->BaseOpcode);
1473 Info.align.reset();
1474 }
1475
1476 Value *RsrcArg = CI.getArgOperand(RsrcIntr->RsrcArg);
1477 if (auto *RsrcPtrTy = dyn_cast<PointerType>(RsrcArg->getType())) {
1478 if (RsrcPtrTy->getAddressSpace() == AMDGPUAS::BUFFER_RESOURCE)
1479 // We conservatively set the memory operand of a buffer intrinsic to the
1480 // base resource pointer, so that we can access alias information about
1481 // those pointers. Cases like "this points at the same value
1482 // but with a different offset" are handled in
1483 // areMemAccessesTriviallyDisjoint.
1484 Info.ptrVal = RsrcArg;
1485 }
1486
1487 if (ME.onlyReadsMemory()) {
1488 if (RsrcIntr->IsImage) {
1489 unsigned MaxNumLanes = 4;
1490
1491 if (!BaseOpcode->Gather4) {
1492 // If this isn't a gather, we may have excess loaded elements in the
1493 // IR type. Check the dmask for the real number of elements loaded.
1494 unsigned DMask =
1495 cast<ConstantInt>(CI.getArgOperand(0))->getZExtValue();
1496 MaxNumLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1497 }
1498
1499 Info.memVT = memVTFromLoadIntrReturn(*this, MF.getDataLayout(),
1500 CI.getType(), MaxNumLanes);
1501 } else {
1502 Info.memVT =
1504 std::numeric_limits<unsigned>::max());
1505 }
1506
1507 // FIXME: What does alignment mean for an image?
1508 Info.opc = ISD::INTRINSIC_W_CHAIN;
1509 Info.flags = Flags | MachineMemOperand::MOLoad;
1510 } else if (ME.onlyWritesMemory()) {
1511 Info.opc = ISD::INTRINSIC_VOID;
1512
1513 Type *DataTy = CI.getArgOperand(0)->getType();
1514 if (RsrcIntr->IsImage) {
1515 unsigned DMask = cast<ConstantInt>(CI.getArgOperand(1))->getZExtValue();
1516 unsigned DMaskLanes = DMask == 0 ? 1 : llvm::popcount(DMask);
1517 Info.memVT = memVTFromLoadIntrData(*this, MF.getDataLayout(), DataTy,
1518 DMaskLanes);
1519 } else
1520 Info.memVT = getValueType(MF.getDataLayout(), DataTy);
1521
1522 Info.flags = Flags | MachineMemOperand::MOStore;
1523 } else {
1524 // Atomic, NoReturn Sampler or prefetch
1525 Info.opc = CI.getType()->isVoidTy() ? ISD::INTRINSIC_VOID
1527
1528 switch (IntrID) {
1529 default:
1530 Info.flags = Flags | MachineMemOperand::MOLoad;
1531 if (!IsSPrefetch)
1532 Info.flags |= MachineMemOperand::MOStore;
1533
1534 if ((RsrcIntr->IsImage && BaseOpcode->NoReturn) || IsSPrefetch) {
1535 // Fake memory access type for no return sampler intrinsics
1536 Info.memVT = MVT::i32;
1537 } else {
1538 // XXX - Should this be volatile without known ordering?
1539 Info.flags |= MachineMemOperand::MOVolatile;
1540 Info.memVT = MVT::getVT(CI.getArgOperand(0)->getType());
1541 }
1542 break;
1543 case Intrinsic::amdgcn_raw_buffer_load_lds:
1544 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
1545 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
1546 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
1547 case Intrinsic::amdgcn_struct_buffer_load_lds:
1548 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
1549 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
1550 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
1551 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1552
1553 // Entry 0: Load from buffer.
1554 // Don't set an offset, since the pointer value always represents the
1555 // base of the buffer.
1556 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1557 Info.flags = Flags | MachineMemOperand::MOLoad;
1558 Infos.push_back(Info);
1559
1560 // Entry 1: Store to LDS.
1561 // Instruction offset is applied, and an additional per-lane offset
1562 // which we simulate using a larger memory type.
1563 Info.memVT = EVT::getIntegerVT(
1564 CI.getContext(), Width * 8 * Subtarget->getWavefrontSize());
1565 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1566 Info.offset = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 2))
1567 ->getZExtValue();
1568 Info.fallbackAddressSpace = AMDGPUAS::LOCAL_ADDRESS;
1569 Info.flags = Flags | MachineMemOperand::MOStore;
1570 Infos.push_back(Info);
1571 return;
1572 }
1573 case Intrinsic::amdgcn_raw_atomic_buffer_load:
1574 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
1575 case Intrinsic::amdgcn_struct_atomic_buffer_load:
1576 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
1577 Info.memVT =
1579 std::numeric_limits<unsigned>::max());
1580 Info.flags = Flags | MachineMemOperand::MOLoad;
1581 Infos.push_back(Info);
1582 return;
1583 }
1584 }
1585 }
1586 Infos.push_back(Info);
1587 return;
1588 }
1589
1590 IntrinsicInfo Info;
1591 switch (IntrID) {
1592 case Intrinsic::amdgcn_ds_ordered_add:
1593 case Intrinsic::amdgcn_ds_ordered_swap: {
1594 Info.opc = ISD::INTRINSIC_W_CHAIN;
1595 Info.memVT = MVT::getVT(CI.getType());
1596 Info.ptrVal = CI.getOperand(0);
1597 Info.align.reset();
1599
1600 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(4));
1601 if (!Vol->isZero())
1602 Info.flags |= MachineMemOperand::MOVolatile;
1603
1604 Infos.push_back(Info);
1605 return;
1606 }
1607 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
1608 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn: {
1609 Info.opc = ISD::INTRINSIC_W_CHAIN;
1610 Info.memVT = MVT::getVT(CI.getOperand(0)->getType());
1611 Info.ptrVal = nullptr;
1612 Info.fallbackAddressSpace = AMDGPUAS::STREAMOUT_REGISTER;
1614 Infos.push_back(Info);
1615 return;
1616 }
1617 case Intrinsic::amdgcn_ds_append:
1618 case Intrinsic::amdgcn_ds_consume: {
1619 Info.opc = ISD::INTRINSIC_W_CHAIN;
1620 Info.memVT = MVT::getVT(CI.getType());
1621 Info.ptrVal = CI.getOperand(0);
1622 Info.align.reset();
1624
1625 const ConstantInt *Vol = cast<ConstantInt>(CI.getOperand(1));
1626 if (!Vol->isZero())
1627 Info.flags |= MachineMemOperand::MOVolatile;
1628
1629 Infos.push_back(Info);
1630 return;
1631 }
1632 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1633 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64: {
1634 Info.opc = (IntrID == Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64)
1637 Info.memVT = MVT::getVT(CI.getType());
1638 Info.ptrVal = CI.getOperand(0);
1639 Info.memVT = MVT::i64;
1640 Info.size = 8;
1641 Info.align.reset();
1643 Info.order = AtomicOrdering::Monotonic;
1644 Infos.push_back(Info);
1645 return;
1646 }
1647 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
1648 case Intrinsic::amdgcn_image_bvh_intersect_ray:
1649 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
1650 Info.opc = ISD::INTRINSIC_W_CHAIN;
1651 Info.memVT =
1652 MVT::getVT(IntrID == Intrinsic::amdgcn_image_bvh_intersect_ray
1653 ? CI.getType()
1655 ->getElementType(0)); // XXX: what is correct VT?
1656
1657 Info.fallbackAddressSpace = AMDGPUAS::BUFFER_RESOURCE;
1658 Info.align.reset();
1659 Info.flags = Flags | MachineMemOperand::MOLoad |
1661 Infos.push_back(Info);
1662 return;
1663 }
1664 case Intrinsic::amdgcn_global_atomic_fmin_num:
1665 case Intrinsic::amdgcn_global_atomic_fmax_num:
1666 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1667 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1668 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
1669 Info.opc = ISD::INTRINSIC_W_CHAIN;
1670 Info.memVT = MVT::getVT(CI.getType());
1671 Info.ptrVal = CI.getOperand(0);
1672 Info.align.reset();
1673 Info.flags =
1676 Infos.push_back(Info);
1677 return;
1678 }
1679 case Intrinsic::amdgcn_cluster_load_b32:
1680 case Intrinsic::amdgcn_cluster_load_b64:
1681 case Intrinsic::amdgcn_cluster_load_b128:
1682 case Intrinsic::amdgcn_ds_load_tr6_b96:
1683 case Intrinsic::amdgcn_ds_load_tr4_b64:
1684 case Intrinsic::amdgcn_ds_load_tr8_b64:
1685 case Intrinsic::amdgcn_ds_load_tr16_b128:
1686 case Intrinsic::amdgcn_global_load_tr6_b96:
1687 case Intrinsic::amdgcn_global_load_tr4_b64:
1688 case Intrinsic::amdgcn_global_load_tr_b64:
1689 case Intrinsic::amdgcn_global_load_tr_b128:
1690 case Intrinsic::amdgcn_ds_read_tr4_b64:
1691 case Intrinsic::amdgcn_ds_read_tr6_b96:
1692 case Intrinsic::amdgcn_ds_read_tr8_b64:
1693 case Intrinsic::amdgcn_ds_read_tr16_b64: {
1694 Info.opc = ISD::INTRINSIC_W_CHAIN;
1695 Info.memVT = MVT::getVT(CI.getType());
1696 Info.ptrVal = CI.getOperand(0);
1697 Info.align.reset();
1698 Info.flags = Flags | MachineMemOperand::MOLoad;
1699 Infos.push_back(Info);
1700 return;
1701 }
1702 case Intrinsic::amdgcn_flat_load_monitor_b32:
1703 case Intrinsic::amdgcn_flat_load_monitor_b64:
1704 case Intrinsic::amdgcn_flat_load_monitor_b128:
1705 case Intrinsic::amdgcn_global_load_monitor_b32:
1706 case Intrinsic::amdgcn_global_load_monitor_b64:
1707 case Intrinsic::amdgcn_global_load_monitor_b128: {
1708 Info.opc = ISD::INTRINSIC_W_CHAIN;
1709 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1710 Info.ptrVal = CI.getOperand(0);
1711 Info.align.reset();
1712 Info.flags = MachineMemOperand::MOLoad;
1713 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1714 Info.ssid = parseSyncscopeMDArg(CI, 2);
1715 Infos.push_back(Info);
1716 return;
1717 }
1718 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
1719 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
1720 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
1721 Info.opc = ISD::INTRINSIC_W_CHAIN;
1722 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1723 Info.ptrVal = CI.getOperand(0);
1724 Info.align.reset();
1726 Info.order = parseAtomicOrderingCABIArg(CI, 1);
1727 Info.ssid = parseSyncscopeMDArg(CI, 2);
1728 Infos.push_back(Info);
1729 return;
1730 }
1731 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
1732 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
1733 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
1734 Info.opc = ISD::INTRINSIC_VOID;
1735 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1736 Info.ptrVal = CI.getArgOperand(0);
1737 Info.align.reset();
1739 Info.order = parseAtomicOrderingCABIArg(CI, 2);
1740 Info.ssid = parseSyncscopeMDArg(CI, 3);
1741 Infos.push_back(Info);
1742 return;
1743 }
1744 case Intrinsic::amdgcn_ds_gws_init:
1745 case Intrinsic::amdgcn_ds_gws_barrier:
1746 case Intrinsic::amdgcn_ds_gws_sema_v:
1747 case Intrinsic::amdgcn_ds_gws_sema_br:
1748 case Intrinsic::amdgcn_ds_gws_sema_p:
1749 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
1750 Info.opc = ISD::INTRINSIC_VOID;
1751
1752 const GCNTargetMachine &TM =
1753 static_cast<const GCNTargetMachine &>(getTargetMachine());
1754
1756 Info.ptrVal = MFI->getGWSPSV(TM);
1757
1758 // This is an abstract access, but we need to specify a type and size.
1759 Info.memVT = MVT::i32;
1760 Info.size = 4;
1761 Info.align = Align(4);
1762
1763 if (IntrID == Intrinsic::amdgcn_ds_gws_barrier)
1764 Info.flags = Flags | MachineMemOperand::MOLoad;
1765 else
1766 Info.flags = Flags | MachineMemOperand::MOStore;
1767 Infos.push_back(Info);
1768 return;
1769 }
1770 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1771 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1772 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1773 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1774 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1775 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1776 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1777 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
1778 // Entry 0: Load from source (global/flat).
1779 Info.opc = ISD::INTRINSIC_VOID;
1780 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1781 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1782 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1783 Info.flags = Flags | MachineMemOperand::MOLoad;
1784 Infos.push_back(Info);
1785
1786 // Entry 1: Store to LDS (same offset).
1787 Info.flags = Flags | MachineMemOperand::MOStore;
1788 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1789 Infos.push_back(Info);
1790 return;
1791 }
1792 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1793 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1794 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1795 case Intrinsic::amdgcn_global_store_async_from_lds_b128: {
1796 // Entry 0: Load from LDS.
1797 Info.opc = ISD::INTRINSIC_VOID;
1798 Info.memVT = EVT::getIntegerVT(CI.getContext(), getIntrMemWidth(IntrID));
1799 Info.ptrVal = CI.getArgOperand(1); // LDS pointer
1800 Info.offset = cast<ConstantInt>(CI.getArgOperand(2))->getSExtValue();
1801 Info.flags = Flags | MachineMemOperand::MOLoad;
1802 Infos.push_back(Info);
1803
1804 // Entry 1: Store to global (same offset).
1805 Info.flags = Flags | MachineMemOperand::MOStore;
1806 Info.ptrVal = CI.getArgOperand(0); // Global pointer
1807 Infos.push_back(Info);
1808 return;
1809 }
1810 case Intrinsic::amdgcn_av_load_b128:
1811 case Intrinsic::amdgcn_av_store_b128: {
1812 bool IsStore = IntrID == Intrinsic::amdgcn_av_store_b128;
1813 Info.opc = IsStore ? ISD::INTRINSIC_VOID : ISD::INTRINSIC_W_CHAIN;
1814 Info.memVT = MVT::v4i32;
1815 Info.ptrVal = CI.getArgOperand(0);
1816 Info.align = Align(16);
1817 Info.flags |=
1819 // Pretend to be atomic so that SIMemoryLegalizer::expandStore sets cache
1820 // flags appropriately.
1821 Info.order = AtomicOrdering::Monotonic;
1822
1823 LLVMContext &Ctx = CI.getContext();
1824 unsigned ScopeIdx = CI.arg_size() - 1;
1825 MDNode *ScopeMD = cast<MDNode>(
1826 cast<MetadataAsValue>(CI.getArgOperand(ScopeIdx))->getMetadata());
1827 StringRef Scope = cast<MDString>(ScopeMD->getOperand(0))->getString();
1828 Info.ssid = Ctx.getOrInsertSyncScopeID(Scope);
1829 Infos.push_back(Info);
1830 return;
1831 }
1832 case Intrinsic::amdgcn_load_to_lds:
1833 case Intrinsic::amdgcn_load_async_to_lds:
1834 case Intrinsic::amdgcn_global_load_lds:
1835 case Intrinsic::amdgcn_global_load_async_lds: {
1836 unsigned Width = cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue();
1837 auto *Aux = cast<ConstantInt>(CI.getArgOperand(CI.arg_size() - 1));
1838 bool IsVolatile = Aux->getZExtValue() & AMDGPU::CPol::VOLATILE;
1839 if (IsVolatile)
1841
1842 // Entry 0: Load from source (global/flat).
1843 Info.opc = ISD::INTRINSIC_VOID;
1844 Info.memVT = EVT::getIntegerVT(CI.getContext(), Width * 8);
1845 Info.ptrVal = CI.getArgOperand(0); // Source pointer
1846 Info.offset = cast<ConstantInt>(CI.getArgOperand(3))->getSExtValue();
1847 Info.flags = Flags | MachineMemOperand::MOLoad;
1848 Infos.push_back(Info);
1849
1850 // Entry 1: Store to LDS.
1851 // Same offset from the instruction, but an additional per-lane offset is
1852 // added. Represent that using a wider memory type.
1853 Info.memVT = EVT::getIntegerVT(CI.getContext(),
1854 Width * 8 * Subtarget->getWavefrontSize());
1855 Info.ptrVal = CI.getArgOperand(1); // LDS destination pointer
1856 Info.flags = Flags | MachineMemOperand::MOStore;
1857 Infos.push_back(Info);
1858 return;
1859 }
1860 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
1861 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
1862 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
1863 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
1864 Info.opc = ISD::INTRINSIC_W_CHAIN;
1865
1866 const GCNTargetMachine &TM =
1867 static_cast<const GCNTargetMachine &>(getTargetMachine());
1868
1870 Info.ptrVal = MFI->getGWSPSV(TM);
1871
1872 // This is an abstract access, but we need to specify a type and size.
1873 Info.memVT = MVT::i32;
1874 Info.size = 4;
1875 Info.align = Align(4);
1876
1878 Infos.push_back(Info);
1879 return;
1880 }
1881 case Intrinsic::amdgcn_s_prefetch_data:
1882 case Intrinsic::amdgcn_s_prefetch_inst:
1883 case Intrinsic::amdgcn_flat_prefetch:
1884 case Intrinsic::amdgcn_global_prefetch: {
1885 Info.opc = ISD::INTRINSIC_VOID;
1886 Info.memVT = EVT::getIntegerVT(CI.getContext(), 8);
1887 Info.ptrVal = CI.getArgOperand(0);
1888 Info.flags = Flags | MachineMemOperand::MOLoad;
1889 Infos.push_back(Info);
1890 return;
1891 }
1892 default:
1893 return;
1894 }
1895}
1896
1898 const CallInst &I, SmallVectorImpl<SDValue> &Ops, SelectionDAG &DAG) const {
1900 case Intrinsic::amdgcn_addrspacecast_nonnull: {
1901 // The DAG's ValueType loses the addrspaces.
1902 // Add them as 2 extra Constant operands "from" and "to".
1903 unsigned SrcAS = I.getOperand(0)->getType()->getPointerAddressSpace();
1904 unsigned DstAS = I.getType()->getPointerAddressSpace();
1905 Ops.push_back(DAG.getTargetConstant(SrcAS, SDLoc(), MVT::i32));
1906 Ops.push_back(DAG.getTargetConstant(DstAS, SDLoc(), MVT::i32));
1907 break;
1908 }
1909 default:
1910 break;
1911 }
1912}
1913
1916 Type *&AccessTy) const {
1917 Value *Ptr = nullptr;
1918 switch (II->getIntrinsicID()) {
1919 case Intrinsic::amdgcn_cluster_load_b128:
1920 case Intrinsic::amdgcn_cluster_load_b64:
1921 case Intrinsic::amdgcn_cluster_load_b32:
1922 case Intrinsic::amdgcn_ds_append:
1923 case Intrinsic::amdgcn_ds_consume:
1924 case Intrinsic::amdgcn_ds_load_tr8_b64:
1925 case Intrinsic::amdgcn_ds_load_tr16_b128:
1926 case Intrinsic::amdgcn_ds_load_tr4_b64:
1927 case Intrinsic::amdgcn_ds_load_tr6_b96:
1928 case Intrinsic::amdgcn_ds_read_tr4_b64:
1929 case Intrinsic::amdgcn_ds_read_tr6_b96:
1930 case Intrinsic::amdgcn_ds_read_tr8_b64:
1931 case Intrinsic::amdgcn_ds_read_tr16_b64:
1932 case Intrinsic::amdgcn_ds_ordered_add:
1933 case Intrinsic::amdgcn_ds_ordered_swap:
1934 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
1935 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
1936 case Intrinsic::amdgcn_flat_atomic_fmax_num:
1937 case Intrinsic::amdgcn_flat_atomic_fmin_num:
1938 case Intrinsic::amdgcn_global_atomic_fmax_num:
1939 case Intrinsic::amdgcn_global_atomic_fmin_num:
1940 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
1941 case Intrinsic::amdgcn_global_load_tr_b64:
1942 case Intrinsic::amdgcn_global_load_tr_b128:
1943 case Intrinsic::amdgcn_global_load_tr4_b64:
1944 case Intrinsic::amdgcn_global_load_tr6_b96:
1945 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
1946 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
1947 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
1948 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
1949 case Intrinsic::amdgcn_av_load_b128:
1950 case Intrinsic::amdgcn_av_store_b128:
1951 Ptr = II->getArgOperand(0);
1952 break;
1953 case Intrinsic::amdgcn_load_to_lds:
1954 case Intrinsic::amdgcn_load_async_to_lds:
1955 case Intrinsic::amdgcn_global_load_lds:
1956 case Intrinsic::amdgcn_global_load_async_lds:
1957 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
1958 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
1959 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
1960 case Intrinsic::amdgcn_global_load_async_to_lds_b128:
1961 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
1962 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
1963 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
1964 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128:
1965 Ptr = II->getArgOperand(1);
1966 break;
1967 default:
1968 return false;
1969 }
1970 AccessTy = II->getType();
1971 Ops.push_back(Ptr);
1972 return true;
1973}
1974
1976 unsigned AddrSpace) const {
1977 if (!Subtarget->hasFlatInstOffsets()) {
1978 // Flat instructions do not have offsets, and only have the register
1979 // address.
1980 return AM.BaseOffs == 0 && AM.Scale == 0;
1981 }
1982
1984 FlatAddrSpace FlatVariant =
1985 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS ? FlatAddrSpace::FlatGlobal
1986 : AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ? FlatAddrSpace::FlatScratch
1987 : FlatAddrSpace::FLAT;
1988
1989 return AM.Scale == 0 &&
1990 (AM.BaseOffs == 0 || Subtarget->getInstrInfo()->isLegalFLATOffset(
1991 AM.BaseOffs, AddrSpace, FlatVariant));
1992}
1993
1995 if (Subtarget->hasFlatGlobalInsts())
1997
1998 if (!Subtarget->hasAddr64() || Subtarget->useFlatForGlobal()) {
1999 // Assume the we will use FLAT for all global memory accesses
2000 // on VI.
2001 // FIXME: This assumption is currently wrong. On VI we still use
2002 // MUBUF instructions for the r + i addressing mode. As currently
2003 // implemented, the MUBUF instructions only work on buffer < 4GB.
2004 // It may be possible to support > 4GB buffers with MUBUF instructions,
2005 // by setting the stride value in the resource descriptor which would
2006 // increase the size limit to (stride * 4GB). However, this is risky,
2007 // because it has never been validated.
2009 }
2010
2011 return isLegalMUBUFAddressingMode(AM);
2012}
2013
2014bool SITargetLowering::isLegalMUBUFAddressingMode(const AddrMode &AM) const {
2015 // MUBUF / MTBUF instructions have a 12-bit unsigned byte offset, and
2016 // additionally can do r + r + i with addr64. 32-bit has more addressing
2017 // mode options. Depending on the resource constant, it can also do
2018 // (i64 r0) + (i32 r1) * (i14 i).
2019 //
2020 // Private arrays end up using a scratch buffer most of the time, so also
2021 // assume those use MUBUF instructions. Scratch loads / stores are currently
2022 // implemented as mubuf instructions with offen bit set, so slightly
2023 // different than the normal addr64.
2024 const SIInstrInfo *TII = Subtarget->getInstrInfo();
2025 if (!TII->isLegalMUBUFImmOffset(AM.BaseOffs))
2026 return false;
2027
2028 // FIXME: Since we can split immediate into soffset and immediate offset,
2029 // would it make sense to allow any immediate?
2030
2031 switch (AM.Scale) {
2032 case 0: // r + i or just i, depending on HasBaseReg.
2033 return true;
2034 case 1:
2035 return true; // We have r + r or r + i.
2036 case 2:
2037 if (AM.HasBaseReg) {
2038 // Reject 2 * r + r.
2039 return false;
2040 }
2041
2042 // Allow 2 * r as r + r
2043 // Or 2 * r + i is allowed as r + r + i.
2044 return true;
2045 default: // Don't allow n * r
2046 return false;
2047 }
2048}
2049
2051 const AddrMode &AM, Type *Ty,
2052 unsigned AS,
2053 Instruction *I) const {
2054 // No global is ever allowed as a base.
2055 if (AM.BaseGV)
2056 return false;
2057
2058 if (AS == AMDGPUAS::GLOBAL_ADDRESS)
2059 return isLegalGlobalAddressingMode(AM);
2060
2061 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
2065 // If the offset isn't a multiple of 4, it probably isn't going to be
2066 // correctly aligned.
2067 // FIXME: Can we get the real alignment here?
2068 if (AM.BaseOffs % 4 != 0)
2069 return isLegalMUBUFAddressingMode(AM);
2070
2071 if (!Subtarget->hasScalarSubwordLoads()) {
2072 // There are no SMRD extloads, so if we have to do a small type access we
2073 // will use a MUBUF load.
2074 // FIXME?: We also need to do this if unaligned, but we don't know the
2075 // alignment here.
2076 if (Ty->isSized() && DL.getTypeStoreSize(Ty) < 4)
2077 return isLegalGlobalAddressingMode(AM);
2078 }
2079
2080 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS) {
2081 // SMRD instructions have an 8-bit, dword offset on SI.
2082 if (!isUInt<8>(AM.BaseOffs / 4))
2083 return false;
2084 } else if (Subtarget->getGeneration() == AMDGPUSubtarget::SEA_ISLANDS) {
2085 // On CI+, this can also be a 32-bit literal constant offset. If it fits
2086 // in 8-bits, it can use a smaller encoding.
2087 if (!isUInt<32>(AM.BaseOffs / 4))
2088 return false;
2089 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX9) {
2090 // On VI, these use the SMEM format and the offset is 20-bit in bytes.
2091 if (!isUInt<20>(AM.BaseOffs))
2092 return false;
2093 } else if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX12) {
2094 // On GFX9 the offset is signed 21-bit in bytes (but must not be negative
2095 // for S_BUFFER_* instructions).
2096 if (!isInt<21>(AM.BaseOffs))
2097 return false;
2098 } else {
2099 // On GFX12, all offsets are signed 24-bit in bytes.
2100 if (!isInt<24>(AM.BaseOffs))
2101 return false;
2102 }
2103
2104 if ((AS == AMDGPUAS::CONSTANT_ADDRESS ||
2106 AM.BaseOffs < 0) {
2107 // Scalar (non-buffer) loads can only use a negative offset if
2108 // soffset+offset is non-negative. Since the compiler can only prove that
2109 // in a few special cases, it is safer to claim that negative offsets are
2110 // not supported.
2111 return false;
2112 }
2113
2114 if (AM.Scale == 0) // r + i or just i, depending on HasBaseReg.
2115 return true;
2116
2117 if (AM.Scale == 1 && AM.HasBaseReg)
2118 return true;
2119
2120 return false;
2121 }
2122
2123 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
2124 return Subtarget->hasFlatScratchEnabled()
2126 : isLegalMUBUFAddressingMode(AM);
2127
2128 if (AS == AMDGPUAS::LOCAL_ADDRESS ||
2129 (AS == AMDGPUAS::REGION_ADDRESS && Subtarget->hasGDS())) {
2130 // Basic, single offset DS instructions allow a 16-bit unsigned immediate
2131 // field.
2132 // XXX - If doing a 4-byte aligned 8-byte type access, we effectively have
2133 // an 8-bit dword offset but we don't know the alignment here.
2134 if (!isUInt<16>(AM.BaseOffs))
2135 return false;
2136
2137 if (AM.Scale == 0) // r + i or just i, depending on HasBaseReg.
2138 return true;
2139
2140 if (AM.Scale == 1 && AM.HasBaseReg)
2141 return true;
2142
2143 return false;
2144 }
2145
2147 // For an unknown address space, this usually means that this is for some
2148 // reason being used for pure arithmetic, and not based on some addressing
2149 // computation. We don't have instructions that compute pointers with any
2150 // addressing modes, so treat them as having no offset like flat
2151 // instructions.
2153 }
2154
2155 // Assume a user alias of global for unknown address spaces.
2156 return isLegalGlobalAddressingMode(AM);
2157}
2158
2160 const MachineFunction &MF) const {
2162 return (MemVT.getSizeInBits() <= 4 * 32);
2163 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
2164 unsigned MaxPrivateBits = 8 * getSubtarget()->getMaxPrivateElementSize();
2165 return (MemVT.getSizeInBits() <= MaxPrivateBits);
2166 }
2168 return (MemVT.getSizeInBits() <= 2 * 32);
2169 return true;
2170}
2171
2173 unsigned Size, unsigned AddrSpace, Align Alignment,
2174 MachineMemOperand::Flags Flags, unsigned *IsFast) const {
2175 if (IsFast)
2176 *IsFast = 0;
2177
2178 if (AddrSpace == AMDGPUAS::LOCAL_ADDRESS ||
2179 AddrSpace == AMDGPUAS::REGION_ADDRESS) {
2180 // Check if alignment requirements for ds_read/write instructions are
2181 // disabled.
2182 if (!Subtarget->hasUnalignedDSAccessEnabled() && Alignment < Align(4))
2183 return false;
2184
2185 Align RequiredAlignment(
2186 PowerOf2Ceil(divideCeil(Size, 8))); // Natural alignment.
2187 if (Subtarget->hasLDSMisalignedBugInWGPMode() && Size > 32 &&
2188 Alignment < RequiredAlignment)
2189 return false;
2190
2191 // Either, the alignment requirements are "enabled", or there is an
2192 // unaligned LDS access related hardware bug though alignment requirements
2193 // are "disabled". In either case, we need to check for proper alignment
2194 // requirements.
2195 //
2196 switch (Size) {
2197 case 64:
2198 // SI has a hardware bug in the LDS / GDS bounds checking: if the base
2199 // address is negative, then the instruction is incorrectly treated as
2200 // out-of-bounds even if base + offsets is in bounds. Split vectorized
2201 // loads here to avoid emitting ds_read2_b32. We may re-combine the
2202 // load later in the SILoadStoreOptimizer.
2203 if (!Subtarget->hasUsableDSOffset() && Alignment < Align(8))
2204 return false;
2205
2206 // 8 byte accessing via ds_read/write_b64 require 8-byte alignment, but we
2207 // can do a 4 byte aligned, 8 byte access in a single operation using
2208 // ds_read2/write2_b32 with adjacent offsets.
2209 RequiredAlignment = Align(4);
2210
2211 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2212 // We will either select ds_read_b64/ds_write_b64 or ds_read2_b32/
2213 // ds_write2_b32 depending on the alignment. In either case with either
2214 // alignment there is no faster way of doing this.
2215
2216 // The numbers returned here and below are not additive, it is a 'speed
2217 // rank'. They are just meant to be compared to decide if a certain way
2218 // of lowering an operation is faster than another. For that purpose
2219 // naturally aligned operation gets it bitsize to indicate that "it
2220 // operates with a speed comparable to N-bit wide load". With the full
2221 // alignment ds128 is slower than ds96 for example. If underaligned it
2222 // is comparable to a speed of a single dword access, which would then
2223 // mean 32 < 128 and it is faster to issue a wide load regardless.
2224 // 1 is simply "slow, don't do it". I.e. comparing an aligned load to a
2225 // wider load which will not be aligned anymore the latter is slower.
2226 if (IsFast)
2227 *IsFast = (Alignment >= RequiredAlignment) ? 64
2228 : (Alignment < Align(4)) ? 32
2229 : 1;
2230 return true;
2231 }
2232
2233 break;
2234 case 96:
2235 if (!Subtarget->hasDS96AndDS128())
2236 return false;
2237
2238 // 12 byte accessing via ds_read/write_b96 require 16-byte alignment on
2239 // gfx8 and older.
2240
2241 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2242 // Naturally aligned access is fastest. However, also report it is Fast
2243 // if memory is aligned less than DWORD. A narrow load or store will be
2244 // be equally slow as a single ds_read_b96/ds_write_b96, but there will
2245 // be more of them, so overall we will pay less penalty issuing a single
2246 // instruction.
2247
2248 // See comment on the values above.
2249 if (IsFast)
2250 *IsFast = (Alignment >= RequiredAlignment) ? 96
2251 : (Alignment < Align(4)) ? 32
2252 : 1;
2253 return true;
2254 }
2255
2256 break;
2257 case 128:
2258 if (!Subtarget->hasDS96AndDS128() || !Subtarget->useDS128())
2259 return false;
2260
2261 // 16 byte accessing via ds_read/write_b128 require 16-byte alignment on
2262 // gfx8 and older, but we can do a 8 byte aligned, 16 byte access in a
2263 // single operation using ds_read2/write2_b64.
2264 RequiredAlignment = Align(8);
2265
2266 if (Subtarget->hasUnalignedDSAccessEnabled()) {
2267 // Naturally aligned access is fastest. However, also report it is Fast
2268 // if memory is aligned less than DWORD. A narrow load or store will be
2269 // be equally slow as a single ds_read_b128/ds_write_b128, but there
2270 // will be more of them, so overall we will pay less penalty issuing a
2271 // single instruction.
2272
2273 // See comment on the values above.
2274 if (IsFast)
2275 *IsFast = (Alignment >= RequiredAlignment) ? 128
2276 : (Alignment < Align(4)) ? 32
2277 : 1;
2278 return true;
2279 }
2280
2281 break;
2282 default:
2283 if (Size > 32)
2284 return false;
2285
2286 break;
2287 }
2288
2289 // See comment on the values above.
2290 // Note that we have a single-dword or sub-dword here, so if underaligned
2291 // it is a slowest possible access, hence returned value is 0.
2292 if (IsFast)
2293 *IsFast = (Alignment >= RequiredAlignment) ? Size : 0;
2294
2295 return Alignment >= RequiredAlignment ||
2296 Subtarget->hasUnalignedDSAccessEnabled();
2297 }
2298
2299 // FIXME: We have to be conservative here and assume that flat operations
2300 // will access scratch. If we had access to the IR function, then we
2301 // could determine if any private memory was used in the function.
2302 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ||
2303 AddrSpace == AMDGPUAS::FLAT_ADDRESS) {
2304 bool AlignedBy4 = Alignment >= Align(4);
2305 if (Subtarget->hasUnalignedScratchAccessEnabled()) {
2306 if (IsFast)
2307 *IsFast = AlignedBy4 ? Size : 1;
2308 return true;
2309 }
2310
2311 if (IsFast)
2312 *IsFast = AlignedBy4;
2313
2314 return AlignedBy4;
2315 }
2316
2317 // So long as they are correct, wide global memory operations perform better
2318 // than multiple smaller memory ops -- even when misaligned
2319 if (AMDGPU::isExtendedGlobalAddrSpace(AddrSpace)) {
2320 if (IsFast)
2321 *IsFast = Size;
2322
2323 return Alignment >= Align(4) ||
2324 Subtarget->hasUnalignedBufferAccessEnabled();
2325 }
2326
2327 // Ensure robust out-of-bounds guarantees for buffer accesses are met when the
2328 // "amdgpu.buffer.oob.mode" module flag has not enabled relaxed untyped-buffer
2329 // OOB semantics. Normally hardware will ensure proper
2330 // out-of-bounds behavior, but in the edge case where an access starts
2331 // out-of-bounds and then enters in-bounds, the entire access would be treated
2332 // as out-of-bounds. Prevent misaligned memory accesses by requiring the
2333 // natural alignment of buffer accesses.
2334 if (AddrSpace == AMDGPUAS::BUFFER_FAT_POINTER ||
2335 AddrSpace == AMDGPUAS::BUFFER_RESOURCE ||
2336 AddrSpace == AMDGPUAS::BUFFER_STRIDED_POINTER) {
2337 if (!Subtarget->hasRelaxedBufferOOBMode() &&
2338 Alignment < Align(PowerOf2Ceil(divideCeil(Size, 8))))
2339 return false;
2340 }
2341
2342 // Smaller than dword value must be aligned.
2343 if (Size < 32)
2344 return false;
2345
2346 // 8.1.6 - For Dword or larger reads or writes, the two LSBs of the
2347 // byte-address are ignored, thus forcing Dword alignment.
2348 // This applies to private, global, and constant memory.
2349 if (IsFast)
2350 *IsFast = 1;
2351
2352 return Size >= 32 && Alignment >= Align(4);
2353}
2354
2356 EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
2357 unsigned *IsFast) const {
2359 Alignment, Flags, IsFast);
2360}
2361
2363 LLVMContext &Context, const MemOp &Op,
2364 const AttributeList &FuncAttributes) const {
2365 // FIXME: Should account for address space here.
2366
2367 // The default fallback uses the private pointer size as a guess for a type to
2368 // use. Make sure we switch these to 64-bit accesses.
2369
2370 if (Op.size() >= 16 &&
2371 Op.isDstAligned(Align(4))) // XXX: Should only do for global
2372 return MVT::v4i32;
2373
2374 if (Op.size() >= 8 && Op.isDstAligned(Align(4)))
2375 return MVT::v2i32;
2376
2377 // Use the default.
2378 return MVT::Other;
2379}
2380
2382 const MemSDNode *MemNode = cast<MemSDNode>(N);
2383 return MemNode->getMemOperand()->getFlags() & MONoClobber;
2384}
2385
2390
2392 unsigned DestAS) const {
2393 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
2394 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
2395 Subtarget->hasGloballyAddressableScratch()) {
2396 // Flat -> private requires subtracting src_flat_scratch_base_lo.
2397 return false;
2398 }
2399
2400 // Flat -> private/local is a simple truncate.
2401 // Flat -> global is no-op
2402 return true;
2403 }
2404
2405 const GCNTargetMachine &TM =
2406 static_cast<const GCNTargetMachine &>(getTargetMachine());
2407 return TM.isNoopAddrSpaceCast(SrcAS, DestAS);
2408}
2409
2417
2419 Type *Ty) const {
2420 // FIXME: Could be smarter if called for vector constants.
2421 return true;
2422}
2423
2426 unsigned Index) const {
2429
2430 // TODO: Add more cases that are cheap.
2431 if (Index == 0)
2434}
2435
2436bool SITargetLowering::isExtractVecEltCheap(EVT VT, unsigned Index) const {
2437 // TODO: This should be more aggressive, particular for 16-bit element
2438 // vectors. However there are some mixed improvements and regressions.
2439 EVT EltTy = VT.getVectorElementType();
2440 unsigned MinAlign = Subtarget->useRealTrue16Insts() ? 16 : 32;
2441 return EltTy.getSizeInBits() % MinAlign == 0;
2442}
2443
2445 if (Subtarget->has16BitInsts() && VT == MVT::i16) {
2446 switch (Op) {
2447 case ISD::LOAD:
2448 case ISD::STORE:
2449 return true;
2450 default:
2451 return false;
2452 }
2453 }
2454
2455 // SimplifySetCC uses this function to determine whether or not it should
2456 // create setcc with i1 operands. We don't have instructions for i1 setcc.
2457 if (VT == MVT::i1 && Op == ISD::SETCC)
2458 return false;
2459
2461}
2462
2465 // This isn't really a constant pool but close enough.
2468 return PtrInfo;
2469}
2470
2471SDValue SITargetLowering::lowerKernArgParameterPtr(SelectionDAG &DAG,
2472 const SDLoc &SL,
2473 SDValue Chain,
2474 uint64_t Offset) const {
2475 const DataLayout &DL = DAG.getDataLayout();
2479
2480 auto [InputPtrReg, RC, ArgTy] =
2481 Info->getPreloadedValue(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
2482
2483 // We may not have the kernarg segment argument if we have no kernel
2484 // arguments.
2485 if (!InputPtrReg)
2486 return DAG.getConstant(Offset, SL, PtrVT);
2487
2489 SDValue BasePtr = DAG.getCopyFromReg(
2490 Chain, SL, MRI.getLiveInVirtReg(InputPtrReg->getRegister()), PtrVT);
2491
2492 return DAG.getObjectPtrOffset(SL, BasePtr, TypeSize::getFixed(Offset));
2493}
2494
2495SDValue SITargetLowering::getImplicitArgPtr(SelectionDAG &DAG,
2496 const SDLoc &SL) const {
2499 return lowerKernArgParameterPtr(DAG, SL, DAG.getEntryNode(), Offset);
2500}
2501
2502SDValue SITargetLowering::getLDSKernelId(SelectionDAG &DAG,
2503 const SDLoc &SL) const {
2504
2506 std::optional<uint32_t> KnownSize =
2508 if (KnownSize.has_value())
2509 return DAG.getConstant(*KnownSize, SL, MVT::i32);
2510 return SDValue();
2511}
2512
2513SDValue SITargetLowering::convertArgType(SelectionDAG &DAG, EVT VT, EVT MemVT,
2514 const SDLoc &SL, SDValue Val,
2515 bool Signed,
2516 const ISD::InputArg *Arg) const {
2517 // First, if it is a widened vector, narrow it.
2518 if (VT.isVector() &&
2520 EVT NarrowedVT =
2523 Val = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, NarrowedVT, Val,
2524 DAG.getConstant(0, SL, MVT::i32));
2525 }
2526
2527 // Then convert the vector elements or scalar value.
2528 if (Arg && (Arg->Flags.isSExt() || Arg->Flags.isZExt()) && VT.bitsLT(MemVT)) {
2529 unsigned Opc = Arg->Flags.isZExt() ? ISD::AssertZext : ISD::AssertSext;
2530 Val = DAG.getNode(Opc, SL, MemVT, Val, DAG.getValueType(VT));
2531 }
2532
2533 if (MemVT.isFloatingPoint()) {
2534 if (VT.isFloatingPoint()) {
2535 Val = getFPExtOrFPRound(DAG, Val, SL, VT);
2536 } else {
2537 assert(!MemVT.isVector());
2538 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
2539 SDValue Cast = DAG.getBitcast(IntVT, Val);
2540 Val = DAG.getAnyExtOrTrunc(Cast, SL, VT);
2541 }
2542 } else if (Signed)
2543 Val = DAG.getSExtOrTrunc(Val, SL, VT);
2544 else
2545 Val = DAG.getZExtOrTrunc(Val, SL, VT);
2546
2547 return Val;
2548}
2549
2550SDValue SITargetLowering::lowerKernargMemParameter(
2551 SelectionDAG &DAG, EVT VT, EVT MemVT, const SDLoc &SL, SDValue Chain,
2552 uint64_t Offset, Align Alignment, bool Signed,
2553 const ISD::InputArg *Arg) const {
2554
2555 MachinePointerInfo PtrInfo =
2557
2558 // Try to avoid using an extload by loading earlier than the argument address,
2559 // and extracting the relevant bits. The load should hopefully be merged with
2560 // the previous argument.
2561 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
2562 // TODO: Handle align < 4 and size >= 4 (can happen with packed structs).
2563 int64_t AlignDownOffset = alignDown(Offset, 4);
2564 int64_t OffsetDiff = Offset - AlignDownOffset;
2565
2566 EVT IntVT = MemVT.changeTypeToInteger();
2567
2568 // TODO: If we passed in the base kernel offset we could have a better
2569 // alignment than 4, but we don't really need it.
2570 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, AlignDownOffset);
2571 SDValue Load = DAG.getLoad(MVT::i32, SL, Chain, Ptr,
2572 PtrInfo.getWithOffset(AlignDownOffset), Align(4),
2575
2576 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, SL, MVT::i32);
2577 SDValue Extract = DAG.getNode(ISD::SRL, SL, MVT::i32, Load, ShiftAmt);
2578
2579 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, SL, IntVT, Extract);
2580 ArgVal = DAG.getNode(ISD::BITCAST, SL, MemVT, ArgVal);
2581 ArgVal = convertArgType(DAG, VT, MemVT, SL, ArgVal, Signed, Arg);
2582
2583 return DAG.getMergeValues({ArgVal, Load.getValue(1)}, SL);
2584 }
2585
2586 SDValue Ptr = lowerKernArgParameterPtr(DAG, SL, Chain, Offset);
2587 SDValue Load = DAG.getLoad(
2588 MemVT, SL, Chain, Ptr, PtrInfo.getWithOffset(Offset), Alignment,
2590
2591 SDValue Val = convertArgType(DAG, VT, MemVT, SL, Load, Signed, Arg);
2592 return DAG.getMergeValues({Val, Load.getValue(1)}, SL);
2593}
2594
2595/// Coerce an argument which was passed in a different ABI type to the original
2596/// expected value type.
2597SDValue SITargetLowering::convertABITypeToValueType(SelectionDAG &DAG,
2598 SDValue Val,
2599 CCValAssign &VA,
2600 const SDLoc &SL) const {
2601 EVT ValVT = VA.getValVT();
2602
2603 // If this is an 8 or 16-bit value, it is really passed promoted
2604 // to 32 bits. Insert an assert[sz]ext to capture this, then
2605 // truncate to the right size.
2606 switch (VA.getLocInfo()) {
2607 case CCValAssign::Full:
2608 return Val;
2609 case CCValAssign::BCvt:
2610 return DAG.getNode(ISD::BITCAST, SL, ValVT, Val);
2611 case CCValAssign::SExt:
2612 Val = DAG.getNode(ISD::AssertSext, SL, VA.getLocVT(), Val,
2613 DAG.getValueType(ValVT));
2614 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2615 case CCValAssign::ZExt:
2616 Val = DAG.getNode(ISD::AssertZext, SL, VA.getLocVT(), Val,
2617 DAG.getValueType(ValVT));
2618 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2619 case CCValAssign::AExt:
2620 return DAG.getNode(ISD::TRUNCATE, SL, ValVT, Val);
2621 default:
2622 llvm_unreachable("Unknown loc info!");
2623 }
2624}
2625
2626SDValue SITargetLowering::lowerStackParameter(SelectionDAG &DAG,
2627 CCValAssign &VA, const SDLoc &SL,
2628 SDValue Chain,
2629 const ISD::InputArg &Arg) const {
2631 MachineFrameInfo &MFI = MF.getFrameInfo();
2632
2633 if (Arg.Flags.isByVal()) {
2634 unsigned Size = Arg.Flags.getByValSize();
2635 int FrameIdx = MFI.CreateFixedObject(Size, VA.getLocMemOffset(), false);
2636 return DAG.getFrameIndex(FrameIdx, MVT::i32);
2637 }
2638
2639 unsigned ArgOffset = VA.getLocMemOffset();
2640 unsigned ArgSize = VA.getValVT().getStoreSize();
2641
2642 int FI = MFI.CreateFixedObject(ArgSize, ArgOffset, true);
2643
2644 // Create load nodes to retrieve arguments from the stack.
2645 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
2646
2647 // For NON_EXTLOAD, generic code in getLoad assert(ValVT == MemVT)
2649 MVT MemVT = VA.getValVT();
2650
2651 switch (VA.getLocInfo()) {
2652 default:
2653 break;
2654 case CCValAssign::BCvt:
2655 MemVT = VA.getLocVT();
2656 break;
2657 case CCValAssign::SExt:
2658 ExtType = ISD::SEXTLOAD;
2659 break;
2660 case CCValAssign::ZExt:
2661 ExtType = ISD::ZEXTLOAD;
2662 break;
2663 case CCValAssign::AExt:
2664 ExtType = ISD::EXTLOAD;
2665 break;
2666 }
2667
2668 SDValue ArgValue = DAG.getExtLoad(
2669 ExtType, SL, VA.getLocVT(), Chain, FIN,
2671
2672 SDValue ConvertedVal = convertABITypeToValueType(DAG, ArgValue, VA, SL);
2673 if (ConvertedVal == ArgValue)
2674 return ConvertedVal;
2675
2676 return DAG.getMergeValues({ConvertedVal, ArgValue.getValue(1)}, SL);
2677}
2678
2679SDValue SITargetLowering::lowerWorkGroupId(
2680 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2683 AMDGPUFunctionArgInfo::PreloadedValue ClusterWorkGroupIdPV) const {
2684 if (!Subtarget->hasClusters())
2685 return getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2686
2687 // Clusters are supported. Return the global position in the grid. If clusters
2688 // are enabled, WorkGroupIdPV returns the cluster ID not the workgroup ID.
2689
2690 // WorkGroupIdXYZ = ClusterId == 0 ?
2691 // ClusterIdXYZ :
2692 // ClusterIdXYZ * (ClusterMaxIdXYZ + 1) + ClusterWorkGroupIdXYZ
2693 SDValue ClusterIdXYZ = getPreloadedValue(DAG, MFI, VT, WorkGroupIdPV);
2694 SDLoc SL(ClusterIdXYZ);
2695 SDValue ClusterMaxIdXYZ = getPreloadedValue(DAG, MFI, VT, ClusterMaxIdPV);
2696 SDValue One = DAG.getConstant(1, SL, VT);
2697 SDValue ClusterSizeXYZ = DAG.getNode(ISD::ADD, SL, VT, ClusterMaxIdXYZ, One);
2698 SDValue ClusterWorkGroupIdXYZ =
2699 getPreloadedValue(DAG, MFI, VT, ClusterWorkGroupIdPV);
2700 SDValue GlobalIdXYZ =
2701 DAG.getNode(ISD::ADD, SL, VT, ClusterWorkGroupIdXYZ,
2702 DAG.getNode(ISD::MUL, SL, VT, ClusterIdXYZ, ClusterSizeXYZ));
2703
2704 switch (MFI.getClusterDims().getKind()) {
2707 return GlobalIdXYZ;
2709 return ClusterIdXYZ;
2711 using namespace AMDGPU::Hwreg;
2712 SDValue ClusterIdField =
2713 DAG.getTargetConstant(HwregEncoding::encode(ID_IB_STS2, 6, 4), SL, VT);
2714 SDNode *GetReg =
2715 DAG.getMachineNode(AMDGPU::S_GETREG_B32_const, SL, VT, ClusterIdField);
2716 SDValue ClusterId(GetReg, 0);
2717 SDValue Zero = DAG.getConstant(0, SL, VT);
2718 return DAG.getNode(ISD::SELECT_CC, SL, VT, ClusterId, Zero, ClusterIdXYZ,
2719 GlobalIdXYZ, DAG.getCondCode(ISD::SETEQ));
2720 }
2721 }
2722
2723 llvm_unreachable("nothing should reach here");
2724}
2725
2726SDValue SITargetLowering::getPreloadedValue(
2727 SelectionDAG &DAG, const SIMachineFunctionInfo &MFI, EVT VT,
2729 const ArgDescriptor *Reg = nullptr;
2730 const TargetRegisterClass *RC = nullptr;
2731 LLT Ty;
2732
2734 const ArgDescriptor WorkGroupIDX =
2735 ArgDescriptor::createRegister(AMDGPU::TTMP9);
2736 // If GridZ is not programmed in an entry function then the hardware will set
2737 // it to all zeros, so there is no need to mask the GridY value in the low
2738 // order bits.
2739 const ArgDescriptor WorkGroupIDY = ArgDescriptor::createRegister(
2740 AMDGPU::TTMP7,
2741 AMDGPU::isEntryFunctionCC(CC) && !MFI.hasWorkGroupIDZ() ? ~0u : 0xFFFFu);
2742 const ArgDescriptor WorkGroupIDZ =
2743 ArgDescriptor::createRegister(AMDGPU::TTMP7, 0xFFFF0000u);
2744 const ArgDescriptor ClusterWorkGroupIDX =
2745 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000000Fu);
2746 const ArgDescriptor ClusterWorkGroupIDY =
2747 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000000F0u);
2748 const ArgDescriptor ClusterWorkGroupIDZ =
2749 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00000F00u);
2750 const ArgDescriptor ClusterWorkGroupMaxIDX =
2751 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0000F000u);
2752 const ArgDescriptor ClusterWorkGroupMaxIDY =
2753 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x000F0000u);
2754 const ArgDescriptor ClusterWorkGroupMaxIDZ =
2755 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x00F00000u);
2756 const ArgDescriptor ClusterWorkGroupMaxFlatID =
2757 ArgDescriptor::createRegister(AMDGPU::TTMP6, 0x0F000000u);
2758
2759 auto LoadConstant = [&](unsigned N) {
2760 return DAG.getConstant(N, SDLoc(), VT);
2761 };
2762
2763 if (Subtarget->hasArchitectedSGPRs() &&
2765 AMDGPU::ClusterDimsAttr ClusterDims = MFI.getClusterDims();
2766 bool HasFixedDims = ClusterDims.isFixedDims();
2767
2768 switch (PVID) {
2770 Reg = &WorkGroupIDX;
2771 RC = &AMDGPU::SReg_32RegClass;
2772 Ty = LLT::scalar(32);
2773 break;
2775 Reg = &WorkGroupIDY;
2776 RC = &AMDGPU::SReg_32RegClass;
2777 Ty = LLT::scalar(32);
2778 break;
2780 Reg = &WorkGroupIDZ;
2781 RC = &AMDGPU::SReg_32RegClass;
2782 Ty = LLT::scalar(32);
2783 break;
2785 if (HasFixedDims && ClusterDims.getDims()[0] == 1)
2786 return LoadConstant(0);
2787 Reg = &ClusterWorkGroupIDX;
2788 RC = &AMDGPU::SReg_32RegClass;
2789 Ty = LLT::scalar(32);
2790 break;
2792 if (HasFixedDims && ClusterDims.getDims()[1] == 1)
2793 return LoadConstant(0);
2794 Reg = &ClusterWorkGroupIDY;
2795 RC = &AMDGPU::SReg_32RegClass;
2796 Ty = LLT::scalar(32);
2797 break;
2799 if (HasFixedDims && ClusterDims.getDims()[2] == 1)
2800 return LoadConstant(0);
2801 Reg = &ClusterWorkGroupIDZ;
2802 RC = &AMDGPU::SReg_32RegClass;
2803 Ty = LLT::scalar(32);
2804 break;
2806 if (HasFixedDims)
2807 return LoadConstant(ClusterDims.getDims()[0] - 1);
2808 Reg = &ClusterWorkGroupMaxIDX;
2809 RC = &AMDGPU::SReg_32RegClass;
2810 Ty = LLT::scalar(32);
2811 break;
2813 if (HasFixedDims)
2814 return LoadConstant(ClusterDims.getDims()[1] - 1);
2815 Reg = &ClusterWorkGroupMaxIDY;
2816 RC = &AMDGPU::SReg_32RegClass;
2817 Ty = LLT::scalar(32);
2818 break;
2820 if (HasFixedDims)
2821 return LoadConstant(ClusterDims.getDims()[2] - 1);
2822 Reg = &ClusterWorkGroupMaxIDZ;
2823 RC = &AMDGPU::SReg_32RegClass;
2824 Ty = LLT::scalar(32);
2825 break;
2827 Reg = &ClusterWorkGroupMaxFlatID;
2828 RC = &AMDGPU::SReg_32RegClass;
2829 Ty = LLT::scalar(32);
2830 break;
2831 default:
2832 break;
2833 }
2834 }
2835
2836 if (!Reg)
2837 std::tie(Reg, RC, Ty) = MFI.getPreloadedValue(PVID);
2838 if (!Reg) {
2840 // It's possible for a kernarg intrinsic call to appear in a kernel with
2841 // no allocated segment, in which case we do not add the user sgpr
2842 // argument, so just return null.
2843 return DAG.getConstant(0, SDLoc(), VT);
2844 }
2845
2846 // It's undefined behavior if a function marked with the amdgpu-no-*
2847 // attributes uses the corresponding intrinsic.
2848 return DAG.getPOISON(VT);
2849 }
2850
2851 return loadInputValue(DAG, RC, VT, SDLoc(DAG.getEntryNode()), *Reg);
2852}
2853
2855 CallingConv::ID CallConv,
2856 ArrayRef<ISD::InputArg> Ins, BitVector &Skipped,
2857 FunctionType *FType,
2858 SIMachineFunctionInfo *Info) {
2859 for (unsigned I = 0, E = Ins.size(), PSInputNum = 0; I != E; ++I) {
2860 const ISD::InputArg *Arg = &Ins[I];
2861
2862 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2863 "vector type argument should have been split");
2864
2865 // First check if it's a PS input addr.
2866 if (CallConv == CallingConv::AMDGPU_PS && !Arg->Flags.isInReg() &&
2867 PSInputNum <= 15) {
2868 bool SkipArg = !Arg->Used && !Info->isPSInputAllocated(PSInputNum);
2869
2870 // Inconveniently only the first part of the split is marked as isSplit,
2871 // so skip to the end. We only want to increment PSInputNum once for the
2872 // entire split argument.
2873 if (Arg->Flags.isSplit()) {
2874 while (!Arg->Flags.isSplitEnd()) {
2875 assert((!Arg->VT.isVector() || Arg->VT.getScalarSizeInBits() == 16) &&
2876 "unexpected vector split in ps argument type");
2877 if (!SkipArg)
2878 Splits.push_back(*Arg);
2879 Arg = &Ins[++I];
2880 }
2881 }
2882
2883 if (SkipArg) {
2884 // We can safely skip PS inputs.
2885 Skipped.set(Arg->getOrigArgIndex());
2886 ++PSInputNum;
2887 continue;
2888 }
2889
2890 Info->markPSInputAllocated(PSInputNum);
2891 if (Arg->Used)
2892 Info->markPSInputEnabled(PSInputNum);
2893
2894 ++PSInputNum;
2895 }
2896
2897 Splits.push_back(*Arg);
2898 }
2899}
2900
2901// Allocate special inputs passed in VGPRs.
2903 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
2904 SIMachineFunctionInfo &Info) const {
2905 const LLT S32 = LLT::scalar(32);
2906 MachineRegisterInfo &MRI = MF.getRegInfo();
2907
2908 if (Info.hasWorkItemIDX()) {
2909 Register Reg = AMDGPU::VGPR0;
2910 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), S32);
2911
2912 CCInfo.AllocateReg(Reg);
2913 unsigned Mask =
2914 (Subtarget->hasPackedTID() && Info.hasWorkItemIDY()) ? 0x3ff : ~0u;
2915 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
2916 }
2917
2918 if (Info.hasWorkItemIDY()) {
2919 assert(Info.hasWorkItemIDX());
2920 if (Subtarget->hasPackedTID()) {
2921 Info.setWorkItemIDY(
2922 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 10));
2923 } else {
2924 unsigned Reg = AMDGPU::VGPR1;
2925 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), S32);
2926
2927 CCInfo.AllocateReg(Reg);
2928 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg));
2929 }
2930 }
2931
2932 if (Info.hasWorkItemIDZ()) {
2933 assert(Info.hasWorkItemIDX() && Info.hasWorkItemIDY());
2934 if (Subtarget->hasPackedTID()) {
2935 Info.setWorkItemIDZ(
2936 ArgDescriptor::createRegister(AMDGPU::VGPR0, 0x3ff << 20));
2937 } else {
2938 unsigned Reg = AMDGPU::VGPR2;
2939 MRI.setType(MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass), S32);
2940
2941 CCInfo.AllocateReg(Reg);
2942 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg));
2943 }
2944 }
2945}
2946
2947// Try to allocate a VGPR at the end of the argument list, or if no argument
2948// VGPRs are left allocating a stack slot.
2949// If \p Mask is given it indicates bitfield position in the register.
2950// If \p Arg is given use it with new ]p Mask instead of allocating new.
2951static ArgDescriptor allocateVGPR32Input(CCState &CCInfo, unsigned Mask = ~0u,
2952 ArgDescriptor Arg = ArgDescriptor()) {
2953 if (Arg.isSet())
2954 return ArgDescriptor::createArg(Arg, Mask);
2955
2956 ArrayRef<MCPhysReg> ArgVGPRs = ArrayRef(AMDGPU::VGPR_32RegClass.begin(), 32);
2957 unsigned RegIdx = CCInfo.getFirstUnallocated(ArgVGPRs);
2958 if (RegIdx == ArgVGPRs.size()) {
2959 // Spill to stack required.
2960 int64_t Offset = CCInfo.AllocateStack(4, Align(4));
2961
2962 return ArgDescriptor::createStack(Offset, Mask);
2963 }
2964
2965 unsigned Reg = ArgVGPRs[RegIdx];
2966 Reg = CCInfo.AllocateReg(Reg);
2967 assert(Reg != AMDGPU::NoRegister);
2968
2969 MachineFunction &MF = CCInfo.getMachineFunction();
2970 Register LiveInVReg = MF.addLiveIn(Reg, &AMDGPU::VGPR_32RegClass);
2971 MF.getRegInfo().setType(LiveInVReg, LLT::scalar(32));
2972 return ArgDescriptor::createRegister(Reg, Mask);
2973}
2974
2976 const TargetRegisterClass *RC,
2977 unsigned NumArgRegs) {
2978 ArrayRef<MCPhysReg> ArgSGPRs = ArrayRef(RC->begin(), 32);
2979 unsigned RegIdx = CCInfo.getFirstUnallocated(ArgSGPRs);
2980 if (RegIdx == ArgSGPRs.size())
2981 report_fatal_error("ran out of SGPRs for arguments");
2982
2983 unsigned Reg = ArgSGPRs[RegIdx];
2984 Reg = CCInfo.AllocateReg(Reg);
2985 assert(Reg != AMDGPU::NoRegister);
2986
2987 MachineFunction &MF = CCInfo.getMachineFunction();
2988 MF.addLiveIn(Reg, RC);
2990}
2991
2992// If this has a fixed position, we still should allocate the register in the
2993// CCInfo state. Technically we could get away with this for values passed
2994// outside of the normal argument range.
2996 const TargetRegisterClass *RC,
2997 MCRegister Reg) {
2998 Reg = CCInfo.AllocateReg(Reg);
2999 assert(Reg != AMDGPU::NoRegister);
3000 MachineFunction &MF = CCInfo.getMachineFunction();
3001 MF.addLiveIn(Reg, RC);
3002}
3003
3004static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg) {
3005 if (Arg) {
3006 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_32RegClass,
3007 Arg.getRegister());
3008 } else
3009 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_32RegClass, 32);
3010}
3011
3012static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg) {
3013 if (Arg) {
3014 allocateFixedSGPRInputImpl(CCInfo, &AMDGPU::SGPR_64RegClass,
3015 Arg.getRegister());
3016 } else
3017 Arg = allocateSGPR32InputImpl(CCInfo, &AMDGPU::SGPR_64RegClass, 16);
3018}
3019
3020/// Allocate implicit function VGPR arguments at the end of allocated user
3021/// arguments.
3023 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3024 SIMachineFunctionInfo &Info) const {
3025 const unsigned Mask = 0x3ff;
3026 ArgDescriptor Arg;
3027
3028 if (Info.hasWorkItemIDX()) {
3029 Arg = allocateVGPR32Input(CCInfo, Mask);
3030 Info.setWorkItemIDX(Arg);
3031 }
3032
3033 if (Info.hasWorkItemIDY()) {
3034 Arg = allocateVGPR32Input(CCInfo, Mask << 10, Arg);
3035 Info.setWorkItemIDY(Arg);
3036 }
3037
3038 if (Info.hasWorkItemIDZ())
3039 Info.setWorkItemIDZ(allocateVGPR32Input(CCInfo, Mask << 20, Arg));
3040}
3041
3042/// Allocate implicit function VGPR arguments in fixed registers.
3044 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3045 SIMachineFunctionInfo &Info) const {
3046 Register Reg = CCInfo.AllocateReg(AMDGPU::VGPR31);
3047 if (!Reg)
3048 report_fatal_error("failed to allocate VGPR for implicit arguments");
3049
3050 const unsigned Mask = 0x3ff;
3051 Info.setWorkItemIDX(ArgDescriptor::createRegister(Reg, Mask));
3052 Info.setWorkItemIDY(ArgDescriptor::createRegister(Reg, Mask << 10));
3053 Info.setWorkItemIDZ(ArgDescriptor::createRegister(Reg, Mask << 20));
3054}
3055
3057 CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI,
3058 SIMachineFunctionInfo &Info) const {
3059 auto &ArgInfo = Info.getArgInfo();
3060 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3061
3062 // TODO: Unify handling with private memory pointers.
3063 if (UserSGPRInfo.hasDispatchPtr())
3064 allocateSGPR64Input(CCInfo, ArgInfo.DispatchPtr);
3065
3066 if (UserSGPRInfo.hasQueuePtr())
3067 allocateSGPR64Input(CCInfo, ArgInfo.QueuePtr);
3068
3069 // Implicit arg ptr takes the place of the kernarg segment pointer. This is a
3070 // constant offset from the kernarg segment.
3071 if (Info.hasImplicitArgPtr())
3072 allocateSGPR64Input(CCInfo, ArgInfo.ImplicitArgPtr);
3073
3074 if (UserSGPRInfo.hasDispatchID())
3075 allocateSGPR64Input(CCInfo, ArgInfo.DispatchID);
3076
3077 // flat_scratch_init is not applicable for non-kernel functions.
3078
3079 if (Info.hasWorkGroupIDX())
3080 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDX);
3081
3082 if (Info.hasWorkGroupIDY())
3083 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDY);
3084
3085 if (Info.hasWorkGroupIDZ())
3086 allocateSGPR32Input(CCInfo, ArgInfo.WorkGroupIDZ);
3087
3088 if (Info.hasLDSKernelId())
3089 allocateSGPR32Input(CCInfo, ArgInfo.LDSKernelId);
3090}
3091
3092// Allocate special inputs passed in user SGPRs.
3094 MachineFunction &MF,
3095 const SIRegisterInfo &TRI,
3096 SIMachineFunctionInfo &Info) const {
3097 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info.getUserSGPRInfo();
3098 if (UserSGPRInfo.hasImplicitBufferPtr()) {
3099 Register ImplicitBufferPtrReg = Info.addImplicitBufferPtr(TRI);
3100 MF.addLiveIn(ImplicitBufferPtrReg, &AMDGPU::SGPR_64RegClass);
3101 CCInfo.AllocateReg(ImplicitBufferPtrReg);
3102 }
3103
3104 // FIXME: How should these inputs interact with inreg / custom SGPR inputs?
3105 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
3106 Register PrivateSegmentBufferReg = Info.addPrivateSegmentBuffer(TRI);
3107 MF.addLiveIn(PrivateSegmentBufferReg, &AMDGPU::SGPR_128RegClass);
3108 CCInfo.AllocateReg(PrivateSegmentBufferReg);
3109 }
3110
3111 if (UserSGPRInfo.hasDispatchPtr()) {
3112 Register DispatchPtrReg = Info.addDispatchPtr(TRI);
3113 MF.addLiveIn(DispatchPtrReg, &AMDGPU::SGPR_64RegClass);
3114 CCInfo.AllocateReg(DispatchPtrReg);
3115 }
3116
3117 if (UserSGPRInfo.hasQueuePtr()) {
3118 Register QueuePtrReg = Info.addQueuePtr(TRI);
3119 MF.addLiveIn(QueuePtrReg, &AMDGPU::SGPR_64RegClass);
3120 CCInfo.AllocateReg(QueuePtrReg);
3121 }
3122
3123 if (UserSGPRInfo.hasKernargSegmentPtr()) {
3124 MachineRegisterInfo &MRI = MF.getRegInfo();
3125 Register InputPtrReg = Info.addKernargSegmentPtr(TRI);
3126 CCInfo.AllocateReg(InputPtrReg);
3127
3128 Register VReg = MF.addLiveIn(InputPtrReg, &AMDGPU::SGPR_64RegClass);
3130 }
3131
3132 if (UserSGPRInfo.hasDispatchID()) {
3133 Register DispatchIDReg = Info.addDispatchID(TRI);
3134 MF.addLiveIn(DispatchIDReg, &AMDGPU::SGPR_64RegClass);
3135 CCInfo.AllocateReg(DispatchIDReg);
3136 }
3137
3138 if (UserSGPRInfo.hasFlatScratchInit() && !getSubtarget()->isAmdPalOS()) {
3139 Register FlatScratchInitReg = Info.addFlatScratchInit(TRI);
3140 MF.addLiveIn(FlatScratchInitReg, &AMDGPU::SGPR_64RegClass);
3141 CCInfo.AllocateReg(FlatScratchInitReg);
3142 }
3143
3144 if (UserSGPRInfo.hasPrivateSegmentSize()) {
3145 Register PrivateSegmentSizeReg = Info.addPrivateSegmentSize(TRI);
3146 MF.addLiveIn(PrivateSegmentSizeReg, &AMDGPU::SGPR_32RegClass);
3147 CCInfo.AllocateReg(PrivateSegmentSizeReg);
3148 }
3149
3150 // TODO: Add GridWorkGroupCount user SGPRs when used. For now with HSA we read
3151 // these from the dispatch pointer.
3152}
3153
3154// Allocate pre-loaded kernel arguemtns. Arguments to be preloading must be
3155// sequential starting from the first argument.
3157 CCState &CCInfo, SmallVectorImpl<CCValAssign> &ArgLocs,
3159 const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const {
3160 Function &F = MF.getFunction();
3161 unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
3162 GCNUserSGPRUsageInfo &SGPRInfo = Info.getUserSGPRInfo();
3163 bool InPreloadSequence = true;
3164 unsigned InIdx = 0;
3165 bool AlignedForImplictArgs = false;
3166 unsigned ImplicitArgOffset = 0;
3167 for (auto &Arg : F.args()) {
3168 if (!InPreloadSequence || !Arg.hasInRegAttr())
3169 break;
3170
3171 unsigned ArgIdx = Arg.getArgNo();
3172 // Don't preload non-original args or parts not in the current preload
3173 // sequence.
3174 if (InIdx < Ins.size() &&
3175 (!Ins[InIdx].isOrigArg() || Ins[InIdx].getOrigArgIndex() != ArgIdx))
3176 break;
3177
3178 for (; InIdx < Ins.size() && Ins[InIdx].isOrigArg() &&
3179 Ins[InIdx].getOrigArgIndex() == ArgIdx;
3180 InIdx++) {
3181 assert(ArgLocs[ArgIdx].isMemLoc());
3182 auto &ArgLoc = ArgLocs[InIdx];
3183 const Align KernelArgBaseAlign = Align(16);
3184 unsigned ArgOffset = ArgLoc.getLocMemOffset();
3185 Align Alignment = commonAlignment(KernelArgBaseAlign, ArgOffset);
3186 unsigned NumAllocSGPRs =
3187 alignTo(ArgLoc.getLocVT().getFixedSizeInBits(), 32) / 32;
3188
3189 // Fix alignment for hidden arguments.
3190 if (Arg.hasAttribute("amdgpu-hidden-argument")) {
3191 if (!AlignedForImplictArgs) {
3192 ImplicitArgOffset =
3193 alignTo(LastExplicitArgOffset,
3194 Subtarget->getAlignmentForImplicitArgPtr()) -
3195 LastExplicitArgOffset;
3196 AlignedForImplictArgs = true;
3197 }
3198 ArgOffset += ImplicitArgOffset;
3199 }
3200
3201 // Arg is preloaded into the previous SGPR.
3202 if (ArgLoc.getLocVT().getStoreSize() < 4 && Alignment < 4) {
3203 assert(InIdx >= 1 && "No previous SGPR");
3204 Info.getArgInfo().PreloadKernArgs[InIdx].Regs.push_back(
3205 Info.getArgInfo().PreloadKernArgs[InIdx - 1].Regs[0]);
3206 continue;
3207 }
3208
3209 unsigned Padding = ArgOffset - LastExplicitArgOffset;
3210 unsigned PaddingSGPRs = alignTo(Padding, 4) / 4;
3211 // Check for free user SGPRs for preloading.
3212 if (PaddingSGPRs + NumAllocSGPRs > SGPRInfo.getNumFreeUserSGPRs()) {
3213 InPreloadSequence = false;
3214 break;
3215 }
3216
3217 // Preload this argument.
3218 const TargetRegisterClass *RC =
3219 TRI.getSGPRClassForBitWidth(NumAllocSGPRs * 32);
3220 SmallVectorImpl<MCRegister> *PreloadRegs =
3221 Info.addPreloadedKernArg(TRI, RC, NumAllocSGPRs, InIdx, PaddingSGPRs);
3222
3223 if (PreloadRegs->size() > 1)
3224 RC = &AMDGPU::SGPR_32RegClass;
3225 for (auto &Reg : *PreloadRegs) {
3226 assert(Reg);
3227 MF.addLiveIn(Reg, RC);
3228 CCInfo.AllocateReg(Reg);
3229 }
3230
3231 LastExplicitArgOffset = NumAllocSGPRs * 4 + ArgOffset;
3232 }
3233 }
3234}
3235
3237 const SIRegisterInfo &TRI,
3238 SIMachineFunctionInfo &Info) const {
3239 // Always allocate this last since it is a synthetic preload.
3240 if (Info.hasLDSKernelId()) {
3241 Register Reg = Info.addLDSKernelId();
3242 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3243 CCInfo.AllocateReg(Reg);
3244 }
3245}
3246
3247// Allocate special input registers that are initialized per-wave.
3250 CallingConv::ID CallConv,
3251 bool IsShader) const {
3252 bool HasArchitectedSGPRs = Subtarget->hasArchitectedSGPRs();
3253 if (Subtarget->hasUserSGPRInit16BugInWave32() && !IsShader) {
3254 // Note: user SGPRs are handled by the front-end for graphics shaders
3255 // Pad up the used user SGPRs with dead inputs.
3256
3257 // TODO: NumRequiredSystemSGPRs computation should be adjusted appropriately
3258 // before enabling architected SGPRs for workgroup IDs.
3259 assert(!HasArchitectedSGPRs && "Unhandled feature for the subtarget");
3260
3261 unsigned CurrentUserSGPRs = Info.getNumUserSGPRs();
3262 // Note we do not count the PrivateSegmentWaveByteOffset. We do not want to
3263 // rely on it to reach 16 since if we end up having no stack usage, it will
3264 // not really be added.
3265 unsigned NumRequiredSystemSGPRs =
3266 Info.hasWorkGroupIDX() + Info.hasWorkGroupIDY() +
3267 Info.hasWorkGroupIDZ() + Info.hasWorkGroupInfo();
3268 for (unsigned i = NumRequiredSystemSGPRs + CurrentUserSGPRs; i < 16; ++i) {
3269 Register Reg = Info.addReservedUserSGPR();
3270 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3271 CCInfo.AllocateReg(Reg);
3272 }
3273 }
3274
3275 if (!HasArchitectedSGPRs) {
3276 if (Info.hasWorkGroupIDX()) {
3277 Register Reg = Info.addWorkGroupIDX();
3278 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3279 CCInfo.AllocateReg(Reg);
3280 }
3281
3282 if (Info.hasWorkGroupIDY()) {
3283 Register Reg = Info.addWorkGroupIDY();
3284 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3285 CCInfo.AllocateReg(Reg);
3286 }
3287
3288 if (Info.hasWorkGroupIDZ()) {
3289 Register Reg = Info.addWorkGroupIDZ();
3290 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3291 CCInfo.AllocateReg(Reg);
3292 }
3293 }
3294
3295 if (Info.hasWorkGroupInfo()) {
3296 Register Reg = Info.addWorkGroupInfo();
3297 MF.addLiveIn(Reg, &AMDGPU::SGPR_32RegClass);
3298 CCInfo.AllocateReg(Reg);
3299 }
3300
3301 if (Info.hasPrivateSegmentWaveByteOffset()) {
3302 // Scratch wave offset passed in system SGPR.
3303 unsigned PrivateSegmentWaveByteOffsetReg;
3304
3305 if (IsShader) {
3306 PrivateSegmentWaveByteOffsetReg =
3307 Info.getPrivateSegmentWaveByteOffsetSystemSGPR();
3308
3309 // This is true if the scratch wave byte offset doesn't have a fixed
3310 // location.
3311 if (PrivateSegmentWaveByteOffsetReg == AMDGPU::NoRegister) {
3312 PrivateSegmentWaveByteOffsetReg = findFirstFreeSGPR(CCInfo);
3313 Info.setPrivateSegmentWaveByteOffset(PrivateSegmentWaveByteOffsetReg);
3314 }
3315 } else
3316 PrivateSegmentWaveByteOffsetReg = Info.addPrivateSegmentWaveByteOffset();
3317
3318 MF.addLiveIn(PrivateSegmentWaveByteOffsetReg, &AMDGPU::SGPR_32RegClass);
3319 CCInfo.AllocateReg(PrivateSegmentWaveByteOffsetReg);
3320 }
3321
3322 assert(!Subtarget->hasUserSGPRInit16BugInWave32() || IsShader ||
3323 Info.getNumPreloadedSGPRs() >= 16);
3324}
3325
3327 MachineFunction &MF,
3328 const SIRegisterInfo &TRI,
3329 SIMachineFunctionInfo &Info) {
3330 // Now that we've figured out where the scratch register inputs are, see if
3331 // should reserve the arguments and use them directly.
3332 MachineFrameInfo &MFI = MF.getFrameInfo();
3333 bool HasStackObjects = MFI.hasStackObjects();
3334 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3335
3336 // Record that we know we have non-spill stack objects so we don't need to
3337 // check all stack objects later.
3338 if (HasStackObjects)
3339 Info.setHasNonSpillStackObjects(true);
3340
3341 // Everything live out of a block is spilled with fast regalloc, so it's
3342 // almost certain that spilling will be required.
3344 HasStackObjects = true;
3345
3346 // For now assume stack access is needed in any callee functions, so we need
3347 // the scratch registers to pass in.
3348 bool RequiresStackAccess = HasStackObjects || MFI.hasCalls();
3349
3350 if (!ST.hasFlatScratchEnabled()) {
3351 if (RequiresStackAccess && ST.isAmdHsaOrMesa(MF.getFunction())) {
3352 // If we have stack objects, we unquestionably need the private buffer
3353 // resource. For the Code Object V2 ABI, this will be the first 4 user
3354 // SGPR inputs. We can reserve those and use them directly.
3355
3356 Register PrivateSegmentBufferReg =
3358 Info.setScratchRSrcReg(PrivateSegmentBufferReg);
3359 } else {
3360 unsigned ReservedBufferReg = TRI.reservedPrivateSegmentBufferReg(MF);
3361 // We tentatively reserve the last registers (skipping the last registers
3362 // which may contain VCC, FLAT_SCR, and XNACK). After register allocation,
3363 // we'll replace these with the ones immediately after those which were
3364 // really allocated. In the prologue copies will be inserted from the
3365 // argument to these reserved registers.
3366
3367 // Without HSA, relocations are used for the scratch pointer and the
3368 // buffer resource setup is always inserted in the prologue. Scratch wave
3369 // offset is still in an input SGPR.
3370 Info.setScratchRSrcReg(ReservedBufferReg);
3371 }
3372 }
3373
3374 MachineRegisterInfo &MRI = MF.getRegInfo();
3375
3376 // For entry functions we have to set up the stack pointer if we use it,
3377 // whereas non-entry functions get this "for free". This means there is no
3378 // intrinsic advantage to using S32 over S34 in cases where we do not have
3379 // calls but do need a frame pointer (i.e. if we are requested to have one
3380 // because frame pointer elimination is disabled). To keep things simple we
3381 // only ever use S32 as the call ABI stack pointer, and so using it does not
3382 // imply we need a separate frame pointer.
3383 //
3384 // Try to use s32 as the SP, but move it if it would interfere with input
3385 // arguments. This won't work with calls though.
3386 //
3387 // FIXME: Move SP to avoid any possible inputs, or find a way to spill input
3388 // registers.
3389 if (!MRI.isLiveIn(AMDGPU::SGPR32)) {
3390 Info.setStackPtrOffsetReg(AMDGPU::SGPR32);
3391 } else {
3393
3394 if (MFI.hasCalls())
3395 report_fatal_error("call in graphics shader with too many input SGPRs");
3396
3397 for (unsigned Reg : AMDGPU::SGPR_32RegClass) {
3398 if (!MRI.isLiveIn(Reg)) {
3399 Info.setStackPtrOffsetReg(Reg);
3400 break;
3401 }
3402 }
3403
3404 if (Info.getStackPtrOffsetReg() == AMDGPU::SP_REG)
3405 report_fatal_error("failed to find register for SP");
3406 }
3407
3408 // hasFP should be accurate for entry functions even before the frame is
3409 // finalized, because it does not rely on the known stack size, only
3410 // properties like whether variable sized objects are present.
3411 if (ST.getFrameLowering()->hasFP(MF)) {
3412 Info.setFrameOffsetReg(AMDGPU::SGPR33);
3413 }
3414}
3415
3418 return !Info->isEntryFunction();
3419}
3420
3422
3424 MachineBasicBlock *Entry,
3425 const SmallVectorImpl<MachineBasicBlock *> &Exits) const {
3427
3428 const MCPhysReg *IStart = TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
3429 if (!IStart)
3430 return;
3431
3432 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3433 MachineRegisterInfo *MRI = &Entry->getParent()->getRegInfo();
3434 MachineBasicBlock::iterator MBBI = Entry->begin();
3435 for (const MCPhysReg *I = IStart; *I; ++I) {
3436 const TargetRegisterClass *RC = nullptr;
3437 if (AMDGPU::SReg_64RegClass.contains(*I))
3438 RC = &AMDGPU::SGPR_64RegClass;
3439 else if (AMDGPU::SReg_32RegClass.contains(*I))
3440 RC = &AMDGPU::SGPR_32RegClass;
3441 else
3442 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3443
3444 Register NewVR = MRI->createVirtualRegister(RC);
3445 // Create copy from CSR to a virtual register.
3446 Entry->addLiveIn(*I);
3447 BuildMI(*Entry, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY), NewVR)
3448 .addReg(*I);
3449
3450 // Insert the copy-back instructions right before the terminator.
3451 for (auto *Exit : Exits)
3452 BuildMI(*Exit, Exit->getFirstTerminator(), DebugLoc(),
3453 TII->get(TargetOpcode::COPY), *I)
3454 .addReg(NewVR);
3455 }
3456}
3457
3459 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
3460 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3461 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
3463
3465 const Function &Fn = MF.getFunction();
3468 bool IsError = false;
3469
3470 if (Subtarget->isAmdHsaOS() && AMDGPU::isGraphics(CallConv)) {
3472 Fn, "unsupported non-compute shaders with HSA", DL.getDebugLoc()));
3473 IsError = true;
3474 }
3475
3478 BitVector Skipped(Fn.arg_size());
3479 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
3480 *DAG.getContext());
3481
3482 bool IsGraphics = AMDGPU::isGraphics(CallConv);
3483 bool IsKernel = AMDGPU::isKernel(CallConv);
3484 bool IsEntryFunc = AMDGPU::isEntryFunctionCC(CallConv);
3485
3486 if (IsGraphics) {
3487 const GCNUserSGPRUsageInfo &UserSGPRInfo = Info->getUserSGPRInfo();
3488 assert(!UserSGPRInfo.hasDispatchPtr() &&
3489 !UserSGPRInfo.hasKernargSegmentPtr() && !Info->hasWorkGroupInfo() &&
3490 !Info->hasLDSKernelId() && !Info->hasWorkItemIDX() &&
3491 !Info->hasWorkItemIDY() && !Info->hasWorkItemIDZ());
3492 (void)UserSGPRInfo;
3493 if (!Subtarget->hasFlatScratchEnabled())
3494 assert(!UserSGPRInfo.hasFlatScratchInit());
3495 if ((CallConv != CallingConv::AMDGPU_CS &&
3496 CallConv != CallingConv::AMDGPU_Gfx &&
3497 CallConv != CallingConv::AMDGPU_Gfx_WholeWave) ||
3498 !Subtarget->hasArchitectedSGPRs())
3499 assert(!Info->hasWorkGroupIDX() && !Info->hasWorkGroupIDY() &&
3500 !Info->hasWorkGroupIDZ());
3501 }
3502
3503 bool IsWholeWaveFunc = Info->isWholeWaveFunction();
3504
3505 if (CallConv == CallingConv::AMDGPU_PS) {
3506 processPSInputArgs(Splits, CallConv, Ins, Skipped, FType, Info);
3507
3508 // At least one interpolation mode must be enabled or else the GPU will
3509 // hang.
3510 //
3511 // Check PSInputAddr instead of PSInputEnable. The idea is that if the user
3512 // set PSInputAddr, the user wants to enable some bits after the compilation
3513 // based on run-time states. Since we can't know what the final PSInputEna
3514 // will look like, so we shouldn't do anything here and the user should take
3515 // responsibility for the correct programming.
3516 //
3517 // Otherwise, the following restrictions apply:
3518 // - At least one of PERSP_* (0xF) or LINEAR_* (0x70) must be enabled.
3519 // - If POS_W_FLOAT (11) is enabled, at least one of PERSP_* must be
3520 // enabled too.
3521 if ((Info->getPSInputAddr() & 0x7F) == 0 ||
3522 ((Info->getPSInputAddr() & 0xF) == 0 && Info->isPSInputAllocated(11))) {
3523 CCInfo.AllocateReg(AMDGPU::VGPR0);
3524 CCInfo.AllocateReg(AMDGPU::VGPR1);
3525 Info->markPSInputAllocated(0);
3526 Info->markPSInputEnabled(0);
3527 }
3528 if (Subtarget->isAmdPalOS()) {
3529 // For isAmdPalOS, the user does not enable some bits after compilation
3530 // based on run-time states; the register values being generated here are
3531 // the final ones set in hardware. Therefore we need to apply the
3532 // workaround to PSInputAddr and PSInputEnable together. (The case where
3533 // a bit is set in PSInputAddr but not PSInputEnable is where the
3534 // frontend set up an input arg for a particular interpolation mode, but
3535 // nothing uses that input arg. Really we should have an earlier pass
3536 // that removes such an arg.)
3537 unsigned PsInputBits = Info->getPSInputAddr() & Info->getPSInputEnable();
3538 if ((PsInputBits & 0x7F) == 0 ||
3539 ((PsInputBits & 0xF) == 0 && (PsInputBits >> 11 & 1)))
3540 Info->markPSInputEnabled(llvm::countr_zero(Info->getPSInputAddr()));
3541 }
3542 } else if (IsKernel) {
3543 assert(Info->hasWorkGroupIDX() && Info->hasWorkItemIDX());
3544 } else {
3545 Splits.append(IsWholeWaveFunc ? std::next(Ins.begin()) : Ins.begin(),
3546 Ins.end());
3547 }
3548
3549 if (IsKernel)
3550 analyzeFormalArgumentsCompute(CCInfo, Ins);
3551
3552 if (IsEntryFunc) {
3553 allocateSpecialEntryInputVGPRs(CCInfo, MF, *TRI, *Info);
3554 allocateHSAUserSGPRs(CCInfo, MF, *TRI, *Info);
3555 if (IsKernel && Subtarget->hasKernargPreload())
3556 allocatePreloadKernArgSGPRs(CCInfo, ArgLocs, Ins, MF, *TRI, *Info);
3557
3558 allocateLDSKernelId(CCInfo, MF, *TRI, *Info);
3559 } else if (!IsGraphics) {
3560 // For the fixed ABI, pass workitem IDs in the last argument register.
3561 allocateSpecialInputVGPRsFixed(CCInfo, MF, *TRI, *Info);
3562
3563 // FIXME: Sink this into allocateSpecialInputSGPRs
3564 if (!Subtarget->hasFlatScratchEnabled())
3565 CCInfo.AllocateReg(Info->getScratchRSrcReg());
3566
3567 allocateSpecialInputSGPRs(CCInfo, MF, *TRI, *Info);
3568 }
3569
3570 if (!IsKernel) {
3571 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, isVarArg);
3572 CCInfo.AnalyzeFormalArguments(Splits, AssignFn);
3573
3574 // This assumes the registers are allocated by CCInfo in ascending order
3575 // with no gaps.
3576 Info->setNumWaveDispatchSGPRs(
3577 CCInfo.getFirstUnallocated(AMDGPU::SGPR_32RegClass.getRegisters()));
3578 Info->setNumWaveDispatchVGPRs(
3579 CCInfo.getFirstUnallocated(AMDGPU::VGPR_32RegClass.getRegisters()));
3580 } else if (Info->getNumKernargPreloadedSGPRs()) {
3581 Info->setNumWaveDispatchSGPRs(Info->getNumUserSGPRs());
3582 }
3583
3585
3586 if (IsWholeWaveFunc) {
3587 SDValue Setup = DAG.getNode(AMDGPUISD::WHOLE_WAVE_SETUP, DL,
3588 {MVT::i1, MVT::Other}, Chain);
3589 InVals.push_back(Setup.getValue(0));
3590 Chains.push_back(Setup.getValue(1));
3591 }
3592
3593 // FIXME: This is the minimum kernel argument alignment. We should improve
3594 // this to the maximum alignment of the arguments.
3595 //
3596 // FIXME: Alignment of explicit arguments totally broken with non-0 explicit
3597 // kern arg offset.
3598 const Align KernelArgBaseAlign = Align(16);
3599
3600 for (unsigned i = IsWholeWaveFunc ? 1 : 0, e = Ins.size(), ArgIdx = 0; i != e;
3601 ++i) {
3602 const ISD::InputArg &Arg = Ins[i];
3603 if ((Arg.isOrigArg() && Skipped[Arg.getOrigArgIndex()]) || IsError) {
3604 InVals.push_back(DAG.getPOISON(Arg.VT));
3605 continue;
3606 }
3607
3608 CCValAssign &VA = ArgLocs[ArgIdx++];
3609 MVT VT = VA.getLocVT();
3610
3611 if (IsEntryFunc && VA.isMemLoc()) {
3612 VT = Ins[i].VT;
3613 EVT MemVT = VA.getLocVT();
3614
3615 const uint64_t Offset = VA.getLocMemOffset();
3616 Align Alignment = commonAlignment(KernelArgBaseAlign, Offset);
3617
3618 if (Arg.Flags.isByRef()) {
3619 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, Chain, Offset);
3620
3621 const GCNTargetMachine &TM =
3622 static_cast<const GCNTargetMachine &>(getTargetMachine());
3623 if (!TM.isNoopAddrSpaceCast(AMDGPUAS::CONSTANT_ADDRESS,
3624 Arg.Flags.getPointerAddrSpace())) {
3627 }
3628
3629 InVals.push_back(Ptr);
3630 continue;
3631 }
3632
3633 SDValue NewArg;
3634 if (Arg.isOrigArg() && Info->getArgInfo().PreloadKernArgs.count(i)) {
3635 if (MemVT.getStoreSize() < 4 && Alignment < 4) {
3636 // In this case the argument is packed into the previous preload SGPR.
3637 int64_t AlignDownOffset = alignDown(Offset, 4);
3638 int64_t OffsetDiff = Offset - AlignDownOffset;
3639 EVT IntVT = MemVT.changeTypeToInteger();
3640
3641 const SIMachineFunctionInfo *Info =
3644 Register Reg =
3645 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs[0];
3646
3647 assert(Reg);
3648 Register VReg = MRI.getLiveInVirtReg(Reg);
3649 SDValue Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3650
3651 SDValue ShiftAmt = DAG.getConstant(OffsetDiff * 8, DL, MVT::i32);
3652 SDValue Extract = DAG.getNode(ISD::SRL, DL, MVT::i32, Copy, ShiftAmt);
3653
3654 SDValue ArgVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Extract);
3655 ArgVal = DAG.getNode(ISD::BITCAST, DL, MemVT, ArgVal);
3656 NewArg = convertArgType(DAG, VT, MemVT, DL, ArgVal,
3657 Ins[i].Flags.isSExt(), &Ins[i]);
3658
3659 NewArg = DAG.getMergeValues({NewArg, Copy.getValue(1)}, DL);
3660 } else {
3661 const SIMachineFunctionInfo *Info =
3664 const SmallVectorImpl<MCRegister> &PreloadRegs =
3665 Info->getArgInfo().PreloadKernArgs.find(i)->getSecond().Regs;
3666
3667 SDValue Copy;
3668 if (PreloadRegs.size() == 1) {
3669 Register VReg = MRI.getLiveInVirtReg(PreloadRegs[0]);
3670 const TargetRegisterClass *RC = MRI.getRegClass(VReg);
3671 NewArg = DAG.getCopyFromReg(
3672 Chain, DL, VReg,
3674 TRI->getRegSizeInBits(*RC)));
3675
3676 } else {
3677 // If the kernarg alignment does not match the alignment of the SGPR
3678 // tuple RC that can accommodate this argument, it will be built up
3679 // via copies from from the individual SGPRs that the argument was
3680 // preloaded to.
3682 for (auto Reg : PreloadRegs) {
3683 Register VReg = MRI.getLiveInVirtReg(Reg);
3684 Copy = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i32);
3685 Elts.push_back(Copy);
3686 }
3687 NewArg =
3688 DAG.getBuildVector(EVT::getVectorVT(*DAG.getContext(), MVT::i32,
3689 PreloadRegs.size()),
3690 DL, Elts);
3691 }
3692
3693 // If the argument was preloaded to multiple consecutive 32-bit
3694 // registers because of misalignment between addressable SGPR tuples
3695 // and the argument size, we can still assume that because of kernarg
3696 // segment alignment restrictions that NewArg's size is the same as
3697 // MemVT and just do a bitcast. If MemVT is less than 32-bits we add a
3698 // truncate since we cannot preload to less than a single SGPR and the
3699 // MemVT may be smaller.
3700 EVT MemVTInt =
3702 if (MemVT.bitsLT(NewArg.getSimpleValueType()))
3703 NewArg = DAG.getNode(ISD::TRUNCATE, DL, MemVTInt, NewArg);
3704
3705 NewArg = DAG.getBitcast(MemVT, NewArg);
3706 NewArg = convertArgType(DAG, VT, MemVT, DL, NewArg,
3707 Ins[i].Flags.isSExt(), &Ins[i]);
3708 NewArg = DAG.getMergeValues({NewArg, Chain}, DL);
3709 }
3710 } else {
3711 // Hidden arguments that are in the kernel signature must be preloaded
3712 // to user SGPRs. Print a diagnostic error if a hidden argument is in
3713 // the argument list and is not preloaded.
3714 if (Arg.isOrigArg()) {
3715 Argument *OrigArg = Fn.getArg(Arg.getOrigArgIndex());
3716 if (OrigArg->hasAttribute("amdgpu-hidden-argument")) {
3718 *OrigArg->getParent(),
3719 "hidden argument in kernel signature was not preloaded",
3720 DL.getDebugLoc()));
3721 }
3722 }
3723
3724 NewArg =
3725 lowerKernargMemParameter(DAG, VT, MemVT, DL, Chain, Offset,
3726 Alignment, Ins[i].Flags.isSExt(), &Ins[i]);
3727 }
3728 Chains.push_back(NewArg.getValue(1));
3729
3730 auto *ParamTy =
3731 dyn_cast<PointerType>(FType->getParamType(Ins[i].getOrigArgIndex()));
3732 if (Subtarget->getGeneration() == AMDGPUSubtarget::SOUTHERN_ISLANDS &&
3733 ParamTy &&
3734 (ParamTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
3735 ParamTy->getAddressSpace() == AMDGPUAS::REGION_ADDRESS)) {
3736 // On SI local pointers are just offsets into LDS, so they are always
3737 // less than 16-bits. On CI and newer they could potentially be
3738 // real pointers, so we can't guarantee their size.
3739 NewArg = DAG.getNode(ISD::AssertZext, DL, NewArg.getValueType(), NewArg,
3740 DAG.getValueType(MVT::i16));
3741 }
3742
3743 InVals.push_back(NewArg);
3744 continue;
3745 }
3746 if (!IsEntryFunc && VA.isMemLoc()) {
3747 SDValue Val = lowerStackParameter(DAG, VA, DL, Chain, Arg);
3748 InVals.push_back(Val);
3749 if (!Arg.Flags.isByVal())
3750 Chains.push_back(Val.getValue(1));
3751 continue;
3752 }
3753
3754 assert(VA.isRegLoc() && "Parameter must be in a register!");
3755
3756 Register Reg = VA.getLocReg();
3757 const TargetRegisterClass *RC = nullptr;
3758 if (AMDGPU::VGPR_32RegClass.contains(Reg))
3759 RC = &AMDGPU::VGPR_32RegClass;
3760 else if (AMDGPU::SGPR_32RegClass.contains(Reg))
3761 RC = &AMDGPU::SGPR_32RegClass;
3762 else
3763 llvm_unreachable("Unexpected register class in LowerFormalArguments!");
3764
3765 Reg = MF.addLiveIn(Reg, RC);
3766 SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, VT);
3767 if (Arg.Flags.isInReg() && RC == &AMDGPU::VGPR_32RegClass) {
3768 // FIXME: Need to forward the chains created by `CopyFromReg`s, make sure
3769 // they will read physical regs before any side effect instructions.
3770 SDValue ReadFirstLane =
3771 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3773 ReadFirstLane, Val);
3774 }
3775
3776 if (Arg.Flags.isSRet()) {
3777 // The return object should be reasonably addressable.
3778 Val = annotateStackObjectPointer(Val, DAG, DL,
3780 }
3781
3782 Val = convertABITypeToValueType(DAG, Val, VA, DL);
3783 InVals.push_back(Val);
3784 }
3785
3786 // Start adding system SGPRs.
3787 if (IsEntryFunc)
3788 allocateSystemSGPRs(CCInfo, MF, *Info, CallConv, IsGraphics);
3789
3790 unsigned StackArgSize = CCInfo.getStackSize();
3791 Info->setBytesInStackArgArea(StackArgSize);
3792
3793 return Chains.empty() ? Chain
3794 : DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
3795}
3796
3797// TODO: If return values can't fit in registers, we should return as many as
3798// possible in registers before passing on stack.
3800 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
3801 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
3802 const Type *RetTy) const {
3803 // Replacing returns with sret/stack usage doesn't make sense for shaders.
3804 // FIXME: Also sort of a workaround for custom vector splitting in LowerReturn
3805 // for shaders. Vector types should be explicitly handled by CC.
3806 if (AMDGPU::isEntryFunctionCC(CallConv))
3807 return true;
3808
3810 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
3811 if (!CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)))
3812 return false;
3813
3814 // We must use the stack if return would require unavailable registers.
3815 unsigned MaxNumVGPRs = Subtarget->getMaxNumVGPRs(MF);
3816 unsigned TotalNumVGPRs = Subtarget->getAddressableNumArchVGPRs();
3817 for (unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i)
3818 if (CCInfo.isAllocated(AMDGPU::VGPR_32RegClass.getRegister(i)))
3819 return false;
3820
3821 return true;
3822}
3823
3824SDValue
3826 bool isVarArg,
3828 const SmallVectorImpl<SDValue> &OutVals,
3829 const SDLoc &DL, SelectionDAG &DAG) const {
3833
3834 if (AMDGPU::isKernel(CallConv)) {
3835 return AMDGPUTargetLowering::LowerReturn(Chain, CallConv, isVarArg, Outs,
3836 OutVals, DL, DAG);
3837 }
3838
3839 bool IsShader = AMDGPU::isShader(CallConv);
3840
3841 Info->setIfReturnsVoid(Outs.empty());
3842 bool IsWaveEnd = Info->returnsVoid() && IsShader;
3843
3844 // CCValAssign - represent the assignment of the return value to a location.
3846
3847 // CCState - Info about the registers and stack slots.
3848 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
3849 *DAG.getContext());
3850
3851 // Analyze outgoing return values.
3852 CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, isVarArg));
3853
3854 SDValue Glue;
3856 RetOps.push_back(Chain); // Operand #0 = Chain (updated below)
3857
3858 SDValue ReadFirstLane =
3859 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
3860 // Copy the result values into the output registers.
3861 for (unsigned I = 0, RealRVLocIdx = 0, E = RVLocs.size(); I != E;
3862 ++I, ++RealRVLocIdx) {
3863 CCValAssign &VA = RVLocs[I];
3864 assert(VA.isRegLoc() && "Can only return in registers!");
3865 // TODO: Partially return in registers if return values don't fit.
3866 SDValue Arg = OutVals[RealRVLocIdx];
3867
3868 // Copied from other backends.
3869 switch (VA.getLocInfo()) {
3870 case CCValAssign::Full:
3871 break;
3872 case CCValAssign::BCvt:
3873 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
3874 break;
3875 case CCValAssign::SExt:
3876 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
3877 break;
3878 case CCValAssign::ZExt:
3879 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
3880 break;
3881 case CCValAssign::AExt:
3882 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
3883 break;
3884 default:
3885 llvm_unreachable("Unknown loc info!");
3886 }
3887 if (TRI->isSGPRPhysReg(VA.getLocReg()))
3889 ReadFirstLane, Arg);
3890 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Glue);
3891 Glue = Chain.getValue(1);
3892 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
3893 }
3894
3895 // FIXME: Does sret work properly?
3896 if (!Info->isEntryFunction()) {
3897 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
3898 const MCPhysReg *I =
3899 TRI->getCalleeSavedRegsViaCopy(&DAG.getMachineFunction());
3900 if (I) {
3901 for (; *I; ++I) {
3902 if (AMDGPU::SReg_64RegClass.contains(*I))
3903 RetOps.push_back(DAG.getRegister(*I, MVT::i64));
3904 else if (AMDGPU::SReg_32RegClass.contains(*I))
3905 RetOps.push_back(DAG.getRegister(*I, MVT::i32));
3906 else
3907 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
3908 }
3909 }
3910 }
3911
3912 // Update chain and glue.
3913 RetOps[0] = Chain;
3914 if (Glue.getNode())
3915 RetOps.push_back(Glue);
3916
3917 unsigned Opc = AMDGPUISD::ENDPGM;
3918 if (!IsWaveEnd)
3919 Opc = Info->isWholeWaveFunction() ? AMDGPUISD::WHOLE_WAVE_RETURN
3920 : IsShader ? AMDGPUISD::RETURN_TO_EPILOG
3921 : AMDGPUISD::RET_GLUE;
3922 return DAG.getNode(Opc, DL, MVT::Other, RetOps);
3923}
3924
3926 SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
3927 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3928 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, bool IsThisReturn,
3929 SDValue ThisVal) const {
3930 CCAssignFn *RetCC = CCAssignFnForReturn(CallConv, IsVarArg);
3931
3932 // Assign locations to each value returned by this call.
3934 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
3935 *DAG.getContext());
3936 CCInfo.AnalyzeCallResult(Ins, RetCC);
3937
3938 // Copy all of the result registers out of their specified physreg.
3939 for (CCValAssign VA : RVLocs) {
3940 SDValue Val;
3941
3942 if (VA.isRegLoc()) {
3943 Val =
3944 DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), InGlue);
3945 Chain = Val.getValue(1);
3946 InGlue = Val.getValue(2);
3947 } else if (VA.isMemLoc()) {
3948 report_fatal_error("TODO: return values in memory");
3949 } else
3950 llvm_unreachable("unknown argument location type");
3951
3952 switch (VA.getLocInfo()) {
3953 case CCValAssign::Full:
3954 break;
3955 case CCValAssign::BCvt:
3956 Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
3957 break;
3958 case CCValAssign::ZExt:
3959 Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val,
3960 DAG.getValueType(VA.getValVT()));
3961 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
3962 break;
3963 case CCValAssign::SExt:
3964 Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val,
3965 DAG.getValueType(VA.getValVT()));
3966 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
3967 break;
3968 case CCValAssign::AExt:
3969 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
3970 break;
3971 default:
3972 llvm_unreachable("Unknown loc info!");
3973 }
3974
3975 InVals.push_back(Val);
3976 }
3977
3978 return Chain;
3979}
3980
3981// Add code to pass special inputs required depending on used features separate
3982// from the explicit user arguments present in the IR.
3984 CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info,
3985 SmallVectorImpl<std::pair<unsigned, SDValue>> &RegsToPass,
3986 SmallVectorImpl<SDValue> &MemOpChains, SDValue Chain) const {
3987 // If we don't have a call site, this was a call inserted by
3988 // legalization. These can never use special inputs.
3989 if (!CLI.CB)
3990 return;
3991
3992 SelectionDAG &DAG = CLI.DAG;
3993 const SDLoc &DL = CLI.DL;
3994 const Function &F = DAG.getMachineFunction().getFunction();
3995
3996 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
3997 const AMDGPUFunctionArgInfo &CallerArgInfo = Info.getArgInfo();
3998
3999 const AMDGPUFunctionArgInfo &CalleeArgInfo =
4001
4002 // TODO: Unify with private memory register handling. This is complicated by
4003 // the fact that at least in kernels, the input argument is not necessarily
4004 // in the same location as the input.
4005 // clang-format off
4006 static constexpr std::pair<AMDGPUFunctionArgInfo::PreloadedValue,
4007 std::array<StringLiteral, 2>> ImplicitAttrs[] = {
4008 {AMDGPUFunctionArgInfo::DISPATCH_PTR, {"amdgpu-no-dispatch-ptr", ""}},
4009 {AMDGPUFunctionArgInfo::QUEUE_PTR, {"amdgpu-no-queue-ptr", ""}},
4010 {AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR, {"amdgpu-no-implicitarg-ptr", ""}},
4011 {AMDGPUFunctionArgInfo::DISPATCH_ID, {"amdgpu-no-dispatch-id", ""}},
4012 {AMDGPUFunctionArgInfo::WORKGROUP_ID_X, {"amdgpu-no-workgroup-id-x", "amdgpu-no-cluster-id-x"}},
4013 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Y, {"amdgpu-no-workgroup-id-y", "amdgpu-no-cluster-id-y"}},
4014 {AMDGPUFunctionArgInfo::WORKGROUP_ID_Z, {"amdgpu-no-workgroup-id-z", "amdgpu-no-cluster-id-z"}},
4015 {AMDGPUFunctionArgInfo::LDS_KERNEL_ID, {"amdgpu-no-lds-kernel-id", ""}},
4016 };
4017 // clang-format on
4018
4019 for (auto [InputID, Attrs] : ImplicitAttrs) {
4020 // If the callee does not use the attribute value, skip copying the value.
4021 if (all_of(Attrs, [&](StringRef Attr) {
4022 return Attr.empty() || CLI.CB->hasFnAttr(Attr);
4023 }))
4024 continue;
4025
4026 const auto [OutgoingArg, ArgRC, ArgTy] =
4027 CalleeArgInfo.getPreloadedValue(InputID);
4028 if (!OutgoingArg)
4029 continue;
4030
4031 const auto [IncomingArg, IncomingArgRC, Ty] =
4032 CallerArgInfo.getPreloadedValue(InputID);
4033 assert(IncomingArgRC == ArgRC);
4034
4035 // All special arguments are ints for now.
4036 EVT ArgVT = TRI->getSpillSize(*ArgRC) == 8 ? MVT::i64 : MVT::i32;
4037 SDValue InputReg;
4038
4039 if (IncomingArg) {
4040 InputReg = loadInputValue(DAG, ArgRC, ArgVT, DL, *IncomingArg);
4041 } else if (InputID == AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR) {
4042 // The implicit arg ptr is special because it doesn't have a corresponding
4043 // input for kernels, and is computed from the kernarg segment pointer.
4044 InputReg = getImplicitArgPtr(DAG, DL);
4045 } else if (InputID == AMDGPUFunctionArgInfo::LDS_KERNEL_ID) {
4046 std::optional<uint32_t> Id =
4048 if (Id.has_value()) {
4049 InputReg = DAG.getConstant(*Id, DL, ArgVT);
4050 } else {
4051 InputReg = DAG.getPOISON(ArgVT);
4052 }
4053 } else {
4054 // We may have proven the input wasn't needed, although the ABI is
4055 // requiring it. We just need to allocate the register appropriately.
4056 InputReg = DAG.getPOISON(ArgVT);
4057 }
4058
4059 if (OutgoingArg->isRegister()) {
4060 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4061 if (!CCInfo.AllocateReg(OutgoingArg->getRegister()))
4062 report_fatal_error("failed to allocate implicit input argument");
4063 } else {
4064 unsigned SpecialArgOffset =
4065 CCInfo.AllocateStack(ArgVT.getStoreSize(), Align(4));
4066 SDValue ArgStore =
4067 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4068 MemOpChains.push_back(ArgStore);
4069 }
4070 }
4071
4072 // Pack workitem IDs into a single register or pass it as is if already
4073 // packed.
4074
4075 auto [OutgoingArg, ArgRC, Ty] =
4077 if (!OutgoingArg)
4078 std::tie(OutgoingArg, ArgRC, Ty) =
4080 if (!OutgoingArg)
4081 std::tie(OutgoingArg, ArgRC, Ty) =
4083 if (!OutgoingArg)
4084 return;
4085
4086 const ArgDescriptor *IncomingArgX = std::get<0>(
4088 const ArgDescriptor *IncomingArgY = std::get<0>(
4090 const ArgDescriptor *IncomingArgZ = std::get<0>(
4092
4093 SDValue InputReg;
4094 SDLoc SL;
4095
4096 const bool NeedWorkItemIDX = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-x");
4097 const bool NeedWorkItemIDY = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-y");
4098 const bool NeedWorkItemIDZ = !CLI.CB->hasFnAttr("amdgpu-no-workitem-id-z");
4099
4100 // If incoming ids are not packed we need to pack them.
4101 if (IncomingArgX && !IncomingArgX->isMasked() && CalleeArgInfo.WorkItemIDX &&
4102 NeedWorkItemIDX) {
4103 if (Subtarget->getMaxWorkitemID(F, 0) != 0) {
4104 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgX);
4105 } else {
4106 InputReg = DAG.getConstant(0, DL, MVT::i32);
4107 }
4108 }
4109
4110 if (IncomingArgY && !IncomingArgY->isMasked() && CalleeArgInfo.WorkItemIDY &&
4111 NeedWorkItemIDY && Subtarget->getMaxWorkitemID(F, 1) != 0) {
4112 SDValue Y = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgY);
4113 Y = DAG.getNode(ISD::SHL, SL, MVT::i32, Y,
4114 DAG.getShiftAmountConstant(10, MVT::i32, SL));
4115 InputReg = InputReg.getNode()
4116 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Y)
4117 : Y;
4118 }
4119
4120 if (IncomingArgZ && !IncomingArgZ->isMasked() && CalleeArgInfo.WorkItemIDZ &&
4121 NeedWorkItemIDZ && Subtarget->getMaxWorkitemID(F, 2) != 0) {
4122 SDValue Z = loadInputValue(DAG, ArgRC, MVT::i32, DL, *IncomingArgZ);
4123 Z = DAG.getNode(ISD::SHL, SL, MVT::i32, Z,
4124 DAG.getShiftAmountConstant(20, MVT::i32, SL));
4125 InputReg = InputReg.getNode()
4126 ? DAG.getNode(ISD::OR, SL, MVT::i32, InputReg, Z)
4127 : Z;
4128 }
4129
4130 if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) {
4131 if (!IncomingArgX && !IncomingArgY && !IncomingArgZ) {
4132 // We're in a situation where the outgoing function requires the workitem
4133 // ID, but the calling function does not have it (e.g a graphics function
4134 // calling a C calling convention function). This is illegal, but we need
4135 // to produce something.
4136 InputReg = DAG.getPOISON(MVT::i32);
4137 } else {
4138 // Workitem ids are already packed, any of present incoming arguments
4139 // will carry all required fields.
4140 ArgDescriptor IncomingArg =
4141 ArgDescriptor::createArg(IncomingArgX ? *IncomingArgX
4142 : IncomingArgY ? *IncomingArgY
4143 : *IncomingArgZ,
4144 ~0u);
4145 InputReg = loadInputValue(DAG, ArgRC, MVT::i32, DL, IncomingArg);
4146 }
4147 }
4148
4149 if (OutgoingArg->isRegister()) {
4150 if (InputReg)
4151 RegsToPass.emplace_back(OutgoingArg->getRegister(), InputReg);
4152
4153 CCInfo.AllocateReg(OutgoingArg->getRegister());
4154 } else {
4155 unsigned SpecialArgOffset = CCInfo.AllocateStack(4, Align(4));
4156 if (InputReg) {
4157 SDValue ArgStore =
4158 storeStackInputValue(DAG, DL, Chain, InputReg, SpecialArgOffset);
4159 MemOpChains.push_back(ArgStore);
4160 }
4161 }
4162}
4163
4165 SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg,
4167 const SmallVectorImpl<SDValue> &OutVals,
4168 const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const {
4169 if (AMDGPU::isChainCC(CalleeCC))
4170 return true;
4171
4172 if (!AMDGPU::mayTailCallThisCC(CalleeCC))
4173 return false;
4174
4175 // For a divergent call target, we need to do a waterfall loop over the
4176 // possible callees which precludes us from using a simple jump.
4177 if (Callee->isDivergent())
4178 return false;
4179
4181 const Function &CallerF = MF.getFunction();
4182 CallingConv::ID CallerCC = CallerF.getCallingConv();
4184 const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC);
4185
4186 // Kernels aren't callable, and don't have a live in return address so it
4187 // doesn't make sense to do a tail call with entry functions.
4188 if (!CallerPreserved)
4189 return false;
4190
4191 bool CCMatch = CallerCC == CalleeCC;
4192
4194 if (AMDGPU::canGuaranteeTCO(CalleeCC) && CCMatch)
4195 return true;
4196 return false;
4197 }
4198
4199 // TODO: Can we handle var args?
4200 if (IsVarArg)
4201 return false;
4202
4203 for (const Argument &Arg : CallerF.args()) {
4204 if (Arg.hasByValAttr())
4205 return false;
4206 }
4207
4208 LLVMContext &Ctx = *DAG.getContext();
4209
4210 // Check that the call results are passed in the same way.
4211 if (!CCState::resultsCompatible(CalleeCC, CallerCC, MF, Ctx, Ins,
4212 CCAssignFnForCall(CalleeCC, IsVarArg),
4213 CCAssignFnForCall(CallerCC, IsVarArg)))
4214 return false;
4215
4216 // The callee has to preserve all registers the caller needs to preserve.
4217 if (!CCMatch) {
4218 const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC);
4219 if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
4220 return false;
4221 }
4222
4223 // Nothing more to check if the callee is taking no arguments.
4224 if (Outs.empty())
4225 return true;
4226
4228 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, Ctx);
4229
4230 // FIXME: We are not allocating special input registers, so we will be
4231 // deciding based on incorrect register assignments.
4232 CCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CalleeCC, IsVarArg));
4233
4234 const SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
4235 // If the stack arguments for this call do not fit into our own save area then
4236 // the call cannot be made tail.
4237 // TODO: Is this really necessary?
4238 if (CCInfo.getStackSize() > FuncInfo->getBytesInStackArgArea())
4239 return false;
4240
4241 for (const auto &[CCVA, ArgVal] : zip_equal(ArgLocs, OutVals)) {
4242 // FIXME: What about inreg arguments that end up passed in memory?
4243 if (!CCVA.isRegLoc())
4244 continue;
4245
4246 // If we are passing an argument in an SGPR, and the value is divergent,
4247 // this call requires a waterfall loop.
4248 if (ArgVal->isDivergent() && TRI->isSGPRPhysReg(CCVA.getLocReg())) {
4249 LLVM_DEBUG(
4250 dbgs() << "Cannot tail call due to divergent outgoing argument in "
4251 << printReg(CCVA.getLocReg(), TRI) << '\n');
4252 return false;
4253 }
4254 }
4255
4256 const MachineRegisterInfo &MRI = MF.getRegInfo();
4257 return parametersInCSRMatch(MRI, CallerPreserved, ArgLocs, OutVals);
4258}
4259
4261 if (!CI->isTailCall())
4262 return false;
4263
4264 const Function *ParentFn = CI->getFunction();
4266 return false;
4267 return true;
4268}
4269
4270namespace {
4271// Chain calls have special arguments that we need to handle. These are
4272// tagging along at the end of the arguments list(s), after the SGPR and VGPR
4273// arguments (index 0 and 1 respectively).
4274enum ChainCallArgIdx {
4275 Exec = 2,
4276 Flags,
4277 NumVGPRs,
4278 FallbackExec,
4279 FallbackCallee
4280};
4281} // anonymous namespace
4282
4283// The wave scratch offset register is used as the global base pointer.
4285 SmallVectorImpl<SDValue> &InVals) const {
4286 CallingConv::ID CallConv = CLI.CallConv;
4287 bool IsChainCallConv = AMDGPU::isChainCC(CallConv);
4288
4289 SelectionDAG &DAG = CLI.DAG;
4290
4291 const SDLoc &DL = CLI.DL;
4292 SDValue Chain = CLI.Chain;
4293 SDValue Callee = CLI.Callee;
4294
4295 llvm::SmallVector<SDValue, 6> ChainCallSpecialArgs;
4296 bool UsesDynamicVGPRs = false;
4297 if (IsChainCallConv) {
4298 // The last arguments should be the value that we need to put in EXEC,
4299 // followed by the flags and any other arguments with special meanings.
4300 // Pop them out of CLI.Outs and CLI.OutVals before we do any processing so
4301 // we don't treat them like the "real" arguments.
4302 auto RequestedExecIt =
4303 llvm::find_if(CLI.Outs, [](const ISD::OutputArg &Arg) {
4304 return Arg.OrigArgIndex == 2;
4305 });
4306 assert(RequestedExecIt != CLI.Outs.end() && "No node for EXEC");
4307
4308 size_t SpecialArgsBeginIdx = RequestedExecIt - CLI.Outs.begin();
4309 CLI.OutVals.erase(CLI.OutVals.begin() + SpecialArgsBeginIdx,
4310 CLI.OutVals.end());
4311 CLI.Outs.erase(RequestedExecIt, CLI.Outs.end());
4312
4313 assert(CLI.Outs.back().OrigArgIndex < 2 &&
4314 "Haven't popped all the special args");
4315
4316 TargetLowering::ArgListEntry RequestedExecArg =
4317 CLI.Args[ChainCallArgIdx::Exec];
4318 if (!RequestedExecArg.Ty->isIntegerTy(Subtarget->getWavefrontSize()))
4319 return lowerUnhandledCall(CLI, InVals, "Invalid value for EXEC");
4320
4321 // Convert constants into TargetConstants, so they become immediate operands
4322 // instead of being selected into S_MOV.
4323 auto PushNodeOrTargetConstant = [&](TargetLowering::ArgListEntry Arg) {
4324 if (const auto *ArgNode = dyn_cast<ConstantSDNode>(Arg.Node)) {
4325 ChainCallSpecialArgs.push_back(DAG.getTargetConstant(
4326 ArgNode->getAPIntValue(), DL, ArgNode->getValueType(0)));
4327 } else
4328 ChainCallSpecialArgs.push_back(Arg.Node);
4329 };
4330
4331 PushNodeOrTargetConstant(RequestedExecArg);
4332
4333 // Process any other special arguments depending on the value of the flags.
4334 TargetLowering::ArgListEntry Flags = CLI.Args[ChainCallArgIdx::Flags];
4335
4336 const APInt &FlagsValue = cast<ConstantSDNode>(Flags.Node)->getAPIntValue();
4337 if (FlagsValue.isZero()) {
4338 if (CLI.Args.size() > ChainCallArgIdx::Flags + 1)
4339 return lowerUnhandledCall(CLI, InVals,
4340 "no additional args allowed if flags == 0");
4341 } else if (FlagsValue.isOneBitSet(0)) {
4342 if (CLI.Args.size() != ChainCallArgIdx::FallbackCallee + 1) {
4343 return lowerUnhandledCall(CLI, InVals, "expected 3 additional args");
4344 }
4345
4346 if (!Subtarget->isWave32()) {
4347 return lowerUnhandledCall(
4348 CLI, InVals, "dynamic VGPR mode is only supported for wave32");
4349 }
4350
4351 UsesDynamicVGPRs = true;
4352 std::for_each(CLI.Args.begin() + ChainCallArgIdx::NumVGPRs,
4353 CLI.Args.end(), PushNodeOrTargetConstant);
4354 }
4355 }
4356
4358 SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
4360 bool &IsTailCall = CLI.IsTailCall;
4361 bool IsVarArg = CLI.IsVarArg;
4362 bool IsSibCall = false;
4364
4365 if (Callee.isUndef() || isNullConstant(Callee)) {
4366 if (!CLI.IsTailCall) {
4367 for (ISD::InputArg &Arg : CLI.Ins)
4368 InVals.push_back(DAG.getPOISON(Arg.VT));
4369 }
4370
4371 return Chain;
4372 }
4373
4374 if (IsVarArg) {
4375 return lowerUnhandledCall(CLI, InVals,
4376 "unsupported call to variadic function ");
4377 }
4378
4379 if (!CLI.CB)
4380 return lowerUnhandledCall(CLI, InVals, "unsupported libcall legalization");
4381
4382 if (IsTailCall && MF.getTarget().Options.GuaranteedTailCallOpt) {
4383 return lowerUnhandledCall(CLI, InVals,
4384 "unsupported required tail call to function ");
4385 }
4386
4387 if (IsTailCall) {
4388 IsTailCall = isEligibleForTailCallOptimization(Callee, CallConv, IsVarArg,
4389 Outs, OutVals, Ins, DAG);
4390 if (!IsTailCall &&
4391 ((CLI.CB && CLI.CB->isMustTailCall()) || IsChainCallConv)) {
4392 report_fatal_error("failed to perform tail call elimination on a call "
4393 "site marked musttail or on llvm.amdgcn.cs.chain");
4394 }
4395
4396 bool TailCallOpt = MF.getTarget().Options.GuaranteedTailCallOpt;
4397
4398 // A sibling call is one where we're under the usual C ABI and not planning
4399 // to change that but can still do a tail call:
4400 if (!TailCallOpt && IsTailCall)
4401 IsSibCall = true;
4402
4403 if (IsTailCall)
4404 ++NumTailCalls;
4405 }
4406
4409 SmallVector<SDValue, 8> MemOpChains;
4410
4411 // Analyze operands of the call, assigning locations to each operand.
4413 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
4414 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, IsVarArg);
4415
4416 if (CallConv != CallingConv::AMDGPU_Gfx && !AMDGPU::isChainCC(CallConv) &&
4418 // With a fixed ABI, allocate fixed registers before user arguments.
4419 passSpecialInputs(CLI, CCInfo, *Info, RegsToPass, MemOpChains, Chain);
4420 }
4421
4422 // Mark the scratch resource descriptor as allocated so the CC analysis
4423 // does not assign user arguments to these registers, matching the callee.
4424 if (!Subtarget->hasFlatScratchEnabled())
4425 CCInfo.AllocateReg(Info->getScratchRSrcReg());
4426
4427 CCInfo.AnalyzeCallOperands(Outs, AssignFn);
4428
4429 // Get a count of how many bytes are to be pushed on the stack.
4430 unsigned NumBytes = CCInfo.getStackSize();
4431
4432 if (IsSibCall) {
4433 // Since we're not changing the ABI to make this a tail call, the memory
4434 // operands are already available in the caller's incoming argument space.
4435 NumBytes = 0;
4436 }
4437
4438 // FPDiff is the byte offset of the call's argument area from the callee's.
4439 // Stores to callee stack arguments will be placed in FixedStackSlots offset
4440 // by this amount for a tail call. In a sibling call it must be 0 because the
4441 // caller will deallocate the entire stack and the callee still expects its
4442 // arguments to begin at SP+0. Completely unused for non-tail calls.
4443 int32_t FPDiff = 0;
4444 MachineFrameInfo &MFI = MF.getFrameInfo();
4445 auto *TRI = Subtarget->getRegisterInfo();
4446
4447 // Adjust the stack pointer for the new arguments...
4448 // These operations are automatically eliminated by the prolog/epilog pass
4449 if (!IsSibCall)
4450 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL);
4451
4452 if (!IsSibCall || IsChainCallConv) {
4453 if (!Subtarget->hasFlatScratchEnabled()) {
4454 SmallVector<SDValue, 4> CopyFromChains;
4455
4456 // In the HSA case, this should be an identity copy.
4457 SDValue ScratchRSrcReg =
4458 DAG.getCopyFromReg(Chain, DL, Info->getScratchRSrcReg(), MVT::v4i32);
4459 RegsToPass.emplace_back(IsChainCallConv
4460 ? AMDGPU::SGPR48_SGPR49_SGPR50_SGPR51
4461 : AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3,
4462 ScratchRSrcReg);
4463 CopyFromChains.push_back(ScratchRSrcReg.getValue(1));
4464 Chain = DAG.getTokenFactor(DL, CopyFromChains);
4465 }
4466 }
4467
4468 const unsigned NumSpecialInputs = RegsToPass.size();
4469
4470 MVT PtrVT = MVT::i32;
4471
4472 // Walk the register/memloc assignments, inserting copies/loads.
4473 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4474 CCValAssign &VA = ArgLocs[i];
4475 SDValue Arg = OutVals[i];
4476
4477 // Promote the value if needed.
4478 switch (VA.getLocInfo()) {
4479 case CCValAssign::Full:
4480 break;
4481 case CCValAssign::BCvt:
4482 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
4483 break;
4484 case CCValAssign::ZExt:
4485 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
4486 break;
4487 case CCValAssign::SExt:
4488 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
4489 break;
4490 case CCValAssign::AExt:
4491 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
4492 break;
4493 case CCValAssign::FPExt:
4494 Arg = DAG.getNode(ISD::FP_EXTEND, DL, VA.getLocVT(), Arg);
4495 break;
4496 default:
4497 llvm_unreachable("Unknown loc info!");
4498 }
4499
4500 if (VA.isRegLoc()) {
4501 RegsToPass.push_back(std::pair(VA.getLocReg(), Arg));
4502 } else {
4503 assert(VA.isMemLoc());
4504
4505 SDValue DstAddr;
4506 MachinePointerInfo DstInfo;
4507
4508 unsigned LocMemOffset = VA.getLocMemOffset();
4509 int32_t Offset = LocMemOffset;
4510
4511 SDValue PtrOff = DAG.getConstant(Offset, DL, PtrVT);
4512 MaybeAlign Alignment;
4513
4514 if (IsTailCall) {
4515 ISD::ArgFlagsTy Flags = Outs[i].Flags;
4516 unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
4517 : VA.getValVT().getStoreSize();
4518
4519 // FIXME: We can have better than the minimum byval required alignment.
4520 Alignment =
4521 Flags.isByVal()
4522 ? Flags.getNonZeroByValAlign()
4523 : commonAlignment(Subtarget->getStackAlignment(), Offset);
4524
4525 Offset = Offset + FPDiff;
4526 int FI = MFI.CreateFixedObject(OpSize, Offset, true);
4527
4528 DstAddr = DAG.getFrameIndex(FI, PtrVT);
4529 DstInfo = MachinePointerInfo::getFixedStack(MF, FI);
4530
4531 // Make sure any stack arguments overlapping with where we're storing
4532 // are loaded before this eventual operation. Otherwise they'll be
4533 // clobbered.
4534
4535 // FIXME: Why is this really necessary? This seems to just result in a
4536 // lot of code to copy the stack and write them back to the same
4537 // locations, which are supposed to be immutable?
4538 Chain = addTokenForArgument(Chain, DAG, MFI, FI);
4539 } else {
4540 // Stores to the argument stack area are relative to the stack pointer.
4541 SDValue SP = DAG.getCopyFromReg(Chain, DL, Info->getStackPtrOffsetReg(),
4542 MVT::i32);
4543 DstAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, SP, PtrOff);
4544 DstInfo = MachinePointerInfo::getStack(MF, LocMemOffset);
4545 Alignment =
4546 commonAlignment(Subtarget->getStackAlignment(), LocMemOffset);
4547 }
4548
4549 if (Outs[i].Flags.isByVal()) {
4550 SDValue SizeNode =
4551 DAG.getConstant(Outs[i].Flags.getByValSize(), DL, MVT::i32);
4552 SDValue Cpy =
4553 DAG.getMemcpy(Chain, DL, DstAddr, Arg, SizeNode,
4554 Outs[i].Flags.getNonZeroByValAlign(),
4555 Outs[i].Flags.getNonZeroByValAlign(),
4556 /*isVol = */ false, /*AlwaysInline = */ true,
4557 /*CI=*/nullptr, std::nullopt, DstInfo,
4559
4560 MemOpChains.push_back(Cpy);
4561 } else {
4562 SDValue Store =
4563 DAG.getStore(Chain, DL, Arg, DstAddr, DstInfo, Alignment);
4564 MemOpChains.push_back(Store);
4565 }
4566 }
4567 }
4568
4569 if (!MemOpChains.empty())
4570 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
4571
4572 SDValue ReadFirstLaneID =
4573 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4574
4575 SDValue TokenGlue;
4576 if (CLI.ConvergenceControlToken) {
4577 TokenGlue = DAG.getNode(ISD::CONVERGENCECTRL_GLUE, DL, MVT::Glue,
4579 }
4580
4581 // Build a sequence of copy-to-reg nodes chained together with token chain
4582 // and flag operands which copy the outgoing args into the appropriate regs.
4583 SDValue InGlue;
4584
4585 unsigned ArgIdx = 0;
4586 for (auto [Reg, Val] : RegsToPass) {
4587 if (ArgIdx++ >= NumSpecialInputs &&
4588 (IsChainCallConv || !Val->isDivergent()) && TRI->isSGPRPhysReg(Reg)) {
4589 // For chain calls, the inreg arguments are required to be
4590 // uniform. Speculatively Insert a readfirstlane in case we cannot prove
4591 // they are uniform.
4592 //
4593 // For other calls, if an inreg arguments is known to be uniform,
4594 // speculatively insert a readfirstlane in case it is in a VGPR.
4595 //
4596 // FIXME: We need to execute this in a waterfall loop if it is a divergent
4597 // value, so let that continue to produce invalid code.
4598
4599 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Val});
4600 if (TokenGlue)
4601 ReadfirstlaneArgs.push_back(TokenGlue);
4603 ReadfirstlaneArgs);
4604 }
4605
4606 Chain = DAG.getCopyToReg(Chain, DL, Reg, Val, InGlue);
4607 InGlue = Chain.getValue(1);
4608 }
4609
4610 // We don't usually want to end the call-sequence here because we would tidy
4611 // the frame up *after* the call, however in the ABI-changing tail-call case
4612 // we've carefully laid out the parameters so that when sp is reset they'll be
4613 // in the correct location.
4614 if (IsTailCall && !IsSibCall) {
4615 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
4616 InGlue = Chain.getValue(1);
4617 }
4618
4619 std::vector<SDValue> Ops({Chain});
4620
4621 // Add a redundant copy of the callee global which will not be legalized, as
4622 // we need direct access to the callee later.
4624 const GlobalValue *GV = GSD->getGlobal();
4625 Ops.push_back(Callee);
4626 Ops.push_back(DAG.getTargetGlobalAddress(GV, DL, MVT::i64));
4627 } else {
4628 if (IsTailCall) {
4629 // isEligibleForTailCallOptimization considered whether the call target is
4630 // divergent, but we may still end up with a uniform value in a VGPR.
4631 // Insert a readfirstlane just in case.
4632 SDValue ReadFirstLaneID =
4633 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
4634
4635 SmallVector<SDValue, 3> ReadfirstlaneArgs({ReadFirstLaneID, Callee});
4636 if (TokenGlue)
4637 ReadfirstlaneArgs.push_back(TokenGlue); // Wire up convergence token.
4638 Callee = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Callee.getValueType(),
4639 ReadfirstlaneArgs);
4640 }
4641
4642 Ops.push_back(Callee);
4643 Ops.push_back(DAG.getTargetConstant(0, DL, MVT::i64));
4644 }
4645
4646 if (IsTailCall) {
4647 // Each tail call may have to adjust the stack by a different amount, so
4648 // this information must travel along with the operation for eventual
4649 // consumption by emitEpilogue.
4650 Ops.push_back(DAG.getTargetConstant(FPDiff, DL, MVT::i32));
4651 }
4652
4653 if (IsChainCallConv)
4654 llvm::append_range(Ops, ChainCallSpecialArgs);
4655
4656 // Add argument registers to the end of the list so that they are known live
4657 // into the call.
4658 for (auto &[Reg, Val] : RegsToPass)
4659 Ops.push_back(DAG.getRegister(Reg, Val.getValueType()));
4660
4661 // Add a register mask operand representing the call-preserved registers.
4662 const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
4663 assert(Mask && "Missing call preserved mask for calling convention");
4664 Ops.push_back(DAG.getRegisterMask(Mask));
4665
4666 if (SDValue Token = CLI.ConvergenceControlToken) {
4668 GlueOps.push_back(Token);
4669 if (InGlue)
4670 GlueOps.push_back(InGlue);
4671
4672 InGlue = SDValue(DAG.getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, DL,
4673 MVT::Glue, GlueOps),
4674 0);
4675 }
4676
4677 if (InGlue)
4678 Ops.push_back(InGlue);
4679
4680 // If we're doing a tall call, use a TC_RETURN here rather than an
4681 // actual call instruction.
4682 if (IsTailCall) {
4683 MFI.setHasTailCall();
4684 unsigned OPC = AMDGPUISD::TC_RETURN;
4685 switch (CallConv) {
4687 OPC = AMDGPUISD::TC_RETURN_GFX;
4688 break;
4691 OPC = UsesDynamicVGPRs ? AMDGPUISD::TC_RETURN_CHAIN_DVGPR
4692 : AMDGPUISD::TC_RETURN_CHAIN;
4693 break;
4694 }
4695
4696 // If the caller is a whole wave function, we need to use a special opcode
4697 // so we can patch up EXEC.
4698 if (Info->isWholeWaveFunction())
4699 OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
4700
4701 return DAG.getNode(OPC, DL, MVT::Other, Ops);
4702 }
4703
4704 // Returns a chain and a flag for retval copy to use.
4705 SDValue Call = DAG.getNode(AMDGPUISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops);
4706 Chain = Call.getValue(0);
4707 InGlue = Call.getValue(1);
4708
4709 uint64_t CalleePopBytes = NumBytes;
4710 Chain = DAG.getCALLSEQ_END(Chain, 0, CalleePopBytes, InGlue, DL);
4711 if (!Ins.empty())
4712 InGlue = Chain.getValue(1);
4713
4714 // Handle result values, copying them out of physregs into vregs that we
4715 // return.
4716 return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG,
4717 InVals, /*IsThisReturn=*/false, SDValue());
4718}
4719
4720// This is similar to the default implementation in ExpandDYNAMIC_STACKALLOC,
4721// except for:
4722// 1. Stack growth direction(default: downwards, AMDGPU: upwards), and
4723// 2. Scale size where, scale = wave-reduction(alloca-size) * wave-size
4725 SelectionDAG &DAG) const {
4726 const MachineFunction &MF = DAG.getMachineFunction();
4728
4729 SDLoc dl(Op);
4730 EVT VT = Op.getValueType();
4731 SDValue Chain = Op.getOperand(0);
4732 Register SPReg = Info->getStackPtrOffsetReg();
4733
4734 // Chain the dynamic stack allocation so that it doesn't modify the stack
4735 // pointer when other instructions are using the stack.
4736 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, dl);
4737
4738 SDValue Size = Op.getOperand(1);
4739 SDValue BaseAddr = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
4740 Align Alignment = cast<ConstantSDNode>(Op.getOperand(2))->getAlignValue();
4741
4742 const TargetFrameLowering *TFL = Subtarget->getFrameLowering();
4744 "Stack grows upwards for AMDGPU");
4745
4746 Chain = BaseAddr.getValue(1);
4747 // When using flat-scratch, the stack offset is unscaled.
4748 const bool HasFlatScratch = Subtarget->hasFlatScratchEnabled();
4749 const unsigned WavefrontSizeLog2 = Subtarget->getWavefrontSizeLog2();
4750
4751 Align StackAlign = TFL->getStackAlign();
4752 if (Alignment > StackAlign) {
4753 uint64_t ScaledAlignment = Alignment.value()
4754 << (HasFlatScratch ? 0 : WavefrontSizeLog2);
4755 uint64_t StackAlignMask = ScaledAlignment - 1;
4756 SDValue TmpAddr = DAG.getNode(ISD::ADD, dl, VT, BaseAddr,
4757 DAG.getConstant(StackAlignMask, dl, VT));
4758 BaseAddr = DAG.getNode(ISD::AND, dl, VT, TmpAddr,
4759 DAG.getSignedConstant(-ScaledAlignment, dl, VT));
4760 }
4761
4762 assert(Size.getValueType() == MVT::i32 && "Size must be 32-bit");
4763 SDValue NewSP;
4765 // Increase the stack pointer by the size of the alloca.
4766 // If not using flat-scratch, we have to scale the size by the wave-size.
4767 SDValue ScaledSize =
4768 HasFlatScratch
4769 ? Size
4770 : DAG.getNode(ISD::SHL, dl, VT, Size,
4771 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4772 NewSP = DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value
4773 } else {
4774 // For dynamic sized alloca, perform wave-wide reduction to get max of
4775 // alloca size(divergent), and then scale it (when not using flat-scratch)
4776 // by wave-size.
4777 SDValue WaveReduction =
4778 DAG.getTargetConstant(Intrinsic::amdgcn_wave_reduce_umax, dl, MVT::i32);
4779 Size = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, WaveReduction,
4780 Size, DAG.getTargetConstant(0, dl, MVT::i32));
4781 SDValue ScaledSize = Size;
4782 if (!HasFlatScratch) {
4783 ScaledSize =
4784 DAG.getNode(ISD::SHL, dl, VT, Size,
4785 DAG.getConstant(WavefrontSizeLog2, dl, MVT::i32));
4786 }
4787 NewSP =
4788 DAG.getNode(ISD::ADD, dl, VT, BaseAddr, ScaledSize); // Value in vgpr.
4789 SDValue ReadFirstLaneID =
4790 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, dl, MVT::i32);
4791 NewSP = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, ReadFirstLaneID,
4792 NewSP);
4793 }
4794
4795 Chain = DAG.getCopyToReg(Chain, dl, SPReg, NewSP); // Output chain
4796 SDValue CallSeqEnd = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), dl);
4797
4798 return DAG.getMergeValues({BaseAddr, CallSeqEnd}, dl);
4799}
4800
4802 if (Op.getValueType() != MVT::i32)
4803 return Op; // Defer to cannot select error.
4804
4806 SDLoc SL(Op);
4807
4808 SDValue CopyFromSP = DAG.getCopyFromReg(Op->getOperand(0), SL, SP, MVT::i32);
4809
4810 // Convert from wave uniform to swizzled vector address. This should protect
4811 // from any edge cases where the stacksave result isn't directly used with
4812 // stackrestore.
4813 SDValue VectorAddress =
4814 DAG.getNode(AMDGPUISD::WAVE_ADDRESS, SL, MVT::i32, CopyFromSP);
4815 return DAG.getMergeValues({VectorAddress, CopyFromSP.getValue(1)}, SL);
4816}
4817
4819 SelectionDAG &DAG) const {
4820 SDLoc SL(Op);
4821 assert(Op.getValueType() == MVT::i32);
4822
4823 uint32_t BothRoundHwReg =
4825 SDValue GetRoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
4826
4827 SDValue IntrinID =
4828 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
4829 SDValue GetReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, Op->getVTList(),
4830 Op.getOperand(0), IntrinID, GetRoundBothImm);
4831
4832 // There are two rounding modes, one for f32 and one for f64/f16. We only
4833 // report in the standard value range if both are the same.
4834 //
4835 // The raw values also differ from the expected FLT_ROUNDS values. Nearest
4836 // ties away from zero is not supported, and the other values are rotated by
4837 // 1.
4838 //
4839 // If the two rounding modes are not the same, report a target defined value.
4840
4841 // Mode register rounding mode fields:
4842 //
4843 // [1:0] Single-precision round mode.
4844 // [3:2] Double/Half-precision round mode.
4845 //
4846 // 0=nearest even; 1= +infinity; 2= -infinity, 3= toward zero.
4847 //
4848 // Hardware Spec
4849 // Toward-0 3 0
4850 // Nearest Even 0 1
4851 // +Inf 1 2
4852 // -Inf 2 3
4853 // NearestAway0 N/A 4
4854 //
4855 // We have to handle 16 permutations of a 4-bit value, so we create a 64-bit
4856 // table we can index by the raw hardware mode.
4857 //
4858 // (trunc (FltRoundConversionTable >> MODE.fp_round)) & 0xf
4859
4860 SDValue BitTable =
4862
4863 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4864 SDValue RoundModeTimesNumBits =
4865 DAG.getNode(ISD::SHL, SL, MVT::i32, GetReg, Two);
4866
4867 // TODO: We could possibly avoid a 64-bit shift and use a simpler table if we
4868 // knew only one mode was demanded.
4869 SDValue TableValue =
4870 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
4871 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
4872
4873 SDValue EntryMask = DAG.getConstant(0xf, SL, MVT::i32);
4874 SDValue TableEntry =
4875 DAG.getNode(ISD::AND, SL, MVT::i32, TruncTable, EntryMask);
4876
4877 // There's a gap in the 4-bit encoded table and actual enum values, so offset
4878 // if it's an extended value.
4879 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
4880 SDValue IsStandardValue =
4881 DAG.getSetCC(SL, MVT::i1, TableEntry, Four, ISD::SETULT);
4882 SDValue EnumOffset = DAG.getNode(ISD::ADD, SL, MVT::i32, TableEntry, Four);
4883 SDValue Result = DAG.getNode(ISD::SELECT, SL, MVT::i32, IsStandardValue,
4884 TableEntry, EnumOffset);
4885
4886 return DAG.getMergeValues({Result, GetReg.getValue(1)}, SL);
4887}
4888
4890 SelectionDAG &DAG) const {
4891 SDLoc SL(Op);
4892
4893 SDValue NewMode = Op.getOperand(1);
4894 assert(NewMode.getValueType() == MVT::i32);
4895
4896 // Index a table of 4-bit entries mapping from the C FLT_ROUNDS values to the
4897 // hardware MODE.fp_round values.
4898 if (auto *ConstMode = dyn_cast<ConstantSDNode>(NewMode)) {
4899 uint32_t ClampedVal = std::min(
4900 static_cast<uint32_t>(ConstMode->getZExtValue()),
4902 NewMode = DAG.getConstant(
4903 AMDGPU::decodeFltRoundToHWConversionTable(ClampedVal), SL, MVT::i32);
4904 } else {
4905 // If we know the input can only be one of the supported standard modes in
4906 // the range 0-3, we can use a simplified mapping to hardware values.
4907 KnownBits KB = DAG.computeKnownBits(NewMode);
4908 const bool UseReducedTable = KB.countMinLeadingZeros() >= 30;
4909 // The supported standard values are 0-3. The extended values start at 8. We
4910 // need to offset by 4 if the value is in the extended range.
4911
4912 if (UseReducedTable) {
4913 // Truncate to the low 32-bits.
4914 SDValue BitTable = DAG.getConstant(
4915 AMDGPU::FltRoundToHWConversionTable & 0xffff, SL, MVT::i32);
4916
4917 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4918 SDValue RoundModeTimesNumBits =
4919 DAG.getNode(ISD::SHL, SL, MVT::i32, NewMode, Two);
4920
4921 NewMode =
4922 DAG.getNode(ISD::SRL, SL, MVT::i32, BitTable, RoundModeTimesNumBits);
4923
4924 // TODO: SimplifyDemandedBits on the setreg source here can likely reduce
4925 // the table extracted bits into inline immediates.
4926 } else {
4927 // table_index = umin(value, value - 4)
4928 // MODE.fp_round = (bit_table >> (table_index << 2)) & 0xf
4929 SDValue BitTable =
4931
4932 SDValue Four = DAG.getConstant(4, SL, MVT::i32);
4933 SDValue OffsetEnum = DAG.getNode(ISD::SUB, SL, MVT::i32, NewMode, Four);
4934 SDValue IndexVal =
4935 DAG.getNode(ISD::UMIN, SL, MVT::i32, NewMode, OffsetEnum);
4936
4937 SDValue Two = DAG.getConstant(2, SL, MVT::i32);
4938 SDValue RoundModeTimesNumBits =
4939 DAG.getNode(ISD::SHL, SL, MVT::i32, IndexVal, Two);
4940
4941 SDValue TableValue =
4942 DAG.getNode(ISD::SRL, SL, MVT::i64, BitTable, RoundModeTimesNumBits);
4943 SDValue TruncTable = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, TableValue);
4944
4945 // No need to mask out the high bits since the setreg will ignore them
4946 // anyway.
4947 NewMode = TruncTable;
4948 }
4949
4950 // Insert a readfirstlane in case the value is a VGPR. We could do this
4951 // earlier and keep more operations scalar, but that interferes with
4952 // combining the source.
4953 SDValue ReadFirstLaneID =
4954 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
4955 NewMode = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
4956 ReadFirstLaneID, NewMode);
4957 }
4958
4959 // N.B. The setreg will be later folded into s_round_mode on supported
4960 // targets.
4961 SDValue IntrinID =
4962 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
4963 uint32_t BothRoundHwReg =
4965 SDValue RoundBothImm = DAG.getTargetConstant(BothRoundHwReg, SL, MVT::i32);
4966
4967 SDValue SetReg =
4968 DAG.getNode(ISD::INTRINSIC_VOID, SL, Op->getVTList(), Op.getOperand(0),
4969 IntrinID, RoundBothImm, NewMode);
4970
4971 return SetReg;
4972}
4973
4975 if (Op->isDivergent() &&
4976 (!Subtarget->hasVmemPrefInsts() || !Op.getConstantOperandVal(4)))
4977 // Cannot do I$ prefetch with divergent pointer.
4978 return SDValue();
4979
4980 switch (cast<MemSDNode>(Op)->getAddressSpace()) {
4984 break;
4986 if (Subtarget->hasSafeSmemPrefetch())
4987 break;
4988 [[fallthrough]];
4989 default:
4990 return SDValue();
4991 }
4992
4993 // I$ prefetch
4994 if (!Subtarget->hasSafeSmemPrefetch() && !Op.getConstantOperandVal(4))
4995 return SDValue();
4996
4997 return Op;
4998}
4999
5000// Work around DAG legality rules only based on the result type.
5002 bool IsStrict = Op.getOpcode() == ISD::STRICT_FP_EXTEND;
5003 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
5004 EVT SrcVT = Src.getValueType();
5005
5006 if (SrcVT.getScalarType() != MVT::bf16)
5007 return Op;
5008
5009 SDLoc SL(Op);
5010 SDValue BitCast =
5011 DAG.getNode(ISD::BITCAST, SL, SrcVT.changeTypeToInteger(), Src);
5012
5013 EVT DstVT = Op.getValueType();
5014 if (IsStrict)
5015 llvm_unreachable("Need STRICT_BF16_TO_FP");
5016
5017 return DAG.getNode(ISD::BF16_TO_FP, SL, DstVT, BitCast);
5018}
5019
5021 SDLoc SL(Op);
5022 if (Op.getValueType() != MVT::i64)
5023 return Op;
5024
5025 uint32_t ModeHwReg =
5027 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5028 uint32_t TrapHwReg =
5030 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5031
5032 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::Other);
5033 SDValue IntrinID =
5034 DAG.getTargetConstant(Intrinsic::amdgcn_s_getreg, SL, MVT::i32);
5035 SDValue GetModeReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5036 Op.getOperand(0), IntrinID, ModeHwRegImm);
5037 SDValue GetTrapReg = DAG.getNode(ISD::INTRINSIC_W_CHAIN, SL, VTList,
5038 Op.getOperand(0), IntrinID, TrapHwRegImm);
5039 SDValue TokenReg =
5040 DAG.getNode(ISD::TokenFactor, SL, MVT::Other, GetModeReg.getValue(1),
5041 GetTrapReg.getValue(1));
5042
5043 SDValue CvtPtr =
5044 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, GetModeReg, GetTrapReg);
5045 SDValue Result = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
5046
5047 return DAG.getMergeValues({Result, TokenReg}, SL);
5048}
5049
5051 SDLoc SL(Op);
5052 if (Op.getOperand(1).getValueType() != MVT::i64)
5053 return Op;
5054
5055 SDValue Input = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op.getOperand(1));
5056 SDValue NewModeReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5057 DAG.getConstant(0, SL, MVT::i32));
5058 SDValue NewTrapReg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Input,
5059 DAG.getConstant(1, SL, MVT::i32));
5060
5061 SDValue ReadFirstLaneID =
5062 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, SL, MVT::i32);
5063 NewModeReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5064 ReadFirstLaneID, NewModeReg);
5065 NewTrapReg = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
5066 ReadFirstLaneID, NewTrapReg);
5067
5068 unsigned ModeHwReg =
5070 SDValue ModeHwRegImm = DAG.getTargetConstant(ModeHwReg, SL, MVT::i32);
5071 unsigned TrapHwReg =
5073 SDValue TrapHwRegImm = DAG.getTargetConstant(TrapHwReg, SL, MVT::i32);
5074
5075 SDValue IntrinID =
5076 DAG.getTargetConstant(Intrinsic::amdgcn_s_setreg, SL, MVT::i32);
5077 SDValue SetModeReg =
5078 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5079 IntrinID, ModeHwRegImm, NewModeReg);
5080 SDValue SetTrapReg =
5081 DAG.getNode(ISD::INTRINSIC_VOID, SL, MVT::Other, Op.getOperand(0),
5082 IntrinID, TrapHwRegImm, NewTrapReg);
5083 return DAG.getNode(ISD::TokenFactor, SL, MVT::Other, SetTrapReg, SetModeReg);
5084}
5085
5087 const MachineFunction &MF) const {
5088 const Function &Fn = MF.getFunction();
5089
5091 .Case("m0", AMDGPU::M0)
5092 .Case("exec", AMDGPU::EXEC)
5093 .Case("exec_lo", AMDGPU::EXEC_LO)
5094 .Case("exec_hi", AMDGPU::EXEC_HI)
5095 .Case("flat_scratch", AMDGPU::FLAT_SCR)
5096 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
5097 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
5098 .Default(Register());
5099 if (!Reg)
5100 return Reg;
5101
5102 if (!Subtarget->hasFlatScrRegister() &&
5103 Subtarget->getRegisterInfo()->regsOverlap(Reg, AMDGPU::FLAT_SCR)) {
5104 Fn.getContext().emitError(Twine("invalid register \"" + StringRef(RegName) +
5105 "\" for subtarget."));
5106 }
5107
5108 switch (Reg) {
5109 case AMDGPU::M0:
5110 case AMDGPU::EXEC_LO:
5111 case AMDGPU::EXEC_HI:
5112 case AMDGPU::FLAT_SCR_LO:
5113 case AMDGPU::FLAT_SCR_HI:
5114 if (VT.getSizeInBits() == 32)
5115 return Reg;
5116 break;
5117 case AMDGPU::EXEC:
5118 case AMDGPU::FLAT_SCR:
5119 if (VT.getSizeInBits() == 64)
5120 return Reg;
5121 break;
5122 default:
5123 llvm_unreachable("missing register type checking");
5124 }
5125
5127 Twine("invalid type for register \"" + StringRef(RegName) + "\"."));
5128}
5129
5130// If kill is not the last instruction, split the block so kill is always a
5131// proper terminator.
5134 MachineBasicBlock *BB) const {
5135 MachineBasicBlock *SplitBB = BB->splitAt(MI, /*UpdateLiveIns=*/true);
5137 MI.setDesc(TII->getKillTerminatorFromPseudo(MI.getOpcode()));
5138 return SplitBB;
5139}
5140
5141// Split block \p MBB at \p MI, as to insert a loop. If \p InstInLoop is true,
5142// \p MI will be the only instruction in the loop body block. Otherwise, it will
5143// be the first instruction in the remainder block.
5144//
5145/// \returns { LoopBody, Remainder }
5146static std::pair<MachineBasicBlock *, MachineBasicBlock *>
5148 MachineFunction *MF = MBB.getParent();
5150
5151 // To insert the loop we need to split the block. Move everything after this
5152 // point to a new block, and insert a new empty block between the two.
5154 MachineBasicBlock *RemainderBB = MF->CreateMachineBasicBlock();
5156 ++MBBI;
5157
5158 MF->insert(MBBI, LoopBB);
5159 MF->insert(MBBI, RemainderBB);
5160
5161 LoopBB->addSuccessor(LoopBB);
5162 LoopBB->addSuccessor(RemainderBB);
5163
5164 // Move the rest of the block into a new block.
5165 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
5166
5167 if (InstInLoop) {
5168 auto Next = std::next(I);
5169
5170 // Move instruction to loop body.
5171 LoopBB->splice(LoopBB->begin(), &MBB, I, Next);
5172
5173 // Move the rest of the block.
5174 RemainderBB->splice(RemainderBB->begin(), &MBB, Next, MBB.end());
5175 } else {
5176 RemainderBB->splice(RemainderBB->begin(), &MBB, I, MBB.end());
5177 }
5178
5179 MBB.addSuccessor(LoopBB);
5180
5181 return std::pair(LoopBB, RemainderBB);
5182}
5183
5184/// Insert \p MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
5186 MachineBasicBlock *MBB = MI.getParent();
5188 auto I = MI.getIterator();
5189 auto E = std::next(I);
5190
5191 // clang-format off
5192 BuildMI(*MBB, E, MI.getDebugLoc(), TII->get(AMDGPU::S_WAITCNT))
5193 .addImm(0);
5194 // clang-format on
5195
5196 MIBundleBuilder Bundler(*MBB, I, E);
5197 finalizeBundle(*MBB, Bundler.begin());
5198}
5199
5202 MachineBasicBlock *BB) const {
5203 const DebugLoc &DL = MI.getDebugLoc();
5204
5206
5208
5209 // Apparently kill flags are only valid if the def is in the same block?
5210 if (MachineOperand *Src = TII->getNamedOperand(MI, AMDGPU::OpName::data0))
5211 Src->setIsKill(false);
5212
5213 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, *BB, true);
5214
5215 MachineBasicBlock::iterator I = LoopBB->end();
5216
5217 const unsigned EncodedReg = AMDGPU::Hwreg::HwregEncoding::encode(
5219
5220 // Clear TRAP_STS.MEM_VIOL
5221 BuildMI(*LoopBB, LoopBB->begin(), DL, TII->get(AMDGPU::S_SETREG_IMM32_B32))
5222 .addImm(0)
5223 .addImm(EncodedReg);
5224
5226
5227 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5228
5229 // Load and check TRAP_STS.MEM_VIOL
5230 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_GETREG_B32), Reg)
5231 .addImm(EncodedReg);
5232
5233 // FIXME: Do we need to use an isel pseudo that may clobber scc?
5234 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CMP_LG_U32))
5235 .addReg(Reg, RegState::Kill)
5236 .addImm(0);
5237 // clang-format off
5238 BuildMI(*LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
5239 .addMBB(LoopBB);
5240 // clang-format on
5241
5242 return RemainderBB;
5243}
5244
5245// Do a v_movrels_b32 or v_movreld_b32 for each unique value of \p IdxReg in the
5246// wavefront. If the value is uniform and just happens to be in a VGPR, this
5247// will only do one iteration. In the worst case, this will loop 64 times.
5248//
5249// TODO: Just use v_readlane_b32 if we know the VGPR has a uniform value.
5252 MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB,
5253 const DebugLoc &DL, const MachineOperand &Idx,
5254 unsigned InitReg, unsigned ResultReg, unsigned PhiReg,
5255 unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode,
5256 Register &SGPRIdxReg) {
5257
5258 MachineFunction *MF = OrigBB.getParent();
5259 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5260 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5263
5264 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5265 Register PhiExec = MRI.createVirtualRegister(BoolRC);
5266 Register NewExec = MRI.createVirtualRegister(BoolRC);
5267 Register CurrentIdxReg =
5268 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5269 Register CondReg = MRI.createVirtualRegister(BoolRC);
5270
5271 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiReg)
5272 .addReg(InitReg)
5273 .addMBB(&OrigBB)
5274 .addReg(ResultReg)
5275 .addMBB(&LoopBB);
5276
5277 BuildMI(LoopBB, I, DL, TII->get(TargetOpcode::PHI), PhiExec)
5278 .addReg(InitSaveExecReg)
5279 .addMBB(&OrigBB)
5280 .addReg(NewExec)
5281 .addMBB(&LoopBB);
5282
5283 // Read the next variant <- also loop target.
5284 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CurrentIdxReg)
5285 .addReg(Idx.getReg(), getUndefRegState(Idx.isUndef()));
5286
5287 // Compare the just read M0 value to all possible Idx values.
5288 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::V_CMP_EQ_U32_e64), CondReg)
5289 .addReg(CurrentIdxReg)
5290 .addReg(Idx.getReg(), {}, Idx.getSubReg());
5291
5292 // Update EXEC, save the original EXEC value to VCC.
5293 BuildMI(LoopBB, I, DL, TII->get(LMC.AndSaveExecOpc), NewExec)
5294 .addReg(CondReg, RegState::Kill);
5295
5296 MRI.setSimpleHint(NewExec, CondReg);
5297
5298 if (UseGPRIdxMode) {
5299 if (Offset == 0) {
5300 SGPRIdxReg = CurrentIdxReg;
5301 } else {
5302 SGPRIdxReg = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
5303 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), SGPRIdxReg)
5304 .addReg(CurrentIdxReg, RegState::Kill)
5305 .addImm(Offset);
5306 }
5307 } else {
5308 // Move index from VCC into M0
5309 if (Offset == 0) {
5310 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5311 .addReg(CurrentIdxReg, RegState::Kill);
5312 } else {
5313 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5314 .addReg(CurrentIdxReg, RegState::Kill)
5315 .addImm(Offset);
5316 }
5317 }
5318
5319 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
5320 MachineInstr *InsertPt =
5321 BuildMI(LoopBB, I, DL, TII->get(LMC.XorTermOpc), LMC.ExecReg)
5322 .addReg(LMC.ExecReg)
5323 .addReg(NewExec);
5324
5325 // XXX - s_xor_b64 sets scc to 1 if the result is nonzero, so can we use
5326 // s_cbranch_scc0?
5327
5328 // Loop back to V_READFIRSTLANE_B32 if there are still variants to cover.
5329 // clang-format off
5330 BuildMI(LoopBB, I, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
5331 .addMBB(&LoopBB);
5332 // clang-format on
5333
5334 return InsertPt->getIterator();
5335}
5336
5337// This has slightly sub-optimal regalloc when the source vector is killed by
5338// the read. The register allocator does not understand that the kill is
5339// per-workitem, so is kept alive for the whole loop so we end up not re-using a
5340// subregister from it, using 1 more VGPR than necessary. This was saved when
5341// this was expanded after register allocation.
5344 unsigned InitResultReg, unsigned PhiReg, int Offset,
5345 bool UseGPRIdxMode, Register &SGPRIdxReg) {
5346 MachineFunction *MF = MBB.getParent();
5347 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5348 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5349 MachineRegisterInfo &MRI = MF->getRegInfo();
5350 const DebugLoc &DL = MI.getDebugLoc();
5352
5353 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
5354 Register DstReg = MI.getOperand(0).getReg();
5355 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
5356 Register TmpExec = MRI.createVirtualRegister(BoolXExecRC);
5358
5359 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), TmpExec);
5360
5361 // Save the EXEC mask
5362 // clang-format off
5363 BuildMI(MBB, I, DL, TII->get(LMC.MovOpc), SaveExec)
5364 .addReg(LMC.ExecReg);
5365 // clang-format on
5366
5367 auto [LoopBB, RemainderBB] = splitBlockForLoop(MI, MBB, false);
5368
5369 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5370
5371 auto InsPt = emitLoadM0FromVGPRLoop(TII, MRI, MBB, *LoopBB, DL, *Idx,
5372 InitResultReg, DstReg, PhiReg, TmpExec,
5373 Offset, UseGPRIdxMode, SGPRIdxReg);
5374
5375 MachineBasicBlock *LandingPad = MF->CreateMachineBasicBlock();
5377 ++MBBI;
5378 MF->insert(MBBI, LandingPad);
5379 LoopBB->removeSuccessor(RemainderBB);
5380 LandingPad->addSuccessor(RemainderBB);
5381 LoopBB->addSuccessor(LandingPad);
5382 MachineBasicBlock::iterator First = LandingPad->begin();
5383 // clang-format off
5384 BuildMI(*LandingPad, First, DL, TII->get(LMC.MovOpc), LMC.ExecReg)
5385 .addReg(SaveExec);
5386 // clang-format on
5387
5388 return InsPt;
5389}
5390
5391// Returns subreg index, offset
5392static std::pair<unsigned, int>
5394 const TargetRegisterClass *SuperRC, unsigned VecReg,
5395 int Offset) {
5396 int NumElts = TRI.getRegSizeInBits(*SuperRC) / 32;
5397
5398 // Skip out of bounds offsets, or else we would end up using an undefined
5399 // register.
5400 if (Offset >= NumElts || Offset < 0)
5401 return std::pair(AMDGPU::sub0, Offset);
5402
5403 return std::pair(SIRegisterInfo::getSubRegFromChannel(Offset), 0);
5404}
5405
5408 int Offset) {
5409 MachineBasicBlock *MBB = MI.getParent();
5410 const DebugLoc &DL = MI.getDebugLoc();
5412
5413 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5414
5415 assert(Idx->getReg() != AMDGPU::NoRegister);
5416
5417 if (Offset == 0) {
5418 // clang-format off
5419 BuildMI(*MBB, I, DL, TII->get(AMDGPU::COPY), AMDGPU::M0)
5420 .add(*Idx);
5421 // clang-format on
5422 } else {
5423 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), AMDGPU::M0)
5424 .add(*Idx)
5425 .addImm(Offset);
5426 }
5427}
5428
5431 int Offset) {
5432 MachineBasicBlock *MBB = MI.getParent();
5433 const DebugLoc &DL = MI.getDebugLoc();
5435
5436 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5437
5438 if (Offset == 0)
5439 return Idx->getReg();
5440
5441 Register Tmp = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
5442 BuildMI(*MBB, I, DL, TII->get(AMDGPU::S_ADD_I32), Tmp)
5443 .add(*Idx)
5444 .addImm(Offset);
5445 return Tmp;
5446}
5447
5450 const GCNSubtarget &ST) {
5451 const SIInstrInfo *TII = ST.getInstrInfo();
5452 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5453 MachineFunction *MF = MBB.getParent();
5454 MachineRegisterInfo &MRI = MF->getRegInfo();
5455
5456 Register Dst = MI.getOperand(0).getReg();
5457 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5458 Register SrcReg = TII->getNamedOperand(MI, AMDGPU::OpName::src)->getReg();
5459 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5460
5461 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcReg);
5462 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5463
5464 unsigned SubReg;
5465 std::tie(SubReg, Offset) =
5466 computeIndirectRegAndOffset(TRI, VecRC, SrcReg, Offset);
5467
5468 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5469
5470 // Check for a SGPR index.
5471 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5473 const DebugLoc &DL = MI.getDebugLoc();
5474
5475 if (UseGPRIdxMode) {
5476 // TODO: Look at the uses to avoid the copy. This may require rescheduling
5477 // to avoid interfering with other uses, so probably requires a new
5478 // optimization pass.
5479 Register Idx = getIndirectSGPRIdx(TII, MRI, MI, Offset);
5480
5481 const MCInstrDesc &GPRIDXDesc =
5482 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5483 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5484 .addReg(SrcReg)
5485 .addReg(Idx)
5486 .addImm(SubReg);
5487 } else {
5489
5490 BuildMI(MBB, I, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5491 .addReg(SrcReg, {}, SubReg)
5492 .addReg(SrcReg, RegState::Implicit);
5493 }
5494
5495 MI.eraseFromParent();
5496
5497 return &MBB;
5498 }
5499
5500 // Control flow needs to be inserted if indexing with a VGPR.
5501 const DebugLoc &DL = MI.getDebugLoc();
5503
5504 Register PhiReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5505 Register InitReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5506
5507 BuildMI(MBB, I, DL, TII->get(TargetOpcode::IMPLICIT_DEF), InitReg);
5508
5509 Register SGPRIdxReg;
5510 auto InsPt = loadM0FromVGPR(TII, MBB, MI, InitReg, PhiReg, Offset,
5511 UseGPRIdxMode, SGPRIdxReg);
5512
5513 MachineBasicBlock *LoopBB = InsPt->getParent();
5514
5515 if (UseGPRIdxMode) {
5516 const MCInstrDesc &GPRIDXDesc =
5517 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), true);
5518
5519 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5520 .addReg(SrcReg)
5521 .addReg(SGPRIdxReg)
5522 .addImm(SubReg);
5523 } else {
5524 BuildMI(*LoopBB, InsPt, DL, TII->get(AMDGPU::V_MOVRELS_B32_e32), Dst)
5525 .addReg(SrcReg, {}, SubReg)
5526 .addReg(SrcReg, RegState::Implicit);
5527 }
5528
5529 MI.eraseFromParent();
5530
5531 return LoopBB;
5532}
5533
5536 const GCNSubtarget &ST) {
5537 const SIInstrInfo *TII = ST.getInstrInfo();
5538 const SIRegisterInfo &TRI = TII->getRegisterInfo();
5539 MachineFunction *MF = MBB.getParent();
5540 MachineRegisterInfo &MRI = MF->getRegInfo();
5541
5542 Register Dst = MI.getOperand(0).getReg();
5543 const MachineOperand *SrcVec = TII->getNamedOperand(MI, AMDGPU::OpName::src);
5544 const MachineOperand *Idx = TII->getNamedOperand(MI, AMDGPU::OpName::idx);
5545 const MachineOperand *Val = TII->getNamedOperand(MI, AMDGPU::OpName::val);
5546 int Offset = TII->getNamedOperand(MI, AMDGPU::OpName::offset)->getImm();
5547 const TargetRegisterClass *VecRC = MRI.getRegClass(SrcVec->getReg());
5548 const TargetRegisterClass *IdxRC = MRI.getRegClass(Idx->getReg());
5549
5550 // This can be an immediate, but will be folded later.
5551 assert(Val->getReg());
5552
5553 unsigned SubReg;
5554 std::tie(SubReg, Offset) =
5555 computeIndirectRegAndOffset(TRI, VecRC, SrcVec->getReg(), Offset);
5556 const bool UseGPRIdxMode = ST.useVGPRIndexMode();
5557
5558 if (Idx->getReg() == AMDGPU::NoRegister) {
5560 const DebugLoc &DL = MI.getDebugLoc();
5561
5562 assert(Offset == 0);
5563
5564 BuildMI(MBB, I, DL, TII->get(TargetOpcode::INSERT_SUBREG), Dst)
5565 .add(*SrcVec)
5566 .add(*Val)
5567 .addImm(SubReg);
5568
5569 MI.eraseFromParent();
5570 return &MBB;
5571 }
5572
5573 // Check for a SGPR index.
5574 if (TII->getRegisterInfo().isSGPRClass(IdxRC)) {
5576 const DebugLoc &DL = MI.getDebugLoc();
5577
5578 if (UseGPRIdxMode) {
5579 Register Idx = getIndirectSGPRIdx(TII, MRI, MI, Offset);
5580
5581 const MCInstrDesc &GPRIDXDesc =
5582 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5583 BuildMI(MBB, I, DL, GPRIDXDesc, Dst)
5584 .addReg(SrcVec->getReg())
5585 .add(*Val)
5586 .addReg(Idx)
5587 .addImm(SubReg);
5588 } else {
5590
5591 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5592 TRI.getRegSizeInBits(*VecRC), 32, false);
5593 BuildMI(MBB, I, DL, MovRelDesc, Dst)
5594 .addReg(SrcVec->getReg())
5595 .add(*Val)
5596 .addImm(SubReg);
5597 }
5598 MI.eraseFromParent();
5599 return &MBB;
5600 }
5601
5602 // Control flow needs to be inserted if indexing with a VGPR.
5603 if (Val->isReg())
5604 MRI.clearKillFlags(Val->getReg());
5605
5606 const DebugLoc &DL = MI.getDebugLoc();
5607
5608 Register PhiReg = MRI.createVirtualRegister(VecRC);
5609
5610 Register SGPRIdxReg;
5611 auto InsPt = loadM0FromVGPR(TII, MBB, MI, SrcVec->getReg(), PhiReg, Offset,
5612 UseGPRIdxMode, SGPRIdxReg);
5613 MachineBasicBlock *LoopBB = InsPt->getParent();
5614
5615 if (UseGPRIdxMode) {
5616 const MCInstrDesc &GPRIDXDesc =
5617 TII->getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
5618
5619 BuildMI(*LoopBB, InsPt, DL, GPRIDXDesc, Dst)
5620 .addReg(PhiReg)
5621 .add(*Val)
5622 .addReg(SGPRIdxReg)
5623 .addImm(SubReg);
5624 } else {
5625 const MCInstrDesc &MovRelDesc = TII->getIndirectRegWriteMovRelPseudo(
5626 TRI.getRegSizeInBits(*VecRC), 32, false);
5627 BuildMI(*LoopBB, InsPt, DL, MovRelDesc, Dst)
5628 .addReg(PhiReg)
5629 .add(*Val)
5630 .addImm(SubReg);
5631 }
5632
5633 MI.eraseFromParent();
5634 return LoopBB;
5635}
5636
5638 MachineBasicBlock *BB) {
5639 // For targets older than GFX12, we emit a sequence of 32-bit operations.
5640 // For GFX12, we emit s_add_u64 and s_sub_u64.
5641 MachineFunction *MF = BB->getParent();
5642 const SIInstrInfo *TII = MF->getSubtarget<GCNSubtarget>().getInstrInfo();
5643 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5645 const DebugLoc &DL = MI.getDebugLoc();
5646 MachineOperand &Dest = MI.getOperand(0);
5647 MachineOperand &Src0 = MI.getOperand(1);
5648 MachineOperand &Src1 = MI.getOperand(2);
5649 bool IsAdd = (MI.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO);
5650 if (ST.hasScalarAddSub64()) {
5651 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64;
5652 // clang-format off
5653 BuildMI(*BB, MI, DL, TII->get(Opc), Dest.getReg())
5654 .add(Src0)
5655 .add(Src1);
5656 // clang-format on
5657 } else {
5658 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5659 const TargetRegisterClass *BoolRC = TRI->getBoolRC();
5660
5661 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5662 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5663
5664 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5665 MI, MRI, Src0, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5666 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5667 MI, MRI, Src0, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5668
5669 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5670 MI, MRI, Src1, BoolRC, AMDGPU::sub0, &AMDGPU::SReg_32RegClass);
5671 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5672 MI, MRI, Src1, BoolRC, AMDGPU::sub1, &AMDGPU::SReg_32RegClass);
5673
5674 unsigned LoOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
5675 unsigned HiOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
5676 BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0).add(Src0Sub0).add(Src1Sub0);
5677 BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1).add(Src0Sub1).add(Src1Sub1);
5678 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
5679 .addReg(DestSub0)
5680 .addImm(AMDGPU::sub0)
5681 .addReg(DestSub1)
5682 .addImm(AMDGPU::sub1);
5683 }
5684 MI.eraseFromParent();
5685 return BB;
5686}
5687
5689 MachineFunction *MF = BB->getParent();
5690 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
5691 const SIInstrInfo *TII = ST.getInstrInfo();
5692 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5693 MachineRegisterInfo &MRI = MF->getRegInfo();
5694 const DebugLoc &DL = MI.getDebugLoc();
5695 Register Dst = MI.getOperand(0).getReg();
5696 const MachineOperand &Src0 = MI.getOperand(1);
5697 const MachineOperand &Src1 = MI.getOperand(2);
5698 Register SrcCond = MI.getOperand(3).getReg();
5699
5700 Register DstLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5701 Register DstHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
5702 const TargetRegisterClass *CondRC = TRI->getWaveMaskRegClass();
5703 Register SrcCondCopy = MRI.createVirtualRegister(CondRC);
5704
5705 int Src0Idx =
5706 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
5707 int Src1Idx =
5708 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);
5709 const TargetRegisterClass *Src0RC =
5710 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src0Idx));
5711 const TargetRegisterClass *Src1RC =
5712 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), Src1Idx));
5713
5714 const TargetRegisterClass *Src0SubRC =
5715 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
5716 const TargetRegisterClass *Src1SubRC =
5717 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
5718
5719 MachineOperand Src0Sub0 = TII->buildExtractSubRegOrImm(
5720 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
5721 MachineOperand Src1Sub0 = TII->buildExtractSubRegOrImm(
5722 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
5723
5724 MachineOperand Src0Sub1 = TII->buildExtractSubRegOrImm(
5725 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
5726 MachineOperand Src1Sub1 = TII->buildExtractSubRegOrImm(
5727 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
5728
5729 BuildMI(*BB, MI, DL, TII->get(AMDGPU::COPY), SrcCondCopy).addReg(SrcCond);
5730 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstLo)
5731 .addImm(0)
5732 .add(Src0Sub0)
5733 .addImm(0)
5734 .add(Src1Sub0)
5735 .addReg(SrcCondCopy);
5736
5737 BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstHi)
5738 .addImm(0)
5739 .add(Src0Sub1)
5740 .addImm(0)
5741 .add(Src1Sub1)
5742 .addReg(SrcCondCopy);
5743
5744 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE), Dst)
5745 .addReg(DstLo)
5746 .addImm(AMDGPU::sub0)
5747 .addReg(DstHi)
5748 .addImm(AMDGPU::sub1);
5749 MI.eraseFromParent();
5750}
5751
5753 switch (Opc) {
5754 case AMDGPU::S_MIN_U32:
5755 return std::numeric_limits<uint32_t>::max();
5756 case AMDGPU::S_MIN_I32:
5757 return std::numeric_limits<int32_t>::max();
5758 case AMDGPU::S_MAX_U32:
5759 return std::numeric_limits<uint32_t>::min();
5760 case AMDGPU::S_MAX_I32:
5761 return std::numeric_limits<int32_t>::min();
5762 case AMDGPU::V_ADD_F32_e64: // -0.0
5763 return 0x80000000;
5764 case AMDGPU::V_SUB_F32_e64: // +0.0
5765 return 0x0;
5766 case AMDGPU::S_ADD_I32:
5767 case AMDGPU::S_SUB_I32:
5768 case AMDGPU::S_OR_B32:
5769 case AMDGPU::S_XOR_B32:
5770 return std::numeric_limits<uint32_t>::min();
5771 case AMDGPU::S_AND_B32:
5772 return std::numeric_limits<uint32_t>::max();
5773 case AMDGPU::V_MIN_F32_e64:
5774 case AMDGPU::V_MAX_F32_e64:
5775 return 0x7fc00000; // qNAN
5776 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5777 return std::numeric_limits<uint64_t>::max();
5778 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5779 return std::numeric_limits<int64_t>::max();
5780 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5781 return std::numeric_limits<uint64_t>::min();
5782 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5783 return std::numeric_limits<int64_t>::min();
5784 case AMDGPU::V_MIN_F64_e64:
5785 case AMDGPU::V_MAX_F64_e64:
5786 case AMDGPU::V_MIN_NUM_F64_e64:
5787 case AMDGPU::V_MAX_NUM_F64_e64:
5788 return 0x7FF8000000000000; // qNAN
5789 case AMDGPU::S_ADD_U64_PSEUDO:
5790 case AMDGPU::S_SUB_U64_PSEUDO:
5791 case AMDGPU::S_OR_B64:
5792 case AMDGPU::S_XOR_B64:
5793 return std::numeric_limits<uint64_t>::min();
5794 case AMDGPU::S_AND_B64:
5795 return std::numeric_limits<uint64_t>::max();
5796 case AMDGPU::V_ADD_F64_e64:
5797 case AMDGPU::V_ADD_F64_pseudo_e64:
5798 return 0x8000000000000000; // -0.0
5799 default:
5800 llvm_unreachable("Unexpected opcode in getIdentityValueForWaveReduction");
5801 }
5802}
5803
5804static bool is32bitWaveReduceOperation(unsigned Opc) {
5805 return Opc == AMDGPU::S_MIN_U32 || Opc == AMDGPU::S_MIN_I32 ||
5806 Opc == AMDGPU::S_MAX_U32 || Opc == AMDGPU::S_MAX_I32 ||
5807 Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32 ||
5808 Opc == AMDGPU::S_AND_B32 || Opc == AMDGPU::S_OR_B32 ||
5809 Opc == AMDGPU::S_XOR_B32 || Opc == AMDGPU::V_MIN_F32_e64 ||
5810 Opc == AMDGPU::V_MAX_F32_e64 || Opc == AMDGPU::V_ADD_F32_e64 ||
5811 Opc == AMDGPU::V_SUB_F32_e64;
5812}
5813
5815 return Opc == AMDGPU::V_MIN_F32_e64 || Opc == AMDGPU::V_MAX_F32_e64 ||
5816 Opc == AMDGPU::V_ADD_F32_e64 || Opc == AMDGPU::V_SUB_F32_e64 ||
5817 Opc == AMDGPU::V_MIN_F64_e64 || Opc == AMDGPU::V_MAX_F64_e64 ||
5818 Opc == AMDGPU::V_MIN_NUM_F64_e64 || Opc == AMDGPU::V_MAX_NUM_F64_e64 ||
5819 Opc == AMDGPU::V_ADD_F64_e64 || Opc == AMDGPU::V_ADD_F64_pseudo_e64;
5820}
5821
5822static std::tuple<unsigned, unsigned>
5824 unsigned DPPOpc;
5825 switch (Opc) {
5826 case AMDGPU::S_MIN_U32:
5827 DPPOpc = AMDGPU::V_MIN_U32_dpp;
5828 break;
5829 case AMDGPU::S_MIN_I32:
5830 DPPOpc = AMDGPU::V_MIN_I32_dpp;
5831 break;
5832 case AMDGPU::S_MAX_U32:
5833 DPPOpc = AMDGPU::V_MAX_U32_dpp;
5834 break;
5835 case AMDGPU::S_MAX_I32:
5836 DPPOpc = AMDGPU::V_MAX_I32_dpp;
5837 break;
5838 case AMDGPU::S_ADD_I32:
5839 case AMDGPU::S_SUB_I32:
5840 DPPOpc = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_dpp
5841 : AMDGPU::V_ADD_CO_U32_dpp;
5842 break;
5843 case AMDGPU::S_AND_B32:
5844 DPPOpc = AMDGPU::V_AND_B32_dpp;
5845 break;
5846 case AMDGPU::S_OR_B32:
5847 DPPOpc = AMDGPU::V_OR_B32_dpp;
5848 break;
5849 case AMDGPU::S_XOR_B32:
5850 DPPOpc = AMDGPU::V_XOR_B32_dpp;
5851 break;
5852 case AMDGPU::V_ADD_F32_e64:
5853 case AMDGPU::V_SUB_F32_e64:
5854 DPPOpc = AMDGPU::V_ADD_F32_dpp;
5855 break;
5856 case AMDGPU::V_MIN_F32_e64:
5857 DPPOpc = AMDGPU::V_MIN_F32_dpp;
5858 break;
5859 case AMDGPU::V_MAX_F32_e64:
5860 DPPOpc = AMDGPU::V_MAX_F32_dpp;
5861 break;
5862 case AMDGPU::V_CMP_LT_U64_e64: // umin.u64
5863 case AMDGPU::V_CMP_LT_I64_e64: // min.i64
5864 case AMDGPU::V_CMP_GT_U64_e64: // umax.u64
5865 case AMDGPU::V_CMP_GT_I64_e64: // max.i64
5866 case AMDGPU::S_ADD_U64_PSEUDO:
5867 case AMDGPU::S_SUB_U64_PSEUDO:
5868 case AMDGPU::S_AND_B64:
5869 case AMDGPU::S_OR_B64:
5870 case AMDGPU::S_XOR_B64:
5871 case AMDGPU::V_MIN_NUM_F64_e64:
5872 case AMDGPU::V_MIN_F64_e64:
5873 case AMDGPU::V_MAX_NUM_F64_e64:
5874 case AMDGPU::V_MAX_F64_e64:
5875 case AMDGPU::V_ADD_F64_pseudo_e64:
5876 case AMDGPU::V_ADD_F64_e64:
5877 DPPOpc = AMDGPU::V_MOV_B64_DPP_PSEUDO;
5878 break;
5879 default:
5880 llvm_unreachable("unhandled lane op");
5881 }
5882 unsigned ClampOpc = Opc;
5883 if (!ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
5884 if (Opc == AMDGPU::S_SUB_I32)
5885 ClampOpc = AMDGPU::S_ADD_I32;
5886 if (Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO)
5887 ClampOpc = AMDGPU::V_ADD_CO_U32_e64;
5888 else if (Opc == AMDGPU::S_AND_B64)
5889 ClampOpc = AMDGPU::V_AND_B32_e64;
5890 else if (Opc == AMDGPU::S_OR_B64)
5891 ClampOpc = AMDGPU::V_OR_B32_e64;
5892 else if (Opc == AMDGPU::S_XOR_B64)
5893 ClampOpc = AMDGPU::V_XOR_B32_e64;
5894 else
5895 ClampOpc = ST.getInstrInfo()->getVALUOp(ClampOpc);
5896 }
5897 return {DPPOpc, ClampOpc};
5898}
5899
5900static std::pair<Register, Register>
5902 const TargetRegisterClass *SrcRC, const GCNSubtarget &ST,
5903 MachineRegisterInfo &MRI) {
5904 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5905 const SIInstrInfo *TII = ST.getInstrInfo();
5906 const TargetRegisterClass *SrcSubRC =
5907 TRI->getSubRegisterClass(SrcRC, AMDGPU::sub0);
5908 Register Op1L =
5909 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub0, SrcSubRC);
5910 Register Op1H =
5911 TII->buildExtractSubReg(MI, MRI, Op, SrcRC, AMDGPU::sub1, SrcSubRC);
5912 return {Op1L, Op1H};
5913}
5914
5917 const GCNSubtarget &ST,
5918 unsigned Opc) {
5920 const SIRegisterInfo *TRI = ST.getRegisterInfo();
5921 const DebugLoc &DL = MI.getDebugLoc();
5922 const SIInstrInfo *TII = ST.getInstrInfo();
5923
5924 // Reduction operations depend on whether the input operand is SGPR or VGPR.
5925 Register SrcReg = MI.getOperand(1).getReg();
5926 bool isSGPR = TRI->isSGPRClass(MRI.getRegClass(SrcReg));
5927 Register DstReg = MI.getOperand(0).getReg();
5928 unsigned Stratergy = static_cast<unsigned>(MI.getOperand(2).getImm());
5929 enum WAVE_REDUCE_STRATEGY : unsigned { DEFAULT = 0, ITERATIVE = 1, DPP = 2 };
5930 MachineBasicBlock *RetBB = nullptr;
5931 unsigned MIOpc = MI.getOpcode();
5932 auto BuildRegSequence = [&](MachineBasicBlock &BB,
5934 Register Src0, Register Src1) {
5935 auto RegSequence =
5936 BuildMI(BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dst)
5937 .addReg(Src0)
5938 .addImm(AMDGPU::sub0)
5939 .addReg(Src1)
5940 .addImm(AMDGPU::sub1);
5941 return RegSequence;
5942 };
5943 if (isSGPR) {
5944 switch (Opc) {
5945 case AMDGPU::S_MIN_U32:
5946 case AMDGPU::S_MIN_I32:
5947 case AMDGPU::V_MIN_F32_e64:
5948 case AMDGPU::S_MAX_U32:
5949 case AMDGPU::S_MAX_I32:
5950 case AMDGPU::V_MAX_F32_e64:
5951 case AMDGPU::S_AND_B32:
5952 case AMDGPU::S_OR_B32: {
5953 // Idempotent operations.
5954 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B32), DstReg).addReg(SrcReg);
5955 RetBB = &BB;
5956 break;
5957 }
5958 case AMDGPU::V_CMP_LT_U64_e64: // umin
5959 case AMDGPU::V_CMP_LT_I64_e64: // min
5960 case AMDGPU::V_CMP_GT_U64_e64: // umax
5961 case AMDGPU::V_CMP_GT_I64_e64: // max
5962 case AMDGPU::V_MIN_F64_e64:
5963 case AMDGPU::V_MIN_NUM_F64_e64:
5964 case AMDGPU::V_MAX_F64_e64:
5965 case AMDGPU::V_MAX_NUM_F64_e64:
5966 case AMDGPU::S_AND_B64:
5967 case AMDGPU::S_OR_B64: {
5968 // Idempotent operations.
5969 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MOV_B64), DstReg).addReg(SrcReg);
5970 RetBB = &BB;
5971 break;
5972 }
5973 case AMDGPU::S_XOR_B32:
5974 case AMDGPU::S_XOR_B64:
5975 case AMDGPU::S_ADD_I32:
5976 case AMDGPU::S_ADD_U64_PSEUDO:
5977 case AMDGPU::V_ADD_F32_e64:
5978 case AMDGPU::V_ADD_F64_e64:
5979 case AMDGPU::V_ADD_F64_pseudo_e64:
5980 case AMDGPU::S_SUB_I32:
5981 case AMDGPU::S_SUB_U64_PSEUDO:
5982 case AMDGPU::V_SUB_F32_e64: {
5983 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
5984 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
5985 Register ExecMask = MRI.createVirtualRegister(WaveMaskRegClass);
5986 Register NumActiveLanes =
5987 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
5988
5989 bool IsWave32 = ST.isWave32();
5990 unsigned MovOpc = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
5991 MCRegister ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
5992 unsigned BitCountOpc =
5993 IsWave32 ? AMDGPU::S_BCNT1_I32_B32 : AMDGPU::S_BCNT1_I32_B64;
5994
5995 BuildMI(BB, MI, DL, TII->get(MovOpc), ExecMask).addReg(ExecReg);
5996
5997 auto NewAccumulator =
5998 BuildMI(BB, MI, DL, TII->get(BitCountOpc), NumActiveLanes)
5999 .addReg(ExecMask);
6000
6001 switch (Opc) {
6002 case AMDGPU::S_XOR_B32:
6003 case AMDGPU::S_XOR_B64: {
6004 // Performing an XOR operation on a uniform value
6005 // depends on the parity of the number of active lanes.
6006 // For even parity, the result will be 0, for odd
6007 // parity the result will be the same as the input value.
6008 Register ParityRegister =
6009 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6010
6011 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_AND_B32), ParityRegister)
6012 .addReg(NewAccumulator->getOperand(0).getReg())
6013 .addImm(1)
6014 .setOperandDead(3); // Dead scc
6015 if (Opc == AMDGPU::S_XOR_B32) {
6016 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6017 .addReg(SrcReg)
6018 .addReg(ParityRegister);
6019 } else {
6020 Register DestSub0 =
6021 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6022 Register DestSub1 =
6023 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6024 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6025 MRI.getRegClass(SrcReg), ST, MRI);
6026 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6027 .addReg(Op1L)
6028 .addReg(ParityRegister);
6029 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub1)
6030 .addReg(Op1H)
6031 .addReg(ParityRegister);
6032 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6033 }
6034 break;
6035 }
6036 case AMDGPU::S_SUB_I32: {
6037 Register NegatedVal = MRI.createVirtualRegister(DstRegClass);
6038
6039 // Take the negation of the source operand.
6040 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedVal)
6041 .addImm(0)
6042 .addReg(SrcReg);
6043 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6044 .addReg(NegatedVal)
6045 .addReg(NewAccumulator->getOperand(0).getReg());
6046 break;
6047 }
6048 case AMDGPU::S_ADD_I32: {
6049 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DstReg)
6050 .addReg(SrcReg)
6051 .addReg(NewAccumulator->getOperand(0).getReg());
6052 break;
6053 }
6054 case AMDGPU::S_ADD_U64_PSEUDO:
6055 case AMDGPU::S_SUB_U64_PSEUDO: {
6056 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6057 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6058 Register Op1H_Op0L_Reg =
6059 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6060 Register Op1L_Op0H_Reg =
6061 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6062 Register CarryReg =
6063 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6064 Register AddReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6065 Register NegatedValLo =
6066 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6067 Register NegatedValHi =
6068 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6069 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6070 MRI.getRegClass(SrcReg), ST, MRI);
6071 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6072 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedValLo)
6073 .addImm(0)
6074 .addReg(NewAccumulator->getOperand(0).getReg())
6075 .setOperandDead(3); // Dead scc
6076 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ASHR_I32), NegatedValHi)
6077 .addReg(NegatedValLo)
6078 .addImm(31)
6079 .setOperandDead(3); // Dead scc
6080 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1L_Op0H_Reg)
6081 .addReg(Op1L)
6082 .addReg(NegatedValHi);
6083 }
6084 Register LowOpcode = Opc == AMDGPU::S_SUB_U64_PSEUDO
6085 ? NegatedValLo
6086 : NewAccumulator->getOperand(0).getReg();
6087 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), DestSub0)
6088 .addReg(Op1L)
6089 .addReg(LowOpcode);
6090 if (ST.hasScalarMulHiInsts()) {
6091 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_HI_U32), CarryReg)
6092 .addReg(Op1L)
6093 .addReg(LowOpcode);
6094 } else {
6095 Register VCarryReg =
6096 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6097 Register LowOpVGPR =
6098 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6099 BuildMI(BB, MI, DL, TII->get(AMDGPU::COPY), LowOpVGPR)
6100 .addReg(LowOpcode);
6101 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_MUL_HI_U32_e64), VCarryReg)
6102 .addReg(Op1L)
6103 .addReg(LowOpVGPR);
6104 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), CarryReg)
6105 .addReg(VCarryReg);
6106 }
6107 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_MUL_I32), Op1H_Op0L_Reg)
6108 .addReg(Op1H)
6109 .addReg(LowOpcode);
6110
6111 Register HiVal = Opc == AMDGPU::S_SUB_U64_PSEUDO ? AddReg : DestSub1;
6112 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), HiVal)
6113 .addReg(CarryReg)
6114 .addReg(Op1H_Op0L_Reg)
6115 .setOperandDead(3); // Dead scc
6116
6117 if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6118 BuildMI(BB, MI, DL, TII->get(AMDGPU::S_ADD_U32), DestSub1)
6119 .addReg(HiVal)
6120 .addReg(Op1L_Op0H_Reg)
6121 .setOperandDead(3); // Dead scc
6122 }
6123 BuildRegSequence(BB, MI, DstReg, DestSub0, DestSub1);
6124 break;
6125 }
6126 case AMDGPU::V_ADD_F32_e64:
6127 case AMDGPU::V_ADD_F64_e64:
6128 case AMDGPU::V_ADD_F64_pseudo_e64:
6129 case AMDGPU::V_SUB_F32_e64: {
6130 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6131 const TargetRegisterClass *VregRC = TII->getRegClass(TII->get(Opc), 0);
6132 Register ActiveLanesVreg = MRI.createVirtualRegister(VregRC);
6133 Register DstVreg = MRI.createVirtualRegister(VregRC);
6134 // Get number of active lanes as a float val.
6135 BuildMI(BB, MI, DL,
6136 TII->get(is32BitOpc ? AMDGPU::V_CVT_F32_I32_e64
6137 : AMDGPU::V_CVT_F64_I32_e64),
6138 ActiveLanesVreg)
6139 .addReg(NewAccumulator->getOperand(0).getReg())
6140 .addImm(0) // clamp
6141 .addImm(0); // output-modifier
6142
6143 // Take negation of input for SUB reduction
6144 unsigned srcMod = (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6145 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64)
6148 unsigned MulOpc = is32BitOpc ? AMDGPU::V_MUL_F32_e64
6149 : ST.getGeneration() >= AMDGPUSubtarget::GFX12
6150 ? AMDGPU::V_MUL_F64_pseudo_e64
6151 : AMDGPU::V_MUL_F64_e64;
6152 auto DestVregInst = BuildMI(BB, MI, DL, TII->get(MulOpc),
6153 DstVreg)
6154 .addImm(srcMod) // src0 modifier
6155 .addReg(SrcReg)
6156 .addImm(SISrcMods::NONE) // src1 modifier
6157 .addReg(ActiveLanesVreg)
6158 .addImm(SISrcMods::NONE) // clamp
6159 .addImm(SISrcMods::NONE); // output-mod
6160 if (is32BitOpc) {
6161 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6162 .addReg(DstVreg);
6163 } else {
6164 Register LaneValueLoReg =
6165 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6166 Register LaneValueHiReg =
6167 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6168 auto [Op1L, Op1H] =
6169 ExtractSubRegs(MI, DestVregInst->getOperand(0), VregRC, ST, MRI);
6170 // lane value input should be in an sgpr
6171 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6172 LaneValueLoReg)
6173 .addReg(Op1L);
6174 BuildMI(BB, MI, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6175 LaneValueHiReg)
6176 .addReg(Op1H);
6177 NewAccumulator =
6178 BuildRegSequence(BB, MI, DstReg, LaneValueLoReg, LaneValueHiReg);
6179 }
6180 }
6181 }
6182 RetBB = &BB;
6183 }
6184 }
6185 } else {
6187 Register SrcReg = MI.getOperand(1).getReg();
6188 bool is32BitOpc = is32bitWaveReduceOperation(Opc);
6190 bool NeedsMovDPP = !is32BitOpc;
6191 // Create virtual registers required for lowering.
6192 const TargetRegisterClass *WaveMaskRegClass = TRI->getWaveMaskRegClass();
6193 const TargetRegisterClass *DstRegClass = MRI.getRegClass(DstReg);
6194 const TargetRegisterClass *SrcRegClass = MRI.getRegClass(SrcReg);
6195 bool IsWave32 = ST.isWave32();
6196 unsigned MovOpcForExec = IsWave32 ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
6197 unsigned ExecReg = IsWave32 ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
6198 if (Stratergy == WAVE_REDUCE_STRATEGY::ITERATIVE ||
6199 !ST.hasDPP()) { // If target doesn't support DPP operations, default to
6200 // iterative stratergy
6201
6202 // To reduce the VGPR using iterative approach, we need to iterate
6203 // over all the active lanes. Lowering consists of ComputeLoop,
6204 // which iterate over only active lanes. We use copy of EXEC register
6205 // as induction variable and every active lane modifies it using bitset0
6206 // so that we will get the next active lane for next iteration.
6207
6208 // Create Control flow for loop
6209 // Split MI's Machine Basic block into For loop
6210 auto [ComputeLoop, ComputeEnd] = splitBlockForLoop(MI, BB, true);
6211
6212 Register LoopIterator = MRI.createVirtualRegister(WaveMaskRegClass);
6213 Register IdentityValReg = MRI.createVirtualRegister(DstRegClass);
6214 Register AccumulatorReg = MRI.createVirtualRegister(DstRegClass);
6215 Register ActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6216 Register NewActiveBitsReg = MRI.createVirtualRegister(WaveMaskRegClass);
6217 Register FF1Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6218 Register LaneValueReg = MRI.createVirtualRegister(DstRegClass);
6219
6220 // Create initial values of induction variable from Exec, Accumulator and
6221 // insert branch instr to newly created ComputeBlock
6222 BuildMI(BB, I, DL, TII->get(MovOpcForExec), LoopIterator).addReg(ExecReg);
6223 uint64_t IdentityValue =
6224 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6225 ? 0x0 // +0.0 for double sub reduction
6227 BuildMI(BB, I, DL,
6228 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6229 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6230 IdentityValReg)
6231 .addImm(IdentityValue);
6232 // clang-format off
6233 BuildMI(BB, I, DL, TII->get(AMDGPU::S_BRANCH))
6234 .addMBB(ComputeLoop);
6235 // clang-format on
6236
6237 // Start constructing ComputeLoop
6238 I = ComputeLoop->begin();
6239 auto Accumulator =
6240 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), AccumulatorReg)
6241 .addReg(IdentityValReg)
6242 .addMBB(&BB);
6243 auto ActiveBits =
6244 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::PHI), ActiveBitsReg)
6245 .addReg(LoopIterator)
6246 .addMBB(&BB);
6247
6248 I = ComputeLoop->end();
6249 MachineInstr *NewAccumulator;
6250 // Perform the computations
6251 unsigned SFFOpc =
6252 IsWave32 ? AMDGPU::S_FF1_I32_B32 : AMDGPU::S_FF1_I32_B64;
6253 BuildMI(*ComputeLoop, I, DL, TII->get(SFFOpc), FF1Reg)
6254 .addReg(ActiveBitsReg);
6255 if (is32BitOpc) {
6256 Register OpDstReg = DstReg;
6257 bool hasSrc0Modifier = AMDGPU::getNamedOperandIdx(
6258 Opc, AMDGPU::OpName::src0_modifiers) != -1;
6259 bool hasSrc1Modifier = AMDGPU::getNamedOperandIdx(
6260 Opc, AMDGPU::OpName::src1_modifiers) != -1;
6261 bool hasClamp =
6262 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1;
6263 bool hasOpSel =
6264 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel) != -1;
6265 bool hasOMod =
6266 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1;
6267 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6268 LaneValueReg)
6269 .addReg(SrcReg)
6270 .addReg(FF1Reg);
6271 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6272 // Get the Lane Value in VGPR to avoid the Constant Bus Restriction
6273 Register LaneValVgpr = MRI.createVirtualRegister(SrcRegClass);
6274 Register VgprResultReg = MRI.createVirtualRegister(SrcRegClass);
6275 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), LaneValVgpr)
6276 .addReg(LaneValueReg);
6277 OpDstReg = VgprResultReg;
6278 LaneValueReg = LaneValVgpr;
6279 }
6280 auto OpInstr = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), OpDstReg);
6281 if (hasSrc0Modifier)
6282 OpInstr.addImm(SISrcMods::NONE); // src0 modifier
6283 OpInstr.addReg(AccumulatorReg); // src0
6284 if (hasSrc1Modifier)
6285 OpInstr.addImm(SISrcMods::NONE); // src1 modifier
6286 OpInstr.addReg(LaneValueReg); // src1
6287 if (hasClamp)
6288 OpInstr.addImm(0); // clamp
6289 if (hasOpSel)
6290 OpInstr.addImm(0); // opsel
6291 if (hasOMod)
6292 OpInstr.addImm(0); // omod
6293 if (ST.getInstrInfo()->isVALU(Opc, /*AllowLDSDMA=*/true)) {
6294 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32),
6295 DstReg)
6296 .addReg(OpDstReg);
6297 }
6298 } else {
6299 Register LaneValueLoReg =
6300 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6301 Register LaneValueHiReg =
6302 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6303 Register LaneValReg =
6304 MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
6305 auto [Op1L, Op1H] = ExtractSubRegs(MI, MI.getOperand(1),
6306 MRI.getRegClass(SrcReg), ST, MRI);
6307 // lane value input should be in an sgpr
6308 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6309 LaneValueLoReg)
6310 .addReg(Op1L)
6311 .addReg(FF1Reg);
6312 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::V_READLANE_B32),
6313 LaneValueHiReg)
6314 .addReg(Op1H)
6315 .addReg(FF1Reg);
6316 auto LaneValue = BuildRegSequence(*ComputeLoop, I, LaneValReg,
6317 LaneValueLoReg, LaneValueHiReg);
6318 switch (Opc) {
6319 case AMDGPU::S_OR_B64:
6320 case AMDGPU::S_AND_B64:
6321 case AMDGPU::S_XOR_B64: {
6322 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6323 .addReg(Accumulator->getOperand(0).getReg())
6324 .addReg(LaneValue->getOperand(0).getReg())
6325 .setOperandDead(3); // Dead scc
6326 break;
6327 }
6328 case AMDGPU::V_CMP_GT_I64_e64:
6329 case AMDGPU::V_CMP_GT_U64_e64:
6330 case AMDGPU::V_CMP_LT_I64_e64:
6331 case AMDGPU::V_CMP_LT_U64_e64: {
6332 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6333 Register ComparisonResultReg =
6334 MRI.createVirtualRegister(WaveMaskRegClass);
6335 int SrcIdx =
6336 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6337 const TargetRegisterClass *VregClass =
6338 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6339 Register AccumulatorVReg = MRI.createVirtualRegister(VregClass);
6340 auto [SrcReg0Sub0, SrcReg0Sub1] = ExtractSubRegs(
6341 MI, Accumulator->getOperand(0), VregClass, ST, MRI);
6342 BuildRegSequence(*ComputeLoop, I, AccumulatorVReg, SrcReg0Sub0,
6343 SrcReg0Sub1);
6344 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), LaneMaskReg)
6345 .addReg(LaneValue->getOperand(0).getReg())
6346 .addReg(AccumulatorVReg);
6347
6348 unsigned AndOpc = IsWave32 ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64;
6349 BuildMI(*ComputeLoop, I, DL, TII->get(AndOpc), ComparisonResultReg)
6350 .addReg(LaneMaskReg)
6351 .addReg(ActiveBitsReg);
6352
6353 NewAccumulator = BuildMI(*ComputeLoop, I, DL,
6354 TII->get(AMDGPU::S_CSELECT_B64), DstReg)
6355 .addReg(LaneValue->getOperand(0).getReg())
6356 .addReg(Accumulator->getOperand(0).getReg());
6357 break;
6358 }
6359 case AMDGPU::V_MIN_F64_e64:
6360 case AMDGPU::V_MIN_NUM_F64_e64:
6361 case AMDGPU::V_MAX_F64_e64:
6362 case AMDGPU::V_MAX_NUM_F64_e64:
6363 case AMDGPU::V_ADD_F64_e64:
6364 case AMDGPU::V_ADD_F64_pseudo_e64: {
6365 int SrcIdx =
6366 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src);
6367 const TargetRegisterClass *VregRC =
6368 TRI->getAllocatableClass(TII->getRegClass(MI.getDesc(), SrcIdx));
6369 Register AccumulatorVReg = MRI.createVirtualRegister(VregRC);
6370 Register DstVreg = MRI.createVirtualRegister(VregRC);
6371 Register LaneValLo =
6372 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6373 Register LaneValHi =
6374 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6375 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::COPY), AccumulatorVReg)
6376 .addReg(Accumulator->getOperand(0).getReg());
6377 unsigned Modifier =
6378 MI.getOpcode() == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64
6381 auto DstVregInst =
6382 BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstVreg)
6383 .addImm(Modifier) // src0 modifiers
6384 .addReg(LaneValue->getOperand(0).getReg())
6385 .addImm(SISrcMods::NONE) // src1 modifiers
6386 .addReg(AccumulatorVReg)
6387 .addImm(SISrcMods::NONE) // clamp
6388 .addImm(SISrcMods::NONE); // omod
6389 auto ReadLaneLo =
6390 BuildMI(*ComputeLoop, I, DL,
6391 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValLo);
6392 auto ReadLaneHi =
6393 BuildMI(*ComputeLoop, I, DL,
6394 TII->get(AMDGPU::V_READFIRSTLANE_B32), LaneValHi);
6395 MachineBasicBlock::iterator Iters = *ReadLaneLo;
6396 auto [Op1L, Op1H] = ExtractSubRegs(*Iters, DstVregInst->getOperand(0),
6397 VregRC, ST, MRI);
6398 ReadLaneLo.addReg(Op1L);
6399 ReadLaneHi.addReg(Op1H);
6400 NewAccumulator =
6401 BuildRegSequence(*ComputeLoop, I, DstReg, LaneValLo, LaneValHi);
6402 break;
6403 }
6404 case AMDGPU::S_ADD_U64_PSEUDO:
6405 case AMDGPU::S_SUB_U64_PSEUDO: {
6406 NewAccumulator = BuildMI(*ComputeLoop, I, DL, TII->get(Opc), DstReg)
6407 .addReg(Accumulator->getOperand(0).getReg())
6408 .addReg(LaneValue->getOperand(0).getReg());
6409 ComputeLoop =
6410 expand64BitScalarArithmetic(*NewAccumulator, ComputeLoop);
6411 break;
6412 }
6413 }
6414 }
6415 // Manipulate the iterator to get the next active lane
6416 unsigned BITSETOpc =
6417 IsWave32 ? AMDGPU::S_BITSET0_B32 : AMDGPU::S_BITSET0_B64;
6418 BuildMI(*ComputeLoop, I, DL, TII->get(BITSETOpc), NewActiveBitsReg)
6419 .addReg(FF1Reg)
6420 .addReg(ActiveBitsReg);
6421
6422 // Add phi nodes
6423 Accumulator.addReg(DstReg).addMBB(ComputeLoop);
6424 ActiveBits.addReg(NewActiveBitsReg).addMBB(ComputeLoop);
6425
6426 // Creating branching
6427 MachineInstrBuilder SetSCCInstr;
6428 if (!ST.hasScalarCompareEq64()) {
6429 // For targets <= gfx7, use an S_OR_B32/B64 instruction to set SCC.
6430 Register LaneMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6431 unsigned CMPOpc = IsWave32 ? AMDGPU::S_OR_B32 : AMDGPU::S_OR_B64;
6432 SetSCCInstr =
6433 BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc), LaneMaskReg);
6434 } else {
6435 unsigned CMPOpc =
6436 IsWave32 ? AMDGPU::S_CMP_LG_U32 : AMDGPU::S_CMP_LG_U64;
6437 SetSCCInstr = BuildMI(*ComputeLoop, I, DL, TII->get(CMPOpc));
6438 }
6439 SetSCCInstr.addReg(NewActiveBitsReg);
6440 if (ST.hasScalarCompareEq64())
6441 SetSCCInstr.addImm(0);
6442 else
6443 SetSCCInstr.addReg(NewActiveBitsReg);
6444 BuildMI(*ComputeLoop, I, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
6445 .addMBB(ComputeLoop);
6446
6447 RetBB = ComputeEnd;
6448 } else {
6449 assert(ST.hasDPP() && "Sub Target does not support DPP Operations");
6450 MachineBasicBlock *CurrBB = &BB;
6451 Register SrcWithIdentity = MRI.createVirtualRegister(SrcRegClass);
6452 Register IdentityVGPR = MRI.createVirtualRegister(SrcRegClass);
6453 Register IdentitySGPR = MRI.createVirtualRegister(DstRegClass);
6454 Register DPPRowShr1 = MRI.createVirtualRegister(SrcRegClass);
6455 Register DPPRowShr2 = MRI.createVirtualRegister(SrcRegClass);
6456 Register DPPRowShr4 = MRI.createVirtualRegister(SrcRegClass);
6457 Register DPPRowShr8 = MRI.createVirtualRegister(SrcRegClass);
6458 Register RowBcast15 = MRI.createVirtualRegister(SrcRegClass);
6459 Register ReducedValSGPR = MRI.createVirtualRegister(DstRegClass);
6460 Register NegatedReducedVal = MRI.createVirtualRegister(DstRegClass);
6461 Register RowBcast31 = MRI.createVirtualRegister(SrcRegClass);
6462 Register UndefExec = MRI.createVirtualRegister(WaveMaskRegClass);
6463 Register FinalDPPResult;
6464 MachineInstr *SrcWithIdentityInstr;
6465 MachineInstr *LastBcastInstr;
6466 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), UndefExec);
6467
6469 BuildMI(*CurrBB, MI, DL,
6470 TII->get(is32BitOpc ? AMDGPU::S_MOV_B32
6471 : AMDGPU::S_MOV_B64_IMM_PSEUDO),
6472 IdentitySGPR)
6473 .addImm(IdentityValue);
6474 auto IdentityCopyInstr =
6475 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::COPY), IdentityVGPR)
6476 .addReg(IdentitySGPR);
6477 auto DPPClampOpcPair = getDPPOpcForWaveReduction(Opc, ST);
6478 unsigned DPPOpc = std::get<0>(DPPClampOpcPair);
6479 unsigned ClampOpc = std::get<1>(DPPClampOpcPair);
6480 auto BuildSetInactiveInstr = [&](Register Dst, Register Src0,
6481 Register Src1) {
6482 return BuildMI(BB, MI, DL, TII->get(AMDGPU::V_SET_INACTIVE_B32),
6483 Dst)
6484 .addImm(0) // src0 modifiers
6485 .addReg(Src0) // src0
6486 .addImm(0) // src1 modifiers
6487 .addReg(Src1) // identity value for inactive lanes
6488 .addReg(UndefExec); // bool i1
6489 };
6490 auto BuildDPPMachineInstr = [&](Register Dst, Register Src,
6491 unsigned DPPCtrl) {
6492 auto DPPInstr =
6493 BuildMI(*CurrBB, MI, DL, TII->get(DPPOpc), Dst).addReg(Src); // old
6494 if (isFPOp && !NeedsMovDPP)
6495 DPPInstr.addImm(SISrcMods::NONE); // src0 modifier
6496 DPPInstr.addReg(Src); // src0
6497 if (isFPOp && !NeedsMovDPP)
6498 DPPInstr.addImm(SISrcMods::NONE); // src1 modifier
6499 if (!NeedsMovDPP)
6500 DPPInstr.addReg(Src); // src1
6501 if (AMDGPU::getNamedOperandIdx(DPPOpc, AMDGPU::OpName::clamp) >= 0)
6502 DPPInstr.addImm(0); // clamp
6503 DPPInstr
6504 .addImm(DPPCtrl) // dpp-ctrl
6505 .addImm(0xf) // row-mask
6506 .addImm(0xf) // bank-mask
6507 .addImm(0); // bound-control
6508 };
6509 auto BuildClampInstr = [&](Register Dst, Register Src0, Register Src1,
6510 bool isAddSub = false,
6511 bool needsCarryIn = false,
6512 Register CarryIn = Register()) {
6513 unsigned InstrOpc = ClampOpc;
6514 Register CarryOutReg = MRI.createVirtualRegister(WaveMaskRegClass);
6515 if (needsCarryIn)
6516 InstrOpc = AMDGPU::V_ADDC_U32_e64;
6517 auto ClampInstr = BuildMI(*CurrBB, MI, DL, TII->get(InstrOpc), Dst);
6518 if (isFPOp)
6519 ClampInstr.addImm(SISrcMods::NONE); // src0 mod
6520 if (isAddSub) {
6521 if (needsCarryIn)
6522 ClampInstr.addReg(CarryOutReg,
6524 RegState::Dead); // killed carry-out reg
6525 else
6526 ClampInstr.addReg(CarryOutReg, RegState::Define); // carry-out reg
6527 }
6528 ClampInstr.addReg(Src0); // src0
6529 if (isFPOp)
6530 ClampInstr.addImm(SISrcMods::NONE); // src1 mod
6531 ClampInstr.addReg(Src1); // src1
6532 if (needsCarryIn)
6533 ClampInstr.addReg(CarryIn, RegState::Kill); // carry-in reg
6534 if (AMDGPU::getNamedOperandIdx(InstrOpc, AMDGPU::OpName::clamp) >= 0)
6535 ClampInstr.addImm(0); // clamp
6536 if (isFPOp)
6537 ClampInstr.addImm(0); // omod
6538 LastBcastInstr = ClampInstr;
6539 return CarryOutReg;
6540 };
6541 auto BuildPostDPPInstr = [&](Register Src0, Register Src1) {
6542 bool isAddSubOpc =
6543 Opc == AMDGPU::S_ADD_U64_PSEUDO || Opc == AMDGPU::S_SUB_U64_PSEUDO;
6544 bool isBitWiseOpc = Opc == AMDGPU::S_AND_B64 ||
6545 Opc == AMDGPU::S_OR_B64 || Opc == AMDGPU::S_XOR_B64;
6546 Register ReturnReg = MRI.createVirtualRegister(SrcRegClass);
6547 if (isAddSubOpc || isBitWiseOpc) {
6548 Register ResLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6549 Register ResHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6550 MachineOperand Src0Operand =
6551 MachineOperand::CreateReg(Src0, /*isDef=*/false);
6552 MachineOperand Src1Operand =
6553 MachineOperand::CreateReg(Src1, /*isDef=*/false);
6554 auto [Src0Lo, Src0Hi] =
6555 ExtractSubRegs(MI, Src0Operand, SrcRegClass, ST, MRI);
6556 auto [Src1Lo, Src1Hi] =
6557 ExtractSubRegs(MI, Src1Operand, SrcRegClass, ST, MRI);
6558 Register CarryReg = BuildClampInstr(
6559 ResLo, Src0Lo, Src1Lo, isAddSubOpc, /*needsCarryIn*/ false);
6560 BuildClampInstr(ResHi, Src0Hi, Src1Hi, isAddSubOpc,
6561 /*needsCarryIn*/ isAddSubOpc, CarryReg);
6562 BuildRegSequence(*CurrBB, MI, ReturnReg, ResLo, ResHi);
6563 } else {
6564 if (isFPOp) {
6565 BuildMI(*CurrBB, MI, DL, TII->get(Opc), ReturnReg)
6566 .addImm(SISrcMods::NONE) // src0 modifiers
6567 .addReg(Src0)
6568 .addImm(SISrcMods::NONE) // src1 modifiers
6569 .addReg(Src1)
6570 .addImm(SISrcMods::NONE) // clamp
6571 .addImm(SISrcMods::NONE); // omod
6572 } else {
6573 Register CmpMaskReg = MRI.createVirtualRegister(WaveMaskRegClass);
6574 BuildMI(*CurrBB, MI, DL, TII->get(Opc), CmpMaskReg)
6575 .addReg(Src0) // src0
6576 .addReg(Src1); // src1
6577 LastBcastInstr =
6578 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B64_PSEUDO),
6579 ReturnReg)
6580 .addReg(Src1) // src0
6581 .addReg(Src0) // src1
6582 .addReg(CmpMaskReg); // src2
6583 expand64BitV_CNDMASK(*LastBcastInstr, CurrBB);
6584 }
6585 }
6586 return ReturnReg;
6587 };
6588
6589 // Set inactive lanes to the identity value.
6590 if (is32BitOpc) {
6591 SrcWithIdentityInstr =
6592 BuildSetInactiveInstr(SrcWithIdentity, SrcReg, IdentityVGPR);
6593 } else {
6594 Register SrcWithIdentitylo =
6595 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6596 Register SrcWithIdentityhi =
6597 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6598 auto [Reg0Sub0, Reg0Sub1] = ExtractSubRegs(
6599 MI, IdentityCopyInstr->getOperand(0), SrcRegClass, ST, MRI);
6600 auto [SrcReg0Sub0, SrcReg0Sub1] =
6601 ExtractSubRegs(MI, MI.getOperand(1), SrcRegClass, ST, MRI);
6602 MachineInstr *SetInactiveLoInstr =
6603 BuildSetInactiveInstr(SrcWithIdentitylo, SrcReg0Sub0, Reg0Sub0);
6604 MachineInstr *SetInactiveHiInstr =
6605 BuildSetInactiveInstr(SrcWithIdentityhi, SrcReg0Sub1, Reg0Sub1);
6606 SrcWithIdentityInstr =
6607 BuildRegSequence(*CurrBB, MI, SrcWithIdentity,
6608 SetInactiveLoInstr->getOperand(0).getReg(),
6609 SetInactiveHiInstr->getOperand(0).getReg());
6610 }
6611 // DPP reduction
6612 Register SrcWithIdentityReg =
6613 SrcWithIdentityInstr->getOperand(0).getReg();
6614 BuildDPPMachineInstr(DPPRowShr1, SrcWithIdentityReg,
6616 if (NeedsMovDPP)
6617 DPPRowShr1 = BuildPostDPPInstr(SrcWithIdentityReg, DPPRowShr1);
6618
6619 BuildDPPMachineInstr(DPPRowShr2, DPPRowShr1,
6621 if (NeedsMovDPP)
6622 DPPRowShr2 = BuildPostDPPInstr(DPPRowShr1, DPPRowShr2);
6623
6624 BuildDPPMachineInstr(DPPRowShr4, DPPRowShr2,
6626 if (NeedsMovDPP)
6627 DPPRowShr4 = BuildPostDPPInstr(DPPRowShr2, DPPRowShr4);
6628
6629 BuildDPPMachineInstr(DPPRowShr8, DPPRowShr4,
6631 if (NeedsMovDPP)
6632 DPPRowShr8 = BuildPostDPPInstr(DPPRowShr4, DPPRowShr8);
6633
6634 if (ST.hasDPPBroadcasts()) {
6635 BuildDPPMachineInstr(RowBcast15, DPPRowShr8, AMDGPU::DPP::BCAST15);
6636 if (NeedsMovDPP)
6637 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, RowBcast15);
6638 } else {
6639 // magic constant: 0x1E0
6640 // To Set BIT_MODE : bit 15 = 0
6641 // XOR mask : bit [14:10] = 0
6642 // OR mask : bit [9:5] = 15
6643 // AND mask : bit [4:0] = 0
6644 if (is32BitOpc) {
6645 Register SwizzledValue =
6646 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6647 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6648 SwizzledValue)
6649 .addReg(DPPRowShr8) // addr
6650 .addImm(0x1E0) // swizzle offset (i16)
6651 .addImm(0x0); // gds (i1)
6652 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue);
6653 } else {
6654 Register SwizzledValuelo =
6655 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6656 Register SwizzledValuehi =
6657 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6658 Register SwizzledValue64 = MRI.createVirtualRegister(SrcRegClass);
6659 MachineOperand DPPRowShr8Op =
6660 MachineOperand::CreateReg(DPPRowShr8, /*isDef=*/false);
6661 auto [Op1L, Op1H] =
6662 ExtractSubRegs(MI, DPPRowShr8Op, SrcRegClass, ST, MRI);
6663 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6664 SwizzledValuelo)
6665 .addReg(Op1L) // addr
6666 .addImm(0x1E0) // swizzle offset (i16)
6667 .addImm(0x0); // gds (i1)
6668 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_SWIZZLE_B32),
6669 SwizzledValuehi)
6670 .addReg(Op1H) // addr
6671 .addImm(0x1E0) // swizzle offset (i16)
6672 .addImm(0x0); // gds (i1)
6673 BuildRegSequence(*CurrBB, MI, SwizzledValue64, SwizzledValuelo,
6674 SwizzledValuehi);
6675 if (NeedsMovDPP)
6676 RowBcast15 = BuildPostDPPInstr(DPPRowShr8, SwizzledValue64);
6677 else
6678 BuildClampInstr(RowBcast15, DPPRowShr8, SwizzledValue64);
6679 }
6680 }
6681 FinalDPPResult = RowBcast15;
6682 if (!IsWave32) {
6683 if (ST.hasDPPBroadcasts()) {
6684 BuildDPPMachineInstr(RowBcast31, RowBcast15, AMDGPU::DPP::BCAST31);
6685 if (NeedsMovDPP)
6686 RowBcast31 = BuildPostDPPInstr(RowBcast15, RowBcast31);
6687 } else {
6688 Register ShiftedThreadID =
6689 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6690 Register PermuteByteOffset =
6691 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6692 Register PermutedValue = MRI.createVirtualRegister(SrcRegClass);
6693 Register Lane32Offset =
6694 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6695 Register WordSizeConst =
6696 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6697 Register ThreadIDRegLo =
6698 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6699 Register ThreadIDReg =
6700 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6701 // Get the thread ID.
6702 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_LO_U32_B32_e64),
6703 ThreadIDRegLo)
6704 .addImm(-1)
6705 .addImm(0);
6706 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MBCNT_HI_U32_B32_e64),
6707 ThreadIDReg)
6708 .addImm(-1)
6709 .addReg(ThreadIDRegLo);
6710 // shift each lane over by 32 positions, so value in 31st lane is
6711 // present in 63rd lane.
6712 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), Lane32Offset)
6713 .addImm(0x20);
6714 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_ADD_U32_e64),
6715 ShiftedThreadID)
6716 .addReg(ThreadIDReg)
6717 .addReg(Lane32Offset)
6718 .addImm(0); // clamp
6719 // multiply by reg size.
6720 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), WordSizeConst)
6721 .addImm(0x4);
6722 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_MUL_LO_U32_e64),
6723 PermuteByteOffset)
6724 .addReg(WordSizeConst)
6725 .addReg(ShiftedThreadID);
6726 // Permute the lanes
6727 if (is32BitOpc) {
6728 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6729 PermutedValue)
6730 .addReg(PermuteByteOffset) // addr
6731 .addReg(RowBcast15) // data
6732 .addImm(0); // offset
6733 } else {
6734 Register PermutedValuelo =
6735 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6736 Register PermutedValuehi =
6737 MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6738 MachineOperand RowBcast15Op =
6739 MachineOperand::CreateReg(RowBcast15, /*isDef=*/false);
6740 auto [RowBcast15Lo, RowBcast15Hi] =
6741 ExtractSubRegs(MI, RowBcast15Op, SrcRegClass, ST, MRI);
6742 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6743 PermutedValuelo)
6744 .addReg(PermuteByteOffset) // addr
6745 .addReg(RowBcast15Lo) // swizzle offset (i16)
6746 .addImm(0x0); // gds (i1)
6747 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::DS_PERMUTE_B32),
6748 PermutedValuehi)
6749 .addReg(PermuteByteOffset) // addr
6750 .addReg(RowBcast15Hi) // swizzle offset (i16)
6751 .addImm(0x0); // gds (i1)
6752 BuildRegSequence(*CurrBB, MI, PermutedValue, PermutedValuelo,
6753 PermutedValuehi);
6754 }
6755 if (NeedsMovDPP)
6756 RowBcast31 = BuildPostDPPInstr(RowBcast15, PermutedValue);
6757 else
6758 BuildClampInstr(RowBcast31, RowBcast15, PermutedValue);
6759 }
6760 FinalDPPResult = RowBcast31;
6761 }
6762 if (MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32 ||
6763 MIOpc == AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64) {
6764 Register NegatedValVGPR = MRI.createVirtualRegister(SrcRegClass);
6765 // Opc for f32 reduction is V_SUB_F32.
6766 // For f64, there is no equivalent V_SUB_F64 opcode, so use
6767 // V_ADD_F64/V_ADD_F64_pseudo, and negate the second operand.
6768 BuildMI(*CurrBB, MI, DL, TII->get(Opc),
6769 NegatedValVGPR)
6770 .addImm(SISrcMods::NONE) // src0 mods
6771 .addReg(IdentityVGPR) // src0
6772 .addImm(is32BitOpc ? SISrcMods::NONE : SISrcMods::NEG) // src1 mods
6773 .addReg(IsWave32 ? RowBcast15 : RowBcast31) // src1
6774 .addImm(SISrcMods::NONE) // clamp
6775 .addImm(SISrcMods::NONE); // omod
6776 FinalDPPResult = NegatedValVGPR;
6777 }
6778 // The final reduced value is in the last lane.
6779 if (is32BitOpc) {
6780 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6781 ReducedValSGPR)
6782 .addReg(FinalDPPResult)
6783 .addImm(ST.getWavefrontSize() - 1);
6784 } else {
6785 Register LaneValueLoReg =
6786 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6787 Register LaneValueHiReg =
6788 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6789 const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
6790 MachineOperand FinalDPPResultOperand =
6791 MachineOperand::CreateReg(FinalDPPResult, /*isDef=*/false);
6792 auto [Op1L, Op1H] =
6793 ExtractSubRegs(MI, FinalDPPResultOperand, SrcRC, ST, MRI);
6794 // lane value input should be in an sgpr
6795 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6796 LaneValueLoReg)
6797 .addReg(Op1L)
6798 .addImm(ST.getWavefrontSize() - 1);
6799 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::V_READLANE_B32),
6800 LaneValueHiReg)
6801 .addReg(Op1H)
6802 .addImm(ST.getWavefrontSize() - 1);
6803 BuildRegSequence(*CurrBB, MI, ReducedValSGPR, LaneValueLoReg,
6804 LaneValueHiReg);
6805 }
6806 if (Opc == AMDGPU::S_SUB_I32) {
6807 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::S_SUB_I32), NegatedReducedVal)
6808 .addImm(0)
6809 .addReg(ReducedValSGPR);
6810 } else if (Opc == AMDGPU::S_SUB_U64_PSEUDO) {
6811 auto NegatedValInstr =
6812 BuildMI(*CurrBB, MI, DL, TII->get(Opc), NegatedReducedVal)
6813 .addImm(0)
6814 .addReg(ReducedValSGPR);
6815 CurrBB = expand64BitScalarArithmetic(*NegatedValInstr, CurrBB);
6816 }
6817 // Mark the final result as a whole-wave-mode calculation.
6818 BuildMI(*CurrBB, MI, DL, TII->get(AMDGPU::STRICT_WWM), DstReg)
6819 .addReg(Opc == AMDGPU::S_SUB_I32 || Opc == AMDGPU::S_SUB_U64_PSEUDO
6820 ? NegatedReducedVal
6821 : ReducedValSGPR);
6822 RetBB = CurrBB;
6823 }
6824 }
6825 MI.eraseFromParent();
6826 return RetBB;
6827}
6828
6831 MachineBasicBlock *BB) const {
6832 MachineFunction *MF = BB->getParent();
6834 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
6836 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
6837 MachineRegisterInfo &MRI = MF->getRegInfo();
6838 const DebugLoc &DL = MI.getDebugLoc();
6839
6840 switch (MI.getOpcode()) {
6841 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U32:
6842 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_U32);
6843 case AMDGPU::WAVE_REDUCE_UMIN_PSEUDO_U64:
6844 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_U64_e64);
6845 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I32:
6846 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MIN_I32);
6847 case AMDGPU::WAVE_REDUCE_MIN_PSEUDO_I64:
6848 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_LT_I64_e64);
6849 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F32:
6850 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MIN_F32_e64);
6851 case AMDGPU::WAVE_REDUCE_FMIN_PSEUDO_F64:
6852 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6853 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6854 ? AMDGPU::V_MIN_NUM_F64_e64
6855 : AMDGPU::V_MIN_F64_e64);
6856 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U32:
6857 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_U32);
6858 case AMDGPU::WAVE_REDUCE_UMAX_PSEUDO_U64:
6859 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_U64_e64);
6860 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I32:
6861 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_MAX_I32);
6862 case AMDGPU::WAVE_REDUCE_MAX_PSEUDO_I64:
6863 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_CMP_GT_I64_e64);
6864 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F32:
6865 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_MAX_F32_e64);
6866 case AMDGPU::WAVE_REDUCE_FMAX_PSEUDO_F64:
6867 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6868 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6869 ? AMDGPU::V_MAX_NUM_F64_e64
6870 : AMDGPU::V_MAX_F64_e64);
6871 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_I32:
6872 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_I32);
6873 case AMDGPU::WAVE_REDUCE_ADD_PSEUDO_U64:
6874 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_ADD_U64_PSEUDO);
6875 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F32:
6876 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_ADD_F32_e64);
6877 case AMDGPU::WAVE_REDUCE_FADD_PSEUDO_F64:
6878 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6879 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6880 ? AMDGPU::V_ADD_F64_pseudo_e64
6881 : AMDGPU::V_ADD_F64_e64);
6882 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_I32:
6883 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_I32);
6884 case AMDGPU::WAVE_REDUCE_SUB_PSEUDO_U64:
6885 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_SUB_U64_PSEUDO);
6886 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F32:
6887 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::V_SUB_F32_e64);
6888 case AMDGPU::WAVE_REDUCE_FSUB_PSEUDO_F64:
6889 // There is no S/V_SUB_F64 opcode. Double type subtraction is expanded as
6890 // fadd + neg, by setting the NEG bit in the instruction.
6891 return lowerWaveReduce(MI, *BB, *getSubtarget(),
6892 ST.getGeneration() >= AMDGPUSubtarget::GFX12
6893 ? AMDGPU::V_ADD_F64_pseudo_e64
6894 : AMDGPU::V_ADD_F64_e64);
6895 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B32:
6896 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B32);
6897 case AMDGPU::WAVE_REDUCE_AND_PSEUDO_B64:
6898 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_AND_B64);
6899 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B32:
6900 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B32);
6901 case AMDGPU::WAVE_REDUCE_OR_PSEUDO_B64:
6902 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_OR_B64);
6903 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B32:
6904 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B32);
6905 case AMDGPU::WAVE_REDUCE_XOR_PSEUDO_B64:
6906 return lowerWaveReduce(MI, *BB, *getSubtarget(), AMDGPU::S_XOR_B64);
6907 case AMDGPU::S_UADDO_PSEUDO:
6908 case AMDGPU::S_USUBO_PSEUDO: {
6909 MachineOperand &Dest0 = MI.getOperand(0);
6910 MachineOperand &Dest1 = MI.getOperand(1);
6911 MachineOperand &Src0 = MI.getOperand(2);
6912 MachineOperand &Src1 = MI.getOperand(3);
6913
6914 unsigned Opc = (MI.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
6915 ? AMDGPU::S_ADD_U32
6916 : AMDGPU::S_SUB_U32;
6917 // clang-format off
6918 BuildMI(*BB, MI, DL, TII->get(Opc), Dest0.getReg())
6919 .add(Src0)
6920 .add(Src1);
6921 // clang-format on
6922
6923 unsigned SelOpc =
6924 Subtarget->isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
6925 BuildMI(*BB, MI, DL, TII->get(SelOpc), Dest1.getReg()).addImm(-1).addImm(0);
6926
6927 MI.eraseFromParent();
6928 return BB;
6929 }
6930 case AMDGPU::S_ADD_U64_PSEUDO:
6931 case AMDGPU::S_SUB_U64_PSEUDO: {
6932 return expand64BitScalarArithmetic(MI, BB);
6933 }
6934 case AMDGPU::V_ADD_U64_PSEUDO:
6935 case AMDGPU::V_SUB_U64_PSEUDO: {
6936 bool IsAdd = (MI.getOpcode() == AMDGPU::V_ADD_U64_PSEUDO);
6937
6938 MachineOperand &Dest = MI.getOperand(0);
6939 MachineOperand &Src0 = MI.getOperand(1);
6940 MachineOperand &Src1 = MI.getOperand(2);
6941
6942 if (ST.hasAddSubU64Insts()) {
6943 auto I = BuildMI(*BB, MI, DL,
6944 TII->get(IsAdd ? AMDGPU::V_ADD_U64_e64
6945 : AMDGPU::V_SUB_U64_e64),
6946 Dest.getReg())
6947 .add(Src0)
6948 .add(Src1)
6949 .addImm(0); // clamp
6950 TII->legalizeOperands(*I);
6951 MI.eraseFromParent();
6952 return BB;
6953 }
6954
6955 if (IsAdd && ST.hasLshlAddU64Inst()) {
6956 auto Add = BuildMI(*BB, MI, DL, TII->get(AMDGPU::V_LSHL_ADD_U64_e64),
6957 Dest.getReg())
6958 .add(Src0)
6959 .addImm(0)
6960 .add(Src1);
6961 TII->legalizeOperands(*Add);
6962 MI.eraseFromParent();
6963 return BB;
6964 }
6965
6966 const auto *CarryRC = TRI->getWaveMaskRegClass();
6967
6968 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6969 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6970
6971 Register CarryReg = MRI.createVirtualRegister(CarryRC);
6972 Register DeadCarryReg = MRI.createVirtualRegister(CarryRC);
6973
6974 const TargetRegisterClass *Src0RC = Src0.isReg()
6975 ? MRI.getRegClass(Src0.getReg())
6976 : &AMDGPU::VReg_64RegClass;
6977 const TargetRegisterClass *Src1RC = Src1.isReg()
6978 ? MRI.getRegClass(Src1.getReg())
6979 : &AMDGPU::VReg_64RegClass;
6980
6981 const TargetRegisterClass *Src0SubRC =
6982 TRI->getSubRegisterClass(Src0RC, AMDGPU::sub0);
6983 const TargetRegisterClass *Src1SubRC =
6984 TRI->getSubRegisterClass(Src1RC, AMDGPU::sub1);
6985
6986 MachineOperand SrcReg0Sub0 = TII->buildExtractSubRegOrImm(
6987 MI, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
6988 MachineOperand SrcReg1Sub0 = TII->buildExtractSubRegOrImm(
6989 MI, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
6990
6991 MachineOperand SrcReg0Sub1 = TII->buildExtractSubRegOrImm(
6992 MI, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
6993 MachineOperand SrcReg1Sub1 = TII->buildExtractSubRegOrImm(
6994 MI, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
6995
6996 unsigned LoOpc =
6997 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
6998 MachineInstr *LoHalf = BuildMI(*BB, MI, DL, TII->get(LoOpc), DestSub0)
6999 .addReg(CarryReg, RegState::Define)
7000 .add(SrcReg0Sub0)
7001 .add(SrcReg1Sub0)
7002 .addImm(0); // clamp bit
7003
7004 unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
7005 MachineInstr *HiHalf =
7006 BuildMI(*BB, MI, DL, TII->get(HiOpc), DestSub1)
7007 .addReg(DeadCarryReg, RegState::Define | RegState::Dead)
7008 .add(SrcReg0Sub1)
7009 .add(SrcReg1Sub1)
7010 .addReg(CarryReg, RegState::Kill)
7011 .addImm(0); // clamp bit
7012
7013 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), Dest.getReg())
7014 .addReg(DestSub0)
7015 .addImm(AMDGPU::sub0)
7016 .addReg(DestSub1)
7017 .addImm(AMDGPU::sub1);
7018 TII->legalizeOperands(*LoHalf);
7019 TII->legalizeOperands(*HiHalf);
7020 MI.eraseFromParent();
7021 return BB;
7022 }
7023 case AMDGPU::S_ADD_CO_PSEUDO:
7024 case AMDGPU::S_SUB_CO_PSEUDO: {
7025 // This pseudo has a chance to be selected
7026 // only from uniform add/subcarry node. All the VGPR operands
7027 // therefore assumed to be splat vectors.
7029 MachineOperand &Dest = MI.getOperand(0);
7030 MachineOperand &CarryDest = MI.getOperand(1);
7031 MachineOperand &Src0 = MI.getOperand(2);
7032 MachineOperand &Src1 = MI.getOperand(3);
7033 MachineOperand &Src2 = MI.getOperand(4);
7034 if (Src0.isReg() && TRI->isVectorRegister(MRI, Src0.getReg())) {
7035 Register RegOp0 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7036 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp0)
7037 .addReg(Src0.getReg());
7038 Src0.setReg(RegOp0);
7039 }
7040 if (Src1.isReg() && TRI->isVectorRegister(MRI, Src1.getReg())) {
7041 Register RegOp1 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7042 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp1)
7043 .addReg(Src1.getReg());
7044 Src1.setReg(RegOp1);
7045 }
7046 Register RegOp2 = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7047 if (TRI->isVectorRegister(MRI, Src2.getReg())) {
7048 BuildMI(*BB, MII, DL, TII->get(AMDGPU::V_READFIRSTLANE_B32), RegOp2)
7049 .addReg(Src2.getReg());
7050 Src2.setReg(RegOp2);
7051 }
7052
7053 if (ST.isWave64()) {
7054 if (ST.hasScalarCompareEq64()) {
7055 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U64))
7056 .addReg(Src2.getReg())
7057 .addImm(0);
7058 } else {
7059 const TargetRegisterClass *Src2RC = MRI.getRegClass(Src2.getReg());
7060 const TargetRegisterClass *SubRC =
7061 TRI->getSubRegisterClass(Src2RC, AMDGPU::sub0);
7062 MachineOperand Src2Sub0 = TII->buildExtractSubRegOrImm(
7063 MII, MRI, Src2, Src2RC, AMDGPU::sub0, SubRC);
7064 MachineOperand Src2Sub1 = TII->buildExtractSubRegOrImm(
7065 MII, MRI, Src2, Src2RC, AMDGPU::sub1, SubRC);
7066 Register Src2_32 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7067
7068 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_OR_B32), Src2_32)
7069 .add(Src2Sub0)
7070 .add(Src2Sub1);
7071
7072 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7073 .addReg(Src2_32, RegState::Kill)
7074 .addImm(0);
7075 }
7076 } else {
7077 BuildMI(*BB, MII, DL, TII->get(AMDGPU::S_CMP_LG_U32))
7078 .addReg(Src2.getReg())
7079 .addImm(0);
7080 }
7081
7082 unsigned Opc = MI.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO
7083 ? AMDGPU::S_ADDC_U32
7084 : AMDGPU::S_SUBB_U32;
7085
7086 BuildMI(*BB, MII, DL, TII->get(Opc), Dest.getReg()).add(Src0).add(Src1);
7087
7088 unsigned SelOpc =
7089 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
7090
7091 BuildMI(*BB, MII, DL, TII->get(SelOpc), CarryDest.getReg())
7092 .addImm(-1)
7093 .addImm(0);
7094
7095 MI.eraseFromParent();
7096 return BB;
7097 }
7098 case AMDGPU::SI_INIT_M0: {
7099 MachineOperand &M0Init = MI.getOperand(0);
7100 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7101 TII->get(M0Init.isReg() ? AMDGPU::COPY : AMDGPU::S_MOV_B32),
7102 AMDGPU::M0)
7103 .add(M0Init);
7104 MI.eraseFromParent();
7105 return BB;
7106 }
7107 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM: {
7108 // Set SCC to true, in case the barrier instruction gets converted to a NOP.
7109 BuildMI(*BB, MI.getIterator(), MI.getDebugLoc(),
7110 TII->get(AMDGPU::S_CMP_EQ_U32))
7111 .addImm(0)
7112 .addImm(0);
7113 return BB;
7114 }
7115 case AMDGPU::GET_GROUPSTATICSIZE: {
7116 assert(getTargetMachine().getTargetTriple().getOS() == Triple::AMDHSA ||
7117 getTargetMachine().getTargetTriple().getOS() == Triple::AMDPAL);
7118 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_MOV_B32))
7119 .add(MI.getOperand(0))
7120 .addImm(MFI->getLDSSize());
7121 MI.eraseFromParent();
7122 return BB;
7123 }
7124 case AMDGPU::GET_SHADERCYCLESHILO: {
7125 assert(MF->getSubtarget<GCNSubtarget>().hasShaderCyclesHiLoRegisters());
7126 // The algorithm is:
7127 //
7128 // hi1 = getreg(SHADER_CYCLES_HI)
7129 // lo1 = getreg(SHADER_CYCLES_LO)
7130 // hi2 = getreg(SHADER_CYCLES_HI)
7131 //
7132 // If hi1 == hi2 then there was no overflow and the result is hi2:lo1.
7133 // Otherwise there was overflow and the result is hi2:0. In both cases the
7134 // result should represent the actual time at some point during the sequence
7135 // of three getregs.
7136 using namespace AMDGPU::Hwreg;
7137 Register RegHi1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7138 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi1)
7139 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7140 Register RegLo1 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7141 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegLo1)
7142 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES, 0, 32));
7143 Register RegHi2 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7144 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_GETREG_B32), RegHi2)
7145 .addImm(HwregEncoding::encode(ID_SHADER_CYCLES_HI, 0, 32));
7146 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CMP_EQ_U32))
7147 .addReg(RegHi1)
7148 .addReg(RegHi2);
7149 Register RegLo = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7150 BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CSELECT_B32), RegLo)
7151 .addReg(RegLo1)
7152 .addImm(0);
7153 BuildMI(*BB, MI, DL, TII->get(AMDGPU::REG_SEQUENCE))
7154 .add(MI.getOperand(0))
7155 .addReg(RegLo)
7156 .addImm(AMDGPU::sub0)
7157 .addReg(RegHi2)
7158 .addImm(AMDGPU::sub1);
7159 MI.eraseFromParent();
7160 return BB;
7161 }
7162 case AMDGPU::SI_INDIRECT_SRC_V1:
7163 case AMDGPU::SI_INDIRECT_SRC_V2:
7164 case AMDGPU::SI_INDIRECT_SRC_V3:
7165 case AMDGPU::SI_INDIRECT_SRC_V4:
7166 case AMDGPU::SI_INDIRECT_SRC_V5:
7167 case AMDGPU::SI_INDIRECT_SRC_V6:
7168 case AMDGPU::SI_INDIRECT_SRC_V7:
7169 case AMDGPU::SI_INDIRECT_SRC_V8:
7170 case AMDGPU::SI_INDIRECT_SRC_V9:
7171 case AMDGPU::SI_INDIRECT_SRC_V10:
7172 case AMDGPU::SI_INDIRECT_SRC_V11:
7173 case AMDGPU::SI_INDIRECT_SRC_V12:
7174 case AMDGPU::SI_INDIRECT_SRC_V16:
7175 case AMDGPU::SI_INDIRECT_SRC_V32:
7176 return emitIndirectSrc(MI, *BB, *getSubtarget());
7177 case AMDGPU::SI_INDIRECT_DST_V1:
7178 case AMDGPU::SI_INDIRECT_DST_V2:
7179 case AMDGPU::SI_INDIRECT_DST_V3:
7180 case AMDGPU::SI_INDIRECT_DST_V4:
7181 case AMDGPU::SI_INDIRECT_DST_V5:
7182 case AMDGPU::SI_INDIRECT_DST_V6:
7183 case AMDGPU::SI_INDIRECT_DST_V7:
7184 case AMDGPU::SI_INDIRECT_DST_V8:
7185 case AMDGPU::SI_INDIRECT_DST_V9:
7186 case AMDGPU::SI_INDIRECT_DST_V10:
7187 case AMDGPU::SI_INDIRECT_DST_V11:
7188 case AMDGPU::SI_INDIRECT_DST_V12:
7189 case AMDGPU::SI_INDIRECT_DST_V16:
7190 case AMDGPU::SI_INDIRECT_DST_V32:
7191 return emitIndirectDst(MI, *BB, *getSubtarget());
7192 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
7193 case AMDGPU::SI_KILL_I1_PSEUDO:
7194 return splitKillBlock(MI, BB);
7195 case AMDGPU::V_CNDMASK_B64_PSEUDO: {
7197 return BB;
7198 }
7199 case AMDGPU::SI_BR_UNDEF: {
7200 MachineInstr *Br = BuildMI(*BB, MI, DL, TII->get(AMDGPU::S_CBRANCH_SCC1))
7201 .add(MI.getOperand(0));
7202 Br->getOperand(1).setIsUndef(); // read undef SCC
7203 MI.eraseFromParent();
7204 return BB;
7205 }
7206 case AMDGPU::ADJCALLSTACKUP:
7207 case AMDGPU::ADJCALLSTACKDOWN: {
7209 MachineInstrBuilder MIB(*MF, &MI);
7210 MIB.addReg(Info->getStackPtrOffsetReg(), RegState::ImplicitDefine)
7211 .addReg(Info->getStackPtrOffsetReg(), RegState::Implicit);
7212 return BB;
7213 }
7214 case AMDGPU::SI_CALL_ISEL: {
7215 unsigned ReturnAddrReg = TII->getRegisterInfo().getReturnAddressReg(*MF);
7216
7218 MIB = BuildMI(*BB, MI, DL, TII->get(AMDGPU::SI_CALL), ReturnAddrReg);
7219
7220 for (const MachineOperand &MO : MI.operands())
7221 MIB.add(MO);
7222
7223 MIB.cloneMemRefs(MI);
7224 MI.eraseFromParent();
7225 return BB;
7226 }
7227 case AMDGPU::V_ADD_CO_U32_e32:
7228 case AMDGPU::V_SUB_CO_U32_e32:
7229 case AMDGPU::V_SUBREV_CO_U32_e32: {
7230 // TODO: Define distinct V_*_I32_Pseudo instructions instead.
7231 unsigned Opc = MI.getOpcode();
7232
7233 bool NeedClampOperand = false;
7234 if (TII->pseudoToMCOpcode(Opc) == -1) {
7236 NeedClampOperand = true;
7237 }
7238
7239 auto I = BuildMI(*BB, MI, DL, TII->get(Opc), MI.getOperand(0).getReg());
7240 if (TII->isVOP3(*I)) {
7241 I.addReg(TRI->getVCC(), RegState::Define);
7242 }
7243 I.add(MI.getOperand(1)).add(MI.getOperand(2));
7244 if (NeedClampOperand)
7245 I.addImm(0); // clamp bit for e64 encoding
7246
7247 TII->legalizeOperands(*I);
7248
7249 MI.eraseFromParent();
7250 return BB;
7251 }
7252 case AMDGPU::V_ADDC_U32_e32:
7253 case AMDGPU::V_SUBB_U32_e32:
7254 case AMDGPU::V_SUBBREV_U32_e32:
7255 // These instructions have an implicit use of vcc which counts towards the
7256 // constant bus limit.
7257 TII->legalizeOperands(MI);
7258 return BB;
7259 case AMDGPU::DS_GWS_INIT:
7260 case AMDGPU::DS_GWS_SEMA_BR:
7261 case AMDGPU::DS_GWS_BARRIER:
7262 case AMDGPU::DS_GWS_SEMA_V:
7263 case AMDGPU::DS_GWS_SEMA_P:
7264 case AMDGPU::DS_GWS_SEMA_RELEASE_ALL:
7265 // A s_waitcnt 0 is required to be the instruction immediately following.
7266 if (getSubtarget()->hasGWSAutoReplay()) {
7268 return BB;
7269 }
7270
7271 return emitGWSMemViolTestLoop(MI, BB);
7272 case AMDGPU::S_SETREG_B32: {
7273 // Try to optimize cases that only set the denormal mode or rounding mode.
7274 //
7275 // If the s_setreg_b32 fully sets all of the bits in the rounding mode or
7276 // denormal mode to a constant, we can use s_round_mode or s_denorm_mode
7277 // instead.
7278 //
7279 // FIXME: This could be predicates on the immediate, but tablegen doesn't
7280 // allow you to have a no side effect instruction in the output of a
7281 // sideeffecting pattern.
7282 auto [ID, Offset, Width] =
7283 AMDGPU::Hwreg::HwregEncoding::decode(MI.getOperand(1).getImm());
7284 if (ID != AMDGPU::Hwreg::ID_MODE)
7285 return BB;
7286
7287 const unsigned WidthMask = maskTrailingOnes<unsigned>(Width);
7288 const unsigned SetMask = WidthMask << Offset;
7289
7290 if (getSubtarget()->hasDenormModeInst()) {
7291 unsigned SetDenormOp = 0;
7292 unsigned SetRoundOp = 0;
7293
7294 // The dedicated instructions can only set the whole denorm or round mode
7295 // at once, not a subset of bits in either.
7296 if (SetMask ==
7298 // If this fully sets both the round and denorm mode, emit the two
7299 // dedicated instructions for these.
7300 SetRoundOp = AMDGPU::S_ROUND_MODE;
7301 SetDenormOp = AMDGPU::S_DENORM_MODE;
7302 } else if (SetMask == AMDGPU::Hwreg::FP_ROUND_MASK) {
7303 SetRoundOp = AMDGPU::S_ROUND_MODE;
7304 } else if (SetMask == AMDGPU::Hwreg::FP_DENORM_MASK) {
7305 SetDenormOp = AMDGPU::S_DENORM_MODE;
7306 }
7307
7308 if (SetRoundOp || SetDenormOp) {
7309 MachineInstr *Def = MRI.getVRegDef(MI.getOperand(0).getReg());
7310 if (Def && Def->isMoveImmediate() && Def->getOperand(1).isImm()) {
7311 unsigned ImmVal = Def->getOperand(1).getImm();
7312 if (SetRoundOp) {
7313 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetRoundOp))
7314 .addImm(ImmVal & 0xf);
7315
7316 // If we also have the denorm mode, get just the denorm mode bits.
7317 ImmVal >>= 4;
7318 }
7319
7320 if (SetDenormOp) {
7321 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SetDenormOp))
7322 .addImm(ImmVal & 0xf);
7323 }
7324
7325 MI.eraseFromParent();
7326 return BB;
7327 }
7328 }
7329 }
7330
7331 // If only FP bits are touched, used the no side effects pseudo.
7332 if ((SetMask & (AMDGPU::Hwreg::FP_ROUND_MASK |
7333 AMDGPU::Hwreg::FP_DENORM_MASK)) == SetMask)
7334 MI.setDesc(TII->get(AMDGPU::S_SETREG_B32_mode));
7335
7336 return BB;
7337 }
7338 case AMDGPU::S_INVERSE_BALLOT_U32:
7339 case AMDGPU::S_INVERSE_BALLOT_U64:
7340 // These opcodes only exist to let SIFixSGPRCopies insert a readfirstlane if
7341 // necessary. After that they are equivalent to a COPY.
7342 MI.setDesc(TII->get(AMDGPU::COPY));
7343 return BB;
7344 case AMDGPU::ENDPGM_TRAP: {
7345 if (BB->succ_empty() && std::next(MI.getIterator()) == BB->end()) {
7346 MI.setDesc(TII->get(AMDGPU::S_ENDPGM));
7347 MI.addOperand(MachineOperand::CreateImm(0));
7348 return BB;
7349 }
7350
7351 // We need a block split to make the real endpgm a terminator. We also don't
7352 // want to break phis in successor blocks, so we can't just delete to the
7353 // end of the block.
7354
7355 MachineBasicBlock *SplitBB = BB->splitAt(MI, false /*UpdateLiveIns*/);
7357 MF->push_back(TrapBB);
7358 // clang-format off
7359 BuildMI(*TrapBB, TrapBB->end(), DL, TII->get(AMDGPU::S_ENDPGM))
7360 .addImm(0);
7361 BuildMI(*BB, &MI, DL, TII->get(AMDGPU::S_CBRANCH_EXECNZ))
7362 .addMBB(TrapBB);
7363 // clang-format on
7364
7365 BB->addSuccessor(TrapBB);
7366 MI.eraseFromParent();
7367 return SplitBB;
7368 }
7369 case AMDGPU::SIMULATED_TRAP: {
7370 assert(Subtarget->hasPrivEnabledTrap2NopBug());
7371 MachineBasicBlock *SplitBB =
7372 TII->insertSimulatedTrap(MRI, *BB, MI, MI.getDebugLoc());
7373 MI.eraseFromParent();
7374 return SplitBB;
7375 }
7376 case AMDGPU::SI_TCRETURN_GFX_WholeWave:
7377 case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN: {
7379
7380 // During ISel, it's difficult to propagate the original EXEC mask to use as
7381 // an input to SI_WHOLE_WAVE_FUNC_RETURN. Set it up here instead.
7382 MachineInstr *Setup = TII->getWholeWaveFunctionSetup(*BB->getParent());
7383 assert(Setup && "Couldn't find SI_SETUP_WHOLE_WAVE_FUNC");
7384 Register OriginalExec = Setup->getOperand(0).getReg();
7385 MF->getRegInfo().clearKillFlags(OriginalExec);
7386 MI.getOperand(0).setReg(OriginalExec);
7387 return BB;
7388 }
7389 case AMDGPU::V_DOT2_F32_F16:
7390 case AMDGPU::V_DOT2_F32_BF16: {
7391 // Hint RA to assign dst and src2 the same physical register.
7392 // For targets without VOP2, but with VOPD, variant of the instruction this
7393 // is one of the conditions to attempt converting VOP3P to VOPD.
7394 MRI.setSimpleHint(MI.getOperand(0).getReg(), MI.getOperand(6).getReg());
7395 return BB;
7396 }
7397 default:
7398 if (TII->isImage(MI) || TII->isMUBUF(MI)) {
7399 if (!MI.mayStore())
7401 return BB;
7402 }
7404 }
7405}
7406
7408 // This currently forces unfolding various combinations of fsub into fma with
7409 // free fneg'd operands. As long as we have fast FMA (controlled by
7410 // isFMAFasterThanFMulAndFAdd), we should perform these.
7411
7412 // When fma is quarter rate, for f64 where add / sub are at best half rate,
7413 // most of these combines appear to be cycle neutral but save on instruction
7414 // count / code size.
7415 return true;
7416}
7417
7419
7421 EVT VT) const {
7422 if (!VT.isVector()) {
7423 return MVT::i1;
7424 }
7425 return EVT::getVectorVT(Ctx, MVT::i1, VT.getVectorNumElements());
7426}
7427
7429 // TODO: Should i16 be used always if legal? For now it would force VALU
7430 // shifts.
7431 return (VT == MVT::i16) ? MVT::i16 : MVT::i32;
7432}
7433
7435 return (Ty.getScalarSizeInBits() <= 16 && Subtarget->has16BitInsts())
7436 ? Ty.changeElementSize(16)
7437 : Ty.changeElementSize(32);
7438}
7439
7440// Answering this is somewhat tricky and depends on the specific device which
7441// have different rates for fma or all f64 operations.
7442//
7443// v_fma_f64 and v_mul_f64 always take the same number of cycles as each other
7444// regardless of which device (although the number of cycles differs between
7445// devices), so it is always profitable for f64.
7446//
7447// v_fma_f32 takes 4 or 16 cycles depending on the device, so it is profitable
7448// only on full rate devices. Normally, we should prefer selecting v_mad_f32
7449// which we can always do even without fused FP ops since it returns the same
7450// result as the separate operations and since it is always full
7451// rate. Therefore, we lie and report that it is not faster for f32. v_mad_f32
7452// however does not support denormals, so we do report fma as faster if we have
7453// a fast fma device and require denormals.
7454//
7456 DenormalFPEnv FPEnv) const {
7457 VT = VT.getScalarType();
7458 if (!VT.isSimple())
7459 return false;
7460
7461 switch (VT.getSimpleVT().SimpleTy) {
7462 case MVT::f32: {
7463 // If mad is not available this depends only on if f32 fma is full rate.
7464 if (!Subtarget->hasMadMacF32Insts())
7465 return Subtarget->hasFastFMAF32();
7466
7467 // Otherwise f32 mad is always full rate and returns the same result as
7468 // the separate operations so should be preferred over fma.
7469 // However does not support denormals.
7471 return Subtarget->hasFastFMAF32() || Subtarget->hasDLInsts();
7472
7473 // If the subtarget has v_fmac_f32, that's just as good as v_mac_f32.
7474 return Subtarget->hasFastFMAF32() && Subtarget->hasDLInsts();
7475 }
7476 case MVT::f64:
7477 return true;
7478 case MVT::f16:
7479 case MVT::bf16:
7480 return Subtarget->has16BitInsts() &&
7482 default:
7483 break;
7484 }
7485
7486 return false;
7487}
7488
7493
7495 Type *Ty) const {
7497 getValueType(F.getDataLayout(), Ty, /*AllowUnknown=*/true),
7498 F.getDenormalFPEnv());
7499}
7500
7502 LLT Ty) const {
7503 switch (Ty.getScalarSizeInBits()) {
7504 case 16:
7505 return isFMAFasterThanFMulAndFAdd(MF, MVT::f16);
7506 case 32:
7507 return isFMAFasterThanFMulAndFAdd(MF, MVT::f32);
7508 case 64:
7509 return isFMAFasterThanFMulAndFAdd(MF, MVT::f64);
7510 default:
7511 break;
7512 }
7513
7514 return false;
7515}
7516
7518 // TODO: Check future ftz flag
7519 // v_mad_f32/v_mac_f32 do not support denormals.
7520 if (VT == MVT::f32)
7521 return Subtarget->hasMadMacF32Insts() &&
7523 if (VT == MVT::f16)
7524 return Subtarget->hasMadF16() &&
7526
7527 return false;
7528}
7529
7531 if (!Ty.isScalar())
7532 return false;
7533
7534 DenormalFPEnv FPEnv = getDenormalFPEnv(*MI.getMF());
7535 if (Ty.getScalarSizeInBits() == 16)
7536 return isFMADLegal(MVT::f16, FPEnv);
7537 if (Ty.getScalarSizeInBits() == 32)
7538 return isFMADLegal(MVT::f32, FPEnv);
7539
7540 return false;
7541}
7542
7544 const SDNode *N) const {
7545 return isFMADLegal(N->getValueType(0),
7547}
7548
7549//===----------------------------------------------------------------------===//
7550// Custom DAG Lowering Operations
7551//===----------------------------------------------------------------------===//
7552
7553// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7554// wider vector type is legal.
7556 SelectionDAG &DAG) const {
7557 unsigned Opc = Op.getOpcode();
7558 EVT VT = Op.getValueType();
7560
7561 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
7562 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VT);
7563
7564 SDLoc SL(Op);
7565
7566 // Forward any trailing scalar operands unchanged to both halves.
7567 SmallVector<SDValue, 2> LoOps = {Lo};
7568 SmallVector<SDValue, 2> HiOps = {Hi};
7569 auto TrailingOps = drop_begin(Op->ops());
7570 LoOps.append(TrailingOps.begin(), TrailingOps.end());
7571 HiOps.append(TrailingOps.begin(), TrailingOps.end());
7572
7573 SDValue OpLo = DAG.getNode(Opc, SL, LoVT, LoOps, Op->getFlags());
7574 SDValue OpHi = DAG.getNode(Opc, SL, HiVT, HiOps, Op->getFlags());
7575
7576 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7577}
7578
7579// Enable lowering of ROTR for vxi32 types. This is a workaround for a
7580// regression whereby extra unnecessary instructions were added to codegen
7581// for rotr operations, casued by legalising v2i32 or. This resulted in extra
7582// instructions to extract the result from the vector.
7584 [[maybe_unused]] EVT VT = Op.getValueType();
7585
7586 assert((VT == MVT::v2i32 || VT == MVT::v4i32 || VT == MVT::v8i32 ||
7587 VT == MVT::v16i32) &&
7588 "Unexpected ValueType.");
7589
7590 return DAG.UnrollVectorOp(Op.getNode());
7591}
7592
7593// Work around LegalizeDAG doing the wrong thing and fully scalarizing if the
7594// wider vector type is legal.
7596 SelectionDAG &DAG) const {
7597 unsigned Opc = Op.getOpcode();
7598 EVT VT = Op.getValueType();
7600
7601 auto [Lo0, Hi0] = DAG.SplitVectorOperand(Op.getNode(), 0);
7602 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7603
7604 SDLoc SL(Op);
7605
7606 SDValue OpLo =
7607 DAG.getNode(Opc, SL, Lo0.getValueType(), Lo0, Lo1, Op->getFlags());
7608 SDValue OpHi =
7609 DAG.getNode(Opc, SL, Hi0.getValueType(), Hi0, Hi1, Op->getFlags());
7610
7611 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7612}
7613
7615 SelectionDAG &DAG) const {
7616 unsigned Opc = Op.getOpcode();
7617 EVT VT = Op.getValueType();
7619
7620 SDValue Op0 = Op.getOperand(0);
7621 auto [Lo0, Hi0] = Op0.getValueType().isVector()
7622 ? DAG.SplitVectorOperand(Op.getNode(), 0)
7623 : std::pair(Op0, Op0);
7624
7625 auto [Lo1, Hi1] = DAG.SplitVectorOperand(Op.getNode(), 1);
7626 auto [Lo2, Hi2] = DAG.SplitVectorOperand(Op.getNode(), 2);
7627
7628 SDLoc SL(Op);
7629 auto ResVT = DAG.GetSplitDestVTs(VT);
7630
7631 SDValue OpLo =
7632 DAG.getNode(Opc, SL, ResVT.first, Lo0, Lo1, Lo2, Op->getFlags());
7633 SDValue OpHi =
7634 DAG.getNode(Opc, SL, ResVT.second, Hi0, Hi1, Hi2, Op->getFlags());
7635
7636 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), VT, OpLo, OpHi);
7637}
7638
7640 switch (Op.getOpcode()) {
7641 default:
7643 case ISD::BRCOND:
7644 return LowerBRCOND(Op, DAG);
7645 case ISD::RETURNADDR:
7646 return LowerRETURNADDR(Op, DAG);
7647 case ISD::SPONENTRY:
7648 return LowerSPONENTRY(Op, DAG);
7649 case ISD::LOAD: {
7650 SDValue Result = LowerLOAD(Op, DAG);
7651 assert((!Result.getNode() || Result.getNode()->getNumValues() == 2) &&
7652 "Load should return a value and a chain");
7653 return Result;
7654 }
7655 case ISD::FSQRT: {
7656 EVT VT = Op.getValueType();
7657 if (VT == MVT::f32)
7658 return lowerFSQRTF32(Op, DAG);
7659 if (VT == MVT::f64)
7660 return lowerFSQRTF64(Op, DAG);
7661 return SDValue();
7662 }
7663 case ISD::FSIN:
7664 case ISD::FCOS:
7665 return LowerTrig(Op, DAG);
7666 case ISD::SELECT:
7667 return LowerSELECT(Op, DAG);
7668 case ISD::FDIV:
7669 return LowerFDIV(Op, DAG);
7670 case ISD::FFREXP:
7671 return LowerFFREXP(Op, DAG);
7673 return LowerATOMIC_CMP_SWAP(Op, DAG);
7674 case ISD::STORE:
7675 return LowerSTORE(Op, DAG);
7676 case ISD::GlobalAddress: {
7679 return LowerGlobalAddress(MFI, Op, DAG);
7680 }
7681 case ISD::BlockAddress:
7682 return LowerBlockAddress(Op, DAG);
7684 return LowerExternalSymbol(Op, DAG);
7686 return LowerINTRINSIC_WO_CHAIN(Op, DAG);
7688 return LowerCONVERT_FROM_ARBITRARY_FP(Op, DAG);
7690 return LowerCONVERT_TO_ARBITRARY_FP(Op, DAG);
7692 return LowerINTRINSIC_W_CHAIN(Op, DAG);
7694 return LowerINTRINSIC_VOID(Op, DAG);
7695 case ISD::ADDRSPACECAST:
7696 return lowerADDRSPACECAST(Op, DAG);
7698 return lowerINSERT_SUBVECTOR(Op, DAG);
7700 return lowerINSERT_VECTOR_ELT(Op, DAG);
7702 return lowerEXTRACT_VECTOR_ELT(Op, DAG);
7704 return lowerVECTOR_SHUFFLE(Op, DAG);
7706 return lowerSCALAR_TO_VECTOR(Op, DAG);
7707 case ISD::BUILD_VECTOR:
7708 return lowerBUILD_VECTOR(Op, DAG);
7709 case ISD::FP_ROUND:
7711 return lowerFP_ROUND(Op, DAG);
7712 case ISD::TRAP:
7713 return lowerTRAP(Op, DAG);
7714 case ISD::DEBUGTRAP:
7715 return lowerDEBUGTRAP(Op, DAG);
7716 case ISD::ABS:
7717 case ISD::FABS:
7718 case ISD::FNEG:
7719 case ISD::FCANONICALIZE:
7720 case ISD::BSWAP:
7721 return splitUnaryVectorOp(Op, DAG);
7724 if (Op.getValueType().isVector() && Op.getValueType() != MVT::v2i16 &&
7725 Op.getOperand(0).getValueType().getScalarType() == MVT::f32)
7726 return splitUnaryVectorOp(Op, DAG);
7727 return LowerFP_TO_INT_SAT(Op, DAG);
7728 case ISD::FSUB:
7729 if (Op.getValueType() == MVT::bf16) {
7730 // Custom expansion:
7731 // fsub bf16 %a, %b -> fadd v2bf16(widen %a), fneg v2bf16(widen %b)
7732 // Then extract back to bf16.
7733 //
7734 // We create fneg on v2bf16 (not bf16) so the instruction selector can
7735 // fold the negation into the packed add's neg_lo/neg_hi modifiers,
7736 // generating a single v_pk_add_bf16 instruction. If we negate bf16 first,
7737 // it becomes a separate v_xor instruction before widening.
7738 SDLoc DL(Op);
7739 SDValue Op0 = Op.getOperand(0);
7740 SDValue Op1 = Op.getOperand(1);
7741
7742 // Widen both operands to v2bf16
7743 SDValue Vec0 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op0);
7744 SDValue Vec1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2bf16, Op1);
7745
7746 // Create FNEG v2bf16 for the second operand
7747 SDValue NegVec1 = DAG.getNode(ISD::FNEG, DL, MVT::v2bf16, Vec1);
7748
7749 // Perform FADD v2bf16
7750 SDValue Result = DAG.getNode(ISD::FADD, DL, MVT::v2bf16, Vec0, NegVec1);
7751
7752 // Extract element 0 back to bf16
7753 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::bf16, Result,
7754 DAG.getConstant(0, DL, MVT::i32));
7755 }
7756 return SDValue();
7757 case ISD::FMINNUM:
7758 case ISD::FMAXNUM:
7759 return lowerFMINNUM_FMAXNUM(Op, DAG);
7760 case ISD::FMINIMUMNUM:
7761 case ISD::FMAXIMUMNUM:
7762 return lowerFMINIMUMNUM_FMAXIMUMNUM(Op, DAG);
7763 case ISD::FLDEXP:
7764 case ISD::STRICT_FLDEXP:
7765 return lowerFLDEXP(Op, DAG);
7766 case ISD::FMA:
7767 return splitTernaryVectorOp(Op, DAG);
7768 case ISD::FP_TO_SINT:
7769 case ISD::FP_TO_UINT:
7770 if (Subtarget->hasVCvtPkIU16F32() && Op.getValueType() == MVT::i16 &&
7771 Op.getOperand(0).getValueType() == MVT::f32) {
7772 // Make f32->i16 legal so we can select V_CVT_PK_[IU]16_F32.
7773 return Op;
7774 }
7775 return LowerFP_TO_INT(Op, DAG);
7776 case ISD::SHL:
7777 case ISD::SRA:
7778 case ISD::SRL:
7779 case ISD::ADD:
7780 case ISD::SUB:
7781 case ISD::SMIN:
7782 case ISD::SMAX:
7783 case ISD::UMIN:
7784 case ISD::UMAX:
7785 case ISD::FMINNUM_IEEE:
7786 case ISD::FMAXNUM_IEEE:
7787 case ISD::FMINIMUM:
7788 case ISD::FMAXIMUM:
7789 case ISD::UADDSAT:
7790 case ISD::USUBSAT:
7791 case ISD::SADDSAT:
7792 case ISD::SSUBSAT:
7793 case ISD::FADD:
7794 case ISD::FMUL:
7795 return splitBinaryVectorOp(Op, DAG);
7796 case ISD::FCOPYSIGN:
7797 return lowerFCOPYSIGN(Op, DAG);
7798 case ISD::MUL:
7799 return lowerMUL(Op, DAG);
7800 case ISD::SMULO:
7801 case ISD::UMULO:
7802 return lowerXMULO(Op, DAG);
7803 case ISD::SMUL_LOHI:
7804 case ISD::UMUL_LOHI:
7805 return lowerXMUL_LOHI(Op, DAG);
7807 return LowerDYNAMIC_STACKALLOC(Op, DAG);
7808 case ISD::STACKSAVE:
7809 return LowerSTACKSAVE(Op, DAG);
7810 case ISD::GET_ROUNDING:
7811 return lowerGET_ROUNDING(Op, DAG);
7812 case ISD::SET_ROUNDING:
7813 return lowerSET_ROUNDING(Op, DAG);
7814 case ISD::PREFETCH:
7815 return lowerPREFETCH(Op, DAG);
7816 case ISD::FP_EXTEND:
7818 return lowerFP_EXTEND(Op, DAG);
7819 case ISD::GET_FPENV:
7820 return lowerGET_FPENV(Op, DAG);
7821 case ISD::SET_FPENV:
7822 return lowerSET_FPENV(Op, DAG);
7823 case ISD::ROTR:
7824 return lowerROTR(Op, DAG);
7825 case ISD::INLINEASM:
7826 return LowerINLINEASM(Op, DAG);
7827 }
7828 return SDValue();
7829}
7830
7831// Used for D16: Casts the result of an instruction into the right vector,
7832// packs values if loads return unpacked values.
7834 const SDLoc &DL, SelectionDAG &DAG,
7835 bool Unpacked) {
7836 if (!LoadVT.isVector())
7837 return Result;
7838
7839 // Cast back to the original packed type or to a larger type that is a
7840 // multiple of 32 bit for D16. Widening the return type is a required for
7841 // legalization.
7842 EVT FittingLoadVT = LoadVT;
7843 if ((LoadVT.getVectorNumElements() % 2) == 1) {
7844 FittingLoadVT =
7846 LoadVT.getVectorNumElements() + 1);
7847 }
7848
7849 if (Unpacked) { // From v2i32/v4i32 back to v2f16/v4f16.
7850 // Truncate to v2i16/v4i16.
7851 EVT IntLoadVT = FittingLoadVT.changeTypeToInteger();
7852
7853 // Workaround legalizer not scalarizing truncate after vector op
7854 // legalization but not creating intermediate vector trunc.
7856 DAG.ExtractVectorElements(Result, Elts);
7857 for (SDValue &Elt : Elts)
7858 Elt = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Elt);
7859
7860 // Pad illegal v1i16/v3fi6 to v4i16
7861 if ((LoadVT.getVectorNumElements() % 2) == 1)
7862 Elts.push_back(DAG.getPOISON(MVT::i16));
7863
7864 Result = DAG.getBuildVector(IntLoadVT, DL, Elts);
7865
7866 // Bitcast to original type (v2f16/v4f16).
7867 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
7868 }
7869
7870 // Cast back to the original packed type.
7871 return DAG.getNode(ISD::BITCAST, DL, FittingLoadVT, Result);
7872}
7873
7874SDValue SITargetLowering::adjustLoadValueType(unsigned Opcode, MemSDNode *M,
7875 SelectionDAG &DAG,
7877 bool IsIntrinsic) const {
7878 SDLoc DL(M);
7879
7880 bool Unpacked = Subtarget->hasUnpackedD16VMem();
7881 EVT LoadVT = M->getValueType(0);
7882
7883 EVT EquivLoadVT = LoadVT;
7884 if (LoadVT.isVector()) {
7885 if (Unpacked) {
7886 EquivLoadVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
7887 LoadVT.getVectorNumElements());
7888 } else if ((LoadVT.getVectorNumElements() % 2) == 1) {
7889 // Widen v3f16 to legal type
7890 EquivLoadVT =
7892 LoadVT.getVectorNumElements() + 1);
7893 }
7894 }
7895
7896 // Change from v4f16/v2f16 to EquivLoadVT.
7897 SDVTList VTList = DAG.getVTList(EquivLoadVT, MVT::Other);
7898
7900 IsIntrinsic ? (unsigned)ISD::INTRINSIC_W_CHAIN : Opcode, DL, VTList, Ops,
7901 M->getMemoryVT(), M->getMemOperand());
7902
7903 SDValue Adjusted = adjustLoadValueTypeImpl(Load, LoadVT, DL, DAG, Unpacked);
7904
7905 return DAG.getMergeValues({Adjusted, Load.getValue(1)}, DL);
7906}
7907
7908SDValue SITargetLowering::lowerIntrinsicLoad(MemSDNode *M, bool IsFormat,
7909 SelectionDAG &DAG,
7910 ArrayRef<SDValue> Ops) const {
7911 SDLoc DL(M);
7912 EVT LoadVT = M->getValueType(0);
7913 EVT EltType = LoadVT.getScalarType();
7914 EVT IntVT = LoadVT.changeTypeToInteger();
7915
7916 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
7917
7918 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
7919 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
7921 "unsupported sub-dword format buffer load", DL.getDebugLoc()));
7922 return DAG.getMergeValues({DAG.getPOISON(LoadVT), M->getOperand(0)}, DL);
7923 }
7924
7925 assert(M->getNumValues() == 2 || M->getNumValues() == 3);
7926 bool IsTFE = M->getNumValues() == 3;
7927
7928 unsigned Opc = IsFormat ? (IsTFE ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
7929 : AMDGPUISD::BUFFER_LOAD_FORMAT)
7930 : IsTFE ? AMDGPUISD::BUFFER_LOAD_TFE
7931 : AMDGPUISD::BUFFER_LOAD;
7932
7933 if (IsD16) {
7934 return adjustLoadValueType(AMDGPUISD::BUFFER_LOAD_FORMAT_D16, M, DAG, Ops);
7935 }
7936
7937 // Handle BUFFER_LOAD_BYTE/UBYTE/SHORT/USHORT overloaded intrinsics
7938 if (!IsD16 && !LoadVT.isVector() && EltType.getSizeInBits() < 32)
7939 return handleByteShortBufferLoads(DAG, LoadVT, DL, Ops, M->getMemOperand(),
7940 IsTFE);
7941
7942 if (isTypeLegal(LoadVT)) {
7943 return getMemIntrinsicNode(Opc, DL, M->getVTList(), Ops, IntVT,
7944 M->getMemOperand(), DAG);
7945 }
7946
7947 EVT CastVT = getEquivalentMemType(*DAG.getContext(), LoadVT);
7948 SDVTList VTList = DAG.getVTList(CastVT, MVT::Other);
7949 SDValue MemNode = getMemIntrinsicNode(Opc, DL, VTList, Ops, CastVT,
7950 M->getMemOperand(), DAG);
7951 return DAG.getMergeValues(
7952 {DAG.getNode(ISD::BITCAST, DL, LoadVT, MemNode), MemNode.getValue(1)},
7953 DL);
7954}
7955
7957 SelectionDAG &DAG) {
7958 EVT VT = N->getValueType(0);
7959 unsigned CondCode = N->getConstantOperandVal(3);
7960 if (!ICmpInst::isIntPredicate(static_cast<ICmpInst::Predicate>(CondCode)))
7961 return DAG.getPOISON(VT);
7962
7963 ICmpInst::Predicate IcInput = static_cast<ICmpInst::Predicate>(CondCode);
7964
7965 SDValue LHS = N->getOperand(1);
7966 SDValue RHS = N->getOperand(2);
7967
7968 SDLoc DL(N);
7969
7970 EVT CmpVT = LHS.getValueType();
7971 if (CmpVT == MVT::i16 && !TLI.isTypeLegal(MVT::i16)) {
7972 unsigned PromoteOp =
7974 LHS = DAG.getNode(PromoteOp, DL, MVT::i32, LHS);
7975 RHS = DAG.getNode(PromoteOp, DL, MVT::i32, RHS);
7976 }
7977
7978 ISD::CondCode CCOpcode = getICmpCondCode(IcInput);
7979
7980 unsigned WavefrontSize = TLI.getSubtarget()->getWavefrontSize();
7981 EVT CCVT = EVT::getIntegerVT(*DAG.getContext(), WavefrontSize);
7982
7983 SDValue SetCC = DAG.getNode(AMDGPUISD::SETCC, DL, CCVT, LHS, RHS,
7984 DAG.getCondCode(CCOpcode));
7985 if (VT.bitsEq(CCVT))
7986 return SetCC;
7987 return DAG.getZExtOrTrunc(SetCC, DL, VT);
7988}
7989
7991 SelectionDAG &DAG) {
7992 EVT VT = N->getValueType(0);
7993
7994 unsigned CondCode = N->getConstantOperandVal(3);
7995 if (!FCmpInst::isFPPredicate(static_cast<FCmpInst::Predicate>(CondCode)))
7996 return DAG.getPOISON(VT);
7997
7998 SDValue Src0 = N->getOperand(1);
7999 SDValue Src1 = N->getOperand(2);
8000 EVT CmpVT = Src0.getValueType();
8001 SDLoc SL(N);
8002
8003 if (CmpVT == MVT::f16 && !TLI.isTypeLegal(CmpVT)) {
8004 Src0 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Src0);
8005 Src1 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Src1);
8006 }
8007
8008 FCmpInst::Predicate IcInput = static_cast<FCmpInst::Predicate>(CondCode);
8009 ISD::CondCode CCOpcode = getFCmpCondCode(IcInput);
8010 unsigned WavefrontSize = TLI.getSubtarget()->getWavefrontSize();
8011 EVT CCVT = EVT::getIntegerVT(*DAG.getContext(), WavefrontSize);
8012 SDValue SetCC = DAG.getNode(AMDGPUISD::SETCC, SL, CCVT, Src0, Src1,
8013 DAG.getCondCode(CCOpcode));
8014 if (VT.bitsEq(CCVT))
8015 return SetCC;
8016 return DAG.getZExtOrTrunc(SetCC, SL, VT);
8017}
8018
8020 SelectionDAG &DAG) {
8021 EVT VT = N->getValueType(0);
8022 SDValue Src = N->getOperand(1);
8023 SDLoc SL(N);
8024
8025 if (Src.getOpcode() == ISD::SETCC) {
8026 SDValue Op0 = Src.getOperand(0);
8027 SDValue Op1 = Src.getOperand(1);
8028 // Need to expand bfloat to float for comparison (setcc).
8029 if (Op0.getValueType() == MVT::bf16) {
8030 Op0 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op0);
8031 Op1 = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op1);
8032 }
8033 // (ballot (ISD::SETCC ...)) -> (AMDGPUISD::SETCC ...)
8034 return DAG.getNode(AMDGPUISD::SETCC, SL, VT, Op0, Op1, Src.getOperand(2));
8035 }
8036 if (const ConstantSDNode *Arg = dyn_cast<ConstantSDNode>(Src)) {
8037 // (ballot 0) -> 0
8038 if (Arg->isZero())
8039 return DAG.getConstant(0, SL, VT);
8040
8041 // (ballot 1) -> EXEC/EXEC_LO
8042 if (Arg->isOne()) {
8043 Register Exec;
8044 if (VT.getScalarSizeInBits() == 32)
8045 Exec = AMDGPU::EXEC_LO;
8046 else if (VT.getScalarSizeInBits() == 64)
8047 Exec = AMDGPU::EXEC;
8048 else
8049 return SDValue();
8050
8051 return DAG.getCopyFromReg(DAG.getEntryNode(), SL, Exec, VT);
8052 }
8053 }
8054
8055 // (ballot (i1 $src)) -> (AMDGPUISD::SETCC (i32 (zext $src)) (i32 0)
8056 // ISD::SETNE)
8057 return DAG.getNode(
8058 AMDGPUISD::SETCC, SL, VT, DAG.getZExtOrTrunc(Src, SL, MVT::i32),
8059 DAG.getConstant(0, SL, MVT::i32), DAG.getCondCode(ISD::SETNE));
8060}
8061
8063 EVT VT);
8064
8066 SelectionDAG &DAG) {
8067 EVT VT = N->getValueType(0);
8068 unsigned ValSize = VT.getSizeInBits();
8069 unsigned IID = N->getConstantOperandVal(0);
8070 bool IsPermLane16 = IID == Intrinsic::amdgcn_permlane16 ||
8071 IID == Intrinsic::amdgcn_permlanex16;
8072 bool IsSetInactive = IID == Intrinsic::amdgcn_set_inactive ||
8073 IID == Intrinsic::amdgcn_set_inactive_chain_arg;
8074 bool IsPermlaneShuffle = IID == Intrinsic::amdgcn_permlane_bcast ||
8075 IID == Intrinsic::amdgcn_permlane_up ||
8076 IID == Intrinsic::amdgcn_permlane_down ||
8077 IID == Intrinsic::amdgcn_permlane_xor;
8078 SDLoc SL(N);
8079 MVT IntVT = MVT::getIntegerVT(ValSize);
8080 const GCNSubtarget *ST = TLI.getSubtarget();
8081
8082 unsigned SplitSize = 32;
8083 if (IID == Intrinsic::amdgcn_update_dpp && (ValSize % 64 == 0) &&
8084 ST->hasDPALU_DPP() &&
8085 AMDGPU::isLegalDPALU_DPPControl(*ST, N->getConstantOperandVal(3)))
8086 SplitSize = 64;
8087
8088 auto createLaneOp = [&DAG, &SL, N, IID](SDValue Src0, SDValue Src1,
8089 SDValue Src2, MVT ValT) -> SDValue {
8091 switch (IID) {
8092 case Intrinsic::amdgcn_permlane16:
8093 case Intrinsic::amdgcn_permlanex16:
8094 case Intrinsic::amdgcn_update_dpp:
8095 Operands.push_back(N->getOperand(6));
8096 Operands.push_back(N->getOperand(5));
8097 Operands.push_back(N->getOperand(4));
8098 [[fallthrough]];
8099 case Intrinsic::amdgcn_writelane:
8100 case Intrinsic::amdgcn_permlane_bcast:
8101 case Intrinsic::amdgcn_permlane_up:
8102 case Intrinsic::amdgcn_permlane_down:
8103 case Intrinsic::amdgcn_permlane_xor:
8104 Operands.push_back(Src2);
8105 [[fallthrough]];
8106 case Intrinsic::amdgcn_readlane:
8107 case Intrinsic::amdgcn_set_inactive:
8108 case Intrinsic::amdgcn_set_inactive_chain_arg:
8109 case Intrinsic::amdgcn_mov_dpp8:
8110 Operands.push_back(Src1);
8111 [[fallthrough]];
8112 case Intrinsic::amdgcn_readfirstlane:
8113 case Intrinsic::amdgcn_permlane64:
8114 Operands.push_back(Src0);
8115 break;
8116 default:
8117 llvm_unreachable("unhandled lane op");
8118 }
8119
8120 Operands.push_back(DAG.getTargetConstant(IID, SL, MVT::i32));
8121 std::reverse(Operands.begin(), Operands.end());
8122
8123 if (SDNode *GL = N->getGluedNode()) {
8124 assert(GL->getOpcode() == ISD::CONVERGENCECTRL_GLUE);
8125 GL = GL->getOperand(0).getNode();
8126 Operands.push_back(DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8127 SDValue(GL, 0)));
8128 }
8129
8130 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, ValT, Operands);
8131 };
8132
8133 SDValue Src0 = N->getOperand(1);
8134 SDValue Src1, Src2;
8135 if (IID == Intrinsic::amdgcn_readlane || IID == Intrinsic::amdgcn_writelane ||
8136 IID == Intrinsic::amdgcn_mov_dpp8 ||
8137 IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16 ||
8138 IsPermlaneShuffle) {
8139 Src1 = N->getOperand(2);
8140 if (IID == Intrinsic::amdgcn_writelane ||
8141 IID == Intrinsic::amdgcn_update_dpp || IsPermLane16 ||
8142 IsPermlaneShuffle)
8143 Src2 = N->getOperand(3);
8144 }
8145
8146 if (ValSize == SplitSize) {
8147 // Already legal
8148 return SDValue();
8149 }
8150
8151 if (ValSize < 32) {
8152 bool IsFloat = VT.isFloatingPoint();
8153 Src0 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src0) : Src0,
8154 SL, MVT::i32);
8155
8156 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16) {
8157 Src1 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src1) : Src1,
8158 SL, MVT::i32);
8159 }
8160
8161 if (IID == Intrinsic::amdgcn_writelane) {
8162 Src2 = DAG.getAnyExtOrTrunc(IsFloat ? DAG.getBitcast(IntVT, Src2) : Src2,
8163 SL, MVT::i32);
8164 }
8165
8166 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, MVT::i32);
8167 SDValue Trunc = DAG.getAnyExtOrTrunc(LaneOp, SL, IntVT);
8168 return IsFloat ? DAG.getBitcast(VT, Trunc) : Trunc;
8169 }
8170
8171 if (ValSize % SplitSize != 0)
8172 return SDValue();
8173
8174 auto unrollLaneOp = [&DAG, &SL](SDNode *N) -> SDValue {
8175 EVT VT = N->getValueType(0);
8176 unsigned NE = VT.getVectorNumElements();
8177 EVT EltVT = VT.getVectorElementType();
8179 unsigned NumOperands = N->getNumOperands();
8180 SmallVector<SDValue, 4> Operands(NumOperands);
8181 SDNode *GL = N->getGluedNode();
8182
8183 // only handle convergencectrl_glue
8185
8186 for (unsigned i = 0; i != NE; ++i) {
8187 for (unsigned j = 0, e = GL ? NumOperands - 1 : NumOperands; j != e;
8188 ++j) {
8189 SDValue Operand = N->getOperand(j);
8190 EVT OperandVT = Operand.getValueType();
8191 if (OperandVT.isVector()) {
8192 // A vector operand; extract a single element.
8193 EVT OperandEltVT = OperandVT.getVectorElementType();
8194 Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, OperandEltVT,
8195 Operand, DAG.getVectorIdxConstant(i, SL));
8196 } else {
8197 // A scalar operand; just use it as is.
8198 Operands[j] = Operand;
8199 }
8200 }
8201
8202 if (GL)
8203 Operands[NumOperands - 1] =
8204 DAG.getNode(ISD::CONVERGENCECTRL_GLUE, SL, MVT::Glue,
8205 SDValue(GL->getOperand(0).getNode(), 0));
8206
8207 Scalars.push_back(DAG.getNode(N->getOpcode(), SL, EltVT, Operands));
8208 }
8209
8210 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NE);
8211 return DAG.getBuildVector(VecVT, SL, Scalars);
8212 };
8213
8214 if (VT.isVector()) {
8215 switch (MVT::SimpleValueType EltTy =
8217 case MVT::i32:
8218 case MVT::f32:
8219 if (SplitSize == 32) {
8220 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VT.getSimpleVT());
8221 return unrollLaneOp(LaneOp.getNode());
8222 }
8223 [[fallthrough]];
8224 case MVT::i16:
8225 case MVT::f16:
8226 case MVT::bf16: {
8227 unsigned SubVecNumElt =
8228 SplitSize / VT.getVectorElementType().getSizeInBits();
8229 MVT SubVecVT = MVT::getVectorVT(EltTy, SubVecNumElt);
8231 SDValue Src0SubVec, Src1SubVec, Src2SubVec;
8232 for (unsigned i = 0, EltIdx = 0; i < ValSize / SplitSize; i++) {
8233 Src0SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src0,
8234 DAG.getConstant(EltIdx, SL, MVT::i32));
8235
8236 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive ||
8237 IsPermLane16) {
8238 Src1SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src1,
8239 DAG.getConstant(EltIdx, SL, MVT::i32));
8240
8241 Pieces.push_back(
8242 createLaneOp(Src0SubVec, Src1SubVec, Src2, SubVecVT));
8243 } else if (IID == Intrinsic::amdgcn_writelane) {
8244 Src2SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, SubVecVT, Src2,
8245 DAG.getConstant(EltIdx, SL, MVT::i32));
8246 Pieces.push_back(
8247 createLaneOp(Src0SubVec, Src1, Src2SubVec, SubVecVT));
8248 } else {
8249 Pieces.push_back(createLaneOp(Src0SubVec, Src1, Src2, SubVecVT));
8250 }
8251
8252 EltIdx += SubVecNumElt;
8253 }
8254 return DAG.getNode(ISD::CONCAT_VECTORS, SL, VT, Pieces);
8255 }
8256 default:
8257 // Handle all other cases by bitcasting to i32 vectors
8258 break;
8259 }
8260 }
8261
8262 MVT VecVT =
8263 MVT::getVectorVT(MVT::getIntegerVT(SplitSize), ValSize / SplitSize);
8264 Src0 = DAG.getBitcast(VecVT, Src0);
8265
8266 if (IID == Intrinsic::amdgcn_update_dpp || IsSetInactive || IsPermLane16)
8267 Src1 = DAG.getBitcast(VecVT, Src1);
8268
8269 if (IID == Intrinsic::amdgcn_writelane)
8270 Src2 = DAG.getBitcast(VecVT, Src2);
8271
8272 SDValue LaneOp = createLaneOp(Src0, Src1, Src2, VecVT);
8273 SDValue UnrolledLaneOp = unrollLaneOp(LaneOp.getNode());
8274 return DAG.getBitcast(VT, UnrolledLaneOp);
8275}
8276
8278 SelectionDAG &DAG) {
8279 EVT VT = N->getValueType(0);
8280
8281 if (VT.getSizeInBits() != 32)
8282 return SDValue();
8283
8284 SDLoc SL(N);
8285
8286 SDValue Value = N->getOperand(1);
8287 SDValue Index = N->getOperand(2);
8288
8289 // ds_bpermute requires index to be multiplied by 4
8290 SDValue ShiftAmount = DAG.getShiftAmountConstant(2, MVT::i32, SL);
8291 SDValue ShiftedIndex =
8292 DAG.getNode(ISD::SHL, SL, Index.getValueType(), Index, ShiftAmount);
8293
8294 // Intrinsics will require i32 to operate on
8295 SDValue ValueI32 = DAG.getBitcast(MVT::i32, Value);
8296
8297 auto MakeIntrinsic = [&DAG, &SL](unsigned IID, MVT RetVT,
8298 SmallVector<SDValue> IntrinArgs) -> SDValue {
8300 Operands[0] = DAG.getTargetConstant(IID, SL, MVT::i32);
8301 Operands.append(IntrinArgs);
8302 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, RetVT, Operands);
8303 };
8304
8305 // If we can bpermute across the whole wave, then just do that
8307 SDValue BPermute = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8308 {ShiftedIndex, ValueI32});
8309 return DAG.getBitcast(VT, BPermute);
8310 }
8311
8312 assert(TLI.getSubtarget()->isWave64());
8313
8314 // Otherwise, we need to make use of whole wave mode
8315 SDValue PoisonVal = DAG.getPOISON(ValueI32->getValueType(0));
8316
8317 // Set inactive lanes to poison
8318 SDValue WWMValue = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8319 {ValueI32, PoisonVal});
8320 SDValue WWMIndex = MakeIntrinsic(Intrinsic::amdgcn_set_inactive, MVT::i32,
8321 {ShiftedIndex, PoisonVal});
8322
8323 SDValue Swapped =
8324 MakeIntrinsic(Intrinsic::amdgcn_permlane64, MVT::i32, {WWMValue});
8325
8326 // Get permutation of each half, then we'll select which one to use
8327 SDValue BPermSameHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute, MVT::i32,
8328 {WWMIndex, WWMValue});
8329 SDValue BPermOtherHalf = MakeIntrinsic(Intrinsic::amdgcn_ds_bpermute,
8330 MVT::i32, {WWMIndex, Swapped});
8331 SDValue BPermOtherHalfWWM =
8332 MakeIntrinsic(Intrinsic::amdgcn_wwm, MVT::i32, {BPermOtherHalf});
8333
8334 // Select which side to take the permute from
8335 SDValue ThreadIDMask = DAG.getAllOnesConstant(SL, MVT::i32);
8336 // We can get away with only using mbcnt_lo here since we're only
8337 // trying to detect which side of 32 each lane is on, and mbcnt_lo
8338 // returns 32 for lanes 32-63.
8339 SDValue ThreadID =
8340 MakeIntrinsic(Intrinsic::amdgcn_mbcnt_lo, MVT::i32,
8341 {ThreadIDMask, DAG.getTargetConstant(0, SL, MVT::i32)});
8342
8343 SDValue SameOrOtherHalf =
8344 DAG.getNode(ISD::AND, SL, MVT::i32,
8345 DAG.getNode(ISD::XOR, SL, MVT::i32, ThreadID, Index),
8346 DAG.getTargetConstant(32, SL, MVT::i32));
8347 SDValue UseSameHalf =
8348 DAG.getSetCC(SL, MVT::i1, SameOrOtherHalf,
8349 DAG.getConstant(0, SL, MVT::i32), ISD::SETEQ);
8350 SDValue Result = DAG.getSelect(SL, MVT::i32, UseSameHalf, BPermSameHalf,
8351 BPermOtherHalfWWM);
8352 return DAG.getBitcast(VT, Result);
8353}
8354
8357 SelectionDAG &DAG) const {
8358 switch (N->getOpcode()) {
8360 if (SDValue Res = lowerINSERT_VECTOR_ELT(SDValue(N, 0), DAG))
8361 Results.push_back(Res);
8362 return;
8363 }
8365 if (SDValue Res = lowerEXTRACT_VECTOR_ELT(SDValue(N, 0), DAG))
8366 Results.push_back(Res);
8367 return;
8368 }
8370 if (SDValue Res = LowerCONVERT_TO_ARBITRARY_FP(SDValue(N, 0), DAG))
8371 Results.push_back(Res);
8372 return;
8373 }
8375 unsigned IID = N->getConstantOperandVal(0);
8376 switch (IID) {
8377 case Intrinsic::amdgcn_wave_reduce_min:
8378 case Intrinsic::amdgcn_wave_reduce_umin:
8379 case Intrinsic::amdgcn_wave_reduce_max:
8380 case Intrinsic::amdgcn_wave_reduce_umax:
8381 case Intrinsic::amdgcn_wave_reduce_add:
8382 case Intrinsic::amdgcn_wave_reduce_sub:
8383 case Intrinsic::amdgcn_wave_reduce_and:
8384 case Intrinsic::amdgcn_wave_reduce_or:
8385 case Intrinsic::amdgcn_wave_reduce_xor: {
8386 EVT VT = N->getValueType(0);
8387 if (isTypeLegal(VT))
8388 return;
8389 SDLoc SL(N);
8390 bool NeedsSignExt = IID == Intrinsic::amdgcn_wave_reduce_min ||
8391 IID == Intrinsic::amdgcn_wave_reduce_max ||
8392 IID == Intrinsic::amdgcn_wave_reduce_add ||
8393 IID == Intrinsic::amdgcn_wave_reduce_sub;
8394 unsigned ExtOpc = NeedsSignExt ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
8395 SDValue ExtSrc = DAG.getNode(ExtOpc, SL, MVT::i32, N->getOperand(1));
8396 SDValue Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
8397 N->getOperand(0), ExtSrc, N->getOperand(2));
8398 Results.push_back(DAG.getNode(ISD::TRUNCATE, SL, VT, Result));
8399 return;
8400 }
8401 case Intrinsic::amdgcn_make_buffer_rsrc:
8402 Results.push_back(lowerPointerAsRsrcIntrin(N, DAG));
8403 return;
8404 case Intrinsic::amdgcn_cvt_pkrtz: {
8405 SDValue Src0 = N->getOperand(1);
8406 SDValue Src1 = N->getOperand(2);
8407 SDLoc SL(N);
8408 SDValue Cvt =
8409 DAG.getNode(AMDGPUISD::CVT_PKRTZ_F16_F32, SL, MVT::i32, Src0, Src1);
8410 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Cvt));
8411 return;
8412 }
8413 case Intrinsic::amdgcn_cvt_pknorm_i16:
8414 case Intrinsic::amdgcn_cvt_pknorm_u16:
8415 case Intrinsic::amdgcn_cvt_pk_i16:
8416 case Intrinsic::amdgcn_cvt_pk_u16: {
8417 SDValue Src0 = N->getOperand(1);
8418 SDValue Src1 = N->getOperand(2);
8419 SDLoc SL(N);
8420 unsigned Opcode;
8421
8422 if (IID == Intrinsic::amdgcn_cvt_pknorm_i16)
8423 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
8424 else if (IID == Intrinsic::amdgcn_cvt_pknorm_u16)
8425 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
8426 else if (IID == Intrinsic::amdgcn_cvt_pk_i16)
8427 Opcode = AMDGPUISD::CVT_PK_I16_I32;
8428 else
8429 Opcode = AMDGPUISD::CVT_PK_U16_U32;
8430
8431 EVT VT = N->getValueType(0);
8432 if (isTypeLegal(VT))
8433 Results.push_back(DAG.getNode(Opcode, SL, VT, Src0, Src1));
8434 else {
8435 SDValue Cvt = DAG.getNode(Opcode, SL, MVT::i32, Src0, Src1);
8436 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, Cvt));
8437 }
8438 return;
8439 }
8440 case Intrinsic::amdgcn_s_buffer_load: {
8441 // Lower llvm.amdgcn.s.buffer.load.(i8, u8) intrinsics. First, we generate
8442 // s_buffer_load_u8 for signed and unsigned load instructions. Next, DAG
8443 // combiner tries to merge the s_buffer_load_u8 with a sext instruction
8444 // (performSignExtendInRegCombine()) and it replaces s_buffer_load_u8 with
8445 // s_buffer_load_i8.
8446 if (!Subtarget->hasScalarSubwordLoads())
8447 return;
8448 SDValue Op = SDValue(N, 0);
8449 SDValue Rsrc = Op.getOperand(1);
8450 SDValue Offset = Op.getOperand(2);
8451 SDValue CachePolicy = Op.getOperand(3);
8452 EVT VT = Op.getValueType();
8453 assert(VT == MVT::i8 && "Expected 8-bit s_buffer_load intrinsics.\n");
8454 SDLoc DL(Op);
8456 const DataLayout &DataLayout = DAG.getDataLayout();
8457 Align Alignment =
8463 VT.getStoreSize(), Alignment);
8464 SDValue LoadVal;
8465 if (!Offset->isDivergent()) {
8466 SDValue Ops[] = {DAG.getEntryNode(), // Chain
8467 Rsrc, // source register
8468 Offset, CachePolicy};
8469 SDValue BufferLoad = DAG.getMemIntrinsicNode(
8470 AMDGPUISD::SBUFFER_LOAD_UBYTE, DL,
8471 DAG.getVTList(MVT::i32, MVT::Other), Ops, VT, MMO);
8472 LoadVal = DAG.getNode(ISD::TRUNCATE, DL, VT, BufferLoad);
8473 } else {
8474 SDValue Ops[] = {
8475 DAG.getEntryNode(), // Chain
8476 Rsrc, // rsrc
8477 DAG.getConstant(0, DL, MVT::i32), // vindex
8478 {}, // voffset
8479 {}, // soffset
8480 {}, // offset
8481 CachePolicy, // cachepolicy
8482 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
8483 };
8484 setBufferOffsets(Offset, DAG, &Ops[3], Align(4));
8485 LoadVal = handleByteShortBufferLoads(DAG, VT, DL, Ops, MMO);
8486 }
8487 Results.push_back(LoadVal);
8488 return;
8489 }
8490 case Intrinsic::amdgcn_dead: {
8491 for (unsigned I = 0, E = N->getNumValues(); I < E; ++I)
8492 Results.push_back(DAG.getPOISON(N->getValueType(I)));
8493 return;
8494 }
8495 }
8496 break;
8497 }
8499 if (SDValue Res = LowerINTRINSIC_W_CHAIN(SDValue(N, 0), DAG)) {
8500 if (Res.getOpcode() == ISD::MERGE_VALUES) {
8501 // FIXME: Hacky
8502 for (unsigned I = 0; I < Res.getNumOperands(); I++) {
8503 Results.push_back(Res.getOperand(I));
8504 }
8505 } else {
8506 Results.push_back(Res);
8507 Results.push_back(Res.getValue(1));
8508 }
8509 return;
8510 }
8511
8512 break;
8513 }
8514 case ISD::SELECT: {
8515 SDLoc SL(N);
8516 EVT VT = N->getValueType(0);
8517 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
8518 SDValue LHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(1));
8519 SDValue RHS = DAG.getNode(ISD::BITCAST, SL, NewVT, N->getOperand(2));
8520
8521 EVT SelectVT = NewVT;
8522 if (NewVT.bitsLT(MVT::i32)) {
8523 LHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, LHS);
8524 RHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, RHS);
8525 SelectVT = MVT::i32;
8526 }
8527
8528 SDValue NewSelect =
8529 DAG.getNode(ISD::SELECT, SL, SelectVT, N->getOperand(0), LHS, RHS);
8530
8531 if (NewVT != SelectVT)
8532 NewSelect = DAG.getNode(ISD::TRUNCATE, SL, NewVT, NewSelect);
8533 Results.push_back(DAG.getNode(ISD::BITCAST, SL, VT, NewSelect));
8534 return;
8535 }
8536 case ISD::FNEG: {
8537 if (N->getValueType(0) != MVT::v2f16)
8538 break;
8539
8540 SDLoc SL(N);
8541 SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::i32, N->getOperand(0));
8542
8543 SDValue Op = DAG.getNode(ISD::XOR, SL, MVT::i32, BC,
8544 DAG.getConstant(0x80008000, SL, MVT::i32));
8545 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8546 return;
8547 }
8548 case ISD::FABS: {
8549 if (N->getValueType(0) != MVT::v2f16)
8550 break;
8551
8552 SDLoc SL(N);
8553 SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::i32, N->getOperand(0));
8554
8555 SDValue Op = DAG.getNode(ISD::AND, SL, MVT::i32, BC,
8556 DAG.getConstant(0x7fff7fff, SL, MVT::i32));
8557 Results.push_back(DAG.getNode(ISD::BITCAST, SL, MVT::v2f16, Op));
8558 return;
8559 }
8560 case ISD::FSQRT: {
8561 if (N->getValueType(0) != MVT::f16)
8562 break;
8563 Results.push_back(lowerFSQRTF16(SDValue(N, 0), DAG));
8564 break;
8565 }
8566 default:
8568 break;
8569 }
8570}
8571
8572/// Helper function for LowerBRCOND
8573static SDNode *findUser(SDValue Value, unsigned Opcode) {
8574
8575 for (SDUse &U : Value->uses()) {
8576 if (U.get() != Value)
8577 continue;
8578
8579 if (U.getUser()->getOpcode() == Opcode)
8580 return U.getUser();
8581 }
8582 return nullptr;
8583}
8584
8585unsigned SITargetLowering::isCFIntrinsic(const SDNode *Intr) const {
8586 if (Intr->getOpcode() == ISD::INTRINSIC_W_CHAIN) {
8587 switch (Intr->getConstantOperandVal(1)) {
8588 case Intrinsic::amdgcn_if:
8589 return AMDGPUISD::IF;
8590 case Intrinsic::amdgcn_else:
8591 return AMDGPUISD::ELSE;
8592 case Intrinsic::amdgcn_loop:
8593 return AMDGPUISD::LOOP;
8594 case Intrinsic::amdgcn_end_cf:
8595 llvm_unreachable("should not occur");
8596 default:
8597 return 0;
8598 }
8599 }
8600
8601 // break, if_break, else_break are all only used as inputs to loop, not
8602 // directly as branch conditions.
8603 return 0;
8604}
8605
8612
8614 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS())
8615 return false;
8616
8617 // FIXME: Either avoid relying on address space here or change the default
8618 // address space for functions to avoid the explicit check.
8619 return (GV->getValueType()->isFunctionTy() ||
8622}
8623
8625 return !shouldEmitFixup(GV) && !shouldEmitGOTReloc(GV);
8626}
8627
8629 if (!GV->hasExternalLinkage())
8630 return true;
8631
8632 // With object linking, external LDS declarations need relocations so the
8633 // linker can assign their offsets.
8635 if (const auto *GVar = dyn_cast<GlobalVariable>(GV)) {
8636 if (GVar->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
8637 assert(GVar->isDeclaration() && "AS3 GVs should be declaration here "
8638 "when object linking is enabled");
8639 return false;
8640 }
8641 }
8642 }
8643
8644 const auto OS = getTargetMachine().getTargetTriple().getOS();
8645 return OS == Triple::AMDHSA || OS == Triple::AMDPAL;
8646}
8647
8648/// This transforms the control flow intrinsics to get the branch destination as
8649/// last parameter, also switches branch target with BR if the need arise
8650SDValue SITargetLowering::LowerBRCOND(SDValue BRCOND, SelectionDAG &DAG) const {
8651 SDLoc DL(BRCOND);
8652
8653 SDNode *Intr = BRCOND.getOperand(1).getNode();
8654 SDValue Target = BRCOND.getOperand(2);
8655 SDNode *BR = nullptr;
8656 SDNode *SetCC = nullptr;
8657
8658 switch (Intr->getOpcode()) {
8659 case ISD::SETCC: {
8660 // As long as we negate the condition everything is fine
8661 SetCC = Intr;
8662 Intr = SetCC->getOperand(0).getNode();
8663 break;
8664 }
8665 case ISD::XOR: {
8666 // Similar to SETCC, if we have (xor c, -1), we will be fine.
8667 SDValue LHS = Intr->getOperand(0);
8668 SDValue RHS = Intr->getOperand(1);
8669 if (auto *C = dyn_cast<ConstantSDNode>(RHS); C && C->getZExtValue()) {
8670 Intr = LHS.getNode();
8671 break;
8672 }
8673 [[fallthrough]];
8674 }
8675 default: {
8676 // Get the target from BR if we don't negate the condition
8677 BR = findUser(BRCOND, ISD::BR);
8678 assert(BR && "brcond missing unconditional branch user");
8679 Target = BR->getOperand(1);
8680 }
8681 }
8682
8683 unsigned CFNode = isCFIntrinsic(Intr);
8684 if (CFNode == 0) {
8685 // This is a uniform branch so we don't need to legalize.
8686 return BRCOND;
8687 }
8688
8689 bool HaveChain = Intr->getOpcode() == ISD::INTRINSIC_VOID ||
8691
8692 assert(!SetCC ||
8693 (SetCC->getConstantOperandVal(1) == 1 &&
8694 cast<CondCodeSDNode>(SetCC->getOperand(2).getNode())->get() ==
8695 ISD::SETNE));
8696
8697 // operands of the new intrinsic call
8699 if (HaveChain)
8700 Ops.push_back(BRCOND.getOperand(0));
8701
8702 Ops.append(Intr->op_begin() + (HaveChain ? 2 : 1), Intr->op_end());
8703 Ops.push_back(Target);
8704
8705 ArrayRef<EVT> Res(Intr->value_begin() + 1, Intr->value_end());
8706
8707 // build the new intrinsic call
8708 SDNode *Result = DAG.getNode(CFNode, DL, DAG.getVTList(Res), Ops).getNode();
8709
8710 if (!HaveChain) {
8711 SDValue Ops[] = {SDValue(Result, 0), BRCOND.getOperand(0)};
8712
8714 }
8715
8716 if (BR) {
8717 // Give the branch instruction our target
8718 SDValue Ops[] = {BR->getOperand(0), BRCOND.getOperand(2)};
8719 SDValue NewBR = DAG.getNode(ISD::BR, DL, BR->getVTList(), Ops);
8720 DAG.ReplaceAllUsesWith(BR, NewBR.getNode());
8721 }
8722
8723 SDValue Chain = SDValue(Result, Result->getNumValues() - 1);
8724
8725 // Copy the intrinsic results to registers
8726 for (unsigned i = 1, e = Intr->getNumValues() - 1; i != e; ++i) {
8727 SDNode *CopyToReg = findUser(SDValue(Intr, i), ISD::CopyToReg);
8728 if (!CopyToReg)
8729 continue;
8730
8731 Chain = DAG.getCopyToReg(Chain, DL, CopyToReg->getOperand(1),
8732 SDValue(Result, i - 1), SDValue());
8733
8734 DAG.ReplaceAllUsesWith(SDValue(CopyToReg, 0), CopyToReg->getOperand(0));
8735 }
8736
8737 // Remove the old intrinsic from the chain
8738 DAG.ReplaceAllUsesOfValueWith(SDValue(Intr, Intr->getNumValues() - 1),
8739 Intr->getOperand(0));
8740
8741 return Chain;
8742}
8743
8744SDValue SITargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
8745 MVT VT = Op.getSimpleValueType();
8746 SDLoc DL(Op);
8747 // Checking the depth
8748 if (Op.getConstantOperandVal(0) != 0)
8749 return DAG.getConstant(0, DL, VT);
8750
8752 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8753 // Check for kernel and shader functions
8754 if (Info->isEntryFunction())
8755 return DAG.getConstant(0, DL, VT);
8756
8757 MachineFrameInfo &MFI = MF.getFrameInfo();
8758 // There is a call to @llvm.returnaddress in this function
8759 MFI.setReturnAddressIsTaken(true);
8760
8761 const SIRegisterInfo *TRI = getSubtarget()->getRegisterInfo();
8762 // Get the return address reg and mark it as an implicit live-in
8763 Register Reg = MF.addLiveIn(TRI->getReturnAddressReg(MF),
8764 getRegClassFor(VT, Op.getNode()->isDivergent()));
8765
8766 return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT);
8767}
8768
8769SDValue SITargetLowering::LowerSPONENTRY(SDValue Op, SelectionDAG &DAG) const {
8771 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
8772
8773 // For functions that set up their own stack, select the GET_STACK_BASE
8774 // pseudo.
8775 if (MFI->isBottomOfStack())
8776 return Op;
8777
8778 // For everything else, create a dummy stack object.
8779 int FI = MF.getFrameInfo().CreateFixedObject(1, 0, /*IsImmutable=*/false);
8780 return DAG.getFrameIndex(FI, Op.getValueType());
8781}
8782
8783SDValue SITargetLowering::getFPExtOrFPRound(SelectionDAG &DAG, SDValue Op,
8784 const SDLoc &DL, EVT VT) const {
8785 return Op.getValueType().bitsLE(VT)
8786 ? DAG.getNode(ISD::FP_EXTEND, DL, VT, Op)
8787 : DAG.getNode(ISD::FP_ROUND, DL, VT, Op,
8788 DAG.getTargetConstant(0, DL, MVT::i32));
8789}
8790
8791SDValue SITargetLowering::splitFP_ROUNDVectorOp(SDValue Op,
8792 SelectionDAG &DAG) const {
8793 EVT DstVT = Op.getValueType();
8794 unsigned NumElts = DstVT.getVectorNumElements();
8795 assert(NumElts > 2 && isPowerOf2_32(NumElts));
8796
8797 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
8798
8799 SDLoc DL(Op);
8800 unsigned Opc = Op.getOpcode();
8801 SDValue Flags = Op.getOperand(1);
8802 EVT HalfDstVT =
8803 EVT::getVectorVT(*DAG.getContext(), DstVT.getScalarType(), NumElts / 2);
8804 SDValue OpLo = DAG.getNode(Opc, DL, HalfDstVT, Lo, Flags);
8805 SDValue OpHi = DAG.getNode(Opc, DL, HalfDstVT, Hi, Flags);
8806
8807 return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, OpLo, OpHi);
8808}
8809
8810SDValue SITargetLowering::lowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const {
8811 bool IsStrict = Op->isStrictFPOpcode();
8812 SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
8813 EVT SrcVT = Src.getValueType();
8814 EVT DstVT = Op.getValueType();
8815
8816 if (DstVT.isVectorOf(MVT::f16)) {
8817 assert(Subtarget->hasCvtPkF16F32Inst() && "support v_cvt_pk_f16_f32");
8818 if (SrcVT.getScalarType() != MVT::f32)
8819 return SDValue();
8820 return SrcVT == MVT::v2f32 ? Op : splitFP_ROUNDVectorOp(Op, DAG);
8821 }
8822
8823 if (SrcVT.getScalarType() != MVT::f64)
8824 return Op;
8825
8826 SDLoc DL(Op);
8827 if (DstVT == MVT::f16) {
8828 // TODO: Handle strictfp
8829 if (Op.getOpcode() != ISD::FP_ROUND)
8830 return Op;
8831
8832 if (!Subtarget->has16BitInsts()) {
8833 SDValue FpToFp16 = DAG.getNode(ISD::FP_TO_FP16, DL, MVT::i32, Src);
8834 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8835 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8836 }
8837 if (Op->getFlags().hasApproximateFuncs()) {
8838 SDValue Flags = Op.getOperand(1);
8839 SDValue Src32 = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, Src, Flags);
8840 return DAG.getNode(ISD::FP_ROUND, DL, MVT::f16, Src32, Flags);
8841 }
8842 SDValue FpToFp16 = LowerF64ToF16Safe(Src, DL, DAG);
8843 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FpToFp16);
8844 return DAG.getNode(ISD::BITCAST, DL, MVT::f16, Trunc);
8845 }
8846
8847 assert(DstVT.getScalarType() == MVT::bf16 &&
8848 "custom lower FP_ROUND for f16 or bf16");
8849 assert(Subtarget->hasBF16ConversionInsts() && "f32 -> bf16 is legal");
8850
8851 // Round-inexact-to-odd f64 to f32, then do the final rounding using the
8852 // hardware f32 -> bf16 instruction.
8853 EVT F32VT = SrcVT.changeElementType(*DAG.getContext(), MVT::f32);
8854 SDValue Rod = expandRoundInexactToOdd(F32VT, Src, DL, DAG);
8855 if (IsStrict) {
8856 return DAG.getNode(
8857 ISD::STRICT_FP_ROUND, DL, {DstVT, MVT::Other},
8858 {Op.getOperand(0), Rod, DAG.getTargetConstant(0, DL, MVT::i32)});
8859 }
8860 return DAG.getNode(ISD::FP_ROUND, DL, DstVT, Rod,
8861 DAG.getTargetConstant(0, DL, MVT::i32));
8862}
8863
8864SDValue SITargetLowering::lowerFMINNUM_FMAXNUM(SDValue Op,
8865 SelectionDAG &DAG) const {
8866 EVT VT = Op.getValueType();
8867 const MachineFunction &MF = DAG.getMachineFunction();
8868 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8869 bool IsIEEEMode = Info->getMode().IEEE;
8870
8871 // FIXME: Assert during selection that this is only selected for
8872 // ieee_mode. Currently a combine can produce the ieee version for non-ieee
8873 // mode functions, but this happens to be OK since it's only done in cases
8874 // where there is known no sNaN.
8875 if (IsIEEEMode)
8876 return expandFMINNUM_FMAXNUM(Op.getNode(), DAG);
8877
8878 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8879 VT == MVT::v16bf16)
8880 return splitBinaryVectorOp(Op, DAG);
8881 return Op;
8882}
8883
8884SDValue
8885SITargetLowering::lowerFMINIMUMNUM_FMAXIMUMNUM(SDValue Op,
8886 SelectionDAG &DAG) const {
8887 EVT VT = Op.getValueType();
8888 const MachineFunction &MF = DAG.getMachineFunction();
8889 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
8890 bool IsIEEEMode = Info->getMode().IEEE;
8891
8892 if (IsIEEEMode)
8893 return expandFMINIMUMNUM_FMAXIMUMNUM(Op.getNode(), DAG);
8894
8895 if (VT == MVT::v4f16 || VT == MVT::v8f16 || VT == MVT::v16f16 ||
8896 VT == MVT::v32f16)
8897 return splitBinaryVectorOp(Op, DAG);
8898 return Op;
8899}
8900
8901SDValue SITargetLowering::lowerFLDEXP(SDValue Op, SelectionDAG &DAG) const {
8902 bool IsStrict = Op.getOpcode() == ISD::STRICT_FLDEXP;
8903 EVT VT = Op.getValueType();
8904 assert(VT == MVT::f16);
8905
8906 SDValue Exp = Op.getOperand(IsStrict ? 2 : 1);
8907 EVT ExpVT = Exp.getValueType();
8908 if (ExpVT == MVT::i16)
8909 return Op;
8910
8911 SDLoc DL(Op);
8912
8913 // Correct the exponent type for f16 to i16.
8914 // Clamp the range of the exponent to the instruction's range.
8915
8916 // TODO: This should be a generic narrowing legalization, and can easily be
8917 // for GlobalISel.
8918
8919 SDValue MinExp = DAG.getSignedConstant(minIntN(16), DL, ExpVT);
8920 SDValue ClampMin = DAG.getNode(ISD::SMAX, DL, ExpVT, Exp, MinExp);
8921
8922 SDValue MaxExp = DAG.getSignedConstant(maxIntN(16), DL, ExpVT);
8923 SDValue Clamp = DAG.getNode(ISD::SMIN, DL, ExpVT, ClampMin, MaxExp);
8924
8925 SDValue TruncExp = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Clamp);
8926
8927 if (IsStrict) {
8928 return DAG.getNode(ISD::STRICT_FLDEXP, DL, {VT, MVT::Other},
8929 {Op.getOperand(0), Op.getOperand(1), TruncExp});
8930 }
8931
8932 return DAG.getNode(ISD::FLDEXP, DL, VT, Op.getOperand(0), TruncExp);
8933}
8934
8936 switch (Op->getOpcode()) {
8937 case ISD::ABS:
8938 case ISD::SRA:
8939 case ISD::SMIN:
8940 case ISD::SMAX:
8941 return ISD::SIGN_EXTEND;
8942 case ISD::SRL:
8943 case ISD::UMIN:
8944 case ISD::UMAX:
8945 case ISD::USUBSAT:
8946 return ISD::ZERO_EXTEND;
8947 case ISD::ADD:
8948 case ISD::SUB:
8949 case ISD::AND:
8950 case ISD::OR:
8951 case ISD::XOR:
8952 case ISD::SHL:
8953 case ISD::SELECT:
8954 case ISD::MUL:
8955 // operation result won't be influenced by garbage high bits.
8956 // TODO: are all of those cases correct, and are there more?
8957 return ISD::ANY_EXTEND;
8958 case ISD::SETCC: {
8959 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
8961 }
8962 default:
8963 llvm_unreachable("unexpected opcode!");
8964 }
8965}
8966
8967SDValue
8968SITargetLowering::promoteUniformUnaryOpToI32(SDValue Op,
8969 DAGCombinerInfo &DCI) const {
8970 EVT OpTy = Op.getValueType();
8971 SelectionDAG &DAG = DCI.DAG;
8972 EVT ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
8973
8974 if (isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
8975 return SDValue();
8976
8977 SDLoc DL(Op);
8978 SDValue Input = Op.getOperand(0);
8979 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
8980 Input = DAG.getNode(ExtOp, DL, ExtTy, Input);
8981
8982 SDValue NewVal = DAG.getNode(Op.getOpcode(), DL, ExtTy, Input);
8983
8984 return DAG.getNode(ISD::TRUNCATE, DL, OpTy, NewVal);
8985}
8986
8987SDValue SITargetLowering::promoteUniformOpToI32(SDValue Op,
8988 DAGCombinerInfo &DCI) const {
8989 const unsigned Opc = Op.getOpcode();
8990 assert(Opc == ISD::ADD || Opc == ISD::SUB || Opc == ISD::SHL ||
8991 Opc == ISD::SRL || Opc == ISD::SRA || Opc == ISD::AND ||
8992 Opc == ISD::OR || Opc == ISD::XOR || Opc == ISD::MUL ||
8993 Opc == ISD::SETCC || Opc == ISD::SELECT || Opc == ISD::SMIN ||
8994 Opc == ISD::SMAX || Opc == ISD::UMIN || Opc == ISD::UMAX ||
8995 Opc == ISD::USUBSAT);
8996
8997 EVT OpTy = (Opc != ISD::SETCC) ? Op.getValueType()
8998 : Op->getOperand(0).getValueType();
8999 auto &DAG = DCI.DAG;
9000 auto ExtTy = OpTy.changeElementType(*DAG.getContext(), MVT::i32);
9001
9002 if (DCI.isBeforeLegalizeOps() ||
9003 isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
9004 return SDValue();
9005
9006 SDLoc DL(Op);
9007 SDValue LHS;
9008 SDValue RHS;
9009 if (Opc == ISD::SELECT) {
9010 LHS = Op->getOperand(1);
9011 RHS = Op->getOperand(2);
9012 } else {
9013 LHS = Op->getOperand(0);
9014 RHS = Op->getOperand(1);
9015 }
9016
9017 const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
9018 LHS = DAG.getNode(ExtOp, DL, ExtTy, {LHS});
9019
9020 // Special case: for shifts, the RHS always needs a zext.
9021 if (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA)
9022 RHS = DAG.getNode(ISD::ZERO_EXTEND, DL, ExtTy, {RHS});
9023 else
9024 RHS = DAG.getNode(ExtOp, DL, ExtTy, {RHS});
9025
9026 // setcc always return i1/i1 vec so no need to truncate after.
9027 if (Opc == ISD::SETCC) {
9028 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
9029 return DAG.getSetCC(DL, Op.getValueType(), LHS, RHS, CC);
9030 }
9031
9032 // For other ops, we extend the operation's return type as well so we need to
9033 // truncate back to the original type.
9034 SDValue NewVal;
9035 if (Opc == ISD::SELECT)
9036 NewVal = DAG.getNode(ISD::SELECT, DL, ExtTy, {Op->getOperand(0), LHS, RHS});
9037 else
9038 NewVal = DAG.getNode(Opc, DL, ExtTy, {LHS, RHS});
9039
9040 return DAG.getZExtOrTrunc(NewVal, DL, OpTy);
9041}
9042
9043SDValue SITargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
9044 SDValue Mag = Op.getOperand(0);
9045 EVT MagVT = Mag.getValueType();
9046
9047 if (MagVT.getVectorNumElements() > 2)
9048 return splitBinaryVectorOp(Op, DAG);
9049
9050 SDValue Sign = Op.getOperand(1);
9051 EVT SignVT = Sign.getValueType();
9052
9053 if (MagVT == SignVT)
9054 return Op;
9055
9056 // fcopysign v2f16:mag, v2f32:sign ->
9057 // fcopysign v2f16:mag,
9058 // bitcast (trunc (srl (bitcast sign to v2i32), 16) to v2i16)
9059
9060 SDLoc SL(Op);
9061 SDValue SignAsInt32 = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Sign);
9062 SDValue ShiftAmt = DAG.getShiftAmountConstant(16, MVT::v2i32, SL);
9063 SDValue SignShifted =
9064 DAG.getNode(ISD::SRL, SL, MVT::v2i32, SignAsInt32, ShiftAmt);
9065 SDValue SignAsInt16 = DAG.getNode(ISD::TRUNCATE, SL, MVT::v2i16, SignShifted);
9066
9067 SDValue SignAsHalf16 = DAG.getNode(ISD::BITCAST, SL, MagVT, SignAsInt16);
9068
9069 return DAG.getNode(ISD::FCOPYSIGN, SL, MagVT, Mag, SignAsHalf16);
9070}
9071
9072// Custom lowering for vector multiplications and s_mul_u64.
9073SDValue SITargetLowering::lowerMUL(SDValue Op, SelectionDAG &DAG) const {
9074 EVT VT = Op.getValueType();
9075
9076 // Split vector operands.
9077 if (VT.isVector())
9078 return splitBinaryVectorOp(Op, DAG);
9079
9080 assert(VT == MVT::i64 && "The following code is a special for s_mul_u64");
9081
9082 // There are four ways to lower s_mul_u64:
9083 //
9084 // 1. If all the operands are uniform, then we lower it as it is.
9085 //
9086 // 2. If the operands are divergent, then we have to split s_mul_u64 in 32-bit
9087 // multiplications because there is not a vector equivalent of s_mul_u64.
9088 //
9089 // 3. If the cost model decides that it is more efficient to use vector
9090 // registers, then we have to split s_mul_u64 in 32-bit multiplications.
9091 // This happens in splitScalarSMULU64() in SIInstrInfo.cpp .
9092 //
9093 // 4. If the cost model decides to use vector registers and both of the
9094 // operands are zero-extended/sign-extended from 32-bits, then we split the
9095 // s_mul_u64 in two 32-bit multiplications. The problem is that it is not
9096 // possible to check if the operands are zero-extended or sign-extended in
9097 // SIInstrInfo.cpp. For this reason, here, we replace s_mul_u64 with
9098 // s_mul_u64_u32_pseudo if both operands are zero-extended and we replace
9099 // s_mul_u64 with s_mul_i64_i32_pseudo if both operands are sign-extended.
9100 // If the cost model decides that we have to use vector registers, then
9101 // splitScalarSMulPseudo() (in SIInstrInfo.cpp) split s_mul_u64_u32/
9102 // s_mul_i64_i32_pseudo in two vector multiplications. If the cost model
9103 // decides that we should use scalar registers, then s_mul_u64_u32_pseudo/
9104 // s_mul_i64_i32_pseudo is lowered as s_mul_u64 in expandPostRAPseudo() in
9105 // SIInstrInfo.cpp .
9106
9107 if (Op->isDivergent())
9108 return SDValue();
9109
9110 SDValue Op0 = Op.getOperand(0);
9111 SDValue Op1 = Op.getOperand(1);
9112 // If all the operands are zero-enteted to 32-bits, then we replace s_mul_u64
9113 // with s_mul_u64_u32_pseudo. If all the operands are sign-extended to
9114 // 32-bits, then we replace s_mul_u64 with s_mul_i64_i32_pseudo.
9115 KnownBits Op0KnownBits = DAG.computeKnownBits(Op0);
9116 unsigned Op0LeadingZeros = Op0KnownBits.countMinLeadingZeros();
9117 KnownBits Op1KnownBits = DAG.computeKnownBits(Op1);
9118 unsigned Op1LeadingZeros = Op1KnownBits.countMinLeadingZeros();
9119 SDLoc SL(Op);
9120 if (Op0LeadingZeros >= 32 && Op1LeadingZeros >= 32)
9121 return SDValue(
9122 DAG.getMachineNode(AMDGPU::S_MUL_U64_U32_PSEUDO, SL, VT, Op0, Op1), 0);
9123 unsigned Op0SignBits = DAG.ComputeNumSignBits(Op0);
9124 unsigned Op1SignBits = DAG.ComputeNumSignBits(Op1);
9125 if (Op0SignBits >= 33 && Op1SignBits >= 33)
9126 return SDValue(
9127 DAG.getMachineNode(AMDGPU::S_MUL_I64_I32_PSEUDO, SL, VT, Op0, Op1), 0);
9128 // If all the operands are uniform, then we lower s_mul_u64 as it is.
9129 return Op;
9130}
9131
9132SDValue SITargetLowering::lowerXMULO(SDValue Op, SelectionDAG &DAG) const {
9133 EVT VT = Op.getValueType();
9134 SDLoc SL(Op);
9135 SDValue LHS = Op.getOperand(0);
9136 SDValue RHS = Op.getOperand(1);
9137 bool isSigned = Op.getOpcode() == ISD::SMULO;
9138
9139 if (ConstantSDNode *RHSC = isConstOrConstSplat(RHS)) {
9140 const APInt &C = RHSC->getAPIntValue();
9141 // mulo(X, 1 << S) -> { X << S, (X << S) >> S != X }
9142 if (C.isPowerOf2()) {
9143 // smulo(x, signed_min) is same as umulo(x, signed_min).
9144 bool UseArithShift = isSigned && !C.isMinSignedValue();
9145 SDValue ShiftAmt = DAG.getConstant(C.logBase2(), SL, MVT::i32);
9146 SDValue Result = DAG.getNode(ISD::SHL, SL, VT, LHS, ShiftAmt);
9147 SDValue Overflow =
9148 DAG.getSetCC(SL, MVT::i1,
9149 DAG.getNode(UseArithShift ? ISD::SRA : ISD::SRL, SL, VT,
9150 Result, ShiftAmt),
9151 LHS, ISD::SETNE);
9152 return DAG.getMergeValues({Result, Overflow}, SL);
9153 }
9154 }
9155
9156 SDValue Result = DAG.getNode(ISD::MUL, SL, VT, LHS, RHS);
9157 SDValue Top =
9158 DAG.getNode(isSigned ? ISD::MULHS : ISD::MULHU, SL, VT, LHS, RHS);
9159
9160 SDValue Sign = isSigned
9161 ? DAG.getNode(ISD::SRA, SL, VT, Result,
9162 DAG.getConstant(VT.getScalarSizeInBits() - 1,
9163 SL, MVT::i32))
9164 : DAG.getConstant(0, SL, VT);
9165 SDValue Overflow = DAG.getSetCC(SL, MVT::i1, Top, Sign, ISD::SETNE);
9166
9167 return DAG.getMergeValues({Result, Overflow}, SL);
9168}
9169
9170SDValue SITargetLowering::lowerXMUL_LOHI(SDValue Op, SelectionDAG &DAG) const {
9171 if (Op->isDivergent()) {
9172 // Select to V_MAD_[IU]64_[IU]32.
9173 return Op;
9174 }
9175 if (Subtarget->hasSMulHi()) {
9176 // Expand to S_MUL_I32 + S_MUL_HI_[IU]32.
9177 return SDValue();
9178 }
9179 // The multiply is uniform but we would have to use V_MUL_HI_[IU]32 to
9180 // calculate the high part, so we might as well do the whole thing with
9181 // V_MAD_[IU]64_[IU]32.
9182 return Op;
9183}
9184
9185SDValue SITargetLowering::lowerTRAP(SDValue Op, SelectionDAG &DAG) const {
9186 if (!Subtarget->hasTrapHandler() ||
9187 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA)
9188 return lowerTrapEndpgm(Op, DAG);
9189
9190 return Subtarget->supportsGetDoorbellID() ? lowerTrapHsa(Op, DAG)
9191 : lowerTrapHsaQueuePtr(Op, DAG);
9192}
9193
9194SDValue SITargetLowering::lowerTrapEndpgm(SDValue Op, SelectionDAG &DAG) const {
9195 SDLoc SL(Op);
9196 SDValue Chain = Op.getOperand(0);
9197 return DAG.getNode(AMDGPUISD::ENDPGM_TRAP, SL, MVT::Other, Chain);
9198}
9199
9200SDValue
9201SITargetLowering::loadImplicitKernelArgument(SelectionDAG &DAG, MVT VT,
9202 const SDLoc &DL, Align Alignment,
9203 ImplicitParameter Param) const {
9205 uint64_t Offset = getImplicitParameterOffset(MF, Param);
9206 SDValue Ptr = lowerKernArgParameterPtr(DAG, DL, DAG.getEntryNode(), Offset);
9207 MachinePointerInfo PtrInfo =
9209 return DAG.getLoad(
9210 VT, DL, DAG.getEntryNode(), Ptr, PtrInfo.getWithOffset(Offset), Alignment,
9212}
9213
9214SDValue SITargetLowering::lowerTrapHsaQueuePtr(SDValue Op,
9215 SelectionDAG &DAG) const {
9216 SDLoc SL(Op);
9217 SDValue Chain = Op.getOperand(0);
9218
9219 SDValue QueuePtr;
9220 // For code object version 5, QueuePtr is passed through implicit kernarg.
9221 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9223 QueuePtr =
9224 loadImplicitKernelArgument(DAG, MVT::i64, SL, Align(8), QUEUE_PTR);
9225 } else {
9227 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9228 Register UserSGPR = Info->getQueuePtrUserSGPR();
9229
9230 if (UserSGPR == AMDGPU::NoRegister) {
9231 // We probably are in a function incorrectly marked with
9232 // amdgpu-no-queue-ptr. This is undefined. We don't want to delete the
9233 // trap, so just use a null pointer.
9234 QueuePtr = DAG.getConstant(0, SL, MVT::i64);
9235 } else {
9236 QueuePtr = CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR,
9237 MVT::i64);
9238 }
9239 }
9240
9241 SDValue SGPR01 = DAG.getRegister(AMDGPU::SGPR0_SGPR1, MVT::i64);
9242 SDValue ToReg = DAG.getCopyToReg(Chain, SL, SGPR01, QueuePtr, SDValue());
9243
9244 uint64_t TrapID = static_cast<uint64_t>(GCNSubtarget::TrapID::LLVMAMDHSATrap);
9245 SDValue Ops[] = {ToReg, DAG.getTargetConstant(TrapID, SL, MVT::i16), SGPR01,
9246 ToReg.getValue(1)};
9247 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9248}
9249
9250SDValue SITargetLowering::lowerTrapHsa(SDValue Op, SelectionDAG &DAG) const {
9251 SDLoc SL(Op);
9252 SDValue Chain = Op.getOperand(0);
9253
9254 // We need to simulate the 's_trap 2' instruction on targets that run in
9255 // PRIV=1 (where it is treated as a nop).
9256 if (Subtarget->hasPrivEnabledTrap2NopBug())
9257 return DAG.getNode(AMDGPUISD::SIMULATED_TRAP, SL, MVT::Other, Chain);
9258
9259 uint64_t TrapID = static_cast<uint64_t>(GCNSubtarget::TrapID::LLVMAMDHSATrap);
9260 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9261 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9262}
9263
9264SDValue SITargetLowering::lowerDEBUGTRAP(SDValue Op, SelectionDAG &DAG) const {
9265 SDLoc SL(Op);
9266 SDValue Chain = Op.getOperand(0);
9268
9269 if (!Subtarget->hasTrapHandler() ||
9270 Subtarget->getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA) {
9271 LLVMContext &Ctx = MF.getFunction().getContext();
9272 Ctx.diagnose(DiagnosticInfoUnsupported(MF.getFunction(),
9273 "debugtrap handler not supported",
9274 Op.getDebugLoc(), DS_Warning));
9275 return Chain;
9276 }
9277
9278 uint64_t TrapID =
9279 static_cast<uint64_t>(GCNSubtarget::TrapID::LLVMAMDHSADebugTrap);
9280 SDValue Ops[] = {Chain, DAG.getTargetConstant(TrapID, SL, MVT::i16)};
9281 return DAG.getNode(AMDGPUISD::TRAP, SL, MVT::Other, Ops);
9282}
9283
9284/// When a divergent value (in VGPR) is passed to an inline asm with an SGPR
9285/// constraint ('s'), we need to insert v_readfirstlane to move the value from
9286/// VGPR to SGPR. This is done by modifying the CopyToReg nodes in the glue
9287/// chain that feed into the INLINEASM node.
9288SDValue SITargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
9289 unsigned NumOps = Op.getNumOperands();
9290
9291 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
9292 SmallSet<Register, 8> SGPRInputRegs;
9293
9294 unsigned NumVals = 0;
9295 for (unsigned I = InlineAsm::Op_FirstOperand; I < NumOps - 1;
9296 I += 1 + NumVals) {
9297 const InlineAsm::Flag Flags(Op.getConstantOperandVal(I));
9298 NumVals = Flags.getNumOperandRegisters();
9299
9300 unsigned RCID;
9301 bool IsSGPRInput = Flags.getKind() == InlineAsm::Kind::RegUse &&
9302 NumVals > 0 && Flags.hasRegClassConstraint(RCID) &&
9303 TRI->isSGPRClass(TRI->getRegClass(RCID));
9304
9305 for (unsigned J = 0; J < NumVals; ++J) {
9306 SDValue Val = Op.getOperand(I + 1 + J);
9307 if (const RegisterSDNode *RegNode =
9309 Register Reg = RegNode->getReg();
9310 if (IsSGPRInput || (Reg.isPhysical() && TRI->isSGPRPhysReg(Reg)))
9311 SGPRInputRegs.insert(Reg);
9312 }
9313 }
9314 }
9315
9316 if (SGPRInputRegs.empty())
9317 return Op;
9318
9319 // Walk the glue chain and insert readfirstlane for divergent SGPR inputs.
9320 SDLoc DL(Op);
9321 SDNode *N = Op.getOperand(NumOps - 1).getNode();
9322
9323 while (N && N->getOpcode() == ISD::CopyToReg) {
9324 Register Reg = cast<RegisterSDNode>(N->getOperand(1))->getReg();
9325 SDValue SrcVal = N->getOperand(2);
9326
9327 // Insert readfirstlane if copying a divergent value to an SGPR input.
9328 if (SrcVal->isDivergent() && SGPRInputRegs.count(Reg)) {
9329 SDValue ReadFirstLaneID =
9330 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
9331 SDValue ReadFirstLane =
9333 ReadFirstLaneID, SrcVal);
9334
9335 SmallVector<SDValue, 4> Ops = {N->getOperand(0), N->getOperand(1),
9336 ReadFirstLane};
9337 if (N->getNumOperands() > 3)
9338 Ops.push_back(N->getOperand(3)); // Glue input
9339
9340 DAG.UpdateNodeOperands(N, Ops);
9341 }
9342
9343 // Follow glue chain to next CopyToReg.
9344 SDNode *Next = nullptr;
9345 for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I) {
9346 if (N->getOperand(I).getValueType() == MVT::Glue) {
9347 Next = N->getOperand(I).getNode();
9348 break;
9349 }
9350 }
9351 N = Next;
9352 }
9353
9354 return Op;
9355}
9356
9357SDValue SITargetLowering::getSegmentAperture(unsigned AS, const SDLoc &DL,
9358 SelectionDAG &DAG) const {
9359 if (Subtarget->hasApertureRegs()) {
9360 const unsigned ApertureRegNo = (AS == AMDGPUAS::LOCAL_ADDRESS)
9361 ? AMDGPU::SRC_SHARED_BASE
9362 : AMDGPU::SRC_PRIVATE_BASE;
9363 assert((ApertureRegNo != AMDGPU::SRC_PRIVATE_BASE ||
9364 !Subtarget->hasGloballyAddressableScratch()) &&
9365 "Cannot use src_private_base with globally addressable scratch!");
9366 // Note: this feature (register) is broken. When used as a 32-bit operand,
9367 // it returns a wrong value (all zeroes?). The real value is in the upper 32
9368 // bits.
9369 //
9370 // To work around the issue, emit a 64 bit copy from this register
9371 // then extract the high bits. Note that this shouldn't even result in a
9372 // shift being emitted and simply become a pair of registers (e.g.):
9373 // s_mov_b64 s[6:7], src_shared_base
9374 // v_mov_b32_e32 v1, s7
9375 SDValue Copy =
9376 DAG.getCopyFromReg(DAG.getEntryNode(), DL, ApertureRegNo, MVT::v2i32);
9377 return DAG.getExtractVectorElt(DL, MVT::i32, Copy, 1);
9378 }
9379
9380 // For code object version 5, private_base and shared_base are passed through
9381 // implicit kernargs.
9382 const Module *M = DAG.getMachineFunction().getFunction().getParent();
9386 return loadImplicitKernelArgument(DAG, MVT::i32, DL, Align(4), Param);
9387 }
9388
9390 SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
9391 Register UserSGPR = Info->getQueuePtrUserSGPR();
9392 if (UserSGPR == AMDGPU::NoRegister) {
9393 // We probably are in a function incorrectly marked with
9394 // amdgpu-no-queue-ptr. This is undefined.
9395 return DAG.getPOISON(MVT::i32);
9396 }
9397
9398 SDValue QueuePtr =
9399 CreateLiveInRegister(DAG, &AMDGPU::SReg_64RegClass, UserSGPR, MVT::i64);
9400
9401 // Offset into amd_queue_t for group_segment_aperture_base_hi /
9402 // private_segment_aperture_base_hi.
9403 uint32_t StructOffset = (AS == AMDGPUAS::LOCAL_ADDRESS) ? 0x40 : 0x44;
9404
9405 SDValue Ptr =
9406 DAG.getObjectPtrOffset(DL, QueuePtr, TypeSize::getFixed(StructOffset));
9407
9408 // TODO: Use custom target PseudoSourceValue.
9409 // TODO: We should use the value from the IR intrinsic call, but it might not
9410 // be available and how do we get it?
9411 MachinePointerInfo PtrInfo(AMDGPUAS::CONSTANT_ADDRESS);
9412 return DAG.getLoad(MVT::i32, DL, QueuePtr.getValue(1), Ptr, PtrInfo,
9413 commonAlignment(Align(64), StructOffset),
9416}
9417
9418/// Return true if the value is a known valid address, such that a null check is
9419/// not necessary.
9421 const AMDGPUTargetMachine &TM, unsigned AddrSpace) {
9423 return true;
9424
9425 if (auto *ConstVal = dyn_cast<ConstantSDNode>(Val))
9426 return ConstVal->getSExtValue() != AMDGPU::getNullPointerValue(AddrSpace);
9427
9428 // TODO: Search through arithmetic, handle arguments and loads
9429 // marked nonnull.
9430 return false;
9431}
9432
9433SDValue SITargetLowering::lowerADDRSPACECAST(SDValue Op,
9434 SelectionDAG &DAG) const {
9435 SDLoc SL(Op);
9436
9437 const AMDGPUTargetMachine &TM =
9438 static_cast<const AMDGPUTargetMachine &>(getTargetMachine());
9439
9440 unsigned DestAS, SrcAS;
9441 SDValue Src;
9442 bool IsNonNull = false;
9443 if (const auto *ASC = dyn_cast<AddrSpaceCastSDNode>(Op)) {
9444 SrcAS = ASC->getSrcAddressSpace();
9445 Src = ASC->getOperand(0);
9446 DestAS = ASC->getDestAddressSpace();
9447 } else {
9448 assert(Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN &&
9449 Op.getConstantOperandVal(0) ==
9450 Intrinsic::amdgcn_addrspacecast_nonnull);
9451 Src = Op->getOperand(1);
9452 SrcAS = Op->getConstantOperandVal(2);
9453 DestAS = Op->getConstantOperandVal(3);
9454 IsNonNull = true;
9455 }
9456
9457 SDValue FlatNullPtr = DAG.getConstant(0, SL, MVT::i64);
9458
9459 // flat -> local/private
9460 if (SrcAS == AMDGPUAS::FLAT_ADDRESS) {
9461 if (DestAS == AMDGPUAS::LOCAL_ADDRESS ||
9462 DestAS == AMDGPUAS::PRIVATE_ADDRESS) {
9463 SDValue Ptr = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9464
9465 if (DestAS == AMDGPUAS::PRIVATE_ADDRESS &&
9466 Subtarget->hasGloballyAddressableScratch()) {
9467 // flat -> private with globally addressable scratch: subtract
9468 // src_flat_scratch_base_lo.
9469 SDValue FlatScratchBaseLo(
9470 DAG.getMachineNode(
9471 AMDGPU::S_MOV_B32, SL, MVT::i32,
9472 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_LO, MVT::i32)),
9473 0);
9474 Ptr = DAG.getNode(ISD::SUB, SL, MVT::i32, Ptr, FlatScratchBaseLo);
9475 }
9476
9477 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9478 return Ptr;
9479
9480 unsigned NullVal = AMDGPU::getNullPointerValue(DestAS);
9481 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9482 SDValue NonNull = DAG.getSetCC(SL, MVT::i1, Src, FlatNullPtr, ISD::SETNE);
9483
9484 return DAG.getNode(ISD::SELECT, SL, MVT::i32, NonNull, Ptr,
9485 SegmentNullPtr);
9486 }
9487 }
9488
9489 // local/private -> flat
9490 if (DestAS == AMDGPUAS::FLAT_ADDRESS) {
9491 if (SrcAS == AMDGPUAS::LOCAL_ADDRESS ||
9492 SrcAS == AMDGPUAS::PRIVATE_ADDRESS) {
9493 SDValue CvtPtr;
9494 if (SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
9495 Subtarget->hasGloballyAddressableScratch()) {
9496 // For wave32: Addr = (TID[4:0] << 52) + FLAT_SCRATCH_BASE + privateAddr
9497 // For wave64: Addr = (TID[5:0] << 51) + FLAT_SCRATCH_BASE + privateAddr
9498 SDValue AllOnes = DAG.getSignedTargetConstant(-1, SL, MVT::i32);
9499 SDValue ThreadID = DAG.getConstant(0, SL, MVT::i32);
9500 ThreadID = DAG.getNode(
9501 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9502 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_lo, SL, MVT::i32),
9503 AllOnes, ThreadID);
9504 if (Subtarget->isWave64())
9505 ThreadID = DAG.getNode(
9506 ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32,
9507 DAG.getTargetConstant(Intrinsic::amdgcn_mbcnt_hi, SL, MVT::i32),
9508 AllOnes, ThreadID);
9509 SDValue ShAmt = DAG.getShiftAmountConstant(
9510 57 - 32 - Subtarget->getWavefrontSizeLog2(), MVT::i32, SL);
9511 SDValue SrcHi = DAG.getNode(ISD::SHL, SL, MVT::i32, ThreadID, ShAmt);
9512 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, SrcHi);
9513 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9514 // Accessing src_flat_scratch_base_lo as a 64-bit operand gives the full
9515 // 64-bit hi:lo value.
9516 SDValue FlatScratchBase = {
9517 DAG.getMachineNode(
9518 AMDGPU::S_MOV_B64, SL, MVT::i64,
9519 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE, MVT::i64)),
9520 0};
9521 CvtPtr = DAG.getNode(ISD::ADD, SL, MVT::i64, CvtPtr, FlatScratchBase);
9522 } else {
9523 SDValue Aperture = getSegmentAperture(SrcAS, SL, DAG);
9524 CvtPtr = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Aperture);
9525 CvtPtr = DAG.getNode(ISD::BITCAST, SL, MVT::i64, CvtPtr);
9526 }
9527
9528 if (IsNonNull || isKnownNonNull(Op, DAG, TM, SrcAS))
9529 return CvtPtr;
9530
9531 unsigned NullVal = AMDGPU::getNullPointerValue(SrcAS);
9532 SDValue SegmentNullPtr = DAG.getConstant(NullVal, SL, MVT::i32);
9533
9534 SDValue NonNull =
9535 DAG.getSetCC(SL, MVT::i1, Src, SegmentNullPtr, ISD::SETNE);
9536
9537 return DAG.getNode(ISD::SELECT, SL, MVT::i64, NonNull, CvtPtr,
9538 FlatNullPtr);
9539 }
9540 }
9541
9542 if (SrcAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9543 Op.getValueType() == MVT::i64) {
9544 const SIMachineFunctionInfo *Info =
9545 DAG.getMachineFunction().getInfo<SIMachineFunctionInfo>();
9546 if (Info->get32BitAddressHighBits() == 0)
9547 return DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i64, Src);
9548
9549 SDValue Hi = DAG.getConstant(Info->get32BitAddressHighBits(), SL, MVT::i32);
9550 SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, Src, Hi);
9551 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
9552 }
9553
9554 if (DestAS == AMDGPUAS::CONSTANT_ADDRESS_32BIT &&
9555 Src.getValueType() == MVT::i64)
9556 return DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Src);
9557
9558 // global <-> flat are no-ops and never emitted.
9559
9560 // Invalid casts are poison.
9561 return DAG.getPOISON(Op->getValueType(0));
9562}
9563
9564// This lowers an INSERT_SUBVECTOR by extracting the individual elements from
9565// the small vector and inserting them into the big vector. That is better than
9566// the default expansion of doing it via a stack slot. Even though the use of
9567// the stack slot would be optimized away afterwards, the stack slot itself
9568// remains.
9569SDValue SITargetLowering::lowerINSERT_SUBVECTOR(SDValue Op,
9570 SelectionDAG &DAG) const {
9571 SDValue Vec = Op.getOperand(0);
9572 SDValue Ins = Op.getOperand(1);
9573 SDValue Idx = Op.getOperand(2);
9574 EVT VecVT = Vec.getValueType();
9575 EVT InsVT = Ins.getValueType();
9576 EVT EltVT = VecVT.getVectorElementType();
9577 unsigned InsNumElts = InsVT.getVectorNumElements();
9578 unsigned IdxVal = Idx->getAsZExtVal();
9579 SDLoc SL(Op);
9580
9581 if (EltVT.getScalarSizeInBits() == 16 && IdxVal % 2 == 0) {
9582 // Insert 32-bit registers at a time.
9583 assert(InsNumElts % 2 == 0 && "expect legal vector types");
9584
9585 unsigned VecNumElts = VecVT.getVectorNumElements();
9586 EVT NewVecVT =
9587 EVT::getVectorVT(*DAG.getContext(), MVT::i32, VecNumElts / 2);
9588 EVT NewInsVT = InsNumElts == 2 ? MVT::i32
9590 MVT::i32, InsNumElts / 2);
9591
9592 Vec = DAG.getNode(ISD::BITCAST, SL, NewVecVT, Vec);
9593 Ins = DAG.getNode(ISD::BITCAST, SL, NewInsVT, Ins);
9594
9595 for (unsigned I = 0; I != InsNumElts / 2; ++I) {
9596 SDValue Elt;
9597 if (InsNumElts == 2) {
9598 Elt = Ins;
9599 } else {
9600 Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Ins,
9601 DAG.getConstant(I, SL, MVT::i32));
9602 }
9603 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, NewVecVT, Vec, Elt,
9604 DAG.getConstant(IdxVal / 2 + I, SL, MVT::i32));
9605 }
9606
9607 return DAG.getNode(ISD::BITCAST, SL, VecVT, Vec);
9608 }
9609
9610 for (unsigned I = 0; I != InsNumElts; ++I) {
9611 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Ins,
9612 DAG.getConstant(I, SL, MVT::i32));
9613 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, SL, VecVT, Vec, Elt,
9614 DAG.getConstant(IdxVal + I, SL, MVT::i32));
9615 }
9616 return Vec;
9617}
9618
9619SDValue SITargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,
9620 SelectionDAG &DAG) const {
9621 SDValue Vec = Op.getOperand(0);
9622 SDValue InsVal = Op.getOperand(1);
9623 SDValue Idx = Op.getOperand(2);
9624 EVT VecVT = Vec.getValueType();
9625 EVT EltVT = VecVT.getVectorElementType();
9626 unsigned VecSize = VecVT.getSizeInBits();
9627 unsigned EltSize = EltVT.getSizeInBits();
9628 SDLoc SL(Op);
9629
9630 // Specially handle the case of v4i16 with static indexing.
9631 unsigned NumElts = VecVT.getVectorNumElements();
9632 auto *KIdx = dyn_cast<ConstantSDNode>(Idx);
9633 if (NumElts == 4 && EltSize == 16 && KIdx) {
9634 SDValue BCVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Vec);
9635
9636 SDValue LoHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9637 DAG.getConstant(0, SL, MVT::i32));
9638 SDValue HiHalf = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BCVec,
9639 DAG.getConstant(1, SL, MVT::i32));
9640
9641 SDValue LoVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, LoHalf);
9642 SDValue HiVec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i16, HiHalf);
9643
9644 unsigned Idx = KIdx->getZExtValue();
9645 bool InsertLo = Idx < 2;
9646 SDValue InsHalf = DAG.getNode(
9647 ISD::INSERT_VECTOR_ELT, SL, MVT::v2i16, InsertLo ? LoVec : HiVec,
9648 DAG.getNode(ISD::BITCAST, SL, MVT::i16, InsVal),
9649 DAG.getConstant(InsertLo ? Idx : (Idx - 2), SL, MVT::i32));
9650
9651 InsHalf = DAG.getNode(ISD::BITCAST, SL, MVT::i32, InsHalf);
9652
9653 SDValue Concat =
9654 InsertLo ? DAG.getBuildVector(MVT::v2i32, SL, {InsHalf, HiHalf})
9655 : DAG.getBuildVector(MVT::v2i32, SL, {LoHalf, InsHalf});
9656
9657 return DAG.getNode(ISD::BITCAST, SL, VecVT, Concat);
9658 }
9659
9660 // Static indexing does not lower to stack access, and hence there is no need
9661 // for special custom lowering to avoid stack access.
9662 if (isa<ConstantSDNode>(Idx))
9663 return SDValue();
9664
9665 // Avoid stack access for dynamic indexing by custom lowering to
9666 // v_bfi_b32 (v_bfm_b32 16, (shl idx, 16)), val, vec
9667
9668 assert(VecSize <= 64 && "Expected target vector size to be <= 64 bits");
9669
9670 MVT IntVT = MVT::getIntegerVT(VecSize);
9671
9672 // Convert vector index to bit-index and get the required bit mask.
9673 assert(isPowerOf2_32(EltSize));
9674 const auto EltMask = maskTrailingOnes<uint64_t>(EltSize);
9675 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9676 SDValue ScaledIdx = DAG.getNode(ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9677 SDValue BFM = DAG.getNode(ISD::SHL, SL, IntVT,
9678 DAG.getConstant(EltMask, SL, IntVT), ScaledIdx);
9679
9680 // 1. Create a congruent vector with the target value in each element.
9681 SDValue ExtVal = DAG.getNode(ISD::BITCAST, SL, IntVT,
9682 DAG.getSplatBuildVector(VecVT, SL, InsVal));
9683
9684 // 2. Mask off all other indices except the required index within (1).
9685 SDValue LHS = DAG.getNode(ISD::AND, SL, IntVT, BFM, ExtVal);
9686
9687 // 3. Mask off the required index within the target vector.
9688 SDValue BCVec = DAG.getNode(ISD::BITCAST, SL, IntVT, Vec);
9689 SDValue RHS =
9690 DAG.getNode(ISD::AND, SL, IntVT, DAG.getNOT(SL, BFM, IntVT), BCVec);
9691
9692 // 4. Get (2) and (3) ORed into the target vector.
9693 SDValue BFI =
9694 DAG.getNode(ISD::OR, SL, IntVT, LHS, RHS, SDNodeFlags::Disjoint);
9695
9696 return DAG.getNode(ISD::BITCAST, SL, VecVT, BFI);
9697}
9698
9699SDValue SITargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op,
9700 SelectionDAG &DAG) const {
9701 SDLoc SL(Op);
9702
9703 EVT ResultVT = Op.getValueType();
9704 SDValue Vec = Op.getOperand(0);
9705 SDValue Idx = Op.getOperand(1);
9706 EVT VecVT = Vec.getValueType();
9707 unsigned VecSize = VecVT.getSizeInBits();
9708 EVT EltVT = VecVT.getVectorElementType();
9709
9710 DAGCombinerInfo DCI(DAG, AfterLegalizeVectorOps, true, nullptr);
9711
9712 // Make sure we do any optimizations that will make it easier to fold
9713 // source modifiers before obscuring it with bit operations.
9714
9715 // XXX - Why doesn't this get called when vector_shuffle is expanded?
9716 if (SDValue Combined = performExtractVectorEltCombine(Op.getNode(), DCI))
9717 return Combined;
9718
9719 if (VecSize == 128 || VecSize == 256 || VecSize == 512) {
9720 SDValue Lo, Hi;
9721 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VecVT);
9722
9723 if (VecSize == 128) {
9724 SDValue V2 = DAG.getBitcast(MVT::v2i64, Vec);
9725 Lo = DAG.getBitcast(LoVT,
9726 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9727 DAG.getConstant(0, SL, MVT::i32)));
9728 Hi = DAG.getBitcast(HiVT,
9729 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9730 DAG.getConstant(1, SL, MVT::i32)));
9731 } else if (VecSize == 256) {
9732 SDValue V2 = DAG.getBitcast(MVT::v4i64, Vec);
9733 SDValue Parts[4];
9734 for (unsigned P = 0; P < 4; ++P) {
9735 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9736 DAG.getConstant(P, SL, MVT::i32));
9737 }
9738
9739 Lo = DAG.getBitcast(LoVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9740 Parts[0], Parts[1]));
9741 Hi = DAG.getBitcast(HiVT, DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i64,
9742 Parts[2], Parts[3]));
9743 } else {
9744 assert(VecSize == 512);
9745
9746 SDValue V2 = DAG.getBitcast(MVT::v8i64, Vec);
9747 SDValue Parts[8];
9748 for (unsigned P = 0; P < 8; ++P) {
9749 Parts[P] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i64, V2,
9750 DAG.getConstant(P, SL, MVT::i32));
9751 }
9752
9753 Lo = DAG.getBitcast(LoVT,
9754 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9755 Parts[0], Parts[1], Parts[2], Parts[3]));
9756 Hi = DAG.getBitcast(HiVT,
9757 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v4i64,
9758 Parts[4], Parts[5], Parts[6], Parts[7]));
9759 }
9760
9761 EVT IdxVT = Idx.getValueType();
9762 unsigned NElem = VecVT.getVectorNumElements();
9763 assert(isPowerOf2_32(NElem));
9764 SDValue IdxMask = DAG.getConstant(NElem / 2 - 1, SL, IdxVT);
9765 SDValue NewIdx = DAG.getNode(ISD::AND, SL, IdxVT, Idx, IdxMask);
9766 SDValue Half = DAG.getSelectCC(SL, Idx, IdxMask, Hi, Lo, ISD::SETUGT);
9767 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Half, NewIdx);
9768 }
9769
9770 assert(VecSize <= 64);
9771
9772 MVT IntVT = MVT::getIntegerVT(VecSize);
9773
9774 // If Vec is just a SCALAR_TO_VECTOR, then use the scalar integer directly.
9775 SDValue VecBC = peekThroughBitcasts(Vec);
9776 if (VecBC.getOpcode() == ISD::SCALAR_TO_VECTOR) {
9777 SDValue Src = VecBC.getOperand(0);
9778 Src = DAG.getBitcast(Src.getValueType().changeTypeToInteger(), Src);
9779 Vec = DAG.getAnyExtOrTrunc(Src, SL, IntVT);
9780 }
9781
9782 unsigned EltSize = EltVT.getSizeInBits();
9783 assert(isPowerOf2_32(EltSize));
9784
9785 SDValue ScaleFactor = DAG.getConstant(Log2_32(EltSize), SL, MVT::i32);
9786
9787 // Convert vector index to bit-index (* EltSize)
9788 SDValue ScaledIdx = DAG.getNode(ISD::SHL, SL, MVT::i32, Idx, ScaleFactor);
9789
9790 SDValue BC = DAG.getNode(ISD::BITCAST, SL, IntVT, Vec);
9791 SDValue Elt = DAG.getNode(ISD::SRL, SL, IntVT, BC, ScaledIdx);
9792
9793 if (ResultVT == MVT::f16 || ResultVT == MVT::bf16) {
9794 SDValue Result = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Elt);
9795 return DAG.getNode(ISD::BITCAST, SL, ResultVT, Result);
9796 }
9797
9798 return DAG.getAnyExtOrTrunc(Elt, SL, ResultVT);
9799}
9800
9801static bool elementPairIsContiguous(ArrayRef<int> Mask, int Elt) {
9802 assert(Elt % 2 == 0);
9803 return Mask[Elt + 1] == Mask[Elt] + 1 && (Mask[Elt] % 2 == 0);
9804}
9805
9806static bool elementPairIsOddToEven(ArrayRef<int> Mask, int Elt) {
9807 assert(Elt % 2 == 0);
9808 return Mask[Elt] >= 0 && Mask[Elt + 1] >= 0 && (Mask[Elt] & 1) &&
9809 !(Mask[Elt + 1] & 1);
9810}
9811
9812SDValue SITargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
9813 SelectionDAG &DAG) const {
9814 SDLoc SL(Op);
9815 EVT ResultVT = Op.getValueType();
9816 ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
9817 MVT EltVT = ResultVT.getVectorElementType().getSimpleVT();
9818 const int NewSrcNumElts = 2;
9819 MVT PackVT = MVT::getVectorVT(EltVT, NewSrcNumElts);
9820 int SrcNumElts = Op.getOperand(0).getValueType().getVectorNumElements();
9821
9822 // Break up the shuffle into registers sized pieces.
9823 //
9824 // We're trying to form sub-shuffles that the register allocation pipeline
9825 // won't be able to figure out, like how to use v_pk_mov_b32 to do a register
9826 // blend or 16-bit op_sel. It should be able to figure out how to reassemble a
9827 // pair of copies into a consecutive register copy, so use the ordinary
9828 // extract_vector_elt lowering unless we can use the shuffle.
9829 //
9830 // TODO: This is a bit of hack, and we should probably always use
9831 // extract_subvector for the largest possible subvector we can (or at least
9832 // use it for PackVT aligned pieces). However we have worse support for
9833 // combines on them don't directly treat extract_subvector / insert_subvector
9834 // as legal. The DAG scheduler also ends up doing a worse job with the
9835 // extract_subvectors.
9836 const bool ShouldUseConsecutiveExtract = EltVT.getSizeInBits() == 16;
9837
9838 // vector_shuffle <0,1,6,7> lhs, rhs
9839 // -> concat_vectors (extract_subvector lhs, 0), (extract_subvector rhs, 2)
9840 //
9841 // vector_shuffle <6,7,2,3> lhs, rhs
9842 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 2)
9843 //
9844 // vector_shuffle <6,7,0,1> lhs, rhs
9845 // -> concat_vectors (extract_subvector rhs, 2), (extract_subvector lhs, 0)
9846
9847 // Avoid scalarizing when both halves are reading from consecutive elements.
9848
9849 // If we're treating 2 element shuffles as legal, also create odd-to-even
9850 // shuffles of neighboring pairs.
9851 //
9852 // vector_shuffle <3,2,7,6> lhs, rhs
9853 // -> concat_vectors vector_shuffle <1, 0> (extract_subvector lhs, 0)
9854 // vector_shuffle <1, 0> (extract_subvector rhs, 2)
9855
9857 for (int I = 0, N = ResultVT.getVectorNumElements(); I != N; I += 2) {
9858 if (ShouldUseConsecutiveExtract &&
9860 const int Idx = SVN->getMaskElt(I);
9861 int VecIdx = Idx < SrcNumElts ? 0 : 1;
9862 int EltIdx = Idx < SrcNumElts ? Idx : Idx - SrcNumElts;
9863 SDValue SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT,
9864 SVN->getOperand(VecIdx),
9865 DAG.getConstant(EltIdx, SL, MVT::i32));
9866 Pieces.push_back(SubVec);
9867 } else if (elementPairIsOddToEven(SVN->getMask(), I) &&
9869 int Idx0 = SVN->getMaskElt(I);
9870 int Idx1 = SVN->getMaskElt(I + 1);
9871
9872 SDValue SrcOp0 = SVN->getOperand(0);
9873 SDValue SrcOp1 = SrcOp0;
9874 if (Idx0 >= SrcNumElts) {
9875 SrcOp0 = SVN->getOperand(1);
9876 Idx0 -= SrcNumElts;
9877 }
9878
9879 if (Idx1 >= SrcNumElts) {
9880 SrcOp1 = SVN->getOperand(1);
9881 Idx1 -= SrcNumElts;
9882 }
9883
9884 int AlignedIdx0 = Idx0 & ~(NewSrcNumElts - 1);
9885 int AlignedIdx1 = Idx1 & ~(NewSrcNumElts - 1);
9886
9887 // Extract nearest even aligned piece.
9888 SDValue SubVec0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp0,
9889 DAG.getConstant(AlignedIdx0, SL, MVT::i32));
9890 SDValue SubVec1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SL, PackVT, SrcOp1,
9891 DAG.getConstant(AlignedIdx1, SL, MVT::i32));
9892
9893 int NewMaskIdx0 = Idx0 - AlignedIdx0;
9894 int NewMaskIdx1 = Idx1 - AlignedIdx1;
9895
9896 SDValue Result0 = SubVec0;
9897 SDValue Result1 = SubVec0;
9898
9899 if (SubVec0 != SubVec1) {
9900 NewMaskIdx1 += NewSrcNumElts;
9901 Result1 = SubVec1;
9902 } else {
9903 Result1 = DAG.getPOISON(PackVT);
9904 }
9905
9906 SDValue Shuf = DAG.getVectorShuffle(PackVT, SL, Result0, Result1,
9907 {NewMaskIdx0, NewMaskIdx1});
9908 Pieces.push_back(Shuf);
9909 } else {
9910 const int Idx0 = SVN->getMaskElt(I);
9911 const int Idx1 = SVN->getMaskElt(I + 1);
9912 int VecIdx0 = Idx0 < SrcNumElts ? 0 : 1;
9913 int VecIdx1 = Idx1 < SrcNumElts ? 0 : 1;
9914 int EltIdx0 = Idx0 < SrcNumElts ? Idx0 : Idx0 - SrcNumElts;
9915 int EltIdx1 = Idx1 < SrcNumElts ? Idx1 : Idx1 - SrcNumElts;
9916
9917 SDValue Vec0 = SVN->getOperand(VecIdx0);
9918 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec0,
9919 DAG.getSignedConstant(EltIdx0, SL, MVT::i32));
9920
9921 SDValue Vec1 = SVN->getOperand(VecIdx1);
9922 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec1,
9923 DAG.getSignedConstant(EltIdx1, SL, MVT::i32));
9924 Pieces.push_back(DAG.getBuildVector(PackVT, SL, {Elt0, Elt1}));
9925 }
9926 }
9927
9928 return DAG.getNode(ISD::CONCAT_VECTORS, SL, ResultVT, Pieces);
9929}
9930
9931SDValue SITargetLowering::lowerSCALAR_TO_VECTOR(SDValue Op,
9932 SelectionDAG &DAG) const {
9933 SDValue SVal = Op.getOperand(0);
9934 EVT ResultVT = Op.getValueType();
9935 EVT SValVT = SVal.getValueType();
9936 SDValue UndefVal = DAG.getPOISON(SValVT);
9937 SDLoc SL(Op);
9938
9940 VElts.push_back(SVal);
9941 for (int I = 1, E = ResultVT.getVectorNumElements(); I < E; ++I)
9942 VElts.push_back(UndefVal);
9943
9944 return DAG.getBuildVector(ResultVT, SL, VElts);
9945}
9946
9947SDValue SITargetLowering::lowerBUILD_VECTOR(SDValue Op,
9948 SelectionDAG &DAG) const {
9949 SDLoc SL(Op);
9950 EVT VT = Op.getValueType();
9951
9952 if (VT == MVT::v2f16 || VT == MVT::v2i16 || VT == MVT::v2bf16) {
9953 assert(!Subtarget->hasVOP3PInsts() && "this should be legal");
9954
9955 SDValue Lo = Op.getOperand(0);
9956 SDValue Hi = Op.getOperand(1);
9957
9958 // Avoid adding defined bits with the zero_extend.
9959 if (Hi.isUndef()) {
9960 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
9961 SDValue ExtLo = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Lo);
9962 return DAG.getNode(ISD::BITCAST, SL, VT, ExtLo);
9963 }
9964
9965 Hi = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Hi);
9966 Hi = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Hi);
9967
9968 SDValue ShlHi = DAG.getNode(ISD::SHL, SL, MVT::i32, Hi,
9969 DAG.getConstant(16, SL, MVT::i32));
9970 if (Lo.isUndef())
9971 return DAG.getNode(ISD::BITCAST, SL, VT, ShlHi);
9972
9973 Lo = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Lo);
9974 Lo = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Lo);
9975
9976 SDValue Or =
9977 DAG.getNode(ISD::OR, SL, MVT::i32, Lo, ShlHi, SDNodeFlags::Disjoint);
9978 return DAG.getNode(ISD::BITCAST, SL, VT, Or);
9979 }
9980
9981 // Split into 2-element chunks.
9982 const unsigned NumParts = VT.getVectorNumElements() / 2;
9983 EVT PartVT = MVT::getVectorVT(VT.getVectorElementType().getSimpleVT(), 2);
9984 MVT PartIntVT = MVT::getIntegerVT(PartVT.getSizeInBits());
9985
9987 for (unsigned P = 0; P < NumParts; ++P) {
9988 SDValue Vec = DAG.getBuildVector(
9989 PartVT, SL, {Op.getOperand(P * 2), Op.getOperand(P * 2 + 1)});
9990 Casts.push_back(DAG.getNode(ISD::BITCAST, SL, PartIntVT, Vec));
9991 }
9992
9993 SDValue Blend =
9994 DAG.getBuildVector(MVT::getVectorVT(PartIntVT, NumParts), SL, Casts);
9995 return DAG.getNode(ISD::BITCAST, SL, VT, Blend);
9996}
9997
9999 const GlobalAddressSDNode *GA) const {
10000 // Named barriers have fixed, non-relocated LDS addresses, so a constant
10001 // offset into an array of them can be folded into the address.
10003 const auto *GV = dyn_cast<GlobalVariable>(GA->getGlobal());
10004 return GV && AMDGPU::isNamedBarrier(*GV);
10005 }
10006
10007 // OSes that use ELF REL relocations (instead of RELA) can only store a
10008 // 32-bit addend in the instruction, so it is not safe to allow offset folding
10009 // which can create arbitrary 64-bit addends. (This is only a problem for
10010 // R_AMDGPU_*32_HI relocations since other relocation types are unaffected by
10011 // the high 32 bits of the addend.)
10012 //
10013 // This should be kept in sync with how HasRelocationAddend is initialized in
10014 // the constructor of ELFAMDGPUAsmBackend.
10015 if (!Subtarget->isAmdHsaOS())
10016 return false;
10017
10018 // We can fold offsets for anything that doesn't require a GOT relocation.
10019 return (GA->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS ||
10023}
10024
10025static SDValue
10027 const SDLoc &DL, int64_t Offset, EVT PtrVT,
10028 unsigned GAFlags = SIInstrInfo::MO_NONE) {
10029 assert(isInt<32>(Offset + 4) && "32-bit offset is expected!");
10030 // In order to support pc-relative addressing, the PC_ADD_REL_OFFSET SDNode is
10031 // lowered to the following code sequence:
10032 //
10033 // For constant address space:
10034 // s_getpc_b64 s[0:1]
10035 // s_add_u32 s0, s0, $symbol
10036 // s_addc_u32 s1, s1, 0
10037 //
10038 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10039 // a fixup or relocation is emitted to replace $symbol with a literal
10040 // constant, which is a pc-relative offset from the encoding of the $symbol
10041 // operand to the global variable.
10042 //
10043 // For global address space:
10044 // s_getpc_b64 s[0:1]
10045 // s_add_u32 s0, s0, $symbol@{gotpc}rel32@lo
10046 // s_addc_u32 s1, s1, $symbol@{gotpc}rel32@hi
10047 //
10048 // s_getpc_b64 returns the address of the s_add_u32 instruction and then
10049 // fixups or relocations are emitted to replace $symbol@*@lo and
10050 // $symbol@*@hi with lower 32 bits and higher 32 bits of a literal constant,
10051 // which is a 64-bit pc-relative offset from the encoding of the $symbol
10052 // operand to the global variable.
10053 if (((const GCNSubtarget &)DAG.getSubtarget()).has64BitLiterals()) {
10054 assert(GAFlags != SIInstrInfo::MO_NONE);
10055
10056 SDValue Ptr =
10057 DAG.getTargetGlobalAddress(GV, DL, MVT::i64, Offset, GAFlags + 2);
10058 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET64, DL, PtrVT, Ptr);
10059 }
10060
10061 SDValue PtrLo = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags);
10062 SDValue PtrHi;
10063 if (GAFlags == SIInstrInfo::MO_NONE)
10064 PtrHi = DAG.getTargetConstant(0, DL, MVT::i32);
10065 else
10066 PtrHi = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, Offset, GAFlags + 1);
10067 return DAG.getNode(AMDGPUISD::PC_ADD_REL_OFFSET, DL, PtrVT, PtrLo, PtrHi);
10068}
10069
10070SDValue SITargetLowering::LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI,
10071 SDValue Op,
10072 SelectionDAG &DAG) const {
10073 GlobalAddressSDNode *GSD = cast<GlobalAddressSDNode>(Op);
10074 SDLoc DL(GSD);
10075 EVT PtrVT = Op.getValueType();
10076
10077 const GlobalValue *GV = GSD->getGlobal();
10083 GV->hasExternalLinkage()) {
10084 const GlobalVariable &GVar = *cast<GlobalVariable>(GV);
10085 // HIP uses an unsized array `extern __shared__ T s[]` or similar
10086 // zero-sized type in other languages to declare the dynamic shared
10087 // memory which size is not known at the compile time. They will be
10088 // allocated by the runtime and placed directly after the static
10089 // allocated ones. They all share the same offset.
10090 if (GVar.getGlobalSize(GVar.getDataLayout()) == 0) {
10091 assert(PtrVT == MVT::i32 && "32-bit pointer is expected.");
10092 // Adjust alignment for that dynamic shared memory array.
10094 MFI->setDynLDSAlign(F, GVar);
10095 MFI->setUsesDynamicLDS(true);
10096 return SDValue(
10097 DAG.getMachineNode(AMDGPU::GET_GROUPSTATICSIZE, DL, PtrVT), 0);
10098 }
10099 }
10101 }
10102
10104 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, GSD->getOffset(),
10106 return DAG.getNode(AMDGPUISD::LDS, DL, MVT::i32, GA);
10107 }
10108
10109 if (Subtarget->isAmdPalOS() || Subtarget->isMesa3DOS()) {
10110 if (Subtarget->has64BitLiterals()) {
10112 GV, DL, MVT::i64, GSD->getOffset(), SIInstrInfo::MO_ABS64);
10113 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B64, DL, MVT::i64, Addr),
10114 0);
10115 }
10116
10117 SDValue AddrLo = DAG.getTargetGlobalAddress(
10118 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_LO);
10119 AddrLo = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrLo), 0};
10120
10121 SDValue AddrHi = DAG.getTargetGlobalAddress(
10122 GV, DL, MVT::i32, GSD->getOffset(), SIInstrInfo::MO_ABS32_HI);
10123 AddrHi = {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, AddrHi), 0};
10124
10125 return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, AddrLo, AddrHi);
10126 }
10127
10128 if (shouldEmitFixup(GV))
10129 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT);
10130
10131 if (shouldEmitPCReloc(GV))
10132 return buildPCRelGlobalAddress(DAG, GV, DL, GSD->getOffset(), PtrVT,
10134
10135 SDValue GOTAddr = buildPCRelGlobalAddress(DAG, GV, DL, 0, PtrVT,
10137 PointerType *PtrTy =
10139 const DataLayout &DataLayout = DAG.getDataLayout();
10140 Align Alignment = DataLayout.getABITypeAlign(PtrTy);
10141 MachinePointerInfo PtrInfo =
10143
10144 return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), GOTAddr, PtrInfo, Alignment,
10147}
10148
10149SDValue SITargetLowering::LowerExternalSymbol(SDValue Op,
10150 SelectionDAG &DAG) const {
10151 // TODO: Handle this. It should be mostly the same as LowerGlobalAddress.
10152 const Function &Fn = DAG.getMachineFunction().getFunction();
10153 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10154 Fn, "unsupported external symbol", Op.getDebugLoc()));
10155 return DAG.getPOISON(Op.getValueType());
10156}
10157
10159 const SDLoc &DL, SDValue V) const {
10160 // We can't use S_MOV_B32 directly, because there is no way to specify m0 as
10161 // the destination register.
10162 //
10163 // We can't use CopyToReg, because MachineCSE won't combine COPY instructions,
10164 // so we will end up with redundant moves to m0.
10165 //
10166 // We use a pseudo to ensure we emit s_mov_b32 with m0 as the direct result.
10167
10168 // A Null SDValue creates a glue result.
10169 SDNode *M0 = DAG.getMachineNode(AMDGPU::SI_INIT_M0, DL, MVT::Other, MVT::Glue,
10170 V, Chain);
10171 return SDValue(M0, 0);
10172}
10173
10174SDValue SITargetLowering::lowerImplicitZextParam(SelectionDAG &DAG, SDValue Op,
10175 MVT VT,
10176 unsigned Offset) const {
10177 SDLoc SL(Op);
10178 SDValue Param = lowerKernargMemParameter(
10179 DAG, MVT::i32, MVT::i32, SL, DAG.getEntryNode(), Offset, Align(4), false);
10180 // The local size values will have the hi 16-bits as zero.
10181 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Param,
10182 DAG.getValueType(VT));
10183}
10184
10186 EVT VT) {
10189 "non-hsa intrinsic with hsa target", DL.getDebugLoc()));
10190 return DAG.getPOISON(VT);
10191}
10192
10194 EVT VT) {
10197 "intrinsic not supported on subtarget", DL.getDebugLoc()));
10198 return DAG.getPOISON(VT);
10199}
10200
10202 ArrayRef<SDValue> Elts) {
10203 assert(!Elts.empty());
10204 MVT Type;
10205 unsigned NumElts = Elts.size();
10206
10207 if (NumElts <= 12) {
10208 Type = MVT::getVectorVT(MVT::f32, NumElts);
10209 } else {
10210 assert(Elts.size() <= 16);
10211 Type = MVT::v16f32;
10212 NumElts = 16;
10213 }
10214
10215 SmallVector<SDValue, 16> VecElts(NumElts);
10216 for (unsigned i = 0; i < Elts.size(); ++i) {
10217 SDValue Elt = Elts[i];
10218 if (Elt.getValueType() != MVT::f32)
10219 Elt = DAG.getBitcast(MVT::f32, Elt);
10220 VecElts[i] = Elt;
10221 }
10222 for (unsigned i = Elts.size(); i < NumElts; ++i)
10223 VecElts[i] = DAG.getPOISON(MVT::f32);
10224
10225 if (NumElts == 1)
10226 return VecElts[0];
10227 return DAG.getBuildVector(Type, DL, VecElts);
10228}
10229
10230static SDValue padEltsToUndef(SelectionDAG &DAG, const SDLoc &DL, EVT CastVT,
10231 SDValue Src, int ExtraElts) {
10232 EVT SrcVT = Src.getValueType();
10233
10235
10236 if (SrcVT.isVector())
10237 DAG.ExtractVectorElements(Src, Elts);
10238 else
10239 Elts.push_back(Src);
10240
10241 SDValue Undef = DAG.getPOISON(SrcVT.getScalarType());
10242 while (ExtraElts--)
10243 Elts.push_back(Undef);
10244
10245 return DAG.getBuildVector(CastVT, DL, Elts);
10246}
10247
10248// Re-construct the required return value for a image load intrinsic.
10249// This is more complicated due to the optional use TexFailCtrl which means the
10250// required return type is an aggregate
10252 ArrayRef<EVT> ResultTypes, bool IsTexFail,
10253 bool Unpacked, bool IsD16, int DMaskPop,
10254 int NumVDataDwords, bool IsAtomicPacked16Bit,
10255 const SDLoc &DL) {
10256 // Determine the required return type. This is the same regardless of
10257 // IsTexFail flag
10258 EVT ReqRetVT = ResultTypes[0];
10259 int ReqRetNumElts = ReqRetVT.isVector() ? ReqRetVT.getVectorNumElements() : 1;
10260 int NumDataDwords = ((IsD16 && !Unpacked) || IsAtomicPacked16Bit)
10261 ? (ReqRetNumElts + 1) / 2
10262 : ReqRetNumElts;
10263
10264 int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2;
10265
10266 MVT DataDwordVT =
10267 NumDataDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, NumDataDwords);
10268
10269 MVT MaskPopVT =
10270 MaskPopDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, MaskPopDwords);
10271
10272 SDValue Data(Result, 0);
10273 SDValue TexFail;
10274
10275 if (DMaskPop > 0 && Data.getValueType() != MaskPopVT) {
10276 SDValue ZeroIdx = DAG.getConstant(0, DL, MVT::i32);
10277 if (MaskPopVT.isVector()) {
10278 Data = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, MaskPopVT,
10279 SDValue(Result, 0), ZeroIdx);
10280 } else {
10281 Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MaskPopVT,
10282 SDValue(Result, 0), ZeroIdx);
10283 }
10284 }
10285
10286 if (DataDwordVT.isVector() && !IsAtomicPacked16Bit)
10287 Data = padEltsToUndef(DAG, DL, DataDwordVT, Data,
10288 NumDataDwords - MaskPopDwords);
10289
10290 if (IsD16)
10291 Data = adjustLoadValueTypeImpl(Data, ReqRetVT, DL, DAG, Unpacked);
10292
10293 EVT LegalReqRetVT = ReqRetVT;
10294 if (!ReqRetVT.isVector()) {
10295 if (!Data.getValueType().isInteger())
10296 Data = DAG.getNode(ISD::BITCAST, DL,
10297 Data.getValueType().changeTypeToInteger(), Data);
10298 Data = DAG.getNode(ISD::TRUNCATE, DL, ReqRetVT.changeTypeToInteger(), Data);
10299 } else {
10300 // We need to widen the return vector to a legal type
10301 if ((ReqRetVT.getVectorNumElements() % 2) == 1 &&
10302 ReqRetVT.getVectorElementType().getSizeInBits() == 16) {
10303 LegalReqRetVT =
10305 ReqRetVT.getVectorNumElements() + 1);
10306 }
10307 }
10308 Data = DAG.getNode(ISD::BITCAST, DL, LegalReqRetVT, Data);
10309
10310 if (IsTexFail) {
10311 TexFail =
10312 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, SDValue(Result, 0),
10313 DAG.getConstant(MaskPopDwords, DL, MVT::i32));
10314
10315 return DAG.getMergeValues({Data, TexFail, SDValue(Result, 1)}, DL);
10316 }
10317
10318 if (Result->getNumValues() == 1)
10319 return Data;
10320
10321 return DAG.getMergeValues({Data, SDValue(Result, 1)}, DL);
10322}
10323
10324static bool parseTexFail(SDValue TexFailCtrl, SelectionDAG &DAG, SDValue *TFE,
10325 SDValue *LWE, bool &IsTexFail) {
10326 auto *TexFailCtrlConst = cast<ConstantSDNode>(TexFailCtrl.getNode());
10327
10328 uint64_t Value = TexFailCtrlConst->getZExtValue();
10329 if (Value) {
10330 IsTexFail = true;
10331 }
10332
10333 SDLoc DL(TexFailCtrlConst);
10334 *TFE = DAG.getTargetConstant((Value & 0x1) ? 1 : 0, DL, MVT::i32);
10335 Value &= ~(uint64_t)0x1;
10336 *LWE = DAG.getTargetConstant((Value & 0x2) ? 1 : 0, DL, MVT::i32);
10337 Value &= ~(uint64_t)0x2;
10338
10339 return Value == 0;
10340}
10341
10343 MVT PackVectorVT,
10344 SmallVectorImpl<SDValue> &PackedAddrs,
10345 unsigned DimIdx, unsigned EndIdx,
10346 unsigned NumGradients) {
10347 SDLoc DL(Op);
10348 for (unsigned I = DimIdx; I < EndIdx; I++) {
10349 SDValue Addr = Op.getOperand(I);
10350
10351 // Gradients are packed with undef for each coordinate.
10352 // In <hi 16 bit>,<lo 16 bit> notation, the registers look like this:
10353 // 1D: undef,dx/dh; undef,dx/dv
10354 // 2D: dy/dh,dx/dh; dy/dv,dx/dv
10355 // 3D: dy/dh,dx/dh; undef,dz/dh; dy/dv,dx/dv; undef,dz/dv
10356 if (((I + 1) >= EndIdx) ||
10357 ((NumGradients / 2) % 2 == 1 && (I == DimIdx + (NumGradients / 2) - 1 ||
10358 I == DimIdx + NumGradients - 1))) {
10359 if (Addr.getValueType() != MVT::i16)
10360 Addr = DAG.getBitcast(MVT::i16, Addr);
10361 Addr = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Addr);
10362 } else {
10363 Addr = DAG.getBuildVector(PackVectorVT, DL, {Addr, Op.getOperand(I + 1)});
10364 I++;
10365 }
10366 Addr = DAG.getBitcast(MVT::f32, Addr);
10367 PackedAddrs.push_back(Addr);
10368 }
10369}
10370
10371/// Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and
10372/// return poison values of \p ResultTypes, preserving the chain if present.
10374 ArrayRef<EVT> ResultTypes,
10375 const SDLoc &DL, const Twine &Msg) {
10377 DAG.getMachineFunction().getFunction(), Msg, DL.getDebugLoc()));
10378 return DAG.getErrorMergeValues(ResultTypes, Op.getOperand(0), DL);
10379}
10380
10381SDValue SITargetLowering::lowerImage(SDValue Op,
10383 SelectionDAG &DAG, bool WithChain) const {
10384 SDLoc DL(Op);
10386 const GCNSubtarget *ST = &MF.getSubtarget<GCNSubtarget>();
10387 unsigned IntrOpcode = Intr->BaseOpcode;
10388 // For image atomic: use no-return opcode if result is unused.
10389 if (Intr->AtomicNoRetBaseOpcode != Intr->BaseOpcode &&
10390 !Op.getNode()->hasAnyUseOfValue(0))
10391 IntrOpcode = Intr->AtomicNoRetBaseOpcode;
10392 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
10394 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfo(Intr->Dim);
10395 bool IsGFX10Plus = AMDGPU::isGFX10Plus(*Subtarget);
10396 bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
10397 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
10398 bool IsGFX13 = AMDGPU::isGFX13(*Subtarget);
10399
10400 SmallVector<EVT, 3> ResultTypes(Op->values());
10401 SmallVector<EVT, 3> OrigResultTypes(Op->values());
10402 if (BaseOpcode->NoReturn && BaseOpcode->Atomic)
10403 ResultTypes.erase(&ResultTypes[0]);
10404
10405 bool IsD16 = false;
10406 bool IsG16 = false;
10407 bool IsA16 = false;
10408 SDValue VData;
10409 int NumVDataDwords = 0;
10410 bool AdjustRetType = false;
10411 bool IsAtomicPacked16Bit = false;
10412
10413 // Offset of intrinsic arguments
10414 const unsigned ArgOffset = WithChain ? 2 : 1;
10415
10416 unsigned DMask;
10417 unsigned DMaskLanes = 0;
10418
10419 if (BaseOpcode->Atomic) {
10420 VData = Op.getOperand(2);
10421
10422 IsAtomicPacked16Bit =
10423 (IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16 ||
10424 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_F16_NORTN ||
10425 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16 ||
10426 IntrOpcode == AMDGPU::IMAGE_ATOMIC_PK_ADD_BF16_NORTN);
10427
10428 if (!IsAtomicPacked16Bit && VData.getValueSizeInBits() != 32 &&
10429 VData.getValueSizeInBits() != 64) {
10430 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10431 "unsupported image atomic data type");
10432 }
10433
10434 bool Is64Bit = VData.getValueSizeInBits() == 64;
10435 if (BaseOpcode->AtomicX2) {
10436 SDValue VData2 = Op.getOperand(3);
10437 VData = DAG.getBuildVector(Is64Bit ? MVT::v2i64 : MVT::v2i32, DL,
10438 {VData, VData2});
10439 if (Is64Bit)
10440 VData = DAG.getBitcast(MVT::v4i32, VData);
10441
10442 if (!BaseOpcode->NoReturn)
10443 ResultTypes[0] = Is64Bit ? MVT::v2i64 : MVT::v2i32;
10444
10445 DMask = Is64Bit ? 0xf : 0x3;
10446 NumVDataDwords = Is64Bit ? 4 : 2;
10447 } else {
10448 DMask = Is64Bit ? 0x3 : 0x1;
10449 NumVDataDwords = Is64Bit ? 2 : 1;
10450 }
10451 } else {
10452 DMask = Op->getConstantOperandVal(ArgOffset + Intr->DMaskIndex);
10453 DMaskLanes = BaseOpcode->Gather4 ? 4 : llvm::popcount(DMask);
10454
10455 if (BaseOpcode->Store) {
10456 VData = Op.getOperand(2);
10457
10458 MVT StoreVT = VData.getSimpleValueType();
10459 MVT StoreScalarVT = StoreVT.getScalarType();
10460 if (StoreScalarVT != MVT::f16 && StoreScalarVT.getSizeInBits() != 32 &&
10461 StoreScalarVT.getSizeInBits() != 64) {
10462 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10463 "unsupported image store data type");
10464 }
10465 if (StoreScalarVT == MVT::f16) {
10466 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10467 return Op; // D16 is unsupported for this instruction
10468
10469 IsD16 = true;
10470 VData = handleD16VData(VData, DAG, true);
10471 }
10472
10473 NumVDataDwords = (VData.getValueType().getSizeInBits() + 31) / 32;
10474 } else if (!BaseOpcode->NoReturn) {
10475 // Work out the num dwords based on the dmask popcount and underlying type
10476 // and whether packing is supported.
10477 MVT LoadVT = ResultTypes[0].getSimpleVT();
10478 MVT LoadScalarVT = LoadVT.getScalarType();
10479 if (LoadScalarVT != MVT::f16 && LoadScalarVT.getSizeInBits() != 32 &&
10480 LoadScalarVT.getSizeInBits() != 64) {
10481 return diagnoseUnsupportedImage(DAG, Op, OrigResultTypes, DL,
10482 "unsupported image load data type");
10483 }
10484 if (LoadScalarVT == MVT::f16) {
10485 if (!Subtarget->hasD16Images() || !BaseOpcode->HasD16)
10486 return Op; // D16 is unsupported for this instruction
10487
10488 IsD16 = true;
10489 }
10490
10491 // Confirm that the return type is large enough for the dmask specified
10492 if ((LoadVT.isVector() && LoadVT.getVectorNumElements() < DMaskLanes) ||
10493 (!LoadVT.isVector() && DMaskLanes > 1))
10494 return Op;
10495
10496 // The sq block of gfx8 and gfx9 do not estimate register use correctly
10497 // for d16 image_gather4, image_gather4_l, and image_gather4_lz
10498 // instructions.
10499 if (IsD16 && !Subtarget->hasUnpackedD16VMem() &&
10500 !(BaseOpcode->Gather4 && Subtarget->hasImageGather4D16Bug()))
10501 NumVDataDwords = (DMaskLanes + 1) / 2;
10502 else
10503 NumVDataDwords = DMaskLanes;
10504
10505 AdjustRetType = true;
10506 }
10507 }
10508
10509 unsigned VAddrEnd = ArgOffset + Intr->VAddrEnd;
10511
10512 // Check for 16 bit addresses or derivatives and pack if true.
10513 MVT VAddrVT =
10514 Op.getOperand(ArgOffset + Intr->GradientStart).getSimpleValueType();
10515 MVT VAddrScalarVT = VAddrVT.getScalarType();
10516 MVT GradPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10517 IsG16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10518
10519 VAddrVT = Op.getOperand(ArgOffset + Intr->CoordStart).getSimpleValueType();
10520 VAddrScalarVT = VAddrVT.getScalarType();
10521 MVT AddrPackVectorVT = VAddrScalarVT == MVT::f16 ? MVT::v2f16 : MVT::v2i16;
10522 IsA16 = VAddrScalarVT == MVT::f16 || VAddrScalarVT == MVT::i16;
10523
10524 // Push back extra arguments.
10525 for (unsigned I = Intr->VAddrStart; I < Intr->GradientStart; I++) {
10526 if (IsA16 && (Op.getOperand(ArgOffset + I).getValueType() == MVT::f16)) {
10527 assert(I == Intr->BiasIndex && "Got unexpected 16-bit extra argument");
10528 // Special handling of bias when A16 is on. Bias is of type half but
10529 // occupies full 32-bit.
10530 SDValue Bias = DAG.getBuildVector(
10531 MVT::v2f16, DL,
10532 {Op.getOperand(ArgOffset + I), DAG.getPOISON(MVT::f16)});
10533 VAddrs.push_back(Bias);
10534 } else {
10535 assert((!IsA16 || Intr->NumBiasArgs == 0 || I != Intr->BiasIndex) &&
10536 "Bias needs to be converted to 16 bit in A16 mode");
10537 VAddrs.push_back(Op.getOperand(ArgOffset + I));
10538 }
10539 }
10540
10541 if (BaseOpcode->Gradients && !ST->hasG16() && (IsA16 != IsG16)) {
10542 // 16 bit gradients are supported, but are tied to the A16 control
10543 // so both gradients and addresses must be 16 bit
10544 LLVM_DEBUG(
10545 dbgs() << "Failed to lower image intrinsic: 16 bit addresses "
10546 "require 16 bit args for both gradients and addresses");
10547 return Op;
10548 }
10549
10550 if (IsA16) {
10551 if (!ST->hasA16()) {
10552 LLVM_DEBUG(dbgs() << "Failed to lower image intrinsic: Target does not "
10553 "support 16 bit addresses\n");
10554 return Op;
10555 }
10556 }
10557
10558 // We've dealt with incorrect input so we know that if IsA16, IsG16
10559 // are set then we have to compress/pack operands (either address,
10560 // gradient or both)
10561 // In the case where a16 and gradients are tied (no G16 support) then we
10562 // have already verified that both IsA16 and IsG16 are true
10563 if (BaseOpcode->Gradients && IsG16 && ST->hasG16()) {
10564 // Activate g16
10565 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
10567 IntrOpcode = G16MappingInfo->G16; // set new opcode to variant with _g16
10568 }
10569
10570 // Add gradients (packed or unpacked)
10571 if (IsG16) {
10572 // Pack the gradients
10573 // const int PackEndIdx = IsA16 ? VAddrEnd : (ArgOffset + Intr->CoordStart);
10574 packImage16bitOpsToDwords(DAG, Op, GradPackVectorVT, VAddrs,
10575 ArgOffset + Intr->GradientStart,
10576 ArgOffset + Intr->CoordStart, Intr->NumGradients);
10577 } else {
10578 for (unsigned I = ArgOffset + Intr->GradientStart;
10579 I < ArgOffset + Intr->CoordStart; I++)
10580 VAddrs.push_back(Op.getOperand(I));
10581 }
10582
10583 // Add addresses (packed or unpacked)
10584 if (IsA16) {
10585 packImage16bitOpsToDwords(DAG, Op, AddrPackVectorVT, VAddrs,
10586 ArgOffset + Intr->CoordStart, VAddrEnd,
10587 0 /* No gradients */);
10588 } else {
10589 // Add uncompressed address
10590 for (unsigned I = ArgOffset + Intr->CoordStart; I < VAddrEnd; I++)
10591 VAddrs.push_back(Op.getOperand(I));
10592 }
10593
10594 // If the register allocator cannot place the address registers contiguously
10595 // without introducing moves, then using the non-sequential address encoding
10596 // is always preferable, since it saves VALU instructions and is usually a
10597 // wash in terms of code size or even better.
10598 //
10599 // However, we currently have no way of hinting to the register allocator that
10600 // MIMG addresses should be placed contiguously when it is possible to do so,
10601 // so force non-NSA for the common 2-address case as a heuristic.
10602 //
10603 // SIShrinkInstructions will convert NSA encodings to non-NSA after register
10604 // allocation when possible.
10605 //
10606 // Partial NSA is allowed on GFX11+ where the final register is a contiguous
10607 // set of the remaining addresses.
10608 const unsigned NSAMaxSize = ST->getNSAMaxSize(BaseOpcode->Sampler);
10609 const bool HasPartialNSAEncoding = ST->hasPartialNSAEncoding();
10610 const bool UseNSA = ST->hasNSAEncoding() &&
10611 VAddrs.size() >= ST->getNSAThreshold(MF) &&
10612 (VAddrs.size() <= NSAMaxSize || HasPartialNSAEncoding);
10613 const bool UsePartialNSA =
10614 UseNSA && HasPartialNSAEncoding && VAddrs.size() > NSAMaxSize;
10615
10616 SDValue VAddr;
10617 if (UsePartialNSA) {
10618 VAddr = getBuildDwordsVector(DAG, DL,
10619 ArrayRef(VAddrs).drop_front(NSAMaxSize - 1));
10620 } else if (!UseNSA) {
10621 VAddr = getBuildDwordsVector(DAG, DL, VAddrs);
10622 }
10623
10624 SDValue True = DAG.getTargetConstant(1, DL, MVT::i1);
10625 SDValue False = DAG.getTargetConstant(0, DL, MVT::i1);
10626 SDValue Unorm;
10627 if (!BaseOpcode->Sampler) {
10628 Unorm = True;
10629 } else {
10630 uint64_t UnormConst =
10631 Op.getConstantOperandVal(ArgOffset + Intr->UnormIndex);
10632
10633 Unorm = UnormConst ? True : False;
10634 }
10635
10636 SDValue TFE;
10637 SDValue LWE;
10638 SDValue TexFail = Op.getOperand(ArgOffset + Intr->TexFailCtrlIndex);
10639 bool IsTexFail = false;
10640 if (!parseTexFail(TexFail, DAG, &TFE, &LWE, IsTexFail))
10641 return Op;
10642
10643 if (IsTexFail) {
10644 if (!DMaskLanes) {
10645 // Expecting to get an error flag since TFC is on - and dmask is 0
10646 // Force dmask to be at least 1 otherwise the instruction will fail
10647 DMask = 0x1;
10648 DMaskLanes = 1;
10649 NumVDataDwords = 1;
10650 }
10651 NumVDataDwords += 1;
10652 AdjustRetType = true;
10653 }
10654
10655 // Has something earlier tagged that the return type needs adjusting
10656 // This happens if the instruction is a load or has set TexFailCtrl flags
10657 if (AdjustRetType) {
10658 // NumVDataDwords reflects the true number of dwords required in the return
10659 // type
10660 if (DMaskLanes == 0 && !BaseOpcode->Store) {
10661 // This is a no-op load. This can be eliminated
10662 SDValue Undef = DAG.getPOISON(Op.getValueType());
10663 if (isa<MemSDNode>(Op))
10664 return DAG.getMergeValues({Undef, Op.getOperand(0)}, DL);
10665 return Undef;
10666 }
10667
10668 EVT NewVT = NumVDataDwords > 1 ? EVT::getVectorVT(*DAG.getContext(),
10669 MVT::i32, NumVDataDwords)
10670 : MVT::i32;
10671
10672 ResultTypes[0] = NewVT;
10673 if (ResultTypes.size() == 3) {
10674 // Original result was aggregate type used for TexFailCtrl results
10675 // The actual instruction returns as a vector type which has now been
10676 // created. Remove the aggregate result.
10677 ResultTypes.erase(&ResultTypes[1]);
10678 }
10679 }
10680
10681 unsigned CPol = Op.getConstantOperandVal(ArgOffset + Intr->CachePolicyIndex);
10682 // Keep GLC only when the atomic's result is actually used.
10683 if (BaseOpcode->Atomic && !BaseOpcode->NoReturn)
10685 if (CPol & ~((IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12) |
10687 return Op;
10688
10690 if (BaseOpcode->Store || BaseOpcode->Atomic)
10691 Ops.push_back(VData); // vdata
10692 if (UsePartialNSA) {
10693 append_range(Ops, ArrayRef(VAddrs).take_front(NSAMaxSize - 1));
10694 Ops.push_back(VAddr);
10695 } else if (UseNSA)
10696 append_range(Ops, VAddrs);
10697 else
10698 Ops.push_back(VAddr);
10699 SDValue Rsrc = Op.getOperand(ArgOffset + Intr->RsrcIndex);
10700 EVT RsrcVT = Rsrc.getValueType();
10701 if (RsrcVT != MVT::v4i32 && RsrcVT != MVT::v8i32)
10702 return Op;
10703 Ops.push_back(Rsrc);
10704 if (BaseOpcode->Sampler) {
10705 SDValue Samp = Op.getOperand(ArgOffset + Intr->SampIndex);
10706 if (Samp.getValueType() != MVT::v4i32)
10707 return Op;
10708 Ops.push_back(Samp);
10709 }
10710 Ops.push_back(DAG.getTargetConstant(DMask, DL, MVT::i32));
10711 if (IsGFX10Plus)
10712 Ops.push_back(DAG.getTargetConstant(DimInfo->Encoding, DL, MVT::i32));
10713 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10714 Ops.push_back(Unorm);
10715 Ops.push_back(DAG.getTargetConstant(CPol, DL, MVT::i32));
10716 Ops.push_back(IsA16 && // r128, a16 for gfx9
10717 ST->hasFeature(AMDGPU::FeatureR128A16)
10718 ? True
10719 : False);
10720 if (IsGFX10Plus)
10721 Ops.push_back(IsA16 ? True : False);
10722
10723 if (!Subtarget->hasGFX90AInsts())
10724 Ops.push_back(TFE); // tfe
10725 else if (TFE->getAsZExtVal()) {
10726 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
10728 "TFE is not supported on this GPU", DL.getDebugLoc()));
10729 }
10730
10731 if (!IsGFX12Plus || BaseOpcode->Sampler || BaseOpcode->MSAA)
10732 Ops.push_back(LWE); // lwe
10733 if (!IsGFX10Plus)
10734 Ops.push_back(DimInfo->DA ? True : False);
10735 if (BaseOpcode->HasD16)
10736 Ops.push_back(IsD16 ? True : False);
10737 if (isa<MemSDNode>(Op))
10738 Ops.push_back(Op.getOperand(0)); // chain
10739
10740 int NumVAddrDwords =
10741 UseNSA ? VAddrs.size() : VAddr.getValueType().getSizeInBits() / 32;
10742 int Opcode = -1;
10743
10744 if (IsGFX13) {
10745 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx13,
10746 NumVDataDwords, NumVAddrDwords);
10747 } else if (IsGFX12Plus) {
10748 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx12,
10749 NumVDataDwords, NumVAddrDwords);
10750 } else if (IsGFX11Plus) {
10751 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10752 UseNSA ? AMDGPU::MIMGEncGfx11NSA
10753 : AMDGPU::MIMGEncGfx11Default,
10754 NumVDataDwords, NumVAddrDwords);
10755 } else if (IsGFX10Plus) {
10756 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
10757 UseNSA ? AMDGPU::MIMGEncGfx10NSA
10758 : AMDGPU::MIMGEncGfx10Default,
10759 NumVDataDwords, NumVAddrDwords);
10760 } else {
10761 if (Subtarget->hasGFX90AInsts()) {
10762 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx90a,
10763 NumVDataDwords, NumVAddrDwords);
10764 if (Opcode == -1) {
10766 DAG, Op, OrigResultTypes, DL,
10767 "requested image instruction is not supported on this GPU");
10768 }
10769 }
10770 if (Opcode == -1 &&
10771 Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10772 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx8,
10773 NumVDataDwords, NumVAddrDwords);
10774 if (Opcode == -1)
10775 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx6,
10776 NumVDataDwords, NumVAddrDwords);
10777 }
10778 if (Opcode == -1)
10779 return Op;
10780
10781 MachineSDNode *NewNode = DAG.getMachineNode(Opcode, DL, ResultTypes, Ops);
10782 if (auto *MemOp = dyn_cast<MemSDNode>(Op)) {
10783 MachineMemOperand *MemRef = MemOp->getMemOperand();
10784 DAG.setNodeMemRefs(NewNode, {MemRef});
10785 }
10786
10787 if (BaseOpcode->NoReturn) {
10788 if (BaseOpcode->Atomic)
10789 return DAG.getMergeValues(
10790 {DAG.getPOISON(OrigResultTypes[0]), SDValue(NewNode, 0)}, DL);
10791
10792 return SDValue(NewNode, 0);
10793 }
10794
10795 if (BaseOpcode->AtomicX2) {
10797 DAG.ExtractVectorElements(SDValue(NewNode, 0), Elt, 0, 1);
10798 return DAG.getMergeValues({Elt[0], SDValue(NewNode, 1)}, DL);
10799 }
10800
10801 return constructRetValue(DAG, NewNode, OrigResultTypes, IsTexFail,
10802 Subtarget->hasUnpackedD16VMem(), IsD16, DMaskLanes,
10803 NumVDataDwords, IsAtomicPacked16Bit, DL);
10804}
10805
10806SDValue SITargetLowering::lowerSBuffer(EVT VT, EVT MemVT, SDLoc DL,
10807 SDValue Chain, SDValue Rsrc,
10808 SDValue Offset, SDValue CachePolicy,
10809 SelectionDAG &DAG,
10810 MachineMemOperand *MMO) const {
10812 bool HasChainResult = MMO != nullptr;
10813
10814 if (!HasChainResult) {
10815 const DataLayout &DataLayout = DAG.getDataLayout();
10816 Align Alignment =
10817 DataLayout.getABITypeAlign(MemVT.getTypeForEVT(*DAG.getContext()));
10818
10819 MMO = MF.getMachineMemOperand(MachinePointerInfo(),
10823 MemVT.getStoreSize(), Alignment);
10824 }
10825
10826 if (!Offset->isDivergent()) {
10827 SDValue Ops[] = {Chain, Rsrc, Offset, CachePolicy};
10828
10829 // Lower llvm.amdgcn.*s.buffer.load.{i,u}N intrinsics. First, generate
10830 // s_buffer_load_u* for signed and unsigned load instructions. Next, DAG
10831 // combiner tries to merge the s_buffer_load_uN with a sext instruction
10832 // (performSignExtendInRegCombine()) and it replaces s_buffer_load_uN with
10833 // s_buffer_load_iN.
10834 auto HandleScalarSubwordLoads = [&](unsigned Opcode) -> SDValue {
10835 SDValue BufferLoad = DAG.getMemIntrinsicNode(
10836 Opcode, DL, DAG.getVTList(MVT::i32, MVT::Other), Ops, MemVT, MMO);
10837 SDValue LoadVal = DAG.getAnyExtOrTrunc(
10838 DAG.getNode(ISD::TRUNCATE, DL, MemVT, BufferLoad), DL, VT);
10839 if (HasChainResult)
10840 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
10841 return LoadVal;
10842 };
10843 if (MemVT == MVT::i8 && Subtarget->hasScalarSubwordLoads())
10844 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_UBYTE);
10845
10846 if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
10847 return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
10848
10849 // Widen vec3 load to vec4.
10850 if (VT.isVector() && VT.getVectorNumElements() == 3 &&
10851 !Subtarget->hasScalarDwordx3Loads()) {
10852 EVT WidenedVT =
10854 auto WidenedOp = DAG.getMemIntrinsicNode(
10855 AMDGPUISD::SBUFFER_LOAD, DL, DAG.getVTList(WidenedVT, MVT::Other),
10856 Ops, WidenedVT,
10857 MF.getMachineMemOperand(MMO, 0, WidenedVT.getStoreSize()));
10858 auto Subvector = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, WidenedOp,
10859 DAG.getVectorIdxConstant(0, DL));
10860 if (HasChainResult)
10861 return DAG.getMergeValues({Subvector, WidenedOp.getValue(1)}, DL);
10862 return Subvector;
10863 }
10864
10865 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_LOAD, DL,
10866 DAG.getVTList(VT, MVT::Other), Ops, MemVT,
10867 MMO);
10868 }
10869
10870 // We have a divergent offset. Emit a MUBUF buffer load instead. We can
10871 // assume that the buffer is unswizzled.
10872 SDValue Ops[] = {
10873 Chain, // Chain
10874 Rsrc, // rsrc
10875 DAG.getConstant(0, DL, MVT::i32), // vindex
10876 {}, // voffset
10877 {}, // soffset
10878 {}, // offset
10879 CachePolicy, // cachepolicy
10880 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
10881 };
10882 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10883 Subtarget->hasScalarSubwordLoads()) {
10884 setBufferOffsets(Offset, DAG, &Ops[3], Align(4));
10885 SDValue Load = handleByteShortBufferLoads(DAG, MemVT, DL, Ops, MMO);
10886 SDValue LoadVal = DAG.getAnyExtOrTrunc(Load.getOperand(0), DL, VT);
10887 if (HasChainResult)
10888 return DAG.getMergeValues({LoadVal, Load.getOperand(1)}, DL);
10889 return LoadVal;
10890 }
10891
10893 unsigned NumLoads = 1;
10894 MVT LoadVT = VT.getSimpleVT();
10895 unsigned NumElts = LoadVT.isVector() ? LoadVT.getVectorNumElements() : 1;
10896 assert((LoadVT.getScalarType() == MVT::i32 ||
10897 LoadVT.getScalarType() == MVT::f32));
10898
10899 if (NumElts == 8 || NumElts == 16) {
10900 NumLoads = NumElts / 4;
10901 LoadVT = MVT::getVectorVT(LoadVT.getScalarType(), 4);
10902 }
10903
10904 SDVTList VTList = DAG.getVTList({LoadVT, MVT::Other});
10905
10906 // Use the alignment to ensure that the required offsets will fit into the
10907 // immediate offsets.
10908 setBufferOffsets(Offset, DAG, &Ops[3],
10909 NumLoads > 1 ? Align(16 * NumLoads) : Align(4));
10910
10911 uint64_t InstOffset = Ops[5]->getAsZExtVal();
10912 unsigned LoadSize = LoadVT.getStoreSize();
10913 for (unsigned i = 0; i < NumLoads; ++i) {
10914 Ops[5] = DAG.getTargetConstant(InstOffset + 16 * i, DL, MVT::i32);
10915 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(MMO, 16 * i, LoadSize);
10916 Loads.push_back(getMemIntrinsicNode(AMDGPUISD::BUFFER_LOAD, DL, VTList, Ops,
10917 LoadVT, LoadMMO, DAG));
10918 }
10919
10920 if (NumElts == 8 || NumElts == 16) {
10921 SDValue LoadVal = DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Loads);
10922 if (HasChainResult) {
10923 SmallVector<SDValue, 4> LoadChains;
10924 for (SDValue Load : Loads)
10925 LoadChains.push_back(Load.getValue(1));
10926 SDValue Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, LoadChains);
10927 return DAG.getMergeValues({LoadVal, Chain}, DL);
10928 }
10929 return LoadVal;
10930 }
10931
10932 return Loads[0];
10933}
10934
10935SDValue SITargetLowering::lowerWaveID(SelectionDAG &DAG, SDValue Op) const {
10936 // With architected SGPRs, waveIDinGroup is in TTMP8[29:25].
10937 if (!Subtarget->hasArchitectedSGPRs())
10938 return {};
10939 SDLoc SL(Op);
10940 MVT VT = MVT::i32;
10941 SDValue TTMP8 = DAG.getCopyFromReg(DAG.getEntryNode(), SL, AMDGPU::TTMP8, VT);
10942 return DAG.getNode(AMDGPUISD::BFE_U32, SL, VT, TTMP8,
10943 DAG.getConstant(25, SL, VT), DAG.getConstant(5, SL, VT));
10944}
10945
10946SDValue SITargetLowering::lowerConstHwRegRead(SelectionDAG &DAG, SDValue Op,
10947 AMDGPU::Hwreg::Id HwReg,
10948 unsigned LowBit,
10949 unsigned Width) const {
10950 SDLoc SL(Op);
10951 using namespace AMDGPU::Hwreg;
10952 return {DAG.getMachineNode(
10953 AMDGPU::S_GETREG_B32_const, SL, MVT::i32,
10954 DAG.getTargetConstant(HwregEncoding::encode(HwReg, LowBit, Width),
10955 SL, MVT::i32)),
10956 0};
10957}
10958
10959SDValue SITargetLowering::lowerWorkitemID(SelectionDAG &DAG, SDValue Op,
10960 unsigned Dim,
10961 const ArgDescriptor &Arg) const {
10962 SDLoc SL(Op);
10964 unsigned MaxID = Subtarget->getMaxWorkitemID(MF.getFunction(), Dim);
10965 if (MaxID == 0)
10966 return DAG.getConstant(0, SL, MVT::i32);
10967
10968 // It's undefined behavior if a function marked with the amdgpu-no-*
10969 // attributes uses the corresponding intrinsic.
10970 if (!Arg)
10971 return DAG.getPOISON(Op->getValueType(0));
10972
10973 SDValue Val = loadInputValue(DAG, &AMDGPU::VGPR_32RegClass, MVT::i32,
10974 SDLoc(DAG.getEntryNode()), Arg);
10975
10976 // Don't bother inserting AssertZext for packed IDs since we're emitting the
10977 // masking operations anyway.
10978 //
10979 // TODO: We could assert the top bit is 0 for the source copy.
10980 if (Arg.isMasked())
10981 return Val;
10982
10983 // Preserve the known bits after expansion to a copy.
10984 EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), llvm::bit_width(MaxID));
10985 return DAG.getNode(ISD::AssertZext, SL, MVT::i32, Val,
10986 DAG.getValueType(SmallVT));
10987}
10988
10989SDValue SITargetLowering::lowerFromFP8(SDValue Op, bool IsBF8,
10990 SelectionDAG &DAG) const {
10991 SDLoc SL(Op);
10992 SDValue Src = Op.getOperand(0);
10993 EVT DstVT = Op.getValueType();
10994 bool IsF16 = DstVT.getVectorElementType() == MVT::f16;
10995 assert((!IsF16 || Subtarget->hasFP8F16ConversionInsts()) &&
10996 "fp8/bf8 -> f16 conversion requires FP8F16ConversionInsts");
10997
10998 unsigned Opc;
10999 if (IsF16)
11000 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F16_BF8 : AMDGPUISD::CVT_PK_F16_FP8;
11001 else
11002 Opc = IsBF8 ? AMDGPUISD::CVT_PK_F32_BF8 : AMDGPUISD::CVT_PK_F32_FP8;
11003
11004 // Pack the two i8 lanes into the integer type the packed HW node reads. The
11005 // f16 form takes i16 and the f32 form takes i32. v2i8 bitcasts to i16
11006 // directly and the f32 node reads the low half of an any-extended i32.
11007 EVT PackedVT =
11009 SDValue AsI16 = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
11010 SDValue Packed = DAG.getAnyExtOrTrunc(AsI16, SL, PackedVT);
11011 return DAG.getNode(Opc, SL, DstVT, Packed);
11012}
11013
11014SDValue
11015SITargetLowering::LowerCONVERT_FROM_ARBITRARY_FP(SDValue Op,
11016 SelectionDAG &DAG) const {
11017 // Only handle OCP FP8 formats (E4M3FN, E5M2). FNUZ formats that are supported
11018 // by gfx942 fall through to the generic expansion.
11019 APFloatBase::Semantics FPSemantic =
11020 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11021 if (FPSemantic != APFloatBase::S_Float8E4M3FN &&
11022 FPSemantic != APFloatBase::S_Float8E5M2)
11023 return SDValue();
11024 const bool IsBF8 = FPSemantic == APFloatBase::S_Float8E5M2;
11025
11026 EVT DstVT = Op.getValueType();
11027 if (!DstVT.isVector()) {
11028 SDValue Src = Op.getOperand(0);
11029 if (Src.getValueType() != MVT::i32) {
11030 SDLoc SL(Op);
11031 SDValue SrcI32 = DAG.getAnyExtOrTrunc(Src, SL, MVT::i32);
11032 return DAG.getNode(ISD::CONVERT_FROM_ARBITRARY_FP, SL, DstVT, SrcI32,
11033 Op.getOperand(1));
11034 }
11035 return Op;
11036 }
11037
11038 EVT EltVT = DstVT.getVectorElementType();
11039 if (EltVT == MVT::f16 || EltVT == MVT::f32)
11040 return lowerFromFP8(Op, IsBF8, DAG);
11041 return SDValue();
11042}
11043
11044SDValue SITargetLowering::lowerToFP8(SDValue Op, bool IsBF8,
11045 SelectionDAG &DAG) const {
11046 SDLoc SL(Op);
11047 SDValue Src = Op.getOperand(0);
11048 EVT ResVT = Op.getValueType();
11049 bool IsF16 = Src.getValueType().getScalarType() == MVT::f16;
11050 assert((!IsF16 || Subtarget->hasF16FP8ConversionInsts()) &&
11051 "f16 -> fp8/bf8 conversion requires F16FP8ConversionInsts");
11052 assert((!ResVT.isVector() || ResVT == MVT::v2i8) &&
11053 "only the v2i8 vector result is custom lowered");
11054
11055 if (IsF16) {
11056 unsigned Opc =
11057 IsBF8 ? AMDGPUISD::CVT_PK_BF8_F16 : AMDGPUISD::CVT_PK_FP8_F16;
11058 SDValue Bytes = DAG.getNode(Opc, SL, MVT::i16, Src);
11059 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11060 }
11061
11062 unsigned Opc = IsBF8 ? AMDGPUISD::CVT_PK_BF8_F32 : AMDGPUISD::CVT_PK_FP8_F32;
11063 SDValue PoisonI32 = DAG.getPOISON(MVT::i32);
11064 SDValue WordSel = DAG.getTargetConstant(0, SL, MVT::i1);
11065
11066 if (!ResVT.isVector()) {
11067 // Convert one lane, the second is unused. Feed it the same source so the
11068 // instruction does not read an undefined register.
11069 SDValue Packed =
11070 DAG.getNode(Opc, SL, MVT::i32, Src, Src, PoisonI32, WordSel);
11071 return DAG.getAnyExtOrTrunc(Packed, SL, ResVT);
11072 }
11073
11074 SDValue A = DAG.getExtractVectorElt(SL, MVT::f32, Src, 0);
11075 SDValue B = DAG.getExtractVectorElt(SL, MVT::f32, Src, 1);
11076 SDValue Packed = DAG.getNode(Opc, SL, MVT::i32, A, B, PoisonI32, WordSel);
11077 SDValue Bytes = DAG.getNode(ISD::TRUNCATE, SL, MVT::i16, Packed);
11078 return DAG.getNode(ISD::BITCAST, SL, ResVT, Bytes);
11079}
11080
11081SDValue
11082SITargetLowering::LowerCONVERT_TO_ARBITRARY_FP(SDValue Op,
11083 SelectionDAG &DAG) const {
11084 // Only the OCP fp8 formats E4M3FN and E5M2 map to HW conversions, everything
11085 // else uses the generic expansion.
11087 static_cast<APFloatBase::Semantics>(Op.getConstantOperandVal(1));
11089 return SDValue();
11090 bool IsBF8 = Sem == APFloatBase::S_Float8E5M2;
11091
11092 // The packed HW conversions round to nearest-even and never saturate.
11093 if (static_cast<RoundingMode>(Op.getConstantOperandVal(2)) !=
11095 return SDValue();
11096 if (Op.getConstantOperandVal(3) != 0)
11097 return SDValue();
11098
11099 EVT SrcEltVT = Op.getOperand(0).getValueType().getScalarType();
11100 // The f32 form is built here rather than by a tablegen pattern because the
11101 // HW result is i32 while the node result is i16 after the i8 promotion.
11102 if (SrcEltVT == MVT::f32)
11103 return lowerToFP8(Op, IsBF8, DAG);
11104 if (SrcEltVT == MVT::f16 && Subtarget->hasF16FP8ConversionInsts()) {
11105 // A scalar conversion is selected from the generic node by tablegen, only
11106 // the illegal v2i8 result type needs lowering here.
11107 if (!Op.getValueType().isVector())
11108 return Op;
11109 return lowerToFP8(Op, IsBF8, DAG);
11110 }
11111 return SDValue();
11112}
11113
11114SDValue SITargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
11115 SelectionDAG &DAG) const {
11117 auto *MFI = MF.getInfo<SIMachineFunctionInfo>();
11118
11119 EVT VT = Op.getValueType();
11120 SDLoc DL(Op);
11121 unsigned IntrinsicID = Op.getConstantOperandVal(0);
11122
11123 // TODO: Should this propagate fast-math-flags?
11124
11125 switch (IntrinsicID) {
11126 case Intrinsic::amdgcn_wave_reduce_min:
11127 case Intrinsic::amdgcn_wave_reduce_umin:
11128 case Intrinsic::amdgcn_wave_reduce_fmin:
11129 case Intrinsic::amdgcn_wave_reduce_max:
11130 case Intrinsic::amdgcn_wave_reduce_umax:
11131 case Intrinsic::amdgcn_wave_reduce_fmax:
11132 case Intrinsic::amdgcn_wave_reduce_add:
11133 case Intrinsic::amdgcn_wave_reduce_fadd:
11134 case Intrinsic::amdgcn_wave_reduce_sub:
11135 case Intrinsic::amdgcn_wave_reduce_fsub:
11136 case Intrinsic::amdgcn_wave_reduce_and:
11137 case Intrinsic::amdgcn_wave_reduce_or:
11138 case Intrinsic::amdgcn_wave_reduce_xor: {
11139 EVT SrcVT = Op.getOperand(1).getValueType();
11140 if (SrcVT.getFixedSizeInBits() == 16) {
11141 bool IsFPOp = SrcVT.isFloatingPoint();
11142 bool NeedsSignExt = IntrinsicID == Intrinsic::amdgcn_wave_reduce_min ||
11143 IntrinsicID == Intrinsic::amdgcn_wave_reduce_max ||
11144 IntrinsicID == Intrinsic::amdgcn_wave_reduce_add ||
11145 IntrinsicID == Intrinsic::amdgcn_wave_reduce_sub;
11146 unsigned ExtOpc = IsFPOp ? ISD::FP_EXTEND
11147 : NeedsSignExt ? ISD::SIGN_EXTEND
11149 auto SrcType = IsFPOp ? MVT::f16 : MVT::i16;
11150 auto ExtType = IsFPOp ? MVT::f32 : MVT::i32;
11151 SDValue ExtendedSrc = DAG.getNode(ExtOpc, DL, ExtType, Op.getOperand(1));
11152 SDValue Strategy = Op.getOperand(2);
11154 Op.getOperand(0), ExtendedSrc, Strategy);
11155 if (IsFPOp)
11156 return DAG.getNode(ISD::FP_ROUND, DL, SrcType, Result,
11157 DAG.getTargetConstant(1, DL, MVT::i32));
11158 else
11159 return DAG.getNode(ISD::TRUNCATE, DL, SrcType, Result);
11160 }
11161 return SDValue();
11162 }
11163 case Intrinsic::amdgcn_implicit_buffer_ptr: {
11164 if (getSubtarget()->isAmdHsaOrMesa(MF.getFunction()))
11165 return emitNonHSAIntrinsicError(DAG, DL, VT);
11166 return getPreloadedValue(DAG, *MFI, VT,
11168 }
11169 case Intrinsic::amdgcn_dispatch_ptr:
11170 case Intrinsic::amdgcn_queue_ptr: {
11171 if (!Subtarget->isAmdHsaOrMesa(MF.getFunction())) {
11172 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11173 MF.getFunction(), "unsupported hsa intrinsic without hsa target",
11174 DL.getDebugLoc()));
11175 return DAG.getPOISON(VT);
11176 }
11177
11178 auto RegID = IntrinsicID == Intrinsic::amdgcn_dispatch_ptr
11181 return getPreloadedValue(DAG, *MFI, VT, RegID);
11182 }
11183 case Intrinsic::amdgcn_implicitarg_ptr: {
11184 if (MFI->isEntryFunction())
11185 return getImplicitArgPtr(DAG, DL);
11186 return getPreloadedValue(DAG, *MFI, VT,
11188 }
11189 case Intrinsic::amdgcn_kernarg_segment_ptr: {
11190 if (!AMDGPU::isKernel(MF.getFunction())) {
11191 // This only makes sense to call in a kernel, so just lower to null.
11192 return DAG.getConstant(0, DL, VT);
11193 }
11194
11195 return getPreloadedValue(DAG, *MFI, VT,
11197 }
11198 case Intrinsic::amdgcn_dispatch_id: {
11199 return getPreloadedValue(DAG, *MFI, VT, AMDGPUFunctionArgInfo::DISPATCH_ID);
11200 }
11201 case Intrinsic::amdgcn_rcp:
11202 return DAG.getNode(AMDGPUISD::RCP, DL, VT, Op.getOperand(1));
11203 case Intrinsic::amdgcn_rsq:
11204 return DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11205 case Intrinsic::amdgcn_rsq_legacy:
11206 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11207 return emitRemovedIntrinsicError(DAG, DL, VT);
11208 return SDValue();
11209 case Intrinsic::amdgcn_rcp_legacy:
11210 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
11211 return emitRemovedIntrinsicError(DAG, DL, VT);
11212 return DAG.getNode(AMDGPUISD::RCP_LEGACY, DL, VT, Op.getOperand(1));
11213 case Intrinsic::amdgcn_fma_legacy:
11214 case Intrinsic::amdgcn_sudot4:
11215 case Intrinsic::amdgcn_sudot8:
11216 case Intrinsic::amdgcn_tanh:
11217 return SDValue();
11218 case Intrinsic::amdgcn_rsq_clamp: {
11219 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11220 return DAG.getNode(AMDGPUISD::RSQ_CLAMP, DL, VT, Op.getOperand(1));
11221
11222 Type *Type = VT.getTypeForEVT(*DAG.getContext());
11223 APFloat Max = APFloat::getLargest(Type->getFltSemantics());
11224 APFloat Min = APFloat::getLargest(Type->getFltSemantics(), true);
11225
11226 SDValue Rsq = DAG.getNode(AMDGPUISD::RSQ, DL, VT, Op.getOperand(1));
11227 SDValue Tmp =
11228 DAG.getNode(ISD::FMINNUM, DL, VT, Rsq, DAG.getConstantFP(Max, DL, VT));
11229 return DAG.getNode(ISD::FMAXNUM, DL, VT, Tmp,
11230 DAG.getConstantFP(Min, DL, VT));
11231 }
11232 case Intrinsic::r600_read_ngroups_x:
11233 if (Subtarget->isAmdHsaOS())
11234 return emitNonHSAIntrinsicError(DAG, DL, VT);
11235
11236 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11238 false);
11239 case Intrinsic::r600_read_ngroups_y:
11240 if (Subtarget->isAmdHsaOS())
11241 return emitNonHSAIntrinsicError(DAG, DL, VT);
11242
11243 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11245 false);
11246 case Intrinsic::r600_read_ngroups_z:
11247 if (Subtarget->isAmdHsaOS())
11248 return emitNonHSAIntrinsicError(DAG, DL, VT);
11249
11250 return lowerKernargMemParameter(DAG, VT, VT, DL, DAG.getEntryNode(),
11252 false);
11253 case Intrinsic::r600_read_local_size_x:
11254 if (Subtarget->isAmdHsaOS())
11255 return emitNonHSAIntrinsicError(DAG, DL, VT);
11256
11257 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11259 case Intrinsic::r600_read_local_size_y:
11260 if (Subtarget->isAmdHsaOS())
11261 return emitNonHSAIntrinsicError(DAG, DL, VT);
11262
11263 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11265 case Intrinsic::r600_read_local_size_z:
11266 if (Subtarget->isAmdHsaOS())
11267 return emitNonHSAIntrinsicError(DAG, DL, VT);
11268
11269 return lowerImplicitZextParam(DAG, Op, MVT::i16,
11271 case Intrinsic::amdgcn_workgroup_id_x:
11272 return lowerWorkGroupId(DAG, *MFI, VT,
11276 case Intrinsic::amdgcn_workgroup_id_y:
11277 return lowerWorkGroupId(DAG, *MFI, VT,
11281 case Intrinsic::amdgcn_workgroup_id_z:
11282 return lowerWorkGroupId(DAG, *MFI, VT,
11286 case Intrinsic::amdgcn_cluster_id_x:
11287 return Subtarget->hasClusters()
11288 ? getPreloadedValue(DAG, *MFI, VT,
11290 : DAG.getPOISON(VT);
11291 case Intrinsic::amdgcn_cluster_id_y:
11292 return Subtarget->hasClusters()
11293 ? getPreloadedValue(DAG, *MFI, VT,
11295 : DAG.getPOISON(VT);
11296 case Intrinsic::amdgcn_cluster_id_z:
11297 return Subtarget->hasClusters()
11298 ? getPreloadedValue(DAG, *MFI, VT,
11300 : DAG.getPOISON(VT);
11301 case Intrinsic::amdgcn_cluster_workgroup_id_x:
11302 return Subtarget->hasClusters()
11303 ? getPreloadedValue(
11304 DAG, *MFI, VT,
11306 : DAG.getPOISON(VT);
11307 case Intrinsic::amdgcn_cluster_workgroup_id_y:
11308 return Subtarget->hasClusters()
11309 ? getPreloadedValue(
11310 DAG, *MFI, VT,
11312 : DAG.getPOISON(VT);
11313 case Intrinsic::amdgcn_cluster_workgroup_id_z:
11314 return Subtarget->hasClusters()
11315 ? getPreloadedValue(
11316 DAG, *MFI, VT,
11318 : DAG.getPOISON(VT);
11319 case Intrinsic::amdgcn_cluster_workgroup_flat_id:
11320 return Subtarget->hasClusters()
11321 ? lowerConstHwRegRead(DAG, Op, AMDGPU::Hwreg::ID_IB_STS2, 21, 4)
11322 : SDValue();
11323 case Intrinsic::amdgcn_cluster_workgroup_max_id_x:
11324 return Subtarget->hasClusters()
11325 ? getPreloadedValue(
11326 DAG, *MFI, VT,
11328 : DAG.getPOISON(VT);
11329 case Intrinsic::amdgcn_cluster_workgroup_max_id_y:
11330 return Subtarget->hasClusters()
11331 ? getPreloadedValue(
11332 DAG, *MFI, VT,
11334 : DAG.getPOISON(VT);
11335 case Intrinsic::amdgcn_cluster_workgroup_max_id_z:
11336 return Subtarget->hasClusters()
11337 ? getPreloadedValue(
11338 DAG, *MFI, VT,
11340 : DAG.getPOISON(VT);
11341 case Intrinsic::amdgcn_cluster_workgroup_max_flat_id:
11342 return Subtarget->hasClusters()
11343 ? getPreloadedValue(
11344 DAG, *MFI, VT,
11346 : DAG.getPOISON(VT);
11347 case Intrinsic::amdgcn_wave_id:
11348 return lowerWaveID(DAG, Op);
11349 case Intrinsic::amdgcn_lds_kernel_id: {
11350 if (MFI->isEntryFunction())
11351 return getLDSKernelId(DAG, DL);
11352 return getPreloadedValue(DAG, *MFI, VT,
11354 }
11355 case Intrinsic::amdgcn_workitem_id_x:
11356 return lowerWorkitemID(DAG, Op, 0, MFI->getArgInfo().WorkItemIDX);
11357 case Intrinsic::amdgcn_workitem_id_y:
11358 return lowerWorkitemID(DAG, Op, 1, MFI->getArgInfo().WorkItemIDY);
11359 case Intrinsic::amdgcn_workitem_id_z:
11360 return lowerWorkitemID(DAG, Op, 2, MFI->getArgInfo().WorkItemIDZ);
11361 case Intrinsic::amdgcn_wavefrontsize:
11362 return DAG.getConstant(MF.getSubtarget<GCNSubtarget>().getWavefrontSize(),
11363 SDLoc(Op), MVT::i32);
11364 case Intrinsic::amdgcn_s_buffer_load: {
11365 unsigned CPol = Op.getConstantOperandVal(3);
11366 // s_buffer_load, because of how it's optimized, can't be volatile
11367 // so reject ones with the volatile bit set.
11368 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
11371 return Op;
11372 return lowerSBuffer(VT, VT, DL, DAG.getEntryNode(), Op.getOperand(1),
11373 Op.getOperand(2), Op.getOperand(3), DAG);
11374 }
11375 case Intrinsic::amdgcn_fdiv_fast:
11376 return lowerFDIV_FAST(Op, DAG);
11377 case Intrinsic::amdgcn_sin:
11378 return DAG.getNode(AMDGPUISD::SIN_HW, DL, VT, Op.getOperand(1));
11379
11380 case Intrinsic::amdgcn_cos:
11381 return DAG.getNode(AMDGPUISD::COS_HW, DL, VT, Op.getOperand(1));
11382
11383 case Intrinsic::amdgcn_mul_u24:
11384 return DAG.getNode(AMDGPUISD::MUL_U24, DL, VT, Op.getOperand(1),
11385 Op.getOperand(2));
11386 case Intrinsic::amdgcn_mul_i24:
11387 return DAG.getNode(AMDGPUISD::MUL_I24, DL, VT, Op.getOperand(1),
11388 Op.getOperand(2));
11389
11390 case Intrinsic::amdgcn_log_clamp: {
11391 if (Subtarget->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS)
11392 return SDValue();
11393
11394 return emitRemovedIntrinsicError(DAG, DL, VT);
11395 }
11396 case Intrinsic::amdgcn_fract:
11397 return DAG.getNode(AMDGPUISD::FRACT, DL, VT, Op.getOperand(1));
11398
11399 case Intrinsic::amdgcn_class: {
11400 SDValue Src = Op.getOperand(1);
11401 EVT SrcVT = Src.getValueType();
11402 bool IsLegal = SrcVT == MVT::f32 || SrcVT == MVT::f64 ||
11403 (SrcVT == MVT::f16 && Subtarget->has16BitInsts());
11404 if (!IsLegal) {
11405 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11407 "llvm.amdgcn.class only supports f16, f32, and f64",
11408 DL.getDebugLoc()));
11409 return DAG.getPOISON(VT);
11410 }
11411 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, VT, Src, Op.getOperand(2));
11412 }
11413 case Intrinsic::amdgcn_div_fmas:
11414 return DAG.getNode(AMDGPUISD::DIV_FMAS, DL, VT, Op.getOperand(1),
11415 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11416
11417 case Intrinsic::amdgcn_div_fixup:
11418 return DAG.getNode(AMDGPUISD::DIV_FIXUP, DL, VT, Op.getOperand(1),
11419 Op.getOperand(2), Op.getOperand(3));
11420
11421 case Intrinsic::amdgcn_div_scale: {
11422 const ConstantSDNode *Param = cast<ConstantSDNode>(Op.getOperand(3));
11423
11424 // Translate to the operands expected by the machine instruction. The
11425 // first parameter must be the same as the first instruction.
11426 SDValue Numerator = Op.getOperand(1);
11427 SDValue Denominator = Op.getOperand(2);
11428
11429 // Note this order is opposite of the machine instruction's operations,
11430 // which is s0.f = Quotient, s1.f = Denominator, s2.f = Numerator. The
11431 // intrinsic has the numerator as the first operand to match a normal
11432 // division operation.
11433
11434 SDValue Src0 = Param->isAllOnes() ? Numerator : Denominator;
11435
11436 return DAG.getNode(AMDGPUISD::DIV_SCALE, DL, Op->getVTList(), Src0,
11437 Denominator, Numerator);
11438 }
11439 case Intrinsic::amdgcn_icmp: {
11440 // There is a Pat that handles this variant, so return it as-is.
11441 if (Op.getOperand(1).getValueType() == MVT::i1 &&
11442 Op.getConstantOperandVal(2) == 0 &&
11443 Op.getConstantOperandVal(3) == ICmpInst::Predicate::ICMP_NE)
11444 return Op;
11445 return lowerICMPIntrinsic(*this, Op.getNode(), DAG);
11446 }
11447 case Intrinsic::amdgcn_fcmp: {
11448 return lowerFCMPIntrinsic(*this, Op.getNode(), DAG);
11449 }
11450 case Intrinsic::amdgcn_ballot:
11451 return lowerBALLOTIntrinsic(*this, Op.getNode(), DAG);
11452 case Intrinsic::amdgcn_fmed3:
11453 return DAG.getNode(AMDGPUISD::FMED3, DL, VT, Op.getOperand(1),
11454 Op.getOperand(2), Op.getOperand(3), Op->getFlags());
11455 case Intrinsic::amdgcn_fdot2:
11456 return DAG.getNode(AMDGPUISD::FDOT2, DL, VT, Op.getOperand(1),
11457 Op.getOperand(2), Op.getOperand(3), Op.getOperand(4));
11458 case Intrinsic::amdgcn_fmul_legacy:
11459 return DAG.getNode(AMDGPUISD::FMUL_LEGACY, DL, VT, Op.getOperand(1),
11460 Op.getOperand(2));
11461 case Intrinsic::amdgcn_sbfe:
11462 return DAG.getNode(AMDGPUISD::BFE_I32, DL, VT, Op.getOperand(1),
11463 Op.getOperand(2), Op.getOperand(3));
11464 case Intrinsic::amdgcn_ubfe:
11465 return DAG.getNode(AMDGPUISD::BFE_U32, DL, VT, Op.getOperand(1),
11466 Op.getOperand(2), Op.getOperand(3));
11467 case Intrinsic::amdgcn_cvt_pkrtz:
11468 case Intrinsic::amdgcn_cvt_pknorm_i16:
11469 case Intrinsic::amdgcn_cvt_pknorm_u16:
11470 case Intrinsic::amdgcn_cvt_pk_i16:
11471 case Intrinsic::amdgcn_cvt_pk_u16: {
11472 // FIXME: Stop adding cast if v2f16/v2i16 are legal.
11473 EVT VT = Op.getValueType();
11474 unsigned Opcode;
11475
11476 if (IntrinsicID == Intrinsic::amdgcn_cvt_pkrtz)
11477 Opcode = AMDGPUISD::CVT_PKRTZ_F16_F32;
11478 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_i16)
11479 Opcode = AMDGPUISD::CVT_PKNORM_I16_F32;
11480 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pknorm_u16)
11481 Opcode = AMDGPUISD::CVT_PKNORM_U16_F32;
11482 else if (IntrinsicID == Intrinsic::amdgcn_cvt_pk_i16)
11483 Opcode = AMDGPUISD::CVT_PK_I16_I32;
11484 else
11485 Opcode = AMDGPUISD::CVT_PK_U16_U32;
11486
11487 if (isTypeLegal(VT))
11488 return DAG.getNode(Opcode, DL, VT, Op.getOperand(1), Op.getOperand(2));
11489
11490 SDValue Node =
11491 DAG.getNode(Opcode, DL, MVT::i32, Op.getOperand(1), Op.getOperand(2));
11492 return DAG.getNode(ISD::BITCAST, DL, VT, Node);
11493 }
11494 case Intrinsic::amdgcn_fmad_ftz:
11495 return DAG.getNode(AMDGPUISD::FMAD_FTZ, DL, VT, Op.getOperand(1),
11496 Op.getOperand(2), Op.getOperand(3));
11497
11498 case Intrinsic::amdgcn_if_break:
11499 return SDValue(DAG.getMachineNode(AMDGPU::SI_IF_BREAK, DL, VT,
11500 Op->getOperand(1), Op->getOperand(2)),
11501 0);
11502
11503 case Intrinsic::amdgcn_groupstaticsize: {
11505 if (OS == Triple::AMDHSA || OS == Triple::AMDPAL)
11506 return Op;
11507
11508 const Module *M = MF.getFunction().getParent();
11509 const GlobalValue *GV =
11510 Intrinsic::getDeclarationIfExists(M, Intrinsic::amdgcn_groupstaticsize);
11511 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, 0,
11513 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11514 }
11515 case Intrinsic::amdgcn_is_shared:
11516 case Intrinsic::amdgcn_is_private: {
11517 SDLoc SL(Op);
11518 SDValue SrcVec =
11519 DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
11520 SDValue SrcHi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, SrcVec,
11521 DAG.getConstant(1, SL, MVT::i32));
11522
11523 unsigned AS = (IntrinsicID == Intrinsic::amdgcn_is_shared)
11525 : AMDGPUAS::PRIVATE_ADDRESS;
11526 if (AS == AMDGPUAS::PRIVATE_ADDRESS &&
11527 Subtarget->hasGloballyAddressableScratch()) {
11528 SDValue FlatScratchBaseHi(
11529 DAG.getMachineNode(
11530 AMDGPU::S_MOV_B32, DL, MVT::i32,
11531 DAG.getRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, MVT::i32)),
11532 0);
11533 // Test bits 63..58 against the aperture address.
11534 return DAG.getSetCC(
11535 SL, MVT::i1,
11536 DAG.getNode(ISD::XOR, SL, MVT::i32, SrcHi, FlatScratchBaseHi),
11537 DAG.getConstant(1u << 26, SL, MVT::i32), ISD::SETULT);
11538 }
11539
11540 SDValue Aperture = getSegmentAperture(AS, SL, DAG);
11541 return DAG.getSetCC(SL, MVT::i1, SrcHi, Aperture, ISD::SETEQ);
11542 }
11543 case Intrinsic::amdgcn_perm:
11544 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op.getOperand(1),
11545 Op.getOperand(2), Op.getOperand(3));
11546 case Intrinsic::amdgcn_reloc_constant: {
11547 Module *M = MF.getFunction().getParent();
11548 const MDNode *Metadata = cast<MDNodeSDNode>(Op.getOperand(1))->getMD();
11549 auto SymbolName = cast<MDString>(Metadata->getOperand(0))->getString();
11550 auto *RelocSymbol = cast<GlobalVariable>(
11551 M->getOrInsertGlobal(SymbolName, Type::getInt32Ty(M->getContext())));
11552 SDValue GA = DAG.getTargetGlobalAddress(RelocSymbol, DL, MVT::i32, 0,
11554 return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0};
11555 }
11556 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
11557 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
11558 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
11559 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
11560 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
11561 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
11562 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
11563 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8: {
11564 if (Op.getOperand(4).getValueType() == MVT::i32)
11565 return SDValue();
11566
11567 SDLoc SL(Op);
11568 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i32);
11569 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11570 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11571 Op.getOperand(3), IndexKeyi32);
11572 }
11573 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
11574 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
11575 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
11576 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
11577 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
11578 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
11579 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
11580 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8: {
11581 if (Op.getOperand(4).getValueType() == MVT::i64)
11582 return SDValue();
11583
11584 SDLoc SL(Op);
11585 auto IndexKeyi64 =
11586 Op.getOperand(4).getValueType() == MVT::v2i32
11587 ? DAG.getBitcast(MVT::i64, Op.getOperand(4))
11588 : DAG.getAnyExtOrTrunc(Op.getOperand(4), SL, MVT::i64);
11589 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11590 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11591 Op.getOperand(3), IndexKeyi64, Op.getOperand(5),
11592 Op.getOperand(6)});
11593 }
11594 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
11595 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
11596 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
11597 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
11598 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
11599 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8: {
11600 EVT IndexKeyTy = IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8
11601 ? MVT::i64
11602 : MVT::i32;
11603 if (Op.getOperand(6).getValueType() == IndexKeyTy)
11604 return SDValue();
11605
11606 SDLoc SL(Op);
11607 auto IndexKey =
11608 Op.getOperand(6).getValueType().isVector()
11609 ? DAG.getBitcast(IndexKeyTy, Op.getOperand(6))
11610 : DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, IndexKeyTy);
11612 Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11613 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11614 IndexKey, Op.getOperand(7), Op.getOperand(8)};
11615 if (IntrinsicID == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8)
11616 Args.push_back(Op.getOperand(9));
11617 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(), Args);
11618 }
11619 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
11620 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
11621 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4: {
11622 if (Op.getOperand(6).getValueType() == MVT::i32)
11623 return SDValue();
11624
11625 SDLoc SL(Op);
11626 auto IndexKeyi32 = DAG.getAnyExtOrTrunc(Op.getOperand(6), SL, MVT::i32);
11627 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, Op.getValueType(),
11628 {Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
11629 Op.getOperand(3), Op.getOperand(4), Op.getOperand(5),
11630 IndexKeyi32, Op.getOperand(7)});
11631 }
11632 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
11633 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
11634 unsigned AFmt = (unsigned)Op.getConstantOperandVal(1);
11635 unsigned BFmt = (unsigned)Op.getConstantOperandVal(3);
11636 unsigned AScaleFmt = (unsigned)Op.getConstantOperandVal(8);
11637 unsigned BScaleFmt = (unsigned)Op.getConstantOperandVal(11);
11638 if (!AMDGPU::isValidWMMAScaleFmtCombination(AFmt, AScaleFmt, BFmt,
11639 BScaleFmt)) {
11641 "invalid matrix and scale format combination in wmma call");
11642 Op->print(errs());
11643 errs() << '\n';
11644 }
11645 return SDValue();
11646 }
11647 case Intrinsic::amdgcn_addrspacecast_nonnull:
11648 return lowerADDRSPACECAST(Op, DAG);
11649 case Intrinsic::amdgcn_readlane:
11650 case Intrinsic::amdgcn_readfirstlane:
11651 case Intrinsic::amdgcn_writelane:
11652 case Intrinsic::amdgcn_permlane16:
11653 case Intrinsic::amdgcn_permlanex16:
11654 case Intrinsic::amdgcn_permlane64:
11655 case Intrinsic::amdgcn_set_inactive:
11656 case Intrinsic::amdgcn_set_inactive_chain_arg:
11657 case Intrinsic::amdgcn_mov_dpp8:
11658 case Intrinsic::amdgcn_update_dpp:
11659 case Intrinsic::amdgcn_permlane_bcast:
11660 case Intrinsic::amdgcn_permlane_up:
11661 case Intrinsic::amdgcn_permlane_down:
11662 case Intrinsic::amdgcn_permlane_xor:
11663 return lowerLaneOp(*this, Op.getNode(), DAG);
11664 case Intrinsic::amdgcn_dead: {
11666 for (const EVT ValTy : Op.getNode()->values())
11667 Poisons.push_back(DAG.getPOISON(ValTy));
11668 return DAG.getMergeValues(Poisons, SDLoc(Op));
11669 }
11670 case Intrinsic::amdgcn_wave_shuffle:
11671 return lowerWaveShuffle(*this, Op.getNode(), DAG);
11672 default:
11673 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
11675 return lowerImage(Op, ImageDimIntr, DAG, false);
11676
11677 return Op;
11678 }
11679}
11680
11681// On targets not supporting constant in soffset field, turn zero to
11682// SGPR_NULL to avoid generating an extra s_mov with zero.
11684 const GCNSubtarget *Subtarget) {
11685 if (Subtarget->hasRestrictedSOffset() && isNullConstant(SOffset))
11686 return DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32);
11687 return SOffset;
11688}
11689
11690SDValue SITargetLowering::lowerRawBufferAtomicIntrin(SDValue Op,
11691 SelectionDAG &DAG,
11692 unsigned NewOpcode) const {
11693 SDLoc DL(Op);
11694
11695 SDValue VData = Op.getOperand(2);
11696 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11697 SmallVector<EVT, 2> ResultTypes(Op->values());
11698 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11699 "unsupported buffer atomic data type");
11700 }
11701 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11702 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
11703 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
11704 SDValue Ops[] = {
11705 Op.getOperand(0), // Chain
11706 VData, // vdata
11707 Rsrc, // rsrc
11708 DAG.getConstant(0, DL, MVT::i32), // vindex
11709 VOffset, // voffset
11710 SOffset, // soffset
11711 Offset, // offset
11712 Op.getOperand(6), // cachepolicy
11713 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11714 };
11715
11716 auto *M = cast<MemSDNode>(Op);
11717
11718 EVT MemVT = VData.getValueType();
11719 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11720 M->getMemOperand());
11721}
11722
11723SDValue
11724SITargetLowering::lowerStructBufferAtomicIntrin(SDValue Op, SelectionDAG &DAG,
11725 unsigned NewOpcode) const {
11726 SDLoc DL(Op);
11727
11728 SDValue VData = Op.getOperand(2);
11729 if (VData.getValueSizeInBits() != 32 && VData.getValueSizeInBits() != 64) {
11730 SmallVector<EVT, 2> ResultTypes(Op->values());
11731 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
11732 "unsupported buffer atomic data type");
11733 }
11734 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
11735 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
11736 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
11737 SDValue Ops[] = {
11738 Op.getOperand(0), // Chain
11739 VData, // vdata
11740 Rsrc, // rsrc
11741 Op.getOperand(4), // vindex
11742 VOffset, // voffset
11743 SOffset, // soffset
11744 Offset, // offset
11745 Op.getOperand(7), // cachepolicy
11746 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
11747 };
11748
11749 auto *M = cast<MemSDNode>(Op);
11750
11751 EVT MemVT = VData.getValueType();
11752 return DAG.getMemIntrinsicNode(NewOpcode, DL, Op->getVTList(), Ops, MemVT,
11753 M->getMemOperand());
11754}
11755
11756SDValue SITargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
11757 SelectionDAG &DAG) const {
11758 unsigned IntrID = Op.getConstantOperandVal(1);
11759 SDLoc DL(Op);
11760
11761 switch (IntrID) {
11762 case Intrinsic::amdgcn_ds_ordered_add:
11763 case Intrinsic::amdgcn_ds_ordered_swap: {
11764 MemSDNode *M = cast<MemSDNode>(Op);
11765 SDValue Chain = M->getOperand(0);
11766 SDValue M0 = M->getOperand(2);
11767 SDValue Value = M->getOperand(3);
11768 unsigned IndexOperand = M->getConstantOperandVal(7);
11769 unsigned WaveRelease = M->getConstantOperandVal(8);
11770 unsigned WaveDone = M->getConstantOperandVal(9);
11771
11772 unsigned OrderedCountIndex = IndexOperand & 0x3f;
11773 IndexOperand &= ~0x3f;
11774 unsigned CountDw = 0;
11775
11776 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10) {
11777 CountDw = (IndexOperand >> 24) & 0xf;
11778 IndexOperand &= ~(0xf << 24);
11779
11780 if (CountDw < 1 || CountDw > 4) {
11781 const Function &Fn = DAG.getMachineFunction().getFunction();
11782 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11783 Fn, "ds_ordered_count: dword count must be between 1 and 4",
11784 DL.getDebugLoc()));
11785 CountDw = 1;
11786 }
11787 }
11788
11789 if (IndexOperand) {
11790 const Function &Fn = DAG.getMachineFunction().getFunction();
11791 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11792 Fn, "ds_ordered_count: bad index operand", DL.getDebugLoc()));
11793 }
11794
11795 if (WaveDone && !WaveRelease) {
11796 // TODO: Move this to IR verifier
11797 const Function &Fn = DAG.getMachineFunction().getFunction();
11798 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11799 Fn, "ds_ordered_count: wave_done requires wave_release",
11800 DL.getDebugLoc()));
11801 }
11802
11803 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
11804 unsigned ShaderType =
11806 unsigned Offset0 = OrderedCountIndex << 2;
11807 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
11808
11809 if (Subtarget->getGeneration() >= AMDGPUSubtarget::GFX10)
11810 Offset1 |= (CountDw - 1) << 6;
11811
11812 if (Subtarget->getGeneration() < AMDGPUSubtarget::GFX11)
11813 Offset1 |= ShaderType << 2;
11814
11815 unsigned Offset = Offset0 | (Offset1 << 8);
11816
11817 SDValue Ops[] = {
11818 Chain, Value, DAG.getTargetConstant(Offset, DL, MVT::i16),
11819 copyToM0(DAG, Chain, DL, M0).getValue(1), // Glue
11820 };
11821 return DAG.getMemIntrinsicNode(AMDGPUISD::DS_ORDERED_COUNT, DL,
11822 M->getVTList(), Ops, M->getMemoryVT(),
11823 M->getMemOperand());
11824 }
11825 case Intrinsic::amdgcn_ptr_s_buffer_load: {
11826 unsigned CPol = Op.getConstantOperandVal(4);
11827 if (CPol & ~((Subtarget->getGeneration() >= AMDGPUSubtarget::GFX12)
11830 return Op;
11831
11832 MemSDNode *M = cast<MemSDNode>(Op);
11833 return lowerSBuffer(
11834 Op.getValueType(), M->getMemoryVT(), DL, Op.getOperand(0),
11835 bufferRsrcPtrToVector(Op.getOperand(2), DAG), Op.getOperand(3),
11836 Op.getOperand(4), DAG, M->getMemOperand());
11837 }
11838 case Intrinsic::amdgcn_raw_buffer_load:
11839 case Intrinsic::amdgcn_raw_ptr_buffer_load:
11840 case Intrinsic::amdgcn_raw_atomic_buffer_load:
11841 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
11842 case Intrinsic::amdgcn_raw_buffer_load_format:
11843 case Intrinsic::amdgcn_raw_ptr_buffer_load_format: {
11844 const bool IsFormat =
11845 IntrID == Intrinsic::amdgcn_raw_buffer_load_format ||
11846 IntrID == Intrinsic::amdgcn_raw_ptr_buffer_load_format;
11847
11848 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
11849 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
11850 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
11851 SDValue Ops[] = {
11852 Op.getOperand(0), // Chain
11853 Rsrc, // rsrc
11854 DAG.getConstant(0, DL, MVT::i32), // vindex
11855 VOffset, // voffset
11856 SOffset, // soffset
11857 Offset, // offset
11858 Op.getOperand(5), // cachepolicy, swizzled buffer
11859 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11860 };
11861
11862 auto *M = cast<MemSDNode>(Op);
11863 return lowerIntrinsicLoad(M, IsFormat, DAG, Ops);
11864 }
11865 case Intrinsic::amdgcn_struct_buffer_load:
11866 case Intrinsic::amdgcn_struct_ptr_buffer_load:
11867 case Intrinsic::amdgcn_struct_buffer_load_format:
11868 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
11869 case Intrinsic::amdgcn_struct_atomic_buffer_load:
11870 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
11871 const bool IsFormat =
11872 IntrID == Intrinsic::amdgcn_struct_buffer_load_format ||
11873 IntrID == Intrinsic::amdgcn_struct_ptr_buffer_load_format;
11874
11875 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
11876 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
11877 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
11878 SDValue Ops[] = {
11879 Op.getOperand(0), // Chain
11880 Rsrc, // rsrc
11881 Op.getOperand(3), // vindex
11882 VOffset, // voffset
11883 SOffset, // soffset
11884 Offset, // offset
11885 Op.getOperand(6), // cachepolicy, swizzled buffer
11886 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
11887 };
11888
11889 return lowerIntrinsicLoad(cast<MemSDNode>(Op), IsFormat, DAG, Ops);
11890 }
11891 case Intrinsic::amdgcn_raw_tbuffer_load:
11892 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
11893 MemSDNode *M = cast<MemSDNode>(Op);
11894 EVT LoadVT = Op.getValueType();
11895 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
11896 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(3), DAG);
11897 auto SOffset = selectSOffset(Op.getOperand(4), DAG, Subtarget);
11898
11899 SDValue Ops[] = {
11900 Op.getOperand(0), // Chain
11901 Rsrc, // rsrc
11902 DAG.getConstant(0, DL, MVT::i32), // vindex
11903 VOffset, // voffset
11904 SOffset, // soffset
11905 Offset, // offset
11906 Op.getOperand(5), // format
11907 Op.getOperand(6), // cachepolicy, swizzled buffer
11908 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
11909 };
11910
11911 if (LoadVT.getScalarSizeInBits() == 16)
11912 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
11913 Ops);
11914 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
11915 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
11916 DAG);
11917 }
11918 case Intrinsic::amdgcn_struct_tbuffer_load:
11919 case Intrinsic::amdgcn_struct_ptr_tbuffer_load: {
11920 MemSDNode *M = cast<MemSDNode>(Op);
11921 EVT LoadVT = Op.getValueType();
11922 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
11923 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
11924 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
11925
11926 SDValue Ops[] = {
11927 Op.getOperand(0), // Chain
11928 Rsrc, // rsrc
11929 Op.getOperand(3), // vindex
11930 VOffset, // voffset
11931 SOffset, // soffset
11932 Offset, // offset
11933 Op.getOperand(6), // format
11934 Op.getOperand(7), // cachepolicy, swizzled buffer
11935 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
11936 };
11937
11938 if (LoadVT.getScalarSizeInBits() == 16)
11939 return adjustLoadValueType(AMDGPUISD::TBUFFER_LOAD_FORMAT_D16, M, DAG,
11940 Ops);
11941 return getMemIntrinsicNode(AMDGPUISD::TBUFFER_LOAD_FORMAT, DL,
11942 Op->getVTList(), Ops, LoadVT, M->getMemOperand(),
11943 DAG);
11944 }
11945 case Intrinsic::amdgcn_raw_buffer_atomic_fadd:
11946 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fadd:
11947 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FADD);
11948 case Intrinsic::amdgcn_struct_buffer_atomic_fadd:
11949 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd:
11950 return lowerStructBufferAtomicIntrin(Op, DAG,
11951 AMDGPUISD::BUFFER_ATOMIC_FADD);
11952 case Intrinsic::amdgcn_raw_buffer_atomic_fmin:
11953 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmin:
11954 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMIN);
11955 case Intrinsic::amdgcn_struct_buffer_atomic_fmin:
11956 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmin:
11957 return lowerStructBufferAtomicIntrin(Op, DAG,
11958 AMDGPUISD::BUFFER_ATOMIC_FMIN);
11959 case Intrinsic::amdgcn_raw_buffer_atomic_fmax:
11960 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_fmax:
11961 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_FMAX);
11962 case Intrinsic::amdgcn_struct_buffer_atomic_fmax:
11963 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fmax:
11964 return lowerStructBufferAtomicIntrin(Op, DAG,
11965 AMDGPUISD::BUFFER_ATOMIC_FMAX);
11966 case Intrinsic::amdgcn_raw_buffer_atomic_swap:
11967 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_swap:
11968 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SWAP);
11969 case Intrinsic::amdgcn_raw_buffer_atomic_add:
11970 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_add:
11971 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
11972 case Intrinsic::amdgcn_raw_buffer_atomic_sub:
11973 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub:
11974 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
11975 case Intrinsic::amdgcn_raw_buffer_atomic_smin:
11976 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smin:
11977 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMIN);
11978 case Intrinsic::amdgcn_raw_buffer_atomic_umin:
11979 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umin:
11980 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMIN);
11981 case Intrinsic::amdgcn_raw_buffer_atomic_smax:
11982 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_smax:
11983 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SMAX);
11984 case Intrinsic::amdgcn_raw_buffer_atomic_umax:
11985 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_umax:
11986 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_UMAX);
11987 case Intrinsic::amdgcn_raw_buffer_atomic_and:
11988 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_and:
11989 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
11990 case Intrinsic::amdgcn_raw_buffer_atomic_or:
11991 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_or:
11992 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
11993 case Intrinsic::amdgcn_raw_buffer_atomic_xor:
11994 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_xor:
11995 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
11996 case Intrinsic::amdgcn_raw_buffer_atomic_inc:
11997 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_inc:
11998 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
11999 case Intrinsic::amdgcn_raw_buffer_atomic_dec:
12000 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_dec:
12001 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12002 case Intrinsic::amdgcn_struct_buffer_atomic_swap:
12003 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_swap:
12004 return lowerStructBufferAtomicIntrin(Op, DAG,
12005 AMDGPUISD::BUFFER_ATOMIC_SWAP);
12006 case Intrinsic::amdgcn_struct_buffer_atomic_add:
12007 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_add:
12008 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_ADD);
12009 case Intrinsic::amdgcn_struct_buffer_atomic_sub:
12010 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub:
12011 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_SUB);
12012 case Intrinsic::amdgcn_struct_buffer_atomic_smin:
12013 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smin:
12014 return lowerStructBufferAtomicIntrin(Op, DAG,
12015 AMDGPUISD::BUFFER_ATOMIC_SMIN);
12016 case Intrinsic::amdgcn_struct_buffer_atomic_umin:
12017 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umin:
12018 return lowerStructBufferAtomicIntrin(Op, DAG,
12019 AMDGPUISD::BUFFER_ATOMIC_UMIN);
12020 case Intrinsic::amdgcn_struct_buffer_atomic_smax:
12021 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_smax:
12022 return lowerStructBufferAtomicIntrin(Op, DAG,
12023 AMDGPUISD::BUFFER_ATOMIC_SMAX);
12024 case Intrinsic::amdgcn_struct_buffer_atomic_umax:
12025 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_umax:
12026 return lowerStructBufferAtomicIntrin(Op, DAG,
12027 AMDGPUISD::BUFFER_ATOMIC_UMAX);
12028 case Intrinsic::amdgcn_struct_buffer_atomic_and:
12029 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_and:
12030 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_AND);
12031 case Intrinsic::amdgcn_struct_buffer_atomic_or:
12032 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_or:
12033 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_OR);
12034 case Intrinsic::amdgcn_struct_buffer_atomic_xor:
12035 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_xor:
12036 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_XOR);
12037 case Intrinsic::amdgcn_struct_buffer_atomic_inc:
12038 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_inc:
12039 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_INC);
12040 case Intrinsic::amdgcn_struct_buffer_atomic_dec:
12041 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_dec:
12042 return lowerStructBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_DEC);
12043 case Intrinsic::amdgcn_raw_buffer_atomic_sub_clamp_u32:
12044 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_sub_clamp_u32:
12045 return lowerRawBufferAtomicIntrin(Op, DAG, AMDGPUISD::BUFFER_ATOMIC_CSUB);
12046 case Intrinsic::amdgcn_struct_buffer_atomic_sub_clamp_u32:
12047 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_sub_clamp_u32:
12048 return lowerStructBufferAtomicIntrin(Op, DAG,
12049 AMDGPUISD::BUFFER_ATOMIC_CSUB);
12050 case Intrinsic::amdgcn_raw_buffer_atomic_cond_sub_u32:
12051 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cond_sub_u32:
12052 return lowerRawBufferAtomicIntrin(Op, DAG,
12053 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12054 case Intrinsic::amdgcn_struct_buffer_atomic_cond_sub_u32:
12055 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cond_sub_u32:
12056 return lowerStructBufferAtomicIntrin(Op, DAG,
12057 AMDGPUISD::BUFFER_ATOMIC_COND_SUB_U32);
12058 case Intrinsic::amdgcn_raw_buffer_atomic_cmpswap:
12059 case Intrinsic::amdgcn_raw_ptr_buffer_atomic_cmpswap: {
12060 SDValue Src = Op.getOperand(2);
12061 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12062 SmallVector<EVT, 2> ResultTypes(Op->values());
12063 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12064 "unsupported buffer atomic data type");
12065 }
12066 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(4), DAG);
12067 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12068 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12069 SDValue Ops[] = {
12070 Op.getOperand(0), // Chain
12071 Op.getOperand(2), // src
12072 Op.getOperand(3), // cmp
12073 Rsrc, // rsrc
12074 DAG.getConstant(0, DL, MVT::i32), // vindex
12075 VOffset, // voffset
12076 SOffset, // soffset
12077 Offset, // offset
12078 Op.getOperand(7), // cachepolicy
12079 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12080 };
12081 EVT VT = Op.getValueType();
12082 auto *M = cast<MemSDNode>(Op);
12083
12084 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12085 Op->getVTList(), Ops, VT,
12086 M->getMemOperand());
12087 }
12088 case Intrinsic::amdgcn_struct_buffer_atomic_cmpswap:
12089 case Intrinsic::amdgcn_struct_ptr_buffer_atomic_cmpswap: {
12090 SDValue Src = Op.getOperand(2);
12091 if (Src.getValueSizeInBits() != 32 && Src.getValueSizeInBits() != 64) {
12092 SmallVector<EVT, 2> ResultTypes(Op->values());
12093 return diagnoseUnsupportedImage(DAG, Op, ResultTypes, DL,
12094 "unsupported buffer atomic data type");
12095 }
12096 SDValue Rsrc = bufferRsrcPtrToVector(Op->getOperand(4), DAG);
12097 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(6), DAG);
12098 auto SOffset = selectSOffset(Op.getOperand(7), DAG, Subtarget);
12099 SDValue Ops[] = {
12100 Op.getOperand(0), // Chain
12101 Op.getOperand(2), // src
12102 Op.getOperand(3), // cmp
12103 Rsrc, // rsrc
12104 Op.getOperand(5), // vindex
12105 VOffset, // voffset
12106 SOffset, // soffset
12107 Offset, // offset
12108 Op.getOperand(8), // cachepolicy
12109 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12110 };
12111 EVT VT = Op.getValueType();
12112 auto *M = cast<MemSDNode>(Op);
12113
12114 return DAG.getMemIntrinsicNode(AMDGPUISD::BUFFER_ATOMIC_CMPSWAP, DL,
12115 Op->getVTList(), Ops, VT,
12116 M->getMemOperand());
12117 }
12118 case Intrinsic::amdgcn_image_bvh_dual_intersect_ray:
12119 case Intrinsic::amdgcn_image_bvh8_intersect_ray: {
12120 MemSDNode *M = cast<MemSDNode>(Op);
12121 SDValue NodePtr = M->getOperand(2);
12122 SDValue RayExtent = M->getOperand(3);
12123 SDValue InstanceMask = M->getOperand(4);
12124 SDValue RayOrigin = M->getOperand(5);
12125 SDValue RayDir = M->getOperand(6);
12126 SDValue Offsets = M->getOperand(7);
12127 SDValue TDescr = M->getOperand(8);
12128
12129 assert(NodePtr.getValueType() == MVT::i64);
12130 assert(RayDir.getValueType() == MVT::v3f32);
12131
12132 bool IsBVH8 = IntrID == Intrinsic::amdgcn_image_bvh8_intersect_ray;
12133 const unsigned NumVDataDwords = 10;
12134 const unsigned NumVAddrDwords = IsBVH8 ? 11 : 12;
12135 int Opcode = AMDGPU::getMIMGOpcode(
12136 IsBVH8 ? AMDGPU::IMAGE_BVH8_INTERSECT_RAY
12137 : AMDGPU::IMAGE_BVH_DUAL_INTERSECT_RAY,
12138 AMDGPU::MIMGEncGfx12, NumVDataDwords, NumVAddrDwords);
12139 assert(Opcode != -1);
12140
12142 Ops.push_back(NodePtr);
12143 Ops.push_back(DAG.getBuildVector(
12144 MVT::v2i32, DL,
12145 {DAG.getBitcast(MVT::i32, RayExtent),
12146 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, InstanceMask)}));
12147 Ops.push_back(RayOrigin);
12148 Ops.push_back(RayDir);
12149 Ops.push_back(Offsets);
12150 Ops.push_back(TDescr);
12151 Ops.push_back(M->getChain());
12152
12153 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12154 MachineMemOperand *MemRef = M->getMemOperand();
12155 DAG.setNodeMemRefs(NewNode, {MemRef});
12156 return SDValue(NewNode, 0);
12157 }
12158 case Intrinsic::amdgcn_image_bvh_intersect_ray: {
12159 MemSDNode *M = cast<MemSDNode>(Op);
12160 SDValue NodePtr = M->getOperand(2);
12161 SDValue RayExtent = M->getOperand(3);
12162 SDValue RayOrigin = M->getOperand(4);
12163 SDValue RayDir = M->getOperand(5);
12164 SDValue RayInvDir = M->getOperand(6);
12165 SDValue TDescr = M->getOperand(7);
12166
12167 assert(NodePtr.getValueType() == MVT::i32 ||
12168 NodePtr.getValueType() == MVT::i64);
12169 assert(RayDir.getValueType() == MVT::v3f16 ||
12170 RayDir.getValueType() == MVT::v3f32);
12171
12172 const bool IsGFX11 = AMDGPU::isGFX11(*Subtarget);
12173 const bool IsGFX11Plus = AMDGPU::isGFX11Plus(*Subtarget);
12174 const bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
12175 const bool IsA16 = RayDir.getValueType().getVectorElementType() == MVT::f16;
12176 const bool Is64 = NodePtr.getValueType() == MVT::i64;
12177 const unsigned NumVDataDwords = 4;
12178 const unsigned NumVAddrDwords = IsA16 ? (Is64 ? 9 : 8) : (Is64 ? 12 : 11);
12179 const unsigned NumVAddrs = IsGFX11Plus ? (IsA16 ? 4 : 5) : NumVAddrDwords;
12180 const bool UseNSA = (Subtarget->hasNSAEncoding() &&
12181 NumVAddrs <= Subtarget->getNSAMaxSize()) ||
12182 IsGFX12Plus;
12183 const unsigned BaseOpcodes[2][2] = {
12184 {AMDGPU::IMAGE_BVH_INTERSECT_RAY, AMDGPU::IMAGE_BVH_INTERSECT_RAY_a16},
12185 {AMDGPU::IMAGE_BVH64_INTERSECT_RAY,
12186 AMDGPU::IMAGE_BVH64_INTERSECT_RAY_a16}};
12187 int Opcode;
12188 if (UseNSA) {
12189 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12190 IsGFX12Plus ? AMDGPU::MIMGEncGfx12
12191 : IsGFX11 ? AMDGPU::MIMGEncGfx11NSA
12192 : AMDGPU::MIMGEncGfx10NSA,
12193 NumVDataDwords, NumVAddrDwords);
12194 } else {
12195 assert(!IsGFX12Plus);
12196 Opcode = AMDGPU::getMIMGOpcode(BaseOpcodes[Is64][IsA16],
12197 IsGFX11 ? AMDGPU::MIMGEncGfx11Default
12198 : AMDGPU::MIMGEncGfx10Default,
12199 NumVDataDwords, NumVAddrDwords);
12200 }
12201 assert(Opcode != -1);
12202
12204
12205 auto packLanes = [&DAG, &Ops, &DL](SDValue Op, bool IsAligned) {
12207 DAG.ExtractVectorElements(Op, Lanes, 0, 3);
12208 if (Lanes[0].getValueSizeInBits() == 32) {
12209 for (unsigned I = 0; I < 3; ++I)
12210 Ops.push_back(DAG.getBitcast(MVT::i32, Lanes[I]));
12211 } else {
12212 if (IsAligned) {
12213 Ops.push_back(DAG.getBitcast(
12214 MVT::i32,
12215 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[0], Lanes[1]})));
12216 Ops.push_back(Lanes[2]);
12217 } else {
12218 SDValue Elt0 = Ops.pop_back_val();
12219 Ops.push_back(DAG.getBitcast(
12220 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL, {Elt0, Lanes[0]})));
12221 Ops.push_back(DAG.getBitcast(
12222 MVT::i32,
12223 DAG.getBuildVector(MVT::v2f16, DL, {Lanes[1], Lanes[2]})));
12224 }
12225 }
12226 };
12227
12228 if (UseNSA && IsGFX11Plus) {
12229 Ops.push_back(NodePtr);
12230 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12231 Ops.push_back(RayOrigin);
12232 if (IsA16) {
12233 SmallVector<SDValue, 3> DirLanes, InvDirLanes, MergedLanes;
12234 DAG.ExtractVectorElements(RayDir, DirLanes, 0, 3);
12235 DAG.ExtractVectorElements(RayInvDir, InvDirLanes, 0, 3);
12236 for (unsigned I = 0; I < 3; ++I) {
12237 MergedLanes.push_back(DAG.getBitcast(
12238 MVT::i32, DAG.getBuildVector(MVT::v2f16, DL,
12239 {DirLanes[I], InvDirLanes[I]})));
12240 }
12241 Ops.push_back(DAG.getBuildVector(MVT::v3i32, DL, MergedLanes));
12242 } else {
12243 Ops.push_back(RayDir);
12244 Ops.push_back(RayInvDir);
12245 }
12246 } else {
12247 if (Is64)
12248 DAG.ExtractVectorElements(DAG.getBitcast(MVT::v2i32, NodePtr), Ops, 0,
12249 2);
12250 else
12251 Ops.push_back(NodePtr);
12252
12253 Ops.push_back(DAG.getBitcast(MVT::i32, RayExtent));
12254 packLanes(RayOrigin, true);
12255 packLanes(RayDir, true);
12256 packLanes(RayInvDir, false);
12257 }
12258
12259 if (!UseNSA) {
12260 // Build a single vector containing all the operands so far prepared.
12261 if (NumVAddrDwords > 12) {
12262 SDValue Undef = DAG.getPOISON(MVT::i32);
12263 Ops.append(16 - Ops.size(), Undef);
12264 }
12265 assert(Ops.size() >= 8 && Ops.size() <= 12);
12266 SDValue MergedOps =
12267 DAG.getBuildVector(MVT::getVectorVT(MVT::i32, Ops.size()), DL, Ops);
12268 Ops.clear();
12269 Ops.push_back(MergedOps);
12270 }
12271
12272 Ops.push_back(TDescr);
12273 Ops.push_back(DAG.getTargetConstant(IsA16, DL, MVT::i1));
12274 Ops.push_back(M->getChain());
12275
12276 auto *NewNode = DAG.getMachineNode(Opcode, DL, M->getVTList(), Ops);
12277 MachineMemOperand *MemRef = M->getMemOperand();
12278 DAG.setNodeMemRefs(NewNode, {MemRef});
12279 return SDValue(NewNode, 0);
12280 }
12281 case Intrinsic::amdgcn_global_atomic_fmin_num:
12282 case Intrinsic::amdgcn_global_atomic_fmax_num:
12283 case Intrinsic::amdgcn_flat_atomic_fmin_num:
12284 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12285 MemSDNode *M = cast<MemSDNode>(Op);
12286 SDValue Ops[] = {
12287 M->getOperand(0), // Chain
12288 M->getOperand(2), // Ptr
12289 M->getOperand(3) // Value
12290 };
12291 unsigned Opcode = 0;
12292 switch (IntrID) {
12293 case Intrinsic::amdgcn_global_atomic_fmin_num:
12294 case Intrinsic::amdgcn_flat_atomic_fmin_num: {
12295 Opcode = ISD::ATOMIC_LOAD_FMIN;
12296 break;
12297 }
12298 case Intrinsic::amdgcn_global_atomic_fmax_num:
12299 case Intrinsic::amdgcn_flat_atomic_fmax_num: {
12300 Opcode = ISD::ATOMIC_LOAD_FMAX;
12301 break;
12302 }
12303 default:
12304 llvm_unreachable("unhandled atomic opcode");
12305 }
12306 return DAG.getAtomic(Opcode, SDLoc(Op), M->getMemoryVT(), M->getVTList(),
12307 Ops, M->getMemOperand());
12308 }
12309 case Intrinsic::amdgcn_s_alloc_vgpr: {
12310 SDValue NumVGPRs = Op.getOperand(2);
12311 if (!NumVGPRs->isDivergent())
12312 return Op;
12313
12314 SDValue ReadFirstLaneID =
12315 DAG.getTargetConstant(Intrinsic::amdgcn_readfirstlane, DL, MVT::i32);
12316 NumVGPRs = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
12317 ReadFirstLaneID, NumVGPRs);
12318
12319 return DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, Op->getVTList(),
12320 Op.getOperand(0), Op.getOperand(1), NumVGPRs);
12321 }
12322 case Intrinsic::amdgcn_s_get_barrier_state:
12323 case Intrinsic::amdgcn_s_get_named_barrier_state: {
12324 SDValue Chain = Op->getOperand(0);
12326 unsigned Opc;
12327
12328 if (isa<ConstantSDNode>(Op->getOperand(2))) {
12329 uint64_t BarID = cast<ConstantSDNode>(Op->getOperand(2))->getZExtValue();
12330 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state)
12331 BarID = (BarID >> 4) & 0x3F;
12332 Opc = AMDGPU::S_GET_BARRIER_STATE_IMM;
12333 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
12334 Ops.push_back(K);
12335 Ops.push_back(Chain);
12336 } else {
12337 Opc = AMDGPU::S_GET_BARRIER_STATE_M0;
12338 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
12339 SDValue M0Val;
12340 M0Val = DAG.getNode(ISD::SRL, DL, MVT::i32, Op->getOperand(2),
12341 DAG.getShiftAmountConstant(4, MVT::i32, DL));
12342 M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, M0Val,
12343 DAG.getConstant(0x3F, DL, MVT::i32));
12344 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
12345 } else
12346 Ops.push_back(copyToM0(DAG, Chain, DL, Op->getOperand(2)).getValue(0));
12347 }
12348
12349 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
12350 return SDValue(NewMI, 0);
12351 }
12352 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
12353 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
12354 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: {
12355 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12356 SDValue Chain = Op->getOperand(0);
12357 SDValue Ptr = Op->getOperand(2);
12358 EVT VT = Op->getValueType(0);
12359 return DAG.getAtomicLoad(ISD::NON_EXTLOAD, DL, MII->getMemoryVT(), VT,
12360 Chain, Ptr, MII->getMemOperand());
12361 }
12362 case Intrinsic::amdgcn_av_load_b128: {
12363 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12364 SDValue Chain = Op->getOperand(0);
12365 SDValue Ptr = Op->getOperand(2);
12366 EVT VT = Op->getValueType(0);
12367 // Lower to a regular ISD::LOAD. The MachineMemOperand carries Monotonic
12368 // ordering and syncscope so that SIMemoryLegalizer sets cache policy bits.
12369 // Address space filtering in the load_global/load_flat PatFrags selects
12370 // the correct GLOBAL vs FLAT instruction.
12371 return DAG.getLoad(VT, DL, Chain, Ptr, MII->getMemOperand());
12372 }
12373 case Intrinsic::amdgcn_flat_load_monitor_b32:
12374 case Intrinsic::amdgcn_flat_load_monitor_b64:
12375 case Intrinsic::amdgcn_flat_load_monitor_b128: {
12376 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12377 SDValue Chain = Op->getOperand(0);
12378 SDValue Ptr = Op->getOperand(2);
12379 return DAG.getMemIntrinsicNode(AMDGPUISD::FLAT_LOAD_MONITOR, DL,
12380 Op->getVTList(), {Chain, Ptr},
12381 MII->getMemoryVT(), MII->getMemOperand());
12382 }
12383 case Intrinsic::amdgcn_global_load_monitor_b32:
12384 case Intrinsic::amdgcn_global_load_monitor_b64:
12385 case Intrinsic::amdgcn_global_load_monitor_b128: {
12386 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
12387 SDValue Chain = Op->getOperand(0);
12388 SDValue Ptr = Op->getOperand(2);
12389 return DAG.getMemIntrinsicNode(AMDGPUISD::GLOBAL_LOAD_MONITOR, DL,
12390 Op->getVTList(), {Chain, Ptr},
12391 MII->getMemoryVT(), MII->getMemOperand());
12392 }
12393 default:
12394
12395 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
12397 return lowerImage(Op, ImageDimIntr, DAG, true);
12398
12399 return SDValue();
12400 }
12401}
12402
12403// Call DAG.getMemIntrinsicNode for a load, but first widen a dwordx3 type to
12404// dwordx4 if on SI and handle TFE loads.
12405SDValue SITargetLowering::getMemIntrinsicNode(unsigned Opcode, const SDLoc &DL,
12406 SDVTList VTList,
12407 ArrayRef<SDValue> Ops, EVT MemVT,
12408 MachineMemOperand *MMO,
12409 SelectionDAG &DAG) const {
12410 LLVMContext &C = *DAG.getContext();
12412 EVT VT = VTList.VTs[0];
12413
12414 assert(VTList.NumVTs == 2 || VTList.NumVTs == 3);
12415 bool IsTFE = VTList.NumVTs == 3;
12416 if (IsTFE) {
12417 unsigned NumValueDWords = divideCeil(VT.getSizeInBits(), 32);
12418 unsigned NumOpDWords = NumValueDWords + 1;
12419 EVT OpDWordsVT = EVT::getVectorVT(C, MVT::i32, NumOpDWords);
12420 SDVTList OpDWordsVTList = DAG.getVTList(OpDWordsVT, VTList.VTs[2]);
12421 MachineMemOperand *OpDWordsMMO =
12422 MF.getMachineMemOperand(MMO, 0, NumOpDWords * 4);
12423 SDValue Op = getMemIntrinsicNode(Opcode, DL, OpDWordsVTList, Ops,
12424 OpDWordsVT, OpDWordsMMO, DAG);
12425 SDValue Status = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
12426 DAG.getVectorIdxConstant(NumValueDWords, DL));
12427 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, DL);
12428 SDValue ValueDWords =
12429 NumValueDWords == 1
12430 ? DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op, ZeroIdx)
12432 EVT::getVectorVT(C, MVT::i32, NumValueDWords), Op,
12433 ZeroIdx);
12434 SDValue Value = DAG.getNode(ISD::BITCAST, DL, VT, ValueDWords);
12435 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
12436 }
12437
12438 if (!Subtarget->hasDwordx3LoadStores() &&
12439 (VT == MVT::v3i32 || VT == MVT::v3f32)) {
12440 EVT WidenedVT = EVT::getVectorVT(C, VT.getVectorElementType(), 4);
12441 EVT WidenedMemVT = EVT::getVectorVT(C, MemVT.getVectorElementType(), 4);
12442 MachineMemOperand *WidenedMMO = MF.getMachineMemOperand(MMO, 0, 16);
12443 SDVTList WidenedVTList = DAG.getVTList(WidenedVT, VTList.VTs[1]);
12444 SDValue Op = DAG.getMemIntrinsicNode(Opcode, DL, WidenedVTList, Ops,
12445 WidenedMemVT, WidenedMMO);
12447 DAG.getVectorIdxConstant(0, DL));
12448 return DAG.getMergeValues({Value, SDValue(Op.getNode(), 1)}, DL);
12449 }
12450
12451 return DAG.getMemIntrinsicNode(Opcode, DL, VTList, Ops, MemVT, MMO);
12452}
12453
12454SDValue SITargetLowering::handleD16VData(SDValue VData, SelectionDAG &DAG,
12455 bool ImageStore) const {
12456 EVT StoreVT = VData.getValueType();
12457
12458 // No change for f16 and legal vector D16 types.
12459 if (!StoreVT.isVector())
12460 return VData;
12461
12462 SDLoc DL(VData);
12463 unsigned NumElements = StoreVT.getVectorNumElements();
12464
12465 if (Subtarget->hasUnpackedD16VMem()) {
12466 // We need to unpack the packed data to store.
12467 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12468 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12469
12470 EVT EquivStoreVT =
12471 EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumElements);
12472 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, EquivStoreVT, IntVData);
12473 return DAG.UnrollVectorOp(ZExt.getNode());
12474 }
12475
12476 // The sq block of gfx8.1 does not estimate register use correctly for d16
12477 // image store instructions. The data operand is computed as if it were not a
12478 // d16 image instruction.
12479 if (ImageStore && Subtarget->hasImageStoreD16Bug()) {
12480 // Bitcast to i16
12481 EVT IntStoreVT = StoreVT.changeTypeToInteger();
12482 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12483
12484 // Decompose into scalars
12486 DAG.ExtractVectorElements(IntVData, Elts);
12487
12488 // Group pairs of i16 into v2i16 and bitcast to i32
12489 SmallVector<SDValue, 4> PackedElts;
12490 for (unsigned I = 0; I < Elts.size() / 2; I += 1) {
12491 SDValue Pair =
12492 DAG.getBuildVector(MVT::v2i16, DL, {Elts[I * 2], Elts[I * 2 + 1]});
12493 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12494 PackedElts.push_back(IntPair);
12495 }
12496 if ((NumElements % 2) == 1) {
12497 // Handle v3i16
12498 unsigned I = Elts.size() / 2;
12499 SDValue Pair = DAG.getBuildVector(MVT::v2i16, DL,
12500 {Elts[I * 2], DAG.getPOISON(MVT::i16)});
12501 SDValue IntPair = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Pair);
12502 PackedElts.push_back(IntPair);
12503 }
12504
12505 // Pad using UNDEF
12506 PackedElts.resize(Elts.size(), DAG.getPOISON(MVT::i32));
12507
12508 // Build final vector
12509 EVT VecVT =
12510 EVT::getVectorVT(*DAG.getContext(), MVT::i32, PackedElts.size());
12511 return DAG.getBuildVector(VecVT, DL, PackedElts);
12512 }
12513
12514 if (NumElements == 3) {
12515 EVT IntStoreVT =
12517 SDValue IntVData = DAG.getNode(ISD::BITCAST, DL, IntStoreVT, VData);
12518
12519 EVT WidenedStoreVT = EVT::getVectorVT(
12520 *DAG.getContext(), StoreVT.getVectorElementType(), NumElements + 1);
12521 EVT WidenedIntVT = EVT::getIntegerVT(*DAG.getContext(),
12522 WidenedStoreVT.getStoreSizeInBits());
12523 SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenedIntVT, IntVData);
12524 return DAG.getNode(ISD::BITCAST, DL, WidenedStoreVT, ZExt);
12525 }
12526
12527 assert(isTypeLegal(StoreVT));
12528 return VData;
12529}
12530
12531static bool isAsyncLDSDMA(Intrinsic::ID Intr) {
12532 switch (Intr) {
12533 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12534 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12535 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12536 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
12537 case Intrinsic::amdgcn_load_async_to_lds:
12538 case Intrinsic::amdgcn_global_load_async_lds:
12539 return true;
12540 }
12541 return false;
12542}
12543
12544SDValue SITargetLowering::LowerINTRINSIC_VOID(SDValue Op,
12545 SelectionDAG &DAG) const {
12546 SDLoc DL(Op);
12547 SDValue Chain = Op.getOperand(0);
12548 unsigned IntrinsicID = Op.getConstantOperandVal(1);
12549
12550 switch (IntrinsicID) {
12551 case Intrinsic::amdgcn_exp_compr: {
12552 SDValue Src0 = Op.getOperand(4);
12553 SDValue Src1 = Op.getOperand(5);
12554 // Hack around illegal type on SI by directly selecting it.
12555 if (isTypeLegal(Src0.getValueType()))
12556 return SDValue();
12557
12558 const ConstantSDNode *Done = cast<ConstantSDNode>(Op.getOperand(6));
12559 SDValue Undef = DAG.getPOISON(MVT::f32);
12560 const SDValue Ops[] = {
12561 Op.getOperand(2), // tgt
12562 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src0), // src0
12563 DAG.getNode(ISD::BITCAST, DL, MVT::f32, Src1), // src1
12564 Undef, // src2
12565 Undef, // src3
12566 Op.getOperand(7), // vm
12567 DAG.getTargetConstant(1, DL, MVT::i1), // compr
12568 Op.getOperand(3), // en
12569 Op.getOperand(0) // Chain
12570 };
12571
12572 unsigned Opc = Done->isZero() ? AMDGPU::EXP : AMDGPU::EXP_DONE;
12573 return SDValue(DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops), 0);
12574 }
12575
12576 case Intrinsic::amdgcn_struct_tbuffer_store:
12577 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
12578 SDValue VData = Op.getOperand(2);
12579 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12580 if (IsD16)
12581 VData = handleD16VData(VData, DAG);
12582 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12583 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12584 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12585 SDValue Ops[] = {
12586 Chain,
12587 VData, // vdata
12588 Rsrc, // rsrc
12589 Op.getOperand(4), // vindex
12590 VOffset, // voffset
12591 SOffset, // soffset
12592 Offset, // offset
12593 Op.getOperand(7), // format
12594 Op.getOperand(8), // cachepolicy, swizzled buffer
12595 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12596 };
12597 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12598 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12599 MemSDNode *M = cast<MemSDNode>(Op);
12600 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12601 M->getMemoryVT(), M->getMemOperand());
12602 }
12603
12604 case Intrinsic::amdgcn_raw_tbuffer_store:
12605 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
12606 SDValue VData = Op.getOperand(2);
12607 bool IsD16 = (VData.getValueType().getScalarSizeInBits() == 16);
12608 if (IsD16)
12609 VData = handleD16VData(VData, DAG);
12610 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12611 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12612 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12613 SDValue Ops[] = {
12614 Chain,
12615 VData, // vdata
12616 Rsrc, // rsrc
12617 DAG.getConstant(0, DL, MVT::i32), // vindex
12618 VOffset, // voffset
12619 SOffset, // soffset
12620 Offset, // offset
12621 Op.getOperand(6), // format
12622 Op.getOperand(7), // cachepolicy, swizzled buffer
12623 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12624 };
12625 unsigned Opc = IsD16 ? AMDGPUISD::TBUFFER_STORE_FORMAT_D16
12626 : AMDGPUISD::TBUFFER_STORE_FORMAT;
12627 MemSDNode *M = cast<MemSDNode>(Op);
12628 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12629 M->getMemoryVT(), M->getMemOperand());
12630 }
12631
12632 case Intrinsic::amdgcn_raw_buffer_store:
12633 case Intrinsic::amdgcn_raw_ptr_buffer_store:
12634 case Intrinsic::amdgcn_raw_buffer_store_format:
12635 case Intrinsic::amdgcn_raw_ptr_buffer_store_format: {
12636 const bool IsFormat =
12637 IntrinsicID == Intrinsic::amdgcn_raw_buffer_store_format ||
12638 IntrinsicID == Intrinsic::amdgcn_raw_ptr_buffer_store_format;
12639
12640 SDValue VData = Op.getOperand(2);
12641 EVT VDataVT = VData.getValueType();
12642 EVT EltType = VDataVT.getScalarType();
12643 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12644
12645 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12646 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12648 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12649 return Chain;
12650 }
12651
12652 if (IsD16) {
12653 VData = handleD16VData(VData, DAG);
12654 VDataVT = VData.getValueType();
12655 }
12656
12657 if (!isTypeLegal(VDataVT)) {
12658 VData =
12659 DAG.getNode(ISD::BITCAST, DL,
12660 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12661 }
12662
12663 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12664 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(4), DAG);
12665 auto SOffset = selectSOffset(Op.getOperand(5), DAG, Subtarget);
12666 SDValue Ops[] = {
12667 Chain,
12668 VData,
12669 Rsrc,
12670 DAG.getConstant(0, DL, MVT::i32), // vindex
12671 VOffset, // voffset
12672 SOffset, // soffset
12673 Offset, // offset
12674 Op.getOperand(6), // cachepolicy, swizzled buffer
12675 DAG.getTargetConstant(0, DL, MVT::i1), // idxen
12676 };
12677 unsigned Opc =
12678 IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT : AMDGPUISD::BUFFER_STORE;
12679 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12680 MemSDNode *M = cast<MemSDNode>(Op);
12681
12682 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12683 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12684 return handleByteShortBufferStores(DAG, VDataVT, DL, Ops, M);
12685
12686 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12687 M->getMemoryVT(), M->getMemOperand());
12688 }
12689
12690 case Intrinsic::amdgcn_struct_buffer_store:
12691 case Intrinsic::amdgcn_struct_ptr_buffer_store:
12692 case Intrinsic::amdgcn_struct_buffer_store_format:
12693 case Intrinsic::amdgcn_struct_ptr_buffer_store_format: {
12694 const bool IsFormat =
12695 IntrinsicID == Intrinsic::amdgcn_struct_buffer_store_format ||
12696 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_store_format;
12697
12698 SDValue VData = Op.getOperand(2);
12699 EVT VDataVT = VData.getValueType();
12700 EVT EltType = VDataVT.getScalarType();
12701 bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
12702
12703 if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
12704 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
12706 "unsupported sub-dword format buffer store", DL.getDebugLoc()));
12707 return Chain;
12708 }
12709
12710 if (IsD16) {
12711 VData = handleD16VData(VData, DAG);
12712 VDataVT = VData.getValueType();
12713 }
12714
12715 if (!isTypeLegal(VDataVT)) {
12716 VData =
12717 DAG.getNode(ISD::BITCAST, DL,
12718 getEquivalentMemType(*DAG.getContext(), VDataVT), VData);
12719 }
12720
12721 auto Rsrc = bufferRsrcPtrToVector(Op.getOperand(3), DAG);
12722 auto [VOffset, Offset] = splitBufferOffsets(Op.getOperand(5), DAG);
12723 auto SOffset = selectSOffset(Op.getOperand(6), DAG, Subtarget);
12724 SDValue Ops[] = {
12725 Chain,
12726 VData,
12727 Rsrc,
12728 Op.getOperand(4), // vindex
12729 VOffset, // voffset
12730 SOffset, // soffset
12731 Offset, // offset
12732 Op.getOperand(7), // cachepolicy, swizzled buffer
12733 DAG.getTargetConstant(1, DL, MVT::i1), // idxen
12734 };
12735 unsigned Opc =
12736 !IsFormat ? AMDGPUISD::BUFFER_STORE : AMDGPUISD::BUFFER_STORE_FORMAT;
12737 Opc = IsD16 ? AMDGPUISD::BUFFER_STORE_FORMAT_D16 : Opc;
12738 MemSDNode *M = cast<MemSDNode>(Op);
12739
12740 // Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
12741 EVT VDataType = VData.getValueType().getScalarType();
12742 if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
12743 return handleByteShortBufferStores(DAG, VDataType, DL, Ops, M);
12744
12745 return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
12746 M->getMemoryVT(), M->getMemOperand());
12747 }
12748 case Intrinsic::amdgcn_raw_buffer_load_lds:
12749 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
12750 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
12751 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
12752 case Intrinsic::amdgcn_struct_buffer_load_lds:
12753 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
12754 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
12755 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
12756 unsigned Opc;
12757 bool HasVIndex =
12758 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_lds ||
12759 IntrinsicID == Intrinsic::amdgcn_struct_buffer_load_async_lds ||
12760 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_lds ||
12761 IntrinsicID == Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds;
12762 unsigned OpOffset = HasVIndex ? 1 : 0;
12763 SDValue VOffset = Op.getOperand(5 + OpOffset);
12764 bool HasVOffset = !isNullConstant(VOffset);
12765 unsigned Size = Op->getConstantOperandVal(4);
12766
12767 switch (Size) {
12768 default:
12769 return SDValue();
12770 case 1:
12771 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
12772 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
12773 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
12774 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
12775 break;
12776 case 2:
12777 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
12778 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
12779 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
12780 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
12781 break;
12782 case 4:
12783 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
12784 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
12785 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
12786 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
12787 break;
12788 case 12:
12789 if (!Subtarget->hasLDSLoadB96_B128())
12790 return SDValue();
12791 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
12792 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
12793 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
12794 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
12795 break;
12796 case 16:
12797 if (!Subtarget->hasLDSLoadB96_B128())
12798 return SDValue();
12799 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
12800 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
12801 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
12802 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
12803 break;
12804 }
12805
12806 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
12807
12809
12810 if (HasVIndex && HasVOffset)
12811 Ops.push_back(DAG.getBuildVector(MVT::v2i32, DL,
12812 {Op.getOperand(5), // VIndex
12813 VOffset}));
12814 else if (HasVIndex)
12815 Ops.push_back(Op.getOperand(5));
12816 else if (HasVOffset)
12817 Ops.push_back(VOffset);
12818
12819 SDValue Rsrc = bufferRsrcPtrToVector(Op.getOperand(2), DAG);
12820 Ops.push_back(Rsrc);
12821 Ops.push_back(Op.getOperand(6 + OpOffset)); // soffset
12822 Ops.push_back(Op.getOperand(7 + OpOffset)); // imm offset
12823 bool IsGFX12Plus = AMDGPU::isGFX12Plus(*Subtarget);
12824 unsigned Aux = Op.getConstantOperandVal(8 + OpOffset);
12825 Ops.push_back(DAG.getTargetConstant(
12826 Aux & (IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12),
12827 DL, MVT::i8)); // cpol
12828 Ops.push_back(DAG.getTargetConstant(
12829 Aux & (IsGFX12Plus ? AMDGPU::CPol::SWZ : AMDGPU::CPol::SWZ_pregfx12)
12830 ? 1
12831 : 0,
12832 DL, MVT::i8)); // swz
12833 Ops.push_back(
12834 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
12835 Ops.push_back(M0Val.getValue(0)); // Chain
12836 Ops.push_back(M0Val.getValue(1)); // Glue
12837
12838 auto *M = cast<MemSDNode>(Op);
12839 auto *Load = DAG.getMachineNode(Opc, DL, M->getVTList(), Ops);
12840 DAG.setNodeMemRefs(Load, M->memoperands());
12841
12842 return SDValue(Load, 0);
12843 }
12844 // Buffers are handled by LowerBufferFatPointers, and we're going to go
12845 // for "trust me" that the remaining cases are global pointers until
12846 // such time as we can put two mem operands on an intrinsic.
12847 case Intrinsic::amdgcn_load_to_lds:
12848 case Intrinsic::amdgcn_load_async_to_lds:
12849 case Intrinsic::amdgcn_global_load_lds:
12850 case Intrinsic::amdgcn_global_load_async_lds: {
12851 if (!Subtarget->hasVMemToLDSLoad())
12852 return SDValue();
12853
12854 unsigned Opc;
12855 unsigned Size = Op->getConstantOperandVal(4);
12856 switch (Size) {
12857 default:
12858 return SDValue();
12859 case 1:
12860 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
12861 break;
12862 case 2:
12863 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
12864 break;
12865 case 4:
12866 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
12867 break;
12868 case 12:
12869 if (!Subtarget->hasLDSLoadB96_B128())
12870 return SDValue();
12871 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
12872 break;
12873 case 16:
12874 if (!Subtarget->hasLDSLoadB96_B128())
12875 return SDValue();
12876 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
12877 break;
12878 }
12879
12880 SDValue M0Val = copyToM0(DAG, Chain, DL, Op.getOperand(3));
12881
12883
12884 SDValue Addr = Op.getOperand(2); // Global ptr
12885 SDValue VOffset;
12886 // Try to split SAddr and VOffset. Global and LDS pointers share the same
12887 // immediate offset, so we cannot use a regular SelectGlobalSAddr().
12888 if (Addr->isDivergent() && Addr->isAnyAdd()) {
12889 SDValue LHS = Addr.getOperand(0);
12890 SDValue RHS = Addr.getOperand(1);
12891
12892 if (LHS->isDivergent())
12893 std::swap(LHS, RHS);
12894
12895 if (!LHS->isDivergent() && RHS.getOpcode() == ISD::ZERO_EXTEND &&
12896 RHS.getOperand(0).getValueType() == MVT::i32) {
12897 // add (i64 sgpr), (zero_extend (i32 vgpr))
12898 Addr = LHS;
12899 VOffset = RHS.getOperand(0);
12900 }
12901 }
12902
12903 Ops.push_back(Addr);
12904 if (!Addr->isDivergent()) {
12906 if (!VOffset)
12907 VOffset =
12908 SDValue(DAG.getMachineNode(AMDGPU::V_MOV_B32_e32, DL, MVT::i32,
12909 DAG.getTargetConstant(0, DL, MVT::i32)),
12910 0);
12911 Ops.push_back(VOffset);
12912 }
12913
12914 Ops.push_back(Op.getOperand(5)); // Offset
12915
12916 unsigned Aux = Op.getConstantOperandVal(6);
12917 Ops.push_back(DAG.getTargetConstant(Aux & ~AMDGPU::CPol::VIRTUAL_BITS, DL,
12918 MVT::i32)); // CPol
12919 Ops.push_back(
12920 DAG.getTargetConstant(isAsyncLDSDMA(IntrinsicID), DL, MVT::i8));
12921
12922 Ops.push_back(M0Val.getValue(0)); // Chain
12923 Ops.push_back(M0Val.getValue(1)); // Glue
12924
12925 auto *M = cast<MemSDNode>(Op);
12926 auto *Load = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
12927 DAG.setNodeMemRefs(Load, M->memoperands());
12928
12929 return SDValue(Load, 0);
12930 }
12931 case Intrinsic::amdgcn_end_cf:
12932 return SDValue(DAG.getMachineNode(AMDGPU::SI_END_CF, DL, MVT::Other,
12933 Op->getOperand(2), Chain),
12934 0);
12935 case Intrinsic::amdgcn_s_barrier_signal_var: {
12936 // Member count of 0 means to re-use a previous member count,
12937 // which, if the named barrier is statically chosen, means we can use
12938 // the immarg form. Otherwisee, fall through to constructiong M0 as for
12939 // s_barrier_init.
12940 SDValue CntOp = Op->getOperand(3);
12941 auto *CntC = dyn_cast<ConstantSDNode>(CntOp);
12942 if (CntC && CntC->isZero()) {
12943 SDValue Chain = Op->getOperand(0);
12944 SDValue BarOp = Op->getOperand(2);
12946
12947 std::optional<uint64_t> BarVal;
12948 if (auto *C = dyn_cast<ConstantSDNode>(BarOp))
12949 BarVal = C->getZExtValue();
12950 else if (auto *GA = dyn_cast<GlobalAddressSDNode>(BarOp))
12952 *GA->getGlobal()))
12953 BarVal = *Addr + GA->getOffset();
12954
12955 if (BarVal) {
12956 unsigned BarID = (*BarVal >> 4) & 0x3F;
12957 Ops.push_back(DAG.getTargetConstant(BarID, DL, MVT::i32));
12958 Ops.push_back(Chain);
12959 auto *NewMI = DAG.getMachineNode(AMDGPU::S_BARRIER_SIGNAL_IMM, DL,
12960 Op->getVTList(), Ops);
12961 return SDValue(NewMI, 0);
12962 }
12963 }
12964 [[fallthrough]];
12965 }
12966 case Intrinsic::amdgcn_s_barrier_init: {
12967 // these two intrinsics have two operands: barrier pointer and member count
12968 SDValue Chain = Op->getOperand(0);
12970 SDValue BarOp = Op->getOperand(2);
12971 SDValue CntOp = Op->getOperand(3);
12972 SDValue M0Val;
12973 unsigned Opc = IntrinsicID == Intrinsic::amdgcn_s_barrier_init
12974 ? AMDGPU::S_BARRIER_INIT_M0
12975 : AMDGPU::S_BARRIER_SIGNAL_M0;
12976 // extract the BarrierID from bits 4-9 of BarOp
12977 SDValue BarID;
12978 BarID = DAG.getNode(ISD::SRL, DL, MVT::i32, BarOp,
12979 DAG.getShiftAmountConstant(4, MVT::i32, DL));
12980 BarID = DAG.getNode(ISD::AND, DL, MVT::i32, BarID,
12981 DAG.getConstant(0x3F, DL, MVT::i32));
12982 // Member count should be put into M0[ShAmt:+6]
12983 // Barrier ID should be put into M0[5:0]
12984 SDValue MemberCnt = DAG.getNode(ISD::AND, DL, MVT::i32, CntOp,
12985 DAG.getConstant(0x3F, DL, MVT::i32));
12986 constexpr unsigned ShAmt = 16;
12987 M0Val = DAG.getNode(ISD::SHL, DL, MVT::i32, MemberCnt,
12988 DAG.getShiftAmountConstant(ShAmt, MVT::i32, DL));
12989
12990 M0Val = DAG.getNode(ISD::OR, DL, MVT::i32, M0Val, BarID);
12991
12992 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
12993
12994 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
12995 return SDValue(NewMI, 0);
12996 }
12997 case Intrinsic::amdgcn_s_wakeup_barrier: {
12998 if (!Subtarget->hasSWakeupBarrier())
12999 return SDValue();
13000 [[fallthrough]];
13001 }
13002 case Intrinsic::amdgcn_s_barrier_join: {
13003 // these three intrinsics have one operand: barrier pointer
13004 SDValue Chain = Op->getOperand(0);
13006 SDValue BarOp = Op->getOperand(2);
13007 unsigned Opc;
13008
13009 if (isa<ConstantSDNode>(BarOp)) {
13010 uint64_t BarVal = cast<ConstantSDNode>(BarOp)->getZExtValue();
13011 switch (IntrinsicID) {
13012 default:
13013 return SDValue();
13014 case Intrinsic::amdgcn_s_barrier_join:
13015 Opc = AMDGPU::S_BARRIER_JOIN_IMM;
13016 break;
13017 case Intrinsic::amdgcn_s_wakeup_barrier:
13018 Opc = AMDGPU::S_WAKEUP_BARRIER_IMM;
13019 break;
13020 }
13021 // extract the BarrierID from bits 4-9 of the immediate
13022 unsigned BarID = (BarVal >> 4) & 0x3F;
13023 SDValue K = DAG.getTargetConstant(BarID, DL, MVT::i32);
13024 Ops.push_back(K);
13025 Ops.push_back(Chain);
13026 } else {
13027 switch (IntrinsicID) {
13028 default:
13029 return SDValue();
13030 case Intrinsic::amdgcn_s_barrier_join:
13031 Opc = AMDGPU::S_BARRIER_JOIN_M0;
13032 break;
13033 case Intrinsic::amdgcn_s_wakeup_barrier:
13034 Opc = AMDGPU::S_WAKEUP_BARRIER_M0;
13035 break;
13036 }
13037 // extract the BarrierID from bits 4-9 of BarOp, copy to M0[5:0]
13038 SDValue M0Val;
13039 M0Val = DAG.getNode(ISD::SRL, DL, MVT::i32, BarOp,
13040 DAG.getShiftAmountConstant(4, MVT::i32, DL));
13041 M0Val = DAG.getNode(ISD::AND, DL, MVT::i32, M0Val,
13042 DAG.getConstant(0x3F, DL, MVT::i32));
13043 Ops.push_back(copyToM0(DAG, Chain, DL, M0Val).getValue(0));
13044 }
13045
13046 auto *NewMI = DAG.getMachineNode(Opc, DL, Op->getVTList(), Ops);
13047 return SDValue(NewMI, 0);
13048 }
13049 case Intrinsic::amdgcn_s_prefetch_data:
13050 case Intrinsic::amdgcn_s_prefetch_inst: {
13051 // For non-global address space preserve the chain and remove the call.
13053 return Op.getOperand(0);
13054 return Op;
13055 }
13056 case Intrinsic::amdgcn_s_buffer_prefetch_data: {
13057 SDValue Ops[] = {
13058 Chain, bufferRsrcPtrToVector(Op.getOperand(2), DAG),
13059 Op.getOperand(3), // offset
13060 Op.getOperand(4), // length
13061 };
13062
13063 MemSDNode *M = cast<MemSDNode>(Op);
13064 return DAG.getMemIntrinsicNode(AMDGPUISD::SBUFFER_PREFETCH_DATA, DL,
13065 Op->getVTList(), Ops, M->getMemoryVT(),
13066 M->getMemOperand());
13067 }
13068 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
13069 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
13070 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
13071 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13072 SDValue Chain = Op->getOperand(0);
13073 SDValue Ptr = Op->getOperand(2);
13074 SDValue Val = Op->getOperand(3);
13075 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MII->getMemoryVT(), Chain, Val,
13076 Ptr, MII->getMemOperand());
13077 }
13078 case Intrinsic::amdgcn_av_store_b128: {
13079 MemIntrinsicSDNode *MII = cast<MemIntrinsicSDNode>(Op);
13080 SDValue Chain = Op->getOperand(0);
13081 SDValue Ptr = Op->getOperand(2);
13082 SDValue Val = Op->getOperand(3);
13083 return DAG.getStore(Chain, DL, Val, Ptr, MII->getMemOperand());
13084 }
13085 default: {
13086 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
13088 return lowerImage(Op, ImageDimIntr, DAG, true);
13089
13090 return Op;
13091 }
13092 }
13093}
13094
13095// Return whether the operation has NoUnsignedWrap property.
13096static bool isNoUnsignedWrap(SDValue Addr) {
13097 return (Addr.getOpcode() == ISD::ADD &&
13098 Addr->getFlags().hasNoUnsignedWrap()) ||
13099 Addr->getOpcode() == ISD::OR;
13100}
13101
13103 EVT PtrVT) const {
13104 return PtrVT == MVT::i64;
13105}
13106
13108 EVT PtrVT) const {
13109 return true;
13110}
13111
13112// The raw.(t)buffer and struct.(t)buffer intrinsics have two offset args:
13113// offset (the offset that is included in bounds checking and swizzling, to be
13114// split between the instruction's voffset and immoffset fields) and soffset
13115// (the offset that is excluded from bounds checking and swizzling, to go in
13116// the instruction's soffset field). This function takes the first kind of
13117// offset and figures out how to split it between voffset and immoffset.
13118std::pair<SDValue, SDValue>
13119SITargetLowering::splitBufferOffsets(SDValue Offset, SelectionDAG &DAG) const {
13120 SDLoc DL(Offset);
13121 const unsigned MaxImm = SIInstrInfo::getMaxMUBUFImmOffset(*Subtarget);
13122 SDValue N0 = Offset;
13123 ConstantSDNode *C1 = nullptr;
13124
13125 if ((C1 = dyn_cast<ConstantSDNode>(N0)))
13126 N0 = SDValue();
13127 else if (DAG.isBaseWithConstantOffset(N0)) {
13128 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13129 // being added, so we can only safely match a 32-bit addition with no
13130 // unsigned overflow.
13131 bool CheckNUW = Subtarget->hasGFX1250Insts();
13132 if (!CheckNUW || isNoUnsignedWrap(N0)) {
13133 C1 = cast<ConstantSDNode>(N0.getOperand(1));
13134 N0 = N0.getOperand(0);
13135 }
13136 }
13137
13138 if (C1) {
13139 unsigned ImmOffset = C1->getZExtValue();
13140 // If the immediate value is too big for the immoffset field, put only bits
13141 // that would normally fit in the immoffset field. The remaining value that
13142 // is copied/added for the voffset field is a large power of 2, and it
13143 // stands more chance of being CSEd with the copy/add for another similar
13144 // load/store.
13145 // However, do not do that rounding down if that is a negative
13146 // number, as it appears to be illegal to have a negative offset in the
13147 // vgpr, even if adding the immediate offset makes it positive.
13148 unsigned Overflow = ImmOffset & ~MaxImm;
13149 ImmOffset -= Overflow;
13150 if ((int32_t)Overflow < 0) {
13151 Overflow += ImmOffset;
13152 ImmOffset = 0;
13153 }
13154 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(ImmOffset, DL, MVT::i32));
13155 if (Overflow) {
13156 auto OverflowVal = DAG.getConstant(Overflow, DL, MVT::i32);
13157 if (!N0)
13158 N0 = OverflowVal;
13159 else {
13160 SDValue Ops[] = {N0, OverflowVal};
13161 N0 = DAG.getNode(ISD::ADD, DL, MVT::i32, Ops);
13162 }
13163 }
13164 }
13165 if (!N0)
13166 N0 = DAG.getConstant(0, DL, MVT::i32);
13167 if (!C1)
13168 C1 = cast<ConstantSDNode>(DAG.getTargetConstant(0, DL, MVT::i32));
13169 return {N0, SDValue(C1, 0)};
13170}
13171
13172// Analyze a combined offset from an amdgcn_s_buffer_load intrinsic and store
13173// the three offsets (voffset, soffset and instoffset) into the SDValue[3] array
13174// pointed to by Offsets.
13175void SITargetLowering::setBufferOffsets(SDValue CombinedOffset,
13176 SelectionDAG &DAG, SDValue *Offsets,
13177 Align Alignment) const {
13178 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
13179 SDLoc DL(CombinedOffset);
13180 if (auto *C = dyn_cast<ConstantSDNode>(CombinedOffset)) {
13181 uint32_t Imm = C->getZExtValue();
13182 uint32_t SOffset, ImmOffset;
13183 if (TII->splitMUBUFOffset(Imm, SOffset, ImmOffset, Alignment)) {
13184 Offsets[0] = DAG.getConstant(0, DL, MVT::i32);
13185 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13186 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13187 return;
13188 }
13189 }
13190 if (DAG.isBaseWithConstantOffset(CombinedOffset)) {
13191 // On GFX1250+, voffset and immoffset are zero-extended from 32 bits before
13192 // being added, so we can only safely match a 32-bit addition with no
13193 // unsigned overflow.
13194 bool CheckNUW = Subtarget->hasGFX1250Insts();
13195 SDValue N0 = CombinedOffset.getOperand(0);
13196 SDValue N1 = CombinedOffset.getOperand(1);
13197 uint32_t SOffset, ImmOffset;
13198 int Offset = cast<ConstantSDNode>(N1)->getSExtValue();
13199 if (Offset >= 0 && (!CheckNUW || isNoUnsignedWrap(CombinedOffset)) &&
13200 TII->splitMUBUFOffset(Offset, SOffset, ImmOffset, Alignment)) {
13201 Offsets[0] = N0;
13202 Offsets[1] = DAG.getConstant(SOffset, DL, MVT::i32);
13203 Offsets[2] = DAG.getTargetConstant(ImmOffset, DL, MVT::i32);
13204 return;
13205 }
13206 }
13207
13208 SDValue SOffsetZero = Subtarget->hasRestrictedSOffset()
13209 ? DAG.getRegister(AMDGPU::SGPR_NULL, MVT::i32)
13210 : DAG.getConstant(0, DL, MVT::i32);
13211
13212 Offsets[0] = CombinedOffset;
13213 Offsets[1] = SOffsetZero;
13214 Offsets[2] = DAG.getTargetConstant(0, DL, MVT::i32);
13215}
13216
13217SDValue SITargetLowering::bufferRsrcPtrToVector(SDValue MaybePointer,
13218 SelectionDAG &DAG) const {
13219 if (!MaybePointer.getValueType().isScalarInteger())
13220 return MaybePointer;
13221
13222 SDValue Rsrc = DAG.getBitcast(MVT::v4i32, MaybePointer);
13223 return Rsrc;
13224}
13225
13226// Wrap a global or flat pointer into a buffer intrinsic using the flags
13227// specified in the intrinsic.
13228SDValue SITargetLowering::lowerPointerAsRsrcIntrin(SDNode *Op,
13229 SelectionDAG &DAG) const {
13230 SDLoc Loc(Op);
13231
13232 SDValue Pointer = Op->getOperand(1);
13233 SDValue Stride = Op->getOperand(2);
13234 SDValue NumRecords = Op->getOperand(3);
13235 SDValue Flags = Op->getOperand(4);
13236
13237 SDValue ExtStride = DAG.getAnyExtOrTrunc(Stride, Loc, MVT::i32);
13238 SDValue Rsrc;
13239
13240 if (Subtarget->has45BitNumRecordsBufferResource()) {
13241 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i64);
13242 NumRecords = DAG.getNode(ISD::AND, Loc, MVT::i64, NumRecords,
13243 DAG.getConstant((1ULL << 45) - 1, Loc, MVT::i64));
13244 SDValue Zero = DAG.getConstant(0, Loc, MVT::i32);
13245 // Build the lower 64-bit value, which has a 57-bit base and the lower 7-bit
13246 // num_records.
13247 SDValue ExtPointer = DAG.getAnyExtOrTrunc(Pointer, Loc, MVT::i64);
13248 SDValue NumRecordsLHS =
13249 DAG.getNode(ISD::SHL, Loc, MVT::i64, NumRecords,
13250 DAG.getShiftAmountConstant(57, MVT::i32, Loc));
13251 SDValue LowHalf =
13252 DAG.getNode(ISD::OR, Loc, MVT::i64, ExtPointer, NumRecordsLHS);
13253
13254 // Build the higher 64-bit value, which has the higher 38-bit num_records,
13255 // 6-bit zero (omit), 16-bit stride and scale and 4-bit flag.
13256 SDValue NumRecordsRHS =
13257 DAG.getNode(ISD::SRL, Loc, MVT::i64, NumRecords,
13258 DAG.getShiftAmountConstant(7, MVT::i32, Loc));
13259 SDValue ShiftedStride =
13260 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13261 DAG.getShiftAmountConstant(12, MVT::i32, Loc));
13262 SDValue ExtShiftedStrideVec =
13263 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedStride);
13264 SDValue ExtShiftedStride =
13265 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedStrideVec);
13266 SDValue ShiftedFlags =
13267 DAG.getNode(ISD::SHL, Loc, MVT::i32, Flags,
13268 DAG.getShiftAmountConstant(28, MVT::i32, Loc));
13269 SDValue ExtShiftedFlagsVec =
13270 DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i32, Zero, ShiftedFlags);
13271 SDValue ExtShiftedFlags =
13272 DAG.getNode(ISD::BITCAST, Loc, MVT::i64, ExtShiftedFlagsVec);
13273 SDValue CombinedFields =
13274 DAG.getNode(ISD::OR, Loc, MVT::i64, NumRecordsRHS, ExtShiftedStride);
13275 SDValue HighHalf =
13276 DAG.getNode(ISD::OR, Loc, MVT::i64, CombinedFields, ExtShiftedFlags);
13277
13278 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v2i64, LowHalf, HighHalf);
13279 } else {
13280 NumRecords = DAG.getZExtOrTrunc(NumRecords, Loc, MVT::i32);
13281 auto [LowHalf, HighHalf] =
13282 DAG.SplitScalar(Pointer, Loc, MVT::i32, MVT::i32);
13283 SDValue Mask = DAG.getConstant(0x0000ffff, Loc, MVT::i32);
13284 SDValue Masked = DAG.getNode(ISD::AND, Loc, MVT::i32, HighHalf, Mask);
13285 SDValue ShiftedStride =
13286 DAG.getNode(ISD::SHL, Loc, MVT::i32, ExtStride,
13287 DAG.getShiftAmountConstant(16, MVT::i32, Loc));
13288 SDValue NewHighHalf =
13289 DAG.getNode(ISD::OR, Loc, MVT::i32, Masked, ShiftedStride);
13290
13291 Rsrc = DAG.getNode(ISD::BUILD_VECTOR, Loc, MVT::v4i32, LowHalf, NewHighHalf,
13292 NumRecords, Flags);
13293 }
13294
13295 SDValue RsrcPtr = DAG.getNode(ISD::BITCAST, Loc, MVT::i128, Rsrc);
13296 return RsrcPtr;
13297}
13298
13299// Handle 8 bit and 16 bit buffer loads
13300SDValue SITargetLowering::handleByteShortBufferLoads(SelectionDAG &DAG,
13301 EVT LoadVT, SDLoc DL,
13303 MachineMemOperand *MMO,
13304 bool IsTFE) const {
13305 EVT IntVT = LoadVT.changeTypeToInteger();
13306
13307 if (IsTFE) {
13308 unsigned Opc = (LoadVT.getScalarType() == MVT::i8)
13309 ? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
13310 : AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
13312 MachineMemOperand *OpMMO = MF.getMachineMemOperand(MMO, 0, 8);
13313 SDVTList VTs = DAG.getVTList(MVT::v2i32, MVT::Other);
13314 SDValue Op = getMemIntrinsicNode(Opc, DL, VTs, Ops, MVT::v2i32, OpMMO, DAG);
13315 SDValue Status = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13316 DAG.getConstant(1, DL, MVT::i32));
13317 SDValue Data = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Op,
13318 DAG.getConstant(0, DL, MVT::i32));
13319 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, IntVT, Data);
13320 SDValue Value = DAG.getNode(ISD::BITCAST, DL, LoadVT, Trunc);
13321 return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
13322 }
13323
13324 unsigned Opc = LoadVT.getScalarType() == MVT::i8
13325 ? AMDGPUISD::BUFFER_LOAD_UBYTE
13326 : AMDGPUISD::BUFFER_LOAD_USHORT;
13327
13328 SDVTList ResList = DAG.getVTList(MVT::i32, MVT::Other);
13329 SDValue BufferLoad =
13330 DAG.getMemIntrinsicNode(Opc, DL, ResList, Ops, IntVT, MMO);
13331 SDValue LoadVal = DAG.getNode(ISD::TRUNCATE, DL, IntVT, BufferLoad);
13332 LoadVal = DAG.getNode(ISD::BITCAST, DL, LoadVT, LoadVal);
13333
13334 return DAG.getMergeValues({LoadVal, BufferLoad.getValue(1)}, DL);
13335}
13336
13337// Handle 8 bit and 16 bit buffer stores
13338SDValue SITargetLowering::handleByteShortBufferStores(SelectionDAG &DAG,
13339 EVT VDataType, SDLoc DL,
13340 SDValue Ops[],
13341 MemSDNode *M) const {
13342 if (VDataType == MVT::f16 || VDataType == MVT::bf16)
13343 Ops[1] = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Ops[1]);
13344
13345 SDValue BufferStoreExt = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Ops[1]);
13346 Ops[1] = BufferStoreExt;
13347 unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
13348 : AMDGPUISD::BUFFER_STORE_SHORT;
13349 ArrayRef<SDValue> OpsRef = ArrayRef(&Ops[0], 9);
13350 return DAG.getMemIntrinsicNode(Opc, DL, M->getVTList(), OpsRef, VDataType,
13351 M->getMemOperand());
13352}
13353
13355 SDValue Op, const SDLoc &SL, EVT VT) {
13356 if (VT.bitsLT(Op.getValueType()))
13357 return DAG.getNode(ISD::TRUNCATE, SL, VT, Op);
13358
13359 switch (ExtType) {
13360 case ISD::SEXTLOAD:
13361 return DAG.getNode(ISD::SIGN_EXTEND, SL, VT, Op);
13362 case ISD::ZEXTLOAD:
13363 return DAG.getNode(ISD::ZERO_EXTEND, SL, VT, Op);
13364 case ISD::EXTLOAD:
13365 return DAG.getNode(ISD::ANY_EXTEND, SL, VT, Op);
13366 case ISD::NON_EXTLOAD:
13367 return Op;
13368 }
13369
13370 llvm_unreachable("invalid ext type");
13371}
13372
13373// Try to turn 8 and 16-bit scalar loads into SMEM eligible 32-bit loads.
13374// TODO: Skip this on GFX12 which does have scalar sub-dword loads.
13375SDValue SITargetLowering::widenLoad(LoadSDNode *Ld,
13376 DAGCombinerInfo &DCI) const {
13377 SelectionDAG &DAG = DCI.DAG;
13378 if (Ld->getAlign() < Align(4) || Ld->isDivergent())
13379 return SDValue();
13380
13381 // FIXME: Constant loads should all be marked invariant.
13382 unsigned AS = Ld->getAddressSpace();
13383 if (AS != AMDGPUAS::CONSTANT_ADDRESS &&
13385 (AS != AMDGPUAS::GLOBAL_ADDRESS || !Ld->isInvariant()))
13386 return SDValue();
13387
13388 // Don't do this early, since it may interfere with adjacent load merging for
13389 // illegal types. We can avoid losing alignment information for exotic types
13390 // pre-legalize.
13391 EVT MemVT = Ld->getMemoryVT();
13392 if ((MemVT.isSimple() && !DCI.isAfterLegalizeDAG()) ||
13393 MemVT.getSizeInBits() >= 32)
13394 return SDValue();
13395
13396 SDLoc SL(Ld);
13397
13398 assert((!MemVT.isVector() || Ld->getExtensionType() == ISD::NON_EXTLOAD) &&
13399 "unexpected vector extload");
13400
13401 // TODO: Drop only high part of range.
13402 SDValue Ptr = Ld->getBasePtr();
13403 SDValue NewLoad = DAG.getLoad(
13404 ISD::UNINDEXED, ISD::NON_EXTLOAD, MVT::i32, SL, Ld->getChain(), Ptr,
13405 Ld->getOffset(), Ld->getPointerInfo(), MVT::i32, Ld->getAlign(),
13406 Ld->getMemOperand()->getFlags(), Ld->getAAInfo()); // Drop ranges
13407
13408 EVT TruncVT = EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits());
13409 if (MemVT.isFloatingPoint()) {
13411 "unexpected fp extload");
13412 TruncVT = MemVT.changeTypeToInteger();
13413 }
13414
13415 SDValue Cvt = NewLoad;
13416 if (Ld->getExtensionType() == ISD::SEXTLOAD) {
13417 Cvt = DAG.getNode(ISD::SIGN_EXTEND_INREG, SL, MVT::i32, NewLoad,
13418 DAG.getValueType(TruncVT));
13419 } else if (Ld->getExtensionType() == ISD::ZEXTLOAD ||
13421 Cvt = DAG.getZeroExtendInReg(NewLoad, SL, TruncVT);
13422 } else {
13424 }
13425
13426 EVT VT = Ld->getValueType(0);
13427 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
13428
13429 DCI.AddToWorklist(Cvt.getNode());
13430
13431 // We may need to handle exotic cases, such as i16->i64 extloads, so insert
13432 // the appropriate extension from the 32-bit load.
13433 Cvt = getLoadExtOrTrunc(DAG, Ld->getExtensionType(), Cvt, SL, IntVT);
13434 DCI.AddToWorklist(Cvt.getNode());
13435
13436 // Handle conversion back to floating point if necessary.
13437 Cvt = DAG.getNode(ISD::BITCAST, SL, VT, Cvt);
13438
13439 return DAG.getMergeValues({Cvt, NewLoad.getValue(1)}, SL);
13440}
13441
13443 const SIMachineFunctionInfo &Info) {
13444 // TODO: Should check if the address can definitely not access stack.
13445 if (Info.isEntryFunction())
13446 return Info.getUserSGPRInfo().hasFlatScratchInit();
13447 return true;
13448}
13449
13450SDValue SITargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
13451 SDLoc DL(Op);
13452 LoadSDNode *Load = cast<LoadSDNode>(Op);
13453 ISD::LoadExtType ExtType = Load->getExtensionType();
13454 EVT MemVT = Load->getMemoryVT();
13455 MachineMemOperand *MMO = Load->getMemOperand();
13456
13457 if (ExtType == ISD::NON_EXTLOAD && MemVT.getSizeInBits() < 32) {
13458 if (MemVT == MVT::i16 && isTypeLegal(MVT::i16))
13459 return SDValue();
13460
13461 // FIXME: Copied from PPC
13462 // First, load into 32 bits, then truncate to 1 bit.
13463
13464 SDValue Chain = Load->getChain();
13465 SDValue BasePtr = Load->getBasePtr();
13466
13467 EVT RealMemVT = (MemVT == MVT::i1) ? MVT::i8 : MVT::i16;
13468
13469 SDValue NewLD = DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, BasePtr,
13470 RealMemVT, MMO);
13471
13472 if (!MemVT.isVector()) {
13473 SDValue Ops[] = {DAG.getNode(ISD::TRUNCATE, DL, MemVT, NewLD),
13474 NewLD.getValue(1)};
13475
13476 return DAG.getMergeValues(Ops, DL);
13477 }
13478
13480 for (unsigned I = 0, N = MemVT.getVectorNumElements(); I != N; ++I) {
13481 SDValue Elt = DAG.getNode(ISD::SRL, DL, MVT::i32, NewLD,
13482 DAG.getConstant(I, DL, MVT::i32));
13483
13484 Elts.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Elt));
13485 }
13486
13487 SDValue Ops[] = {DAG.getBuildVector(MemVT, DL, Elts), NewLD.getValue(1)};
13488
13489 return DAG.getMergeValues(Ops, DL);
13490 }
13491
13492 if (!MemVT.isVector())
13493 return SDValue();
13494
13495 assert(Op.getValueType().getVectorElementType() == MVT::i32 &&
13496 "Custom lowering for non-i32 vectors hasn't been implemented.");
13497
13498 Align Alignment = Load->getAlign();
13499 unsigned AS = Load->getAddressSpace();
13500 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
13501 AS == AMDGPUAS::FLAT_ADDRESS &&
13502 Alignment.value() < MemVT.getStoreSize() && MemVT.getSizeInBits() > 32) {
13503 return SplitVectorLoad(Op, DAG);
13504 }
13505
13507 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
13508 // If there is a possibility that flat instruction access scratch memory
13509 // then we need to use the same legalization rules we use for private.
13510 if (AS == AMDGPUAS::FLAT_ADDRESS &&
13511 !Subtarget->hasMultiDwordFlatScratchAddressing())
13512 AS = addressMayBeAccessedAsPrivate(Load->getMemOperand(), *MFI)
13515
13516 unsigned NumElements = MemVT.getVectorNumElements();
13517
13518 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13520 (AS == AMDGPUAS::GLOBAL_ADDRESS &&
13521 Subtarget->getScalarizeGlobalBehavior() && Load->isSimple() &&
13522 (Load->isInvariant() || isMemOpHasNoClobberedMemOperand(Load)))) {
13523 if ((!Op->isDivergent() || AMDGPU::isUniformMMO(MMO)) &&
13524 Alignment >= Align(4) && NumElements < 32) {
13525 if (MemVT.isPow2VectorType() ||
13526 (Subtarget->hasScalarDwordx3Loads() && NumElements == 3))
13527 return SDValue();
13528 return WidenOrSplitVectorLoad(Op, DAG);
13529 }
13530 // Non-uniform loads will be selected to MUBUF instructions, so they
13531 // have the same legalization requirements as global and private
13532 // loads.
13533 //
13534 }
13535 if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
13538 if (NumElements > 4)
13539 return SplitVectorLoad(Op, DAG);
13540 // v3 loads not supported on SI.
13541 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13542 return WidenOrSplitVectorLoad(Op, DAG);
13543
13544 // v3 and v4 loads are supported for private and global memory.
13545 return SDValue();
13546 }
13547 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
13548 // Depending on the setting of the private_element_size field in the
13549 // resource descriptor, we can only make private accesses up to a certain
13550 // size.
13551 switch (Subtarget->getMaxPrivateElementSize()) {
13552 case 4: {
13553 auto [Op0, Op1] = scalarizeVectorLoad(Load, DAG);
13554 return DAG.getMergeValues({Op0, Op1}, DL);
13555 }
13556 case 8:
13557 if (NumElements > 2)
13558 return SplitVectorLoad(Op, DAG);
13559 return SDValue();
13560 case 16:
13561 // Same as global/flat
13562 if (NumElements > 4)
13563 return SplitVectorLoad(Op, DAG);
13564 // v3 loads not supported on SI.
13565 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
13566 return WidenOrSplitVectorLoad(Op, DAG);
13567
13568 return SDValue();
13569 default:
13570 llvm_unreachable("unsupported private_element_size");
13571 }
13572 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
13573 unsigned Fast = 0;
13574 auto Flags = Load->getMemOperand()->getFlags();
13576 Load->getAlign(), Flags, &Fast) &&
13577 Fast > 1)
13578 return SDValue();
13579
13580 if (MemVT.isVector())
13581 return SplitVectorLoad(Op, DAG);
13582 }
13583
13585 MemVT, *Load->getMemOperand())) {
13586 auto [Op0, Op1] = expandUnalignedLoad(Load, DAG);
13587 return DAG.getMergeValues({Op0, Op1}, DL);
13588 }
13589
13590 return SDValue();
13591}
13592
13593SDValue SITargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
13594 EVT VT = Op.getValueType();
13595 if (VT.getSizeInBits() == 128 || VT.getSizeInBits() == 256 ||
13596 VT.getSizeInBits() == 512)
13597 return splitTernaryVectorOp(Op, DAG);
13598
13599 assert(VT.getSizeInBits() == 64);
13600
13601 SDLoc DL(Op);
13602 SDValue Cond = DAG.getFreeze(Op.getOperand(0));
13603
13604 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
13605 SDValue One = DAG.getConstant(1, DL, MVT::i32);
13606
13607 SDValue LHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(1));
13608 SDValue RHS = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Op.getOperand(2));
13609
13610 SDValue Lo0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, Zero);
13611 SDValue Lo1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, Zero);
13612
13613 SDValue Lo = DAG.getSelect(DL, MVT::i32, Cond, Lo0, Lo1);
13614
13615 SDValue Hi0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, LHS, One);
13616 SDValue Hi1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, RHS, One);
13617
13618 SDValue Hi = DAG.getSelect(DL, MVT::i32, Cond, Hi0, Hi1);
13619
13620 SDValue Res = DAG.getBuildVector(MVT::v2i32, DL, {Lo, Hi});
13621 return DAG.getNode(ISD::BITCAST, DL, VT, Res);
13622}
13623
13624// Catch division cases where we can use shortcuts with rcp and rsq
13625// instructions.
13626SDValue SITargetLowering::lowerFastUnsafeFDIV(SDValue Op,
13627 SelectionDAG &DAG) const {
13628 SDLoc SL(Op);
13629 SDValue LHS = Op.getOperand(0);
13630 SDValue RHS = Op.getOperand(1);
13631 EVT VT = Op.getValueType();
13632 const SDNodeFlags Flags = Op->getFlags();
13633
13634 bool AllowInaccurateRcp = Flags.hasApproximateFuncs();
13635
13636 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
13637 // Without !fpmath accuracy information, we can't do more because we don't
13638 // know exactly whether rcp is accurate enough to meet !fpmath requirement.
13639 // f16 is always accurate enough
13640 if (!AllowInaccurateRcp && VT != MVT::f16 && VT != MVT::bf16)
13641 return SDValue();
13642
13643 if (CLHS->isOne()) {
13644 // v_rcp_f32 and v_rsq_f32 do not support denormals, and according to
13645 // the CI documentation has a worst case error of 1 ulp.
13646 // OpenCL requires <= 2.5 ulp for 1.0 / x, so it should always be OK to
13647 // use it as long as we aren't trying to use denormals.
13648 //
13649 // v_rcp_f16 and v_rsq_f16 DO support denormals and 0.51ulp.
13650
13651 // 1.0 / sqrt(x) -> rsq(x)
13652
13653 // XXX - Is afn sufficient to do this for f64? The maximum ULP
13654 // error seems really high at 2^29 ULP.
13655 // 1.0 / x -> rcp(x)
13656 return DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13657 }
13658
13659 // Same as for 1.0, but expand the sign out of the constant.
13660 if (CLHS->isMinusOne()) {
13661 // -1.0 / x -> rcp (fneg x)
13662 SDValue FNegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
13663 return DAG.getNode(AMDGPUISD::RCP, SL, VT, FNegRHS);
13664 }
13665 }
13666
13667 // For f16 and bf16 require afn or arcp.
13668 // For f32 require afn.
13669 if (!AllowInaccurateRcp &&
13670 ((VT != MVT::f16 && VT != MVT::bf16) || !Flags.hasAllowReciprocal()))
13671 return SDValue();
13672
13673 // Turn into multiply by the reciprocal.
13674 // x / y -> x * (1.0 / y)
13675 SDValue Recip = DAG.getNode(AMDGPUISD::RCP, SL, VT, RHS);
13676 return DAG.getNode(ISD::FMUL, SL, VT, LHS, Recip, Flags);
13677}
13678
13679SDValue SITargetLowering::lowerFastUnsafeFDIV64(SDValue Op,
13680 SelectionDAG &DAG) const {
13681 SDLoc SL(Op);
13682 SDValue X = Op.getOperand(0);
13683 SDValue Y = Op.getOperand(1);
13684 EVT VT = Op.getValueType();
13685 const SDNodeFlags Flags = Op->getFlags();
13686
13687 bool AllowInaccurateDiv = Flags.hasApproximateFuncs();
13688 if (!AllowInaccurateDiv)
13689 return SDValue();
13690
13691 const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(X);
13692 bool IsNegRcp = CLHS && CLHS->isMinusOne();
13693
13694 // Pull out the negation so it folds for free into the source modifiers.
13695 if (IsNegRcp)
13696 X = DAG.getConstantFP(1.0, SL, VT);
13697
13698 SDValue NegY = IsNegRcp ? Y : DAG.getNode(ISD::FNEG, SL, VT, Y);
13699 SDValue One = DAG.getConstantFP(1.0, SL, VT);
13700
13701 SDValue R = DAG.getNode(AMDGPUISD::RCP, SL, VT, Y);
13702 if (IsNegRcp)
13703 R = DAG.getNode(ISD::FNEG, SL, VT, R);
13704
13705 SDValue Tmp0 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13706
13707 R = DAG.getNode(ISD::FMA, SL, VT, Tmp0, R, R);
13708 SDValue Tmp1 = DAG.getNode(ISD::FMA, SL, VT, NegY, R, One);
13709 R = DAG.getNode(ISD::FMA, SL, VT, Tmp1, R, R);
13710
13711 // Skip the last 2 correction terms for reciprocal.
13712 if (IsNegRcp || (CLHS && CLHS->isOne()))
13713 return R;
13714
13715 SDValue Ret = DAG.getNode(ISD::FMUL, SL, VT, X, R);
13716 SDValue Tmp2 = DAG.getNode(ISD::FMA, SL, VT, NegY, Ret, X);
13717 return DAG.getNode(ISD::FMA, SL, VT, Tmp2, R, Ret);
13718}
13719
13720static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13721 EVT VT, SDValue A, SDValue B, SDValue GlueChain,
13722 SDNodeFlags Flags) {
13723 if (GlueChain->getNumValues() <= 1) {
13724 return DAG.getNode(Opcode, SL, VT, A, B, Flags);
13725 }
13726
13727 assert(GlueChain->getNumValues() == 3);
13728
13729 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13730 switch (Opcode) {
13731 default:
13732 llvm_unreachable("no chain equivalent for opcode");
13733 case ISD::FMUL:
13734 Opcode = AMDGPUISD::FMUL_W_CHAIN;
13735 break;
13736 }
13737
13738 return DAG.getNode(Opcode, SL, VTList,
13739 {GlueChain.getValue(1), A, B, GlueChain.getValue(2)},
13740 Flags);
13741}
13742
13743static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL,
13744 EVT VT, SDValue A, SDValue B, SDValue C,
13745 SDValue GlueChain, SDNodeFlags Flags) {
13746 if (GlueChain->getNumValues() <= 1) {
13747 return DAG.getNode(Opcode, SL, VT, {A, B, C}, Flags);
13748 }
13749
13750 assert(GlueChain->getNumValues() == 3);
13751
13752 SDVTList VTList = DAG.getVTList(VT, MVT::Other, MVT::Glue);
13753 switch (Opcode) {
13754 default:
13755 llvm_unreachable("no chain equivalent for opcode");
13756 case ISD::FMA:
13757 Opcode = AMDGPUISD::FMA_W_CHAIN;
13758 break;
13759 }
13760
13761 return DAG.getNode(Opcode, SL, VTList,
13762 {GlueChain.getValue(1), A, B, C, GlueChain.getValue(2)},
13763 Flags);
13764}
13765
13766SDValue SITargetLowering::LowerFDIV16(SDValue Op, SelectionDAG &DAG) const {
13767 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
13768 return FastLowered;
13769
13770 SDLoc SL(Op);
13771 EVT VT = Op.getValueType();
13772 SDValue LHS = Op.getOperand(0);
13773 SDValue RHS = Op.getOperand(1);
13774
13775 SDValue LHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, LHS);
13776 SDValue RHSExt = DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, RHS);
13777
13778 if (VT == MVT::bf16) {
13779 SDValue ExtDiv =
13780 DAG.getNode(ISD::FDIV, SL, MVT::f32, LHSExt, RHSExt, Op->getFlags());
13781 return DAG.getNode(ISD::FP_ROUND, SL, MVT::bf16, ExtDiv,
13782 DAG.getTargetConstant(0, SL, MVT::i32));
13783 }
13784
13785 assert(VT == MVT::f16);
13786
13787 // a32.u = opx(V_CVT_F32_F16, a.u); // CVT to F32
13788 // b32.u = opx(V_CVT_F32_F16, b.u); // CVT to F32
13789 // r32.u = opx(V_RCP_F32, b32.u); // rcp = 1 / d
13790 // q32.u = opx(V_MUL_F32, a32.u, r32.u); // q = n * rcp
13791 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
13792 // q32.u = opx(V_MAD_F32, e32.u, r32.u, q32.u); // q = n * rcp
13793 // e32.u = opx(V_MAD_F32, (b32.u^_neg32), q32.u, a32.u); // err = -d * q + n
13794 // tmp.u = opx(V_MUL_F32, e32.u, r32.u);
13795 // tmp.u = opx(V_AND_B32, tmp.u, 0xff800000)
13796 // q32.u = opx(V_ADD_F32, tmp.u, q32.u);
13797 // q16.u = opx(V_CVT_F16_F32, q32.u);
13798 // q16.u = opx(V_DIV_FIXUP_F16, q16.u, b.u, a.u); // q = touchup(q, d, n)
13799
13800 // We will use ISD::FMA on targets that don't support ISD::FMAD.
13801 unsigned FMADOpCode =
13803 SDValue NegRHSExt = DAG.getNode(ISD::FNEG, SL, MVT::f32, RHSExt);
13804 SDValue Rcp =
13805 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, RHSExt, Op->getFlags());
13806 SDValue Quot =
13807 DAG.getNode(ISD::FMUL, SL, MVT::f32, LHSExt, Rcp, Op->getFlags());
13808 SDValue Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13809 Op->getFlags());
13810 Quot = DAG.getNode(FMADOpCode, SL, MVT::f32, Err, Rcp, Quot, Op->getFlags());
13811 Err = DAG.getNode(FMADOpCode, SL, MVT::f32, NegRHSExt, Quot, LHSExt,
13812 Op->getFlags());
13813 SDValue Tmp = DAG.getNode(ISD::FMUL, SL, MVT::f32, Err, Rcp, Op->getFlags());
13814 SDValue TmpCast = DAG.getNode(ISD::BITCAST, SL, MVT::i32, Tmp);
13815 TmpCast = DAG.getNode(ISD::AND, SL, MVT::i32, TmpCast,
13816 DAG.getConstant(0xff800000, SL, MVT::i32));
13817 Tmp = DAG.getNode(ISD::BITCAST, SL, MVT::f32, TmpCast);
13818 Quot = DAG.getNode(ISD::FADD, SL, MVT::f32, Tmp, Quot, Op->getFlags());
13819 SDValue RDst = DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Quot,
13820 DAG.getTargetConstant(0, SL, MVT::i32));
13821 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f16, RDst, RHS, LHS,
13822 Op->getFlags());
13823}
13824
13825// Faster 2.5 ULP division that does not support denormals.
13826SDValue SITargetLowering::lowerFDIV_FAST(SDValue Op, SelectionDAG &DAG) const {
13827 SDNodeFlags Flags = Op->getFlags();
13828 SDLoc SL(Op);
13829 SDValue LHS = Op.getOperand(1);
13830 SDValue RHS = Op.getOperand(2);
13831
13832 // TODO: The combiner should probably handle elimination of redundant fabs.
13834 ? RHS
13835 : DAG.getNode(ISD::FABS, SL, MVT::f32, RHS, Flags);
13836
13837 const APFloat K0Val(0x1p+96f);
13838 const SDValue K0 = DAG.getConstantFP(K0Val, SL, MVT::f32);
13839
13840 const APFloat K1Val(0x1p-32f);
13841 const SDValue K1 = DAG.getConstantFP(K1Val, SL, MVT::f32);
13842
13843 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
13844
13845 EVT SetCCVT =
13846 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
13847
13848 SDValue r2 = DAG.getSetCC(SL, SetCCVT, r1, K0, ISD::SETOGT);
13849
13850 SDValue r3 = DAG.getNode(ISD::SELECT, SL, MVT::f32, r2, K1, One, Flags);
13851
13852 r1 = DAG.getNode(ISD::FMUL, SL, MVT::f32, RHS, r3, Flags);
13853
13854 // rcp does not support denormals.
13855 SDValue r0 = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, r1, Flags);
13856
13857 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f32, LHS, r0, Flags);
13858
13859 return DAG.getNode(ISD::FMUL, SL, MVT::f32, r3, Mul, Flags);
13860}
13861
13862// Returns immediate value for setting the F32 denorm mode when using the
13863// S_DENORM_MODE instruction.
13865 const SIMachineFunctionInfo *Info,
13866 const GCNSubtarget *ST) {
13867 assert(ST->hasDenormModeInst() && "Requires S_DENORM_MODE");
13868 uint32_t DPDenormModeDefault = Info->getMode().fpDenormModeDPValue();
13869 uint32_t Mode = SPDenormMode | (DPDenormModeDefault << 2);
13870 return DAG.getTargetConstant(Mode, SDLoc(), MVT::i32);
13871}
13872
13873SDValue SITargetLowering::LowerFDIV32(SDValue Op, SelectionDAG &DAG) const {
13874 if (SDValue FastLowered = lowerFastUnsafeFDIV(Op, DAG))
13875 return FastLowered;
13876
13877 // The selection matcher assumes anything with a chain selecting to a
13878 // mayRaiseFPException machine instruction. Since we're introducing a chain
13879 // here, we need to explicitly report nofpexcept for the regular fdiv
13880 // lowering.
13881 SDNodeFlags Flags = Op->getFlags();
13882 Flags.setNoFPExcept(true);
13883
13884 SDLoc SL(Op);
13885 SDValue LHS = Op.getOperand(0);
13886 SDValue RHS = Op.getOperand(1);
13887
13888 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
13889
13890 SDVTList ScaleVT = DAG.getVTList(MVT::f32, MVT::i1);
13891
13892 SDValue DenominatorScaled =
13893 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {RHS, RHS, LHS}, Flags);
13894 SDValue NumeratorScaled =
13895 DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, {LHS, RHS, LHS}, Flags);
13896
13897 // Denominator is scaled to not be denormal, so using rcp is ok.
13898 SDValue ApproxRcp =
13899 DAG.getNode(AMDGPUISD::RCP, SL, MVT::f32, DenominatorScaled, Flags);
13900 SDValue NegDivScale0 =
13901 DAG.getNode(ISD::FNEG, SL, MVT::f32, DenominatorScaled, Flags);
13902
13903 using namespace AMDGPU::Hwreg;
13904 const unsigned Denorm32Reg = HwregEncoding::encode(ID_MODE, 4, 2);
13905 const SDValue BitField = DAG.getTargetConstant(Denorm32Reg, SL, MVT::i32);
13906
13907 const MachineFunction &MF = DAG.getMachineFunction();
13908 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
13909 const DenormalMode DenormMode = Info->getMode().FP32Denormals;
13910
13911 const bool PreservesDenormals = DenormMode == DenormalMode::getIEEE();
13912 const bool HasDynamicDenormals =
13913 (DenormMode.Input == DenormalMode::Dynamic) ||
13914 (DenormMode.Output == DenormalMode::Dynamic);
13915
13916 SDValue SavedDenormMode;
13917
13918 if (!PreservesDenormals) {
13919 // Note we can't use the STRICT_FMA/STRICT_FMUL for the non-strict FDIV
13920 // lowering. The chain dependence is insufficient, and we need glue. We do
13921 // not need the glue variants in a strictfp function.
13922
13923 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
13924
13925 SDValue Glue = DAG.getEntryNode();
13926 if (HasDynamicDenormals) {
13927 SDNode *GetReg = DAG.getMachineNode(AMDGPU::S_GETREG_B32, SL,
13928 DAG.getVTList(MVT::i32, MVT::Glue),
13929 {BitField, Glue});
13930 SavedDenormMode = SDValue(GetReg, 0);
13931
13932 Glue = DAG.getMergeValues(
13933 {DAG.getEntryNode(), SDValue(GetReg, 0), SDValue(GetReg, 1)}, SL);
13934 }
13935
13936 SDNode *EnableDenorm;
13937 if (Subtarget->hasDenormModeInst()) {
13938 const SDValue EnableDenormValue =
13939 getSPDenormModeValue(FP_DENORM_FLUSH_NONE, DAG, Info, Subtarget);
13940
13941 EnableDenorm = DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs, Glue,
13942 EnableDenormValue)
13943 .getNode();
13944 } else {
13945 const SDValue EnableDenormValue =
13946 DAG.getConstant(FP_DENORM_FLUSH_NONE, SL, MVT::i32);
13947 EnableDenorm = DAG.getMachineNode(AMDGPU::S_SETREG_B32, SL, BindParamVTs,
13948 {EnableDenormValue, BitField, Glue});
13949 }
13950
13951 SDValue Ops[3] = {NegDivScale0, SDValue(EnableDenorm, 0),
13952 SDValue(EnableDenorm, 1)};
13953
13954 NegDivScale0 = DAG.getMergeValues(Ops, SL);
13955 }
13956
13957 SDValue Fma0 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0,
13958 ApproxRcp, One, NegDivScale0, Flags);
13959
13960 SDValue Fma1 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma0, ApproxRcp,
13961 ApproxRcp, Fma0, Flags);
13962
13963 SDValue Mul = getFPBinOp(DAG, ISD::FMUL, SL, MVT::f32, NumeratorScaled, Fma1,
13964 Fma1, Flags);
13965
13966 SDValue Fma2 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Mul,
13967 NumeratorScaled, Mul, Flags);
13968
13969 SDValue Fma3 =
13970 getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, Fma2, Fma1, Mul, Fma2, Flags);
13971
13972 SDValue Fma4 = getFPTernOp(DAG, ISD::FMA, SL, MVT::f32, NegDivScale0, Fma3,
13973 NumeratorScaled, Fma3, Flags);
13974
13975 if (!PreservesDenormals) {
13976 SDNode *DisableDenorm;
13977 if (!HasDynamicDenormals && Subtarget->hasDenormModeInst()) {
13978 const SDValue DisableDenormValue = getSPDenormModeValue(
13979 FP_DENORM_FLUSH_IN_FLUSH_OUT, DAG, Info, Subtarget);
13980
13981 SDVTList BindParamVTs = DAG.getVTList(MVT::Other, MVT::Glue);
13982 DisableDenorm =
13983 DAG.getNode(AMDGPUISD::DENORM_MODE, SL, BindParamVTs,
13984 Fma4.getValue(1), DisableDenormValue, Fma4.getValue(2))
13985 .getNode();
13986 } else {
13987 assert(HasDynamicDenormals == (bool)SavedDenormMode);
13988 const SDValue DisableDenormValue =
13989 HasDynamicDenormals
13990 ? SavedDenormMode
13991 : DAG.getConstant(FP_DENORM_FLUSH_IN_FLUSH_OUT, SL, MVT::i32);
13992
13993 DisableDenorm = DAG.getMachineNode(
13994 AMDGPU::S_SETREG_B32, SL, MVT::Other,
13995 {DisableDenormValue, BitField, Fma4.getValue(1), Fma4.getValue(2)});
13996 }
13997
13998 SDValue OutputChain = DAG.getNode(ISD::TokenFactor, SL, MVT::Other,
13999 SDValue(DisableDenorm, 0), DAG.getRoot());
14000 DAG.setRoot(OutputChain);
14001 }
14002
14003 SDValue Scale = NumeratorScaled.getValue(1);
14004 SDValue Fmas = DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f32,
14005 {Fma4, Fma1, Fma3, Scale}, Flags);
14006
14007 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f32, Fmas, RHS, LHS, Flags);
14008}
14009
14010SDValue SITargetLowering::LowerFDIV64(SDValue Op, SelectionDAG &DAG) const {
14011 if (SDValue FastLowered = lowerFastUnsafeFDIV64(Op, DAG))
14012 return FastLowered;
14013
14014 SDLoc SL(Op);
14015 SDValue X = Op.getOperand(0);
14016 SDValue Y = Op.getOperand(1);
14017
14018 const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f64);
14019
14020 SDVTList ScaleVT = DAG.getVTList(MVT::f64, MVT::i1);
14021
14022 SDValue DivScale0 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, Y, Y, X);
14023
14024 SDValue NegDivScale0 = DAG.getNode(ISD::FNEG, SL, MVT::f64, DivScale0);
14025
14026 SDValue Rcp = DAG.getNode(AMDGPUISD::RCP, SL, MVT::f64, DivScale0);
14027
14028 SDValue Fma0 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Rcp, One);
14029
14030 SDValue Fma1 = DAG.getNode(ISD::FMA, SL, MVT::f64, Rcp, Fma0, Rcp);
14031
14032 SDValue Fma2 = DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Fma1, One);
14033
14034 SDValue DivScale1 = DAG.getNode(AMDGPUISD::DIV_SCALE, SL, ScaleVT, X, Y, X);
14035
14036 SDValue Fma3 = DAG.getNode(ISD::FMA, SL, MVT::f64, Fma1, Fma2, Fma1);
14037 SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f64, DivScale1, Fma3);
14038
14039 SDValue Fma4 =
14040 DAG.getNode(ISD::FMA, SL, MVT::f64, NegDivScale0, Mul, DivScale1);
14041
14042 SDValue Scale;
14043
14044 if (!Subtarget->hasUsableDivScaleConditionOutput()) {
14045 // Workaround a hardware bug on SI where the condition output from div_scale
14046 // is not usable.
14047
14048 const SDValue Hi = DAG.getConstant(1, SL, MVT::i32);
14049
14050 // Figure out if the scale to use for div_fmas.
14051 SDValue NumBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, X);
14052 SDValue DenBC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Y);
14053 SDValue Scale0BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale0);
14054 SDValue Scale1BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, DivScale1);
14055
14056 SDValue NumHi =
14057 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, NumBC, Hi);
14058 SDValue DenHi =
14059 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, DenBC, Hi);
14060
14061 SDValue Scale0Hi =
14062 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale0BC, Hi);
14063 SDValue Scale1Hi =
14064 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Scale1BC, Hi);
14065
14066 SDValue CmpDen = DAG.getSetCC(SL, MVT::i1, DenHi, Scale0Hi, ISD::SETEQ);
14067 SDValue CmpNum = DAG.getSetCC(SL, MVT::i1, NumHi, Scale1Hi, ISD::SETEQ);
14068 Scale = DAG.getNode(ISD::XOR, SL, MVT::i1, CmpNum, CmpDen);
14069 } else {
14070 Scale = DivScale1.getValue(1);
14071 }
14072
14073 SDValue Fmas =
14074 DAG.getNode(AMDGPUISD::DIV_FMAS, SL, MVT::f64, Fma4, Fma3, Mul, Scale);
14075
14076 return DAG.getNode(AMDGPUISD::DIV_FIXUP, SL, MVT::f64, Fmas, Y, X);
14077}
14078
14079SDValue SITargetLowering::LowerFDIV(SDValue Op, SelectionDAG &DAG) const {
14080 EVT VT = Op.getValueType();
14081
14082 if (VT == MVT::f32)
14083 return LowerFDIV32(Op, DAG);
14084
14085 if (VT == MVT::f64)
14086 return LowerFDIV64(Op, DAG);
14087
14088 if (VT == MVT::f16 || VT == MVT::bf16)
14089 return LowerFDIV16(Op, DAG);
14090
14091 llvm_unreachable("Unexpected type for fdiv");
14092}
14093
14094SDValue SITargetLowering::LowerFFREXP(SDValue Op, SelectionDAG &DAG) const {
14095 SDLoc dl(Op);
14096 SDValue Val = Op.getOperand(0);
14097 EVT VT = Val.getValueType();
14098 EVT ResultExpVT = Op->getValueType(1);
14099 EVT InstrExpVT = VT == MVT::f16 ? MVT::i16 : MVT::i32;
14100
14101 SDValue Mant = DAG.getNode(
14103 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_mant, dl, MVT::i32), Val);
14104
14105 SDValue Exp = DAG.getNode(
14106 ISD::INTRINSIC_WO_CHAIN, dl, InstrExpVT,
14107 DAG.getTargetConstant(Intrinsic::amdgcn_frexp_exp, dl, MVT::i32), Val);
14108
14109 if (Subtarget->hasFractBug()) {
14110 SDValue Fabs = DAG.getNode(ISD::FABS, dl, VT, Val);
14111 SDValue Inf =
14113
14114 SDValue IsFinite = DAG.getSetCC(dl, MVT::i1, Fabs, Inf, ISD::SETOLT);
14115 SDValue Zero = DAG.getConstant(0, dl, InstrExpVT);
14116 Exp = DAG.getNode(ISD::SELECT, dl, InstrExpVT, IsFinite, Exp, Zero);
14117 Mant = DAG.getNode(ISD::SELECT, dl, VT, IsFinite, Mant, Val);
14118 }
14119
14120 SDValue CastExp = DAG.getSExtOrTrunc(Exp, dl, ResultExpVT);
14121 return DAG.getMergeValues({Mant, CastExp}, dl);
14122}
14123
14124SDValue SITargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const {
14125 SDLoc DL(Op);
14126 StoreSDNode *Store = cast<StoreSDNode>(Op);
14127 EVT VT = Store->getMemoryVT();
14128
14129 if (VT == MVT::i1) {
14130 return DAG.getTruncStore(
14131 Store->getChain(), DL,
14132 DAG.getSExtOrTrunc(Store->getValue(), DL, MVT::i32),
14133 Store->getBasePtr(), MVT::i1, Store->getMemOperand());
14134 }
14135
14136 assert(VT.isVector() &&
14137 Store->getValue().getValueType().getScalarType() == MVT::i32);
14138
14139 unsigned AS = Store->getAddressSpace();
14140 if (Subtarget->hasLDSMisalignedBugInWGPMode() &&
14141 AS == AMDGPUAS::FLAT_ADDRESS &&
14142 Store->getAlign().value() < VT.getStoreSize() &&
14143 VT.getSizeInBits() > 32) {
14144 return SplitVectorStore(Op, DAG);
14145 }
14146
14148 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
14149 // If there is a possibility that flat instruction access scratch memory
14150 // then we need to use the same legalization rules we use for private.
14151 if (AS == AMDGPUAS::FLAT_ADDRESS &&
14152 !Subtarget->hasMultiDwordFlatScratchAddressing())
14153 AS = addressMayBeAccessedAsPrivate(Store->getMemOperand(), *MFI)
14156
14157 unsigned NumElements = VT.getVectorNumElements();
14159 if (NumElements > 4)
14160 return SplitVectorStore(Op, DAG);
14161 // v3 stores not supported on SI.
14162 if (NumElements == 3 && !Subtarget->hasDwordx3LoadStores())
14163 return SplitVectorStore(Op, DAG);
14164
14166 VT, *Store->getMemOperand()))
14167 return expandUnalignedStore(Store, DAG);
14168
14169 return SDValue();
14170 }
14171 if (AS == AMDGPUAS::PRIVATE_ADDRESS) {
14172 switch (Subtarget->getMaxPrivateElementSize()) {
14173 case 4:
14174 return scalarizeVectorStore(Store, DAG);
14175 case 8:
14176 if (NumElements > 2)
14177 return SplitVectorStore(Op, DAG);
14178 return SDValue();
14179 case 16:
14180 if (NumElements > 4 ||
14181 (NumElements == 3 && !Subtarget->hasFlatScratchEnabled()))
14182 return SplitVectorStore(Op, DAG);
14183 return SDValue();
14184 default:
14185 llvm_unreachable("unsupported private_element_size");
14186 }
14187 } else if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) {
14188 unsigned Fast = 0;
14189 auto Flags = Store->getMemOperand()->getFlags();
14191 Store->getAlign(), Flags, &Fast) &&
14192 Fast > 1)
14193 return SDValue();
14194
14195 if (VT.isVector())
14196 return SplitVectorStore(Op, DAG);
14197
14198 return expandUnalignedStore(Store, DAG);
14199 }
14200
14201 // Probably an invalid store. If so we'll end up emitting a selection error.
14202 return SDValue();
14203}
14204
14205// Avoid the full correct expansion for f32 sqrt when promoting from f16.
14206SDValue SITargetLowering::lowerFSQRTF16(SDValue Op, SelectionDAG &DAG) const {
14207 SDLoc SL(Op);
14208 assert(!Subtarget->has16BitInsts());
14209 SDNodeFlags Flags = Op->getFlags();
14210 SDValue Ext =
14211 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, Op.getOperand(0), Flags);
14212
14213 SDValue SqrtID = DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, SL, MVT::i32);
14214 SDValue Sqrt =
14215 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::f32, SqrtID, Ext, Flags);
14216
14217 return DAG.getNode(ISD::FP_ROUND, SL, MVT::f16, Sqrt,
14218 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
14219}
14220
14221SDValue SITargetLowering::lowerFSQRTF32(SDValue Op, SelectionDAG &DAG) const {
14222 SDLoc DL(Op);
14223 SDNodeFlags Flags = Op->getFlags();
14224 MVT VT = Op.getValueType().getSimpleVT();
14225 const SDValue X = Op.getOperand(0);
14226
14227 if (allowApproxFunc(DAG, Flags)) {
14228 // Instruction is 1ulp but ignores denormals.
14229 return DAG.getNode(
14231 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32), X, Flags);
14232 }
14233
14234 SDValue ScaleThreshold = DAG.getConstantFP(0x1.0p-96f, DL, VT);
14235 SDValue NeedScale = DAG.getSetCC(DL, MVT::i1, X, ScaleThreshold, ISD::SETOLT);
14236
14237 SDValue ScaleUpFactor = DAG.getConstantFP(0x1.0p+32f, DL, VT);
14238
14239 SDValue ScaledX = DAG.getNode(ISD::FMUL, DL, VT, X, ScaleUpFactor, Flags);
14240
14241 SDValue SqrtX =
14242 DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledX, X, Flags);
14243
14244 SDValue SqrtS;
14245 if (needsDenormHandlingF32(DAG, X, Flags)) {
14246 SDValue SqrtID =
14247 DAG.getTargetConstant(Intrinsic::amdgcn_sqrt, DL, MVT::i32);
14248 SqrtS = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, SqrtID, SqrtX, Flags);
14249
14250 SDValue SqrtSAsInt = DAG.getNode(ISD::BITCAST, DL, MVT::i32, SqrtS);
14251 SDValue SqrtSNextDownInt =
14252 DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14253 DAG.getAllOnesConstant(DL, MVT::i32));
14254 SDValue SqrtSNextDown = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextDownInt);
14255
14256 SDValue NegSqrtSNextDown =
14257 DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextDown, Flags);
14258
14259 SDValue SqrtVP =
14260 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextDown, SqrtS, SqrtX, Flags);
14261
14262 SDValue SqrtSNextUpInt = DAG.getNode(ISD::ADD, DL, MVT::i32, SqrtSAsInt,
14263 DAG.getConstant(1, DL, MVT::i32));
14264 SDValue SqrtSNextUp = DAG.getNode(ISD::BITCAST, DL, VT, SqrtSNextUpInt);
14265
14266 SDValue NegSqrtSNextUp = DAG.getNode(ISD::FNEG, DL, VT, SqrtSNextUp, Flags);
14267 SDValue SqrtVS =
14268 DAG.getNode(ISD::FMA, DL, VT, NegSqrtSNextUp, SqrtS, SqrtX, Flags);
14269
14270 SDValue Zero = DAG.getConstantFP(0.0f, DL, VT);
14271 SDValue SqrtVPLE0 = DAG.getSetCC(DL, MVT::i1, SqrtVP, Zero, ISD::SETOLE);
14272
14273 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPLE0, SqrtSNextDown, SqrtS,
14274 Flags);
14275
14276 SDValue SqrtVPVSGT0 = DAG.getSetCC(DL, MVT::i1, SqrtVS, Zero, ISD::SETOGT);
14277 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, SqrtVPVSGT0, SqrtSNextUp, SqrtS,
14278 Flags);
14279 } else {
14280 SDValue SqrtR = DAG.getNode(AMDGPUISD::RSQ, DL, VT, SqrtX, Flags);
14281
14282 SqrtS = DAG.getNode(ISD::FMUL, DL, VT, SqrtX, SqrtR, Flags);
14283
14284 SDValue Half = DAG.getConstantFP(0.5f, DL, VT);
14285 SDValue SqrtH = DAG.getNode(ISD::FMUL, DL, VT, SqrtR, Half, Flags);
14286 SDValue NegSqrtH = DAG.getNode(ISD::FNEG, DL, VT, SqrtH, Flags);
14287
14288 SDValue SqrtE = DAG.getNode(ISD::FMA, DL, VT, NegSqrtH, SqrtS, Half, Flags);
14289 SqrtH = DAG.getNode(ISD::FMA, DL, VT, SqrtH, SqrtE, SqrtH, Flags);
14290 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtS, SqrtE, SqrtS, Flags);
14291
14292 SDValue NegSqrtS = DAG.getNode(ISD::FNEG, DL, VT, SqrtS, Flags);
14293 SDValue SqrtD =
14294 DAG.getNode(ISD::FMA, DL, VT, NegSqrtS, SqrtS, SqrtX, Flags);
14295 SqrtS = DAG.getNode(ISD::FMA, DL, VT, SqrtD, SqrtH, SqrtS, Flags);
14296 }
14297
14298 SDValue ScaleDownFactor = DAG.getConstantFP(0x1.0p-16f, DL, VT);
14299
14300 SDValue ScaledDown =
14301 DAG.getNode(ISD::FMUL, DL, VT, SqrtS, ScaleDownFactor, Flags);
14302
14303 SqrtS = DAG.getNode(ISD::SELECT, DL, VT, NeedScale, ScaledDown, SqrtS, Flags);
14304 SDValue IsZeroOrInf =
14305 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14306 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14307
14308 return DAG.getNode(ISD::SELECT, DL, VT, IsZeroOrInf, SqrtX, SqrtS, Flags);
14309}
14310
14311SDValue SITargetLowering::lowerFSQRTF64(SDValue Op, SelectionDAG &DAG) const {
14312 // For double type, the SQRT and RSQ instructions don't have required
14313 // precision, we apply Goldschmidt's algorithm to improve the result:
14314 //
14315 // y0 = rsq(x)
14316 // g0 = x * y0
14317 // h0 = 0.5 * y0
14318 //
14319 // r0 = 0.5 - h0 * g0
14320 // g1 = g0 * r0 + g0
14321 // h1 = h0 * r0 + h0
14322 //
14323 // r1 = 0.5 - h1 * g1 => d0 = x - g1 * g1
14324 // g2 = g1 * r1 + g1 g2 = d0 * h1 + g1
14325 // h2 = h1 * r1 + h1
14326 //
14327 // r2 = 0.5 - h2 * g2 => d1 = x - g2 * g2
14328 // g3 = g2 * r2 + g2 g3 = d1 * h1 + g2
14329 //
14330 // sqrt(x) = g3
14331
14332 SDNodeFlags Flags = Op->getFlags();
14333
14334 SDLoc DL(Op);
14335
14336 SDValue X = Op.getOperand(0);
14337 SDValue ZeroInt = DAG.getConstant(0, DL, MVT::i32);
14338
14339 SDValue SqrtX = X;
14340 SDValue Scaling;
14341 if (!Flags.hasApproximateFuncs()) {
14342 SDValue ScaleConstant = DAG.getConstantFP(0x1.0p-767, DL, MVT::f64);
14343 Scaling = DAG.getSetCC(DL, MVT::i1, X, ScaleConstant, ISD::SETOLT);
14344
14345 // Scale up input if it is too small.
14346 SDValue ScaleUpFactor = DAG.getConstant(256, DL, MVT::i32);
14347 SDValue ScaleUp =
14348 DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling, ScaleUpFactor, ZeroInt);
14349 SqrtX = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, X, ScaleUp, Flags);
14350 }
14351
14352 SDValue SqrtY = DAG.getNode(AMDGPUISD::RSQ, DL, MVT::f64, SqrtX);
14353
14354 SDValue SqrtS0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtX, SqrtY);
14355
14356 SDValue Half = DAG.getConstantFP(0.5, DL, MVT::f64);
14357 SDValue SqrtH0 = DAG.getNode(ISD::FMUL, DL, MVT::f64, SqrtY, Half);
14358
14359 SDValue NegSqrtH0 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtH0);
14360 SDValue SqrtR0 = DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtH0, SqrtS0, Half);
14361
14362 SDValue SqrtH1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtH0, SqrtR0, SqrtH0);
14363
14364 SDValue SqrtS1 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtS0, SqrtR0, SqrtS0);
14365
14366 SDValue NegSqrtS1 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS1);
14367 SDValue SqrtD0 =
14368 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS1, SqrtS1, SqrtX);
14369
14370 SDValue SqrtS2 = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD0, SqrtH1, SqrtS1);
14371
14372 SDValue SqrtRet = SqrtS2;
14373 if (!Flags.hasApproximateFuncs()) {
14374 SDValue NegSqrtS2 = DAG.getNode(ISD::FNEG, DL, MVT::f64, SqrtS2);
14375 SDValue SqrtD1 =
14376 DAG.getNode(ISD::FMA, DL, MVT::f64, NegSqrtS2, SqrtS2, SqrtX);
14377
14378 SqrtRet = DAG.getNode(ISD::FMA, DL, MVT::f64, SqrtD1, SqrtH1, SqrtS2);
14379
14380 SDValue ScaleDownFactor = DAG.getSignedConstant(-128, DL, MVT::i32);
14381 SDValue ScaleDown = DAG.getNode(ISD::SELECT, DL, MVT::i32, Scaling,
14382 ScaleDownFactor, ZeroInt);
14383 SqrtRet = DAG.getNode(ISD::FLDEXP, DL, MVT::f64, SqrtRet, ScaleDown, Flags);
14384 }
14385
14386 // TODO: Check for DAZ and expand to subnormals
14387
14388 SDValue IsZeroOrInf;
14389 if (Flags.hasNoInfs()) {
14390 SDValue Zero = DAG.getConstantFP(0.0, DL, MVT::f64);
14391 IsZeroOrInf = DAG.getSetCC(DL, MVT::i1, SqrtX, Zero, ISD::SETOEQ);
14392 } else {
14393 IsZeroOrInf =
14394 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, SqrtX,
14395 DAG.getTargetConstant(fcZero | fcPosInf, DL, MVT::i32));
14396 }
14397
14398 // If x is +INF, +0, or -0, use its original value
14399 return DAG.getNode(ISD::SELECT, DL, MVT::f64, IsZeroOrInf, SqrtX, SqrtRet,
14400 Flags);
14401}
14402
14403SDValue SITargetLowering::LowerTrig(SDValue Op, SelectionDAG &DAG) const {
14404 SDLoc DL(Op);
14405 EVT VT = Op.getValueType();
14406 SDValue Arg = Op.getOperand(0);
14407 SDValue TrigVal;
14408
14409 // Propagate fast-math flags so that the multiply we introduce can be folded
14410 // if Arg is already the result of a multiply by constant.
14411 auto Flags = Op->getFlags();
14412
14413 // AMDGPUISD nodes of vector type must be unrolled here since
14414 // they will not be expanded elsewhere.
14415 auto UnrollIfVec = [&DAG](SDValue V) -> SDValue {
14416 if (!V.getValueType().isVector())
14417 return V;
14418
14419 return DAG.UnrollVectorOp(cast<SDNode>(V));
14420 };
14421
14422 SDValue OneOver2Pi = DAG.getConstantFP(0.5 * numbers::inv_pi, DL, VT);
14423
14424 if (Subtarget->hasTrigReducedRange()) {
14425 SDValue MulVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14426 TrigVal = UnrollIfVec(DAG.getNode(AMDGPUISD::FRACT, DL, VT, MulVal, Flags));
14427 } else {
14428 TrigVal = DAG.getNode(ISD::FMUL, DL, VT, Arg, OneOver2Pi, Flags);
14429 }
14430
14431 switch (Op.getOpcode()) {
14432 case ISD::FCOS:
14433 TrigVal = DAG.getNode(AMDGPUISD::COS_HW, SDLoc(Op), VT, TrigVal, Flags);
14434 break;
14435 case ISD::FSIN:
14436 TrigVal = DAG.getNode(AMDGPUISD::SIN_HW, SDLoc(Op), VT, TrigVal, Flags);
14437 break;
14438 default:
14439 llvm_unreachable("Wrong trig opcode");
14440 }
14441
14442 return UnrollIfVec(TrigVal);
14443}
14444
14445SDValue SITargetLowering::LowerATOMIC_CMP_SWAP(SDValue Op,
14446 SelectionDAG &DAG) const {
14447 AtomicSDNode *AtomicNode = cast<AtomicSDNode>(Op);
14448 assert(AtomicNode->isCompareAndSwap());
14449 unsigned AS = AtomicNode->getAddressSpace();
14450
14451 // No custom lowering required for local address space
14453 return Op;
14454
14455 // Non-local address space requires custom lowering for atomic compare
14456 // and swap; cmp and swap should be in a v2i32 or v2i64 in case of _X2
14457 SDLoc DL(Op);
14458 SDValue ChainIn = Op.getOperand(0);
14459 SDValue Addr = Op.getOperand(1);
14460 SDValue Old = Op.getOperand(2);
14461 SDValue New = Op.getOperand(3);
14462 EVT VT = Op.getValueType();
14463 MVT SimpleVT = VT.getSimpleVT();
14464 MVT VecType = MVT::getVectorVT(SimpleVT, 2);
14465
14466 SDValue NewOld = DAG.getBuildVector(VecType, DL, {New, Old});
14467 SDValue Ops[] = {ChainIn, Addr, NewOld};
14468
14469 return DAG.getMemIntrinsicNode(AMDGPUISD::ATOMIC_CMP_SWAP, DL,
14470 Op->getVTList(), Ops, VT,
14471 AtomicNode->getMemOperand());
14472}
14473
14474//===----------------------------------------------------------------------===//
14475// Custom DAG optimizations
14476//===----------------------------------------------------------------------===//
14477
14478SDValue
14479SITargetLowering::performUCharToFloatCombine(SDNode *N,
14480 DAGCombinerInfo &DCI) const {
14481 EVT VT = N->getValueType(0);
14482 EVT ScalarVT = VT.getScalarType();
14483 if (ScalarVT != MVT::f32 && ScalarVT != MVT::f16)
14484 return SDValue();
14485
14486 SelectionDAG &DAG = DCI.DAG;
14487 SDLoc DL(N);
14488
14489 SDValue Src = N->getOperand(0);
14490 EVT SrcVT = Src.getValueType();
14491
14492 // TODO: We could try to match extracting the higher bytes, which would be
14493 // easier if i8 vectors weren't promoted to i32 vectors, particularly after
14494 // types are legalized. v4i8 -> v4f32 is probably the only case to worry
14495 // about in practice.
14496 if (DCI.isAfterLegalizeDAG() && SrcVT == MVT::i32) {
14497 if (DAG.MaskedValueIsZero(Src, APInt::getHighBitsSet(32, 24))) {
14498 SDValue Cvt = DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0, DL, MVT::f32, Src);
14499 DCI.AddToWorklist(Cvt.getNode());
14500
14501 // For the f16 case, fold to a cast to f32 and then cast back to f16.
14502 if (ScalarVT != MVT::f32) {
14503 Cvt = DAG.getNode(ISD::FP_ROUND, DL, VT, Cvt,
14504 DAG.getTargetConstant(0, DL, MVT::i32));
14505 }
14506 return Cvt;
14507 }
14508 }
14509
14510 return SDValue();
14511}
14512
14513SDValue SITargetLowering::performFCopySignCombine(SDNode *N,
14514 DAGCombinerInfo &DCI) const {
14515 SDValue MagnitudeOp = N->getOperand(0);
14516 SDValue SignOp = N->getOperand(1);
14517
14518 // The generic combine for fcopysign + fp cast is too conservative with
14519 // vectors, and also gets confused by the splitting we will perform here, so
14520 // peek through FP casts.
14521 if (SignOp.getOpcode() == ISD::FP_EXTEND ||
14522 SignOp.getOpcode() == ISD::FP_ROUND)
14523 SignOp = SignOp.getOperand(0);
14524
14525 SelectionDAG &DAG = DCI.DAG;
14526 SDLoc DL(N);
14527 EVT SignVT = SignOp.getValueType();
14528
14529 // f64 fcopysign is really an f32 copysign on the high bits, so replace the
14530 // lower half with a copy.
14531 // fcopysign f64:x, _:y -> x.lo32, (fcopysign (f32 x.hi32), _:y)
14532 EVT MagVT = MagnitudeOp.getValueType();
14533
14534 unsigned NumElts = MagVT.isVector() ? MagVT.getVectorNumElements() : 1;
14535
14536 if (MagVT.getScalarType() == MVT::f64) {
14537 EVT F32VT = MagVT.isVector()
14538 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14539 : MVT::v2f32;
14540
14541 SDValue MagAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, MagnitudeOp);
14542
14544 for (unsigned I = 0; I != NumElts; ++I) {
14545 SDValue MagLo =
14546 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14547 DAG.getConstant(2 * I, DL, MVT::i32));
14548 SDValue MagHi =
14549 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, MagAsVector,
14550 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14551
14552 SDValue SignOpElt =
14553 MagVT.isVector()
14555 SignOp, DAG.getConstant(I, DL, MVT::i32))
14556 : SignOp;
14557
14558 SDValue HiOp =
14559 DAG.getNode(ISD::FCOPYSIGN, DL, MVT::f32, MagHi, SignOpElt);
14560
14561 SDValue Vector =
14562 DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v2f32, MagLo, HiOp);
14563
14564 SDValue NewElt = DAG.getNode(ISD::BITCAST, DL, MVT::f64, Vector);
14565 NewElts.push_back(NewElt);
14566 }
14567
14568 if (NewElts.size() == 1)
14569 return NewElts[0];
14570
14571 return DAG.getNode(ISD::BUILD_VECTOR, DL, MagVT, NewElts);
14572 }
14573
14574 if (SignVT.getScalarType() != MVT::f64)
14575 return SDValue();
14576
14577 // Reduce width of sign operand, we only need the highest bit.
14578 //
14579 // fcopysign f64:x, f64:y ->
14580 // fcopysign f64:x, (extract_vector_elt (bitcast f64:y to v2f32), 1)
14581 // TODO: In some cases it might make sense to go all the way to f16.
14582
14583 EVT F32VT = MagVT.isVector()
14584 ? EVT::getVectorVT(*DAG.getContext(), MVT::f32, 2 * NumElts)
14585 : MVT::v2f32;
14586
14587 SDValue SignAsVector = DAG.getNode(ISD::BITCAST, DL, F32VT, SignOp);
14588
14589 SmallVector<SDValue, 8> F32Signs;
14590 for (unsigned I = 0; I != NumElts; ++I) {
14591 // Take sign from odd elements of cast vector
14592 SDValue SignAsF32 =
14593 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, SignAsVector,
14594 DAG.getConstant(2 * I + 1, DL, MVT::i32));
14595 F32Signs.push_back(SignAsF32);
14596 }
14597
14598 SDValue NewSign =
14599 NumElts == 1
14600 ? F32Signs.back()
14602 EVT::getVectorVT(*DAG.getContext(), MVT::f32, NumElts),
14603 F32Signs);
14604
14605 return DAG.getNode(ISD::FCOPYSIGN, DL, N->getValueType(0), N->getOperand(0),
14606 NewSign);
14607}
14608
14609// (shl (add x, c1), c2) -> add (shl x, c2), (shl c1, c2)
14610// (shl (or x, c1), c2) -> add (shl x, c2), (shl c1, c2) iff x and c1 share no
14611// bits
14612
14613// This is a variant of
14614// (mul (add x, c1), c2) -> add (mul x, c2), (mul c1, c2),
14615//
14616// The normal DAG combiner will do this, but only if the add has one use since
14617// that would increase the number of instructions.
14618//
14619// This prevents us from seeing a constant offset that can be folded into a
14620// memory instruction's addressing mode. If we know the resulting add offset of
14621// a pointer can be folded into an addressing offset, we can replace the pointer
14622// operand with the add of new constant offset. This eliminates one of the uses,
14623// and may allow the remaining use to also be simplified.
14624//
14625SDValue SITargetLowering::performSHLPtrCombine(SDNode *N, unsigned AddrSpace,
14626 EVT MemVT,
14627 DAGCombinerInfo &DCI) const {
14628 SDValue N0 = N->getOperand(0);
14629 SDValue N1 = N->getOperand(1);
14630
14631 // We only do this to handle cases where it's profitable when there are
14632 // multiple uses of the add, so defer to the standard combine.
14633 if ((!N0->isAnyAdd() && N0.getOpcode() != ISD::OR) || N0->hasOneUse())
14634 return SDValue();
14635
14636 const ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(N1);
14637 if (!CN1)
14638 return SDValue();
14639
14640 const ConstantSDNode *CAdd = dyn_cast<ConstantSDNode>(N0.getOperand(1));
14641 if (!CAdd)
14642 return SDValue();
14643
14644 SelectionDAG &DAG = DCI.DAG;
14645
14646 if (N0->getOpcode() == ISD::OR &&
14647 !DAG.haveNoCommonBitsSet(N0.getOperand(0), N0.getOperand(1)))
14648 return SDValue();
14649
14650 // If the resulting offset is too large, we can't fold it into the
14651 // addressing mode offset.
14652 APInt Offset = CAdd->getAPIntValue() << CN1->getAPIntValue();
14653 Type *Ty = MemVT.getTypeForEVT(*DCI.DAG.getContext());
14654
14655 AddrMode AM;
14656 AM.HasBaseReg = true;
14657 AM.BaseOffs = Offset.getSExtValue();
14658 if (!isLegalAddressingMode(DCI.DAG.getDataLayout(), AM, Ty, AddrSpace))
14659 return SDValue();
14660
14661 SDLoc SL(N);
14662 EVT VT = N->getValueType(0);
14663
14664 SDValue ShlX = DAG.getNode(ISD::SHL, SL, VT, N0.getOperand(0), N1);
14665 SDValue COffset = DAG.getConstant(Offset, SL, VT);
14666
14667 SDNodeFlags Flags;
14668 Flags.setNoUnsignedWrap(
14669 N->getFlags().hasNoUnsignedWrap() &&
14670 (N0.getOpcode() == ISD::OR || N0->getFlags().hasNoUnsignedWrap()));
14671
14672 // Use ISD::ADD even if the original operation was ISD::PTRADD, since we can't
14673 // be sure that the new left operand is a proper base pointer.
14674 return DAG.getNode(ISD::ADD, SL, VT, ShlX, COffset, Flags);
14675}
14676
14677/// MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset
14678/// by the chain and intrinsic ID. Theoretically we would also need to check the
14679/// specific intrinsic, but they all place the pointer operand first.
14680static unsigned getBasePtrIndex(const MemSDNode *N) {
14681 switch (N->getOpcode()) {
14682 case ISD::STORE:
14685 return 2;
14686 default:
14687 return 1;
14688 }
14689}
14690
14691SDValue SITargetLowering::performMemSDNodeCombine(MemSDNode *N,
14692 DAGCombinerInfo &DCI) const {
14693 SelectionDAG &DAG = DCI.DAG;
14694
14695 unsigned PtrIdx = getBasePtrIndex(N);
14696 SDValue Ptr = N->getOperand(PtrIdx);
14697
14698 // TODO: We could also do this for multiplies.
14699 if (Ptr.getOpcode() == ISD::SHL) {
14700 SDValue NewPtr = performSHLPtrCombine(Ptr.getNode(), N->getAddressSpace(),
14701 N->getMemoryVT(), DCI);
14702 if (NewPtr) {
14703 SmallVector<SDValue, 8> NewOps(N->ops());
14704
14705 NewOps[PtrIdx] = NewPtr;
14706 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
14707 }
14708 }
14709
14710 return SDValue();
14711}
14712
14713static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val) {
14714 return (Opc == ISD::AND && (Val == 0 || Val == 0xffffffff)) ||
14715 (Opc == ISD::OR && (Val == 0xffffffff || Val == 0)) ||
14716 (Opc == ISD::XOR && Val == 0);
14717}
14718
14719// Break up 64-bit bit operation of a constant into two 32-bit and/or/xor. This
14720// will typically happen anyway for a VALU 64-bit and. This exposes other 32-bit
14721// integer combine opportunities since most 64-bit operations are decomposed
14722// this way. TODO: We won't want this for SALU especially if it is an inline
14723// immediate.
14724SDValue SITargetLowering::splitBinaryBitConstantOp(
14725 DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS,
14726 const ConstantSDNode *CRHS) const {
14727 uint64_t Val = CRHS->getZExtValue();
14728 uint32_t ValLo = Lo_32(Val);
14729 uint32_t ValHi = Hi_32(Val);
14730 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
14731
14732 if ((bitOpWithConstantIsReducible(Opc, ValLo) ||
14734 (CRHS->hasOneUse() && !TII->isInlineConstant(CRHS->getAPIntValue()))) {
14735 // We have 64-bit scalar and/or/xor, but do not have vector forms.
14736 if (Subtarget->has64BitLiterals() && CRHS->hasOneUse() &&
14737 !CRHS->user_begin()->isDivergent())
14738 return SDValue();
14739
14740 // If we need to materialize a 64-bit immediate, it will be split up later
14741 // anyway. Avoid creating the harder to understand 64-bit immediate
14742 // materialization.
14743 return splitBinaryBitConstantOpImpl(DCI, SL, Opc, LHS, ValLo, ValHi);
14744 }
14745
14746 return SDValue();
14747}
14748
14750 if (V.getValueType() != MVT::i1)
14751 return false;
14752 switch (V.getOpcode()) {
14753 default:
14754 break;
14755 case ISD::SETCC:
14756 case ISD::IS_FPCLASS:
14757 case AMDGPUISD::FP_CLASS:
14758 return true;
14759 case ISD::AND:
14760 case ISD::OR:
14761 case ISD::XOR:
14762 return isBoolSGPR(V.getOperand(0)) && isBoolSGPR(V.getOperand(1));
14763 case ISD::SADDO:
14764 case ISD::UADDO:
14765 case ISD::SSUBO:
14766 case ISD::USUBO:
14767 case ISD::SMULO:
14768 case ISD::UMULO:
14769 return V.getResNo() == 1;
14771 unsigned IntrinsicID = V.getConstantOperandVal(0);
14772 switch (IntrinsicID) {
14773 case Intrinsic::amdgcn_is_shared:
14774 case Intrinsic::amdgcn_is_private:
14775 return true;
14776 default:
14777 return false;
14778 }
14779
14780 return false;
14781 }
14782 }
14783 return false;
14784}
14785
14786// If a constant has all zeroes or all ones within each byte return it.
14787// Otherwise return 0.
14789 // 0xff for any zero byte in the mask
14790 uint32_t ZeroByteMask = 0;
14791 if (!(C & 0x000000ff))
14792 ZeroByteMask |= 0x000000ff;
14793 if (!(C & 0x0000ff00))
14794 ZeroByteMask |= 0x0000ff00;
14795 if (!(C & 0x00ff0000))
14796 ZeroByteMask |= 0x00ff0000;
14797 if (!(C & 0xff000000))
14798 ZeroByteMask |= 0xff000000;
14799 uint32_t NonZeroByteMask = ~ZeroByteMask; // 0xff for any non-zero byte
14800 if ((NonZeroByteMask & C) != NonZeroByteMask)
14801 return 0; // Partial bytes selected.
14802 return C;
14803}
14804
14805// Check if a node selects whole bytes from its operand 0 starting at a byte
14806// boundary while masking the rest. Returns select mask as in the v_perm_b32
14807// or -1 if not succeeded.
14808// Note byte select encoding:
14809// value 0-3 selects corresponding source byte;
14810// value 0xc selects zero;
14811// value 0xff selects 0xff.
14813 assert(V.getValueSizeInBits() == 32);
14814
14815 if (V.getNumOperands() != 2)
14816 return ~0;
14817
14818 ConstantSDNode *N1 = dyn_cast<ConstantSDNode>(V.getOperand(1));
14819 if (!N1)
14820 return ~0;
14821
14822 uint32_t C = N1->getZExtValue();
14823
14824 switch (V.getOpcode()) {
14825 default:
14826 break;
14827 case ISD::AND:
14828 if (uint32_t ConstMask = getConstantPermuteMask(C))
14829 return (0x03020100 & ConstMask) | (0x0c0c0c0c & ~ConstMask);
14830 break;
14831
14832 case ISD::OR:
14833 if (uint32_t ConstMask = getConstantPermuteMask(C))
14834 return (0x03020100 & ~ConstMask) | ConstMask;
14835 break;
14836
14837 case ISD::SHL:
14838 if (C % 8)
14839 return ~0;
14840
14841 return uint32_t((0x030201000c0c0c0cull << C) >> 32);
14842
14843 case ISD::SRL:
14844 if (C % 8)
14845 return ~0;
14846
14847 return uint32_t(0x0c0c0c0c03020100ull >> C);
14848 }
14849
14850 return ~0;
14851}
14852
14853SDValue SITargetLowering::performAndCombine(SDNode *N,
14854 DAGCombinerInfo &DCI) const {
14855 if (DCI.isBeforeLegalize())
14856 return SDValue();
14857
14858 SelectionDAG &DAG = DCI.DAG;
14859 EVT VT = N->getValueType(0);
14860 SDValue LHS = N->getOperand(0);
14861 SDValue RHS = N->getOperand(1);
14862
14863 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS);
14864 if (VT == MVT::i64 && CRHS) {
14865 if (SDValue Split =
14866 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::AND, LHS, CRHS))
14867 return Split;
14868 }
14869
14870 if (CRHS && VT == MVT::i32) {
14871 // and (srl x, c), mask => shl (bfe x, nb + c, mask >> nb), nb
14872 // nb = number of trailing zeroes in mask
14873 // It can be optimized out using SDWA for GFX8+ in the SDWA peephole pass,
14874 // given that we are selecting 8 or 16 bit fields starting at byte boundary.
14875 uint64_t Mask = CRHS->getZExtValue();
14876 unsigned Bits = llvm::popcount(Mask);
14877 if (getSubtarget()->hasSDWA() && LHS->getOpcode() == ISD::SRL &&
14878 (Bits == 8 || Bits == 16) && isShiftedMask_64(Mask) && !(Mask & 1)) {
14879 if (auto *CShift = dyn_cast<ConstantSDNode>(LHS->getOperand(1))) {
14880 unsigned Shift = CShift->getZExtValue();
14881 unsigned NB = CRHS->getAPIntValue().countr_zero();
14882 unsigned Offset = NB + Shift;
14883 if ((Offset & (Bits - 1)) == 0) { // Starts at a byte or word boundary.
14884 SDLoc SL(N);
14885 SDValue BFE =
14886 DAG.getNode(AMDGPUISD::BFE_U32, SL, MVT::i32, LHS->getOperand(0),
14887 DAG.getConstant(Offset, SL, MVT::i32),
14888 DAG.getConstant(Bits, SL, MVT::i32));
14889 EVT NarrowVT = EVT::getIntegerVT(*DAG.getContext(), Bits);
14890 SDValue Ext = DAG.getNode(ISD::AssertZext, SL, VT, BFE,
14891 DAG.getValueType(NarrowVT));
14892 SDValue Shl = DAG.getNode(ISD::SHL, SDLoc(LHS), VT, Ext,
14893 DAG.getConstant(NB, SDLoc(CRHS), MVT::i32));
14894 return Shl;
14895 }
14896 }
14897 }
14898
14899 // and (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
14900 if (LHS.hasOneUse() && LHS.getOpcode() == AMDGPUISD::PERM &&
14901 isa<ConstantSDNode>(LHS.getOperand(2))) {
14902 uint32_t Sel = getConstantPermuteMask(Mask);
14903 if (!Sel)
14904 return SDValue();
14905
14906 // Select 0xc for all zero bytes
14907 Sel = (LHS.getConstantOperandVal(2) & Sel) | (~Sel & 0x0c0c0c0c);
14908 SDLoc DL(N);
14909 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
14910 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
14911 }
14912 }
14913
14914 // (and (fcmp ord x, x), (fcmp une (fabs x), inf)) ->
14915 // fp_class x, ~(s_nan | q_nan | n_infinity | p_infinity)
14916 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == ISD::SETCC) {
14917 ISD::CondCode LCC = cast<CondCodeSDNode>(LHS.getOperand(2))->get();
14918 ISD::CondCode RCC = cast<CondCodeSDNode>(RHS.getOperand(2))->get();
14919
14920 SDValue X = LHS.getOperand(0);
14921 SDValue Y = RHS.getOperand(0);
14922 if (Y.getOpcode() != ISD::FABS || Y.getOperand(0) != X ||
14923 !isTypeLegal(X.getValueType()))
14924 return SDValue();
14925
14926 if (LCC == ISD::SETO) {
14927 if (X != LHS.getOperand(1))
14928 return SDValue();
14929
14930 if (RCC == ISD::SETUNE) {
14931 const ConstantFPSDNode *C1 =
14932 dyn_cast<ConstantFPSDNode>(RHS.getOperand(1));
14933 if (!C1 || !C1->isInfinity() || C1->isNegative())
14934 return SDValue();
14935
14936 const uint32_t Mask = SIInstrFlags::N_NORMAL |
14940
14941 static_assert(
14944 0x3ff) == Mask,
14945 "mask not equal");
14946
14947 SDLoc DL(N);
14948 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, X,
14949 DAG.getConstant(Mask, DL, MVT::i32));
14950 }
14951 }
14952 }
14953
14954 if (RHS.getOpcode() == ISD::SETCC && LHS.getOpcode() == AMDGPUISD::FP_CLASS)
14955 std::swap(LHS, RHS);
14956
14957 if (LHS.getOpcode() == ISD::SETCC && RHS.getOpcode() == AMDGPUISD::FP_CLASS &&
14958 RHS.hasOneUse()) {
14959 ISD::CondCode LCC = cast<CondCodeSDNode>(LHS.getOperand(2))->get();
14960 // and (fcmp seto), (fp_class x, mask) -> fp_class x, mask & ~(p_nan |
14961 // n_nan) and (fcmp setuo), (fp_class x, mask) -> fp_class x, mask & (p_nan
14962 // | n_nan)
14963 const ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
14964 if ((LCC == ISD::SETO || LCC == ISD::SETUO) && Mask &&
14965 (RHS.getOperand(0) == LHS.getOperand(0) &&
14966 LHS.getOperand(0) == LHS.getOperand(1))) {
14967 const unsigned OrdMask = SIInstrFlags::S_NAN | SIInstrFlags::Q_NAN;
14968 unsigned NewMask = LCC == ISD::SETO ? Mask->getZExtValue() & ~OrdMask
14969 : Mask->getZExtValue() & OrdMask;
14970
14971 SDLoc DL(N);
14972 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, RHS.getOperand(0),
14973 DAG.getConstant(NewMask, DL, MVT::i32));
14974 }
14975 }
14976
14977 if (VT == MVT::i32 && (RHS.getOpcode() == ISD::SIGN_EXTEND ||
14978 LHS.getOpcode() == ISD::SIGN_EXTEND)) {
14979 // and x, (sext cc from i1) => select cc, x, 0
14980 if (RHS.getOpcode() != ISD::SIGN_EXTEND)
14981 std::swap(LHS, RHS);
14982 if (isBoolSGPR(RHS.getOperand(0)))
14983 return DAG.getSelect(SDLoc(N), MVT::i32, RHS.getOperand(0), LHS,
14984 DAG.getConstant(0, SDLoc(N), MVT::i32));
14985 }
14986
14987 // and (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
14988 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
14989 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
14990 N->isDivergent() && TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
14991 uint32_t LHSMask = getPermuteMask(LHS);
14992 uint32_t RHSMask = getPermuteMask(RHS);
14993 if (LHSMask != ~0u && RHSMask != ~0u) {
14994 // Canonicalize the expression in an attempt to have fewer unique masks
14995 // and therefore fewer registers used to hold the masks.
14996 if (LHSMask > RHSMask) {
14997 std::swap(LHSMask, RHSMask);
14998 std::swap(LHS, RHS);
14999 }
15000
15001 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15002 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15003 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15004 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15005
15006 // Check of we need to combine values from two sources within a byte.
15007 if (!(LHSUsedLanes & RHSUsedLanes) &&
15008 // If we select high and lower word keep it for SDWA.
15009 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15010 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15011 // Each byte in each mask is either selector mask 0-3, or has higher
15012 // bits set in either of masks, which can be 0xff for 0xff or 0x0c for
15013 // zero. If 0x0c is in either mask it shall always be 0x0c. Otherwise
15014 // mask which is not 0xff wins. By anding both masks we have a correct
15015 // result except that 0x0c shall be corrected to give 0x0c only.
15016 uint32_t Mask = LHSMask & RHSMask;
15017 for (unsigned I = 0; I < 32; I += 8) {
15018 uint32_t ByteSel = 0xff << I;
15019 if ((LHSMask & ByteSel) == 0x0c || (RHSMask & ByteSel) == 0x0c)
15020 Mask &= (0x0c << I) & 0xffffffff;
15021 }
15022
15023 // Add 4 to each active LHS lane. It will not affect any existing 0xff
15024 // or 0x0c.
15025 uint32_t Sel = Mask | (LHSUsedLanes & 0x04040404);
15026 SDLoc DL(N);
15027
15028 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15029 RHS.getOperand(0),
15030 DAG.getConstant(Sel, DL, MVT::i32));
15031 }
15032 }
15033 }
15034
15035 return SDValue();
15036}
15037
15038// A key component of v_perm is a mapping between byte position of the src
15039// operands, and the byte position of the dest. To provide such, we need: 1. the
15040// node that provides x byte of the dest of the OR, and 2. the byte of the node
15041// used to provide that x byte. calculateByteProvider finds which node provides
15042// a certain byte of the dest of the OR, and calculateSrcByte takes that node,
15043// and finds an ultimate src and byte position For example: The supported
15044// LoadCombine pattern for vector loads is as follows
15045// t1
15046// or
15047// / \
15048// t2 t3
15049// zext shl
15050// | | \
15051// t4 t5 16
15052// or anyext
15053// / \ |
15054// t6 t7 t8
15055// srl shl or
15056// / | / \ / \
15057// t9 t10 t11 t12 t13 t14
15058// trunc* 8 trunc* 8 and and
15059// | | / | | \
15060// t15 t16 t17 t18 t19 t20
15061// trunc* 255 srl -256
15062// | / \
15063// t15 t15 16
15064//
15065// *In this example, the truncs are from i32->i16
15066//
15067// calculateByteProvider would find t6, t7, t13, and t14 for bytes 0-3
15068// respectively. calculateSrcByte would find (given node) -> ultimate src &
15069// byteposition: t6 -> t15 & 1, t7 -> t16 & 0, t13 -> t15 & 0, t14 -> t15 & 3.
15070// After finding the mapping, we can combine the tree into vperm t15, t16,
15071// 0x05000407
15072
15073// Find the source and byte position from a node.
15074// \p DestByte is the byte position of the dest of the or that the src
15075// ultimately provides. \p SrcIndex is the byte of the src that maps to this
15076// dest of the or byte. \p Depth tracks how many recursive iterations we have
15077// performed.
15078static const std::optional<ByteProvider<SDValue>>
15079calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex = 0,
15080 unsigned Depth = 0) {
15081 // We may need to recursively traverse a series of SRLs
15082 if (Depth >= 6)
15083 return std::nullopt;
15084
15085 if (Op.getValueSizeInBits() < 8)
15086 return std::nullopt;
15087
15088 if (Op.getValueType().isVector())
15089 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15090
15091 switch (Op->getOpcode()) {
15092 case ISD::TRUNCATE: {
15093 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15094 }
15095
15096 case ISD::ANY_EXTEND:
15097 case ISD::SIGN_EXTEND:
15098 case ISD::ZERO_EXTEND:
15100 SDValue NarrowOp = Op->getOperand(0);
15101 auto NarrowVT = NarrowOp.getValueType();
15102 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG) {
15103 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15104 NarrowVT = VTSign->getVT();
15105 }
15106 if (!NarrowVT.isByteSized())
15107 return std::nullopt;
15108 uint64_t NarrowByteWidth = NarrowVT.getStoreSize();
15109
15110 if (SrcIndex >= NarrowByteWidth)
15111 return std::nullopt;
15112 return calculateSrcByte(Op->getOperand(0), DestByte, SrcIndex, Depth + 1);
15113 }
15114
15115 case ISD::SRA:
15116 case ISD::SRL: {
15117 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15118 if (!ShiftOp)
15119 return std::nullopt;
15120
15121 uint64_t BitShift = ShiftOp->getZExtValue();
15122
15123 if (BitShift % 8 != 0)
15124 return std::nullopt;
15125
15126 uint64_t NewSrcIndex = SrcIndex + BitShift / 8;
15127 if (NewSrcIndex >= Op.getScalarValueSizeInBits() / 8)
15128 return std::nullopt;
15129
15130 return calculateSrcByte(Op->getOperand(0), DestByte, NewSrcIndex,
15131 Depth + 1);
15132 }
15133
15134 default: {
15135 return ByteProvider<SDValue>::getSrc(Op, DestByte, SrcIndex);
15136 }
15137 }
15138 llvm_unreachable("fully handled switch");
15139}
15140
15141// For a byte position in the result of an Or, traverse the tree and find the
15142// node (and the byte of the node) which ultimately provides this {Or,
15143// BytePosition}. \p Op is the operand we are currently examining. \p Index is
15144// the byte position of the Op that corresponds with the originally requested
15145// byte of the Or \p Depth tracks how many recursive iterations we have
15146// performed. \p StartingIndex is the originally requested byte of the Or
15147static const std::optional<ByteProvider<SDValue>>
15148calculateByteProvider(const SDValue &Op, unsigned Index, unsigned Depth,
15149 unsigned StartingIndex = 0) {
15150 // Finding Src tree of RHS of or typically requires at least 1 additional
15151 // depth
15152 if (Depth > 6)
15153 return std::nullopt;
15154
15155 unsigned BitWidth = Op.getScalarValueSizeInBits();
15156 if (BitWidth % 8 != 0)
15157 return std::nullopt;
15158 if (Index > BitWidth / 8 - 1)
15159 return std::nullopt;
15160
15161 bool IsVec = Op.getValueType().isVector();
15162 switch (Op.getOpcode()) {
15163 case ISD::OR: {
15164 if (IsVec)
15165 return std::nullopt;
15166
15167 auto RHS = calculateByteProvider(Op.getOperand(1), Index, Depth + 1,
15168 StartingIndex);
15169 if (!RHS)
15170 return std::nullopt;
15171 auto LHS = calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15172 StartingIndex);
15173 if (!LHS)
15174 return std::nullopt;
15175 // A well formed Or will have two ByteProviders for each byte, one of which
15176 // is constant zero
15177 if (!LHS->isConstantZero() && !RHS->isConstantZero())
15178 return std::nullopt;
15179 if (!LHS || LHS->isConstantZero())
15180 return RHS;
15181 if (!RHS || RHS->isConstantZero())
15182 return LHS;
15183 return std::nullopt;
15184 }
15185
15186 case ISD::AND: {
15187 if (IsVec)
15188 return std::nullopt;
15189
15190 auto *BitMaskOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15191 if (!BitMaskOp)
15192 return std::nullopt;
15193
15194 uint32_t BitMask = BitMaskOp->getZExtValue();
15195 // Bits we expect for our StartingIndex
15196 uint32_t IndexMask = 0xFF << (Index * 8);
15197
15198 if ((IndexMask & BitMask) != IndexMask) {
15199 // If the result of the and partially provides the byte, then it
15200 // is not well formatted
15201 if (IndexMask & BitMask)
15202 return std::nullopt;
15204 }
15205
15206 return calculateSrcByte(Op->getOperand(0), StartingIndex, Index);
15207 }
15208
15209 case ISD::FSHR: {
15210 if (IsVec)
15211 return std::nullopt;
15212
15213 // fshr(X,Y,Z): (X << (BW - (Z % BW))) | (Y >> (Z % BW))
15214 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15215 if (!ShiftOp || Op.getValueType().isVector())
15216 return std::nullopt;
15217
15218 uint64_t BitsProvided = Op.getValueSizeInBits();
15219 if (BitsProvided % 8 != 0)
15220 return std::nullopt;
15221
15222 uint64_t BitShift = ShiftOp->getAPIntValue().urem(BitsProvided);
15223 if (BitShift % 8)
15224 return std::nullopt;
15225
15226 uint64_t ConcatSizeInBytes = BitsProvided / 4;
15227 uint64_t ByteShift = BitShift / 8;
15228
15229 uint64_t NewIndex = (Index + ByteShift) % ConcatSizeInBytes;
15230 uint64_t BytesProvided = BitsProvided / 8;
15231 SDValue NextOp = Op.getOperand(NewIndex >= BytesProvided ? 0 : 1);
15232 NewIndex %= BytesProvided;
15233 return calculateByteProvider(NextOp, NewIndex, Depth + 1, StartingIndex);
15234 }
15235
15236 case ISD::SRA:
15237 case ISD::SRL: {
15238 if (IsVec)
15239 return std::nullopt;
15240
15241 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15242 if (!ShiftOp)
15243 return std::nullopt;
15244
15245 uint64_t BitShift = ShiftOp->getZExtValue();
15246 if (BitShift % 8)
15247 return std::nullopt;
15248
15249 auto BitsProvided = Op.getScalarValueSizeInBits();
15250 if (BitsProvided % 8 != 0)
15251 return std::nullopt;
15252
15253 uint64_t BytesProvided = BitsProvided / 8;
15254 uint64_t ByteShift = BitShift / 8;
15255 if (Index + ByteShift < BytesProvided)
15256 return calculateSrcByte(Op->getOperand(0), StartingIndex,
15257 Index + ByteShift);
15258 // SRA's out-of-range bytes are sign bits, not constant zero.
15259 if (Op.getOpcode() == ISD::SRA)
15260 return std::nullopt;
15262 }
15263
15264 case ISD::SHL: {
15265 if (IsVec)
15266 return std::nullopt;
15267
15268 auto *ShiftOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15269 if (!ShiftOp)
15270 return std::nullopt;
15271
15272 uint64_t BitShift = ShiftOp->getZExtValue();
15273 if (BitShift % 8 != 0)
15274 return std::nullopt;
15275 uint64_t ByteShift = BitShift / 8;
15276
15277 // If we are shifting by an amount greater than (or equal to)
15278 // the index we are trying to provide, then it provides 0s. If not,
15279 // then this bytes are not definitively 0s, and the corresponding byte
15280 // of interest is Index - ByteShift of the src
15281 return Index < ByteShift
15283 : calculateByteProvider(Op.getOperand(0), Index - ByteShift,
15284 Depth + 1, StartingIndex);
15285 }
15286 case ISD::ANY_EXTEND:
15287 case ISD::SIGN_EXTEND:
15288 case ISD::ZERO_EXTEND:
15290 case ISD::AssertZext:
15291 case ISD::AssertSext: {
15292 if (IsVec)
15293 return std::nullopt;
15294
15295 SDValue NarrowOp = Op->getOperand(0);
15296 unsigned NarrowBitWidth = NarrowOp.getValueSizeInBits();
15297 if (Op->getOpcode() == ISD::SIGN_EXTEND_INREG ||
15298 Op->getOpcode() == ISD::AssertZext ||
15299 Op->getOpcode() == ISD::AssertSext) {
15300 auto *VTSign = cast<VTSDNode>(Op->getOperand(1));
15301 NarrowBitWidth = VTSign->getVT().getSizeInBits();
15302 }
15303 if (NarrowBitWidth % 8 != 0)
15304 return std::nullopt;
15305 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15306
15307 if (Index >= NarrowByteWidth)
15308 return Op.getOpcode() == ISD::ZERO_EXTEND
15309 ? std::optional<ByteProvider<SDValue>>(
15311 : std::nullopt;
15312 return calculateByteProvider(NarrowOp, Index, Depth + 1, StartingIndex);
15313 }
15314
15315 case ISD::TRUNCATE: {
15316 if (IsVec)
15317 return std::nullopt;
15318
15319 uint64_t NarrowByteWidth = BitWidth / 8;
15320
15321 if (NarrowByteWidth >= Index) {
15322 return calculateByteProvider(Op.getOperand(0), Index, Depth + 1,
15323 StartingIndex);
15324 }
15325
15326 return std::nullopt;
15327 }
15328
15329 case ISD::CopyFromReg: {
15330 if (BitWidth / 8 > Index)
15331 return calculateSrcByte(Op, StartingIndex, Index);
15332
15333 return std::nullopt;
15334 }
15335
15336 case ISD::LOAD: {
15337 auto *L = cast<LoadSDNode>(Op.getNode());
15338
15339 unsigned NarrowBitWidth = L->getMemoryVT().getSizeInBits();
15340 if (NarrowBitWidth % 8 != 0)
15341 return std::nullopt;
15342 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
15343
15344 // If the width of the load does not reach byte we are trying to provide for
15345 // and it is not a ZEXTLOAD, then the load does not provide for the byte in
15346 // question
15347 if (Index >= NarrowByteWidth) {
15348 return L->getExtensionType() == ISD::ZEXTLOAD
15349 ? std::optional<ByteProvider<SDValue>>(
15351 : std::nullopt;
15352 }
15353
15354 if (NarrowByteWidth > Index) {
15355 return calculateSrcByte(Op, StartingIndex, Index);
15356 }
15357
15358 return std::nullopt;
15359 }
15360
15361 case ISD::BSWAP: {
15362 if (IsVec)
15363 return std::nullopt;
15364
15365 return calculateByteProvider(Op->getOperand(0), BitWidth / 8 - Index - 1,
15366 Depth + 1, StartingIndex);
15367 }
15368
15370 auto *IdxOp = dyn_cast<ConstantSDNode>(Op->getOperand(1));
15371 if (!IdxOp)
15372 return std::nullopt;
15373 auto VecIdx = IdxOp->getZExtValue();
15374 auto ScalarSize = Op.getScalarValueSizeInBits();
15375 if (ScalarSize < 32)
15376 Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index;
15377 return calculateSrcByte(ScalarSize >= 32 ? Op : Op.getOperand(0),
15378 StartingIndex, Index);
15379 }
15380
15381 case AMDGPUISD::PERM: {
15382 if (IsVec)
15383 return std::nullopt;
15384
15385 auto *PermMask = dyn_cast<ConstantSDNode>(Op->getOperand(2));
15386 if (!PermMask)
15387 return std::nullopt;
15388
15389 auto IdxMask =
15390 (PermMask->getZExtValue() & (0xFF << (Index * 8))) >> (Index * 8);
15391 if (IdxMask > 0x07 && IdxMask != 0x0c)
15392 return std::nullopt;
15393
15394 auto NextOp = Op.getOperand(IdxMask > 0x03 ? 0 : 1);
15395 auto NextIndex = IdxMask > 0x03 ? IdxMask % 4 : IdxMask;
15396
15397 return IdxMask != 0x0c ? calculateSrcByte(NextOp, StartingIndex, NextIndex)
15400 }
15401
15402 default: {
15403 return std::nullopt;
15404 }
15405 }
15406
15407 llvm_unreachable("fully handled switch");
15408}
15409
15410// Returns true if the Operand is a scalar and is 16 bits
15411static bool isExtendedFrom16Bits(SDValue &Operand) {
15412
15413 switch (Operand.getOpcode()) {
15414 case ISD::ANY_EXTEND:
15415 case ISD::SIGN_EXTEND:
15416 case ISD::ZERO_EXTEND: {
15417 auto OpVT = Operand.getOperand(0).getValueType();
15418 return !OpVT.isVector() && OpVT.getSizeInBits() == 16;
15419 }
15420 case ISD::LOAD: {
15421 LoadSDNode *L = cast<LoadSDNode>(Operand.getNode());
15422 auto ExtType = cast<LoadSDNode>(L)->getExtensionType();
15423 if (ExtType == ISD::ZEXTLOAD || ExtType == ISD::SEXTLOAD ||
15424 ExtType == ISD::EXTLOAD) {
15425 auto MemVT = L->getMemoryVT();
15426 return !MemVT.isVector() && MemVT.getSizeInBits() == 16;
15427 }
15428 return L->getMemoryVT().getSizeInBits() == 16;
15429 }
15430 default:
15431 return false;
15432 }
15433}
15434
15435// Returns true if the mask matches consecutive bytes, and the first byte
15436// begins at a power of 2 byte offset from 0th byte
15437static bool addresses16Bits(int Mask) {
15438 int Low8 = Mask & 0xff;
15439 int Hi8 = (Mask & 0xff00) >> 8;
15440
15441 assert(Low8 < 8 && Hi8 < 8);
15442 // Are the bytes contiguous in the order of increasing addresses.
15443 bool IsConsecutive = (Hi8 - Low8 == 1);
15444 // Is the first byte at location that is aligned for 16 bit instructions.
15445 // A counter example is taking 2 consecutive bytes starting at the 8th bit.
15446 // In this case, we still need code to extract the 16 bit operand, so it
15447 // is better to use i8 v_perm
15448 bool Is16Aligned = !(Low8 % 2);
15449
15450 return IsConsecutive && Is16Aligned;
15451}
15452
15453// Do not lower into v_perm if the operands are actually 16 bit
15454// and the selected bits (based on PermMask) correspond with two
15455// easily addressable 16 bit operands.
15457 SDValue &OtherOp) {
15458 int Low16 = PermMask & 0xffff;
15459 int Hi16 = (PermMask & 0xffff0000) >> 16;
15460
15461 auto TempOp = peekThroughBitcasts(Op);
15462 auto TempOtherOp = peekThroughBitcasts(OtherOp);
15463
15464 auto OpIs16Bit =
15465 TempOp.getValueSizeInBits() == 16 || isExtendedFrom16Bits(TempOp);
15466 if (!OpIs16Bit)
15467 return true;
15468
15469 auto OtherOpIs16Bit = TempOtherOp.getValueSizeInBits() == 16 ||
15470 isExtendedFrom16Bits(TempOtherOp);
15471 if (!OtherOpIs16Bit)
15472 return true;
15473
15474 // Do we cleanly address both
15475 return !addresses16Bits(Low16) || !addresses16Bits(Hi16);
15476}
15477
15479 unsigned DWordOffset) {
15480 SDValue Ret;
15481
15482 auto TypeSize = Src.getValueSizeInBits().getFixedValue();
15483 // ByteProvider must be at least 8 bits
15484 assert(Src.getValueSizeInBits().isKnownMultipleOf(8));
15485
15486 if (TypeSize <= 32)
15487 return DAG.getBitcastedAnyExtOrTrunc(Src, SL, MVT::i32);
15488
15489 if (Src.getValueType().isVector()) {
15490 auto ScalarTySize = Src.getScalarValueSizeInBits();
15491 auto ScalarTy = Src.getValueType().getScalarType();
15492 if (ScalarTySize == 32) {
15493 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Src,
15494 DAG.getConstant(DWordOffset, SL, MVT::i32));
15495 }
15496 if (ScalarTySize > 32) {
15497 Ret = DAG.getNode(
15498 ISD::EXTRACT_VECTOR_ELT, SL, ScalarTy, Src,
15499 DAG.getConstant(DWordOffset / (ScalarTySize / 32), SL, MVT::i32));
15500 auto ShiftVal = 32 * (DWordOffset % (ScalarTySize / 32));
15501 if (ShiftVal)
15502 Ret = DAG.getNode(ISD::SRL, SL, Ret.getValueType(), Ret,
15503 DAG.getConstant(ShiftVal, SL, MVT::i32));
15504 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15505 }
15506
15507 assert(ScalarTySize < 32);
15508 auto NumElements = TypeSize / ScalarTySize;
15509 auto Trunc32Elements = (ScalarTySize * NumElements) / 32;
15510 auto NormalizedTrunc = Trunc32Elements * 32 / ScalarTySize;
15511 auto NumElementsIn32 = 32 / ScalarTySize;
15512 auto NumAvailElements = DWordOffset < Trunc32Elements
15513 ? NumElementsIn32
15514 : NumElements - NormalizedTrunc;
15515
15517 DAG.ExtractVectorElements(Src, VecSrcs, DWordOffset * NumElementsIn32,
15518 NumAvailElements);
15519
15520 Ret = DAG.getBuildVector(
15521 MVT::getVectorVT(MVT::getIntegerVT(ScalarTySize), NumAvailElements), SL,
15522 VecSrcs);
15523 return Ret = DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15524 }
15525
15526 /// Scalar Type
15527 auto ShiftVal = 32 * DWordOffset;
15528 Ret = DAG.getNode(ISD::SRL, SL, Src.getValueType(), Src,
15529 DAG.getConstant(ShiftVal, SL, MVT::i32));
15530 return DAG.getBitcastedAnyExtOrTrunc(Ret, SL, MVT::i32);
15531}
15532
15534 SelectionDAG &DAG = DCI.DAG;
15535 [[maybe_unused]] EVT VT = N->getValueType(0);
15537
15538 // VT is known to be MVT::i32, so we need to provide 4 bytes.
15539 assert(VT == MVT::i32);
15540 for (int i = 0; i < 4; i++) {
15541 // Find the ByteProvider that provides the ith byte of the result of OR
15542 std::optional<ByteProvider<SDValue>> P =
15543 calculateByteProvider(SDValue(N, 0), i, 0, /*StartingIndex = */ i);
15544 // TODO support constantZero
15545 if (!P || P->isConstantZero())
15546 return SDValue();
15547
15548 PermNodes.push_back(*P);
15549 }
15550 if (PermNodes.size() != 4)
15551 return SDValue();
15552
15553 std::pair<unsigned, unsigned> FirstSrc(0, PermNodes[0].SrcOffset / 4);
15554 std::optional<std::pair<unsigned, unsigned>> SecondSrc;
15555 uint64_t PermMask = 0x00000000;
15556 for (size_t i = 0; i < PermNodes.size(); i++) {
15557 auto PermOp = PermNodes[i];
15558 // Since the mask is applied to Src1:Src2, Src1 bytes must be offset
15559 // by sizeof(Src2) = 4
15560 int SrcByteAdjust = 4;
15561
15562 // If the Src uses a byte from a different DWORD, then it corresponds
15563 // with a difference source
15564 if (!PermOp.hasSameSrc(PermNodes[FirstSrc.first]) ||
15565 ((PermOp.SrcOffset / 4) != FirstSrc.second)) {
15566 if (SecondSrc)
15567 if (!PermOp.hasSameSrc(PermNodes[SecondSrc->first]) ||
15568 ((PermOp.SrcOffset / 4) != SecondSrc->second))
15569 return SDValue();
15570
15571 // Set the index of the second distinct Src node
15572 SecondSrc = {i, PermNodes[i].SrcOffset / 4};
15573 assert(!(PermNodes[SecondSrc->first].Src->getValueSizeInBits() % 8));
15574 SrcByteAdjust = 0;
15575 }
15576 assert((PermOp.SrcOffset % 4) + SrcByteAdjust < 8);
15578 PermMask |= ((PermOp.SrcOffset % 4) + SrcByteAdjust) << (i * 8);
15579 }
15580 SDLoc DL(N);
15581 SDValue Op = *PermNodes[FirstSrc.first].Src;
15582 Op = getDWordFromOffset(DAG, DL, Op, FirstSrc.second);
15583 assert(Op.getValueSizeInBits() == 32);
15584
15585 // Check that we are not just extracting the bytes in order from an op
15586 if (!SecondSrc) {
15587 int Low16 = PermMask & 0xffff;
15588 int Hi16 = (PermMask & 0xffff0000) >> 16;
15589
15590 bool WellFormedLow = (Low16 == 0x0504) || (Low16 == 0x0100);
15591 bool WellFormedHi = (Hi16 == 0x0706) || (Hi16 == 0x0302);
15592
15593 // The perm op would really just produce Op. So combine into Op
15594 if (WellFormedLow && WellFormedHi)
15595 return DAG.getBitcast(MVT::getIntegerVT(32), Op);
15596 }
15597
15598 SDValue OtherOp = SecondSrc ? *PermNodes[SecondSrc->first].Src : Op;
15599
15600 if (SecondSrc) {
15601 OtherOp = getDWordFromOffset(DAG, DL, OtherOp, SecondSrc->second);
15602 assert(OtherOp.getValueSizeInBits() == 32);
15603 }
15604
15605 // Check that we haven't just recreated the same FSHR node.
15606 if (N->getOpcode() == ISD::FSHR &&
15607 (N->getOperand(0) == Op || N->getOperand(0) == OtherOp) &&
15608 (N->getOperand(1) == Op || N->getOperand(1) == OtherOp))
15609 return SDValue();
15610
15611 if (hasNon16BitAccesses(PermMask, Op, OtherOp)) {
15612
15613 assert(Op.getValueType().isByteSized() &&
15614 OtherOp.getValueType().isByteSized());
15615
15616 // If the ultimate src is less than 32 bits, then we will only be
15617 // using bytes 0: Op.getValueSizeInBytes() - 1 in the or.
15618 // CalculateByteProvider would not have returned Op as source if we
15619 // used a byte that is outside its ValueType. Thus, we are free to
15620 // ANY_EXTEND as the extended bits are dont-cares.
15621 Op = DAG.getBitcastedAnyExtOrTrunc(Op, DL, MVT::i32);
15622 OtherOp = DAG.getBitcastedAnyExtOrTrunc(OtherOp, DL, MVT::i32);
15623
15624 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op, OtherOp,
15625 DAG.getConstant(PermMask, DL, MVT::i32));
15626 }
15627 return SDValue();
15628}
15629
15630SDValue SITargetLowering::performOrCombine(SDNode *N,
15631 DAGCombinerInfo &DCI) const {
15632 SelectionDAG &DAG = DCI.DAG;
15633 SDValue LHS = N->getOperand(0);
15634 SDValue RHS = N->getOperand(1);
15635
15636 EVT VT = N->getValueType(0);
15637 if (VT == MVT::i1) {
15638 // or (fp_class x, c1), (fp_class x, c2) -> fp_class x, (c1 | c2)
15639 if (LHS.getOpcode() == AMDGPUISD::FP_CLASS &&
15640 RHS.getOpcode() == AMDGPUISD::FP_CLASS) {
15641 SDValue Src = LHS.getOperand(0);
15642 if (Src != RHS.getOperand(0))
15643 return SDValue();
15644
15645 const ConstantSDNode *CLHS = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
15646 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(RHS.getOperand(1));
15647 if (!CLHS || !CRHS)
15648 return SDValue();
15649
15650 // Only 10 bits are used.
15651 static const uint32_t MaxMask = 0x3ff;
15652
15653 uint32_t NewMask =
15654 (CLHS->getZExtValue() | CRHS->getZExtValue()) & MaxMask;
15655 SDLoc DL(N);
15656 return DAG.getNode(AMDGPUISD::FP_CLASS, DL, MVT::i1, Src,
15657 DAG.getConstant(NewMask, DL, MVT::i32));
15658 }
15659
15660 return SDValue();
15661 }
15662
15663 // or (perm x, y, c1), c2 -> perm x, y, permute_mask(c1, c2)
15665 LHS.getOpcode() == AMDGPUISD::PERM &&
15666 isa<ConstantSDNode>(LHS.getOperand(2))) {
15667 uint32_t Sel = getConstantPermuteMask(N->getConstantOperandVal(1));
15668 if (!Sel)
15669 return SDValue();
15670
15671 Sel |= LHS.getConstantOperandVal(2);
15672 SDLoc DL(N);
15673 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15674 LHS.getOperand(1), DAG.getConstant(Sel, DL, MVT::i32));
15675 }
15676
15677 // or (op x, c1), (op y, c2) -> perm x, y, permute_mask(c1, c2)
15678 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
15679 if (VT == MVT::i32 && LHS.hasOneUse() && RHS.hasOneUse() &&
15680 N->isDivergent() && TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
15681
15682 // If all the uses of an or need to extract the individual elements, do not
15683 // attempt to lower into v_perm
15684 auto usesCombinedOperand = [](SDNode *OrUse) {
15685 // If we have any non-vectorized use, then it is a candidate for v_perm
15686 if (OrUse->getOpcode() != ISD::BITCAST ||
15687 !OrUse->getValueType(0).isVector())
15688 return true;
15689
15690 // If we have any non-vectorized use, then it is a candidate for v_perm
15691 for (auto *VUser : OrUse->users()) {
15692 if (!VUser->getValueType(0).isVector())
15693 return true;
15694
15695 // If the use of a vector is a store, then combining via a v_perm
15696 // is beneficial.
15697 // TODO -- whitelist more uses
15698 for (auto VectorwiseOp : {ISD::STORE, ISD::CopyToReg, ISD::CopyFromReg})
15699 if (VUser->getOpcode() == VectorwiseOp)
15700 return true;
15701 }
15702 return false;
15703 };
15704
15705 if (!any_of(N->users(), usesCombinedOperand))
15706 return SDValue();
15707
15708 uint32_t LHSMask = getPermuteMask(LHS);
15709 uint32_t RHSMask = getPermuteMask(RHS);
15710
15711 if (LHSMask != ~0u && RHSMask != ~0u) {
15712 // Canonicalize the expression in an attempt to have fewer unique masks
15713 // and therefore fewer registers used to hold the masks.
15714 if (LHSMask > RHSMask) {
15715 std::swap(LHSMask, RHSMask);
15716 std::swap(LHS, RHS);
15717 }
15718
15719 // Select 0xc for each lane used from source operand. Zero has 0xc mask
15720 // set, 0xff have 0xff in the mask, actual lanes are in the 0-3 range.
15721 uint32_t LHSUsedLanes = ~(LHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15722 uint32_t RHSUsedLanes = ~(RHSMask & 0x0c0c0c0c) & 0x0c0c0c0c;
15723
15724 // Check of we need to combine values from two sources within a byte.
15725 if (!(LHSUsedLanes & RHSUsedLanes) &&
15726 // If we select high and lower word keep it for SDWA.
15727 // TODO: teach SDWA to work with v_perm_b32 and remove the check.
15728 !(LHSUsedLanes == 0x0c0c0000 && RHSUsedLanes == 0x00000c0c)) {
15729 // Kill zero bytes selected by other mask. Zero value is 0xc.
15730 LHSMask &= ~RHSUsedLanes;
15731 RHSMask &= ~LHSUsedLanes;
15732 // Add 4 to each active LHS lane
15733 LHSMask |= LHSUsedLanes & 0x04040404;
15734 // Combine masks
15735 uint32_t Sel = LHSMask | RHSMask;
15736 SDLoc DL(N);
15737
15738 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, LHS.getOperand(0),
15739 RHS.getOperand(0),
15740 DAG.getConstant(Sel, DL, MVT::i32));
15741 }
15742 }
15743 if (LHSMask == ~0u || RHSMask == ~0u) {
15744 if (SDValue Perm = matchPERM(N, DCI))
15745 return Perm;
15746 }
15747 }
15748
15749 // Detect identity v2i32 OR and replace with identity source node.
15750 // Specifically an Or that has operands constructed from the same source node
15751 // via extract_vector_elt and build_vector. I.E.
15752 // v2i32 or(
15753 // v2i32 build_vector(
15754 // i32 extract_elt(%IdentitySrc, 0),
15755 // i32 0
15756 // ),
15757 // v2i32 build_vector(
15758 // i32 0,
15759 // i32 extract_elt(%IdentitySrc, 1)
15760 // ) )
15761 // =>
15762 // v2i32 %IdentitySrc
15763
15764 if (VT == MVT::v2i32 && LHS->getOpcode() == ISD::BUILD_VECTOR &&
15765 RHS->getOpcode() == ISD::BUILD_VECTOR) {
15766
15767 ConstantSDNode *LC = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
15768 ConstantSDNode *RC = dyn_cast<ConstantSDNode>(RHS->getOperand(0));
15769
15770 // Test for and normalise build vectors.
15771 if (LC && RC && LC->getZExtValue() == 0 && RC->getZExtValue() == 0) {
15772
15773 // Get the extract_vector_element operands.
15774 SDValue LEVE = LHS->getOperand(0);
15775 SDValue REVE = RHS->getOperand(1);
15776
15777 if (LEVE->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15779 // Check that different elements from the same vector are
15780 // extracted.
15781 if (LEVE->getOperand(0) == REVE->getOperand(0) &&
15782 LEVE->getOperand(1) != REVE->getOperand(1)) {
15783 SDValue IdentitySrc = LEVE.getOperand(0);
15784 return IdentitySrc;
15785 }
15786 }
15787 }
15788 }
15789
15790 if (VT != MVT::i64 || DCI.isBeforeLegalizeOps())
15791 return SDValue();
15792
15793 // TODO: This could be a generic combine with a predicate for extracting the
15794 // high half of an integer being free.
15795
15796 // (or i64:x, (zero_extend i32:y)) ->
15797 // i64 (bitcast (v2i32 build_vector (or i32:y, lo_32(x)), hi_32(x)))
15798 if (LHS.getOpcode() == ISD::ZERO_EXTEND &&
15799 RHS.getOpcode() != ISD::ZERO_EXTEND)
15800 std::swap(LHS, RHS);
15801
15802 if (RHS.getOpcode() == ISD::ZERO_EXTEND) {
15803 SDValue ExtSrc = RHS.getOperand(0);
15804 EVT SrcVT = ExtSrc.getValueType();
15805 if (SrcVT == MVT::i32) {
15806 SDLoc SL(N);
15807 auto [LowLHS, HiBits] = split64BitValue(LHS, DAG);
15808 SDValue LowOr = DAG.getNode(ISD::OR, SL, MVT::i32, LowLHS, ExtSrc);
15809
15810 DCI.AddToWorklist(LowOr.getNode());
15811 DCI.AddToWorklist(HiBits.getNode());
15812
15813 SDValue Vec =
15814 DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32, LowOr, HiBits);
15815 return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
15816 }
15817 }
15818
15819 const ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
15820 if (CRHS) {
15821 if (SDValue Split = splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::OR,
15822 N->getOperand(0), CRHS))
15823 return Split;
15824 }
15825
15826 return SDValue();
15827}
15828
15829SDValue SITargetLowering::performXorCombine(SDNode *N,
15830 DAGCombinerInfo &DCI) const {
15831 if (SDValue RV = reassociateScalarOps(N, DCI.DAG))
15832 return RV;
15833
15834 SDValue LHS = N->getOperand(0);
15835 SDValue RHS = N->getOperand(1);
15836
15837 const ConstantSDNode *CRHS = isConstOrConstSplat(RHS);
15838 SelectionDAG &DAG = DCI.DAG;
15839
15840 EVT VT = N->getValueType(0);
15841 if (CRHS && VT == MVT::i64) {
15842 if (SDValue Split =
15843 splitBinaryBitConstantOp(DCI, SDLoc(N), ISD::XOR, LHS, CRHS))
15844 return Split;
15845 }
15846
15847 // v2i32 (xor (vselect cc, x, y), K) ->
15848 // (v2i32 svelect cc, (xor x, K), (xor y, K)) This enables the xor to be
15849 // replaced with source modifiers when the select is lowered to CNDMASK.
15850 unsigned Opc = LHS.getOpcode();
15851 if (((Opc == ISD::VSELECT && VT == MVT::v2i32) ||
15852 (Opc == ISD::SELECT && VT == MVT::i64)) &&
15853 CRHS && CRHS->getAPIntValue().isSignMask()) {
15854 SDValue CC = LHS->getOperand(0);
15855 SDValue TRUE = LHS->getOperand(1);
15856 SDValue FALSE = LHS->getOperand(2);
15857 SDValue XTrue = DAG.getNode(ISD::XOR, SDLoc(N), VT, TRUE, RHS);
15858 SDValue XFalse = DAG.getNode(ISD::XOR, SDLoc(N), VT, FALSE, RHS);
15859 SDValue XSelect =
15860 DAG.getNode(ISD::VSELECT, SDLoc(N), VT, CC, XTrue, XFalse);
15861 return XSelect;
15862 }
15863
15864 // Make sure to apply the 64-bit constant splitting fold before trying to fold
15865 // fneg-like xors into 64-bit select.
15866 if (LHS.getOpcode() == ISD::SELECT && VT == MVT::i32) {
15867 // This looks like an fneg, try to fold as a source modifier.
15868 if (CRHS && CRHS->getAPIntValue().isSignMask() &&
15870 // xor (select c, a, b), 0x80000000 ->
15871 // bitcast (select c, (fneg (bitcast a)), (fneg (bitcast b)))
15872 SDLoc DL(N);
15873 SDValue CastLHS =
15874 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(1));
15875 SDValue CastRHS =
15876 DAG.getNode(ISD::BITCAST, DL, MVT::f32, LHS->getOperand(2));
15877 SDValue FNegLHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastLHS);
15878 SDValue FNegRHS = DAG.getNode(ISD::FNEG, DL, MVT::f32, CastRHS);
15879 SDValue NewSelect = DAG.getNode(ISD::SELECT, DL, MVT::f32,
15880 LHS->getOperand(0), FNegLHS, FNegRHS);
15881 return DAG.getNode(ISD::BITCAST, DL, VT, NewSelect);
15882 }
15883 }
15884
15885 return SDValue();
15886}
15887
15888SDValue
15889SITargetLowering::performZeroOrAnyExtendCombine(SDNode *N,
15890 DAGCombinerInfo &DCI) const {
15891 if (!Subtarget->has16BitInsts() ||
15892 DCI.getDAGCombineLevel() < AfterLegalizeTypes)
15893 return SDValue();
15894
15895 EVT VT = N->getValueType(0);
15896 if (VT != MVT::i32)
15897 return SDValue();
15898
15899 SDValue Src = N->getOperand(0);
15900 if (Src.getValueType() != MVT::i16)
15901 return SDValue();
15902
15903 if (!Src->hasOneUse())
15904 return SDValue();
15905
15906 // TODO: We bail out below if SrcOffset is not in the first dword (>= 4). It's
15907 // possible we're missing out on some combine opportunities, but we'd need to
15908 // weigh the cost of extracting the byte from the upper dwords.
15909
15910 std::optional<ByteProvider<SDValue>> BP0 =
15911 calculateByteProvider(SDValue(N, 0), 0, 0, 0);
15912 if (!BP0 || BP0->SrcOffset >= 4 || !BP0->Src)
15913 return SDValue();
15914 SDValue V0 = *BP0->Src;
15915
15916 std::optional<ByteProvider<SDValue>> BP1 =
15917 calculateByteProvider(SDValue(N, 0), 1, 0, 1);
15918 if (!BP1 || BP1->SrcOffset >= 4 || !BP1->Src)
15919 return SDValue();
15920
15921 SDValue V1 = *BP1->Src;
15922
15923 if (V0 == V1)
15924 return SDValue();
15925
15926 SelectionDAG &DAG = DCI.DAG;
15927 SDLoc DL(N);
15928 uint32_t PermMask = 0x0c0c0c0c;
15929 if (V0) {
15930 V0 = DAG.getBitcastedAnyExtOrTrunc(V0, DL, MVT::i32);
15931 PermMask = (PermMask & ~0xFF) | (BP0->SrcOffset + 4);
15932 }
15933
15934 if (V1) {
15935 V1 = DAG.getBitcastedAnyExtOrTrunc(V1, DL, MVT::i32);
15936 PermMask = (PermMask & ~(0xFF << 8)) | (BP1->SrcOffset << 8);
15937 }
15938
15939 return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, V0, V1,
15940 DAG.getConstant(PermMask, DL, MVT::i32));
15941}
15942
15943SDValue
15944SITargetLowering::performSignExtendInRegCombine(SDNode *N,
15945 DAGCombinerInfo &DCI) const {
15946 SDValue Src = N->getOperand(0);
15947 auto *VTSign = cast<VTSDNode>(N->getOperand(1));
15948
15949 // Combine s_buffer_load_u8 or s_buffer_load_u16 with sext and replace them
15950 // with s_buffer_load_i8 and s_buffer_load_i16 respectively.
15951 if (((Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE &&
15952 VTSign->getVT() == MVT::i8) ||
15953 (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_USHORT &&
15954 VTSign->getVT() == MVT::i16))) {
15955 assert(Subtarget->hasScalarSubwordLoads() &&
15956 "s_buffer_load_{u8, i8} are supported "
15957 "in GFX12 (or newer) architectures.");
15958 unsigned Opc = (Src.getOpcode() == AMDGPUISD::SBUFFER_LOAD_UBYTE)
15959 ? AMDGPUISD::SBUFFER_LOAD_BYTE
15960 : AMDGPUISD::SBUFFER_LOAD_SHORT;
15961 SDLoc DL(N);
15962 SDVTList ResList =
15963 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
15964 SDValue Ops[] = {
15965 Src.getOperand(0), // Chain
15966 Src.getOperand(1), // source register
15967 Src.getOperand(2), // offset
15968 Src.getOperand(3) // cachePolicy
15969 };
15970 auto *M = cast<MemSDNode>(Src);
15971 SDValue BufferLoad = DCI.DAG.getMemIntrinsicNode(
15972 Opc, DL, ResList, Ops, M->getMemoryVT(), M->getMemOperand());
15973 return DCI.DAG.getMergeValues({BufferLoad, BufferLoad.getValue(1)}, DL);
15974 }
15975 if (((Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE &&
15976 VTSign->getVT() == MVT::i8) ||
15977 (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_USHORT &&
15978 VTSign->getVT() == MVT::i16)) &&
15979 Src.hasOneUse()) {
15980 auto *M = cast<MemSDNode>(Src);
15981 SDValue Ops[] = {Src.getOperand(0), // Chain
15982 Src.getOperand(1), // rsrc
15983 Src.getOperand(2), // vindex
15984 Src.getOperand(3), // voffset
15985 Src.getOperand(4), // soffset
15986 Src.getOperand(5), // offset
15987 Src.getOperand(6), Src.getOperand(7)};
15988 // replace with BUFFER_LOAD_BYTE/SHORT
15989 SDVTList ResList =
15990 DCI.DAG.getVTList(MVT::i32, Src.getOperand(0).getValueType());
15991 unsigned Opc = (Src.getOpcode() == AMDGPUISD::BUFFER_LOAD_UBYTE)
15992 ? AMDGPUISD::BUFFER_LOAD_BYTE
15993 : AMDGPUISD::BUFFER_LOAD_SHORT;
15994 SDValue BufferLoadSignExt = DCI.DAG.getMemIntrinsicNode(
15995 Opc, SDLoc(N), ResList, Ops, M->getMemoryVT(), M->getMemOperand());
15996 return DCI.DAG.getMergeValues(
15997 {BufferLoadSignExt, BufferLoadSignExt.getValue(1)}, SDLoc(N));
15998 }
15999 return SDValue();
16000}
16001
16002SDValue SITargetLowering::performClassCombine(SDNode *N,
16003 DAGCombinerInfo &DCI) const {
16004 SelectionDAG &DAG = DCI.DAG;
16005 SDValue Mask = N->getOperand(1);
16006
16007 // fp_class x, 0 -> false
16008 if (isNullConstant(Mask))
16009 return DAG.getConstant(0, SDLoc(N), MVT::i1);
16010
16011 if (N->getOperand(0).isUndef())
16012 return DAG.getUNDEF(MVT::i1);
16013
16014 return SDValue();
16015}
16016
16017SDValue SITargetLowering::performRcpCombine(SDNode *N,
16018 DAGCombinerInfo &DCI) const {
16019 EVT VT = N->getValueType(0);
16020 SDValue N0 = N->getOperand(0);
16021
16022 if (N0.isUndef()) {
16023 return DCI.DAG.getConstantFP(APFloat::getQNaN(VT.getFltSemantics()),
16024 SDLoc(N), VT);
16025 }
16026
16027 // TODO: Could handle f32 + amdgcn.sqrt but probably never reaches here.
16028 if ((VT == MVT::f16 && N0.getOpcode() == ISD::FSQRT) &&
16029 N->getFlags().hasAllowContract() && N0->getFlags().hasAllowContract()) {
16030 return DCI.DAG.getNode(AMDGPUISD::RSQ, SDLoc(N), VT, N0.getOperand(0),
16031 N->getFlags());
16032 }
16033
16035}
16036
16038 SDNodeFlags UserFlags,
16039 unsigned MaxDepth) const {
16040 EVT VT = Op.getValueType();
16041 assert(VT.isFloatingPoint() &&
16042 "expected a floating-point value to query canonicality of");
16043 return isCanonicalized(DAG, Op, VT.getScalarType(), UserFlags, MaxDepth);
16044}
16045
16047 EVT QueryVT, SDNodeFlags UserFlags,
16048 unsigned MaxDepth) const {
16049 assert(QueryVT.isFloatingPoint() && !QueryVT.isVector() &&
16050 "QueryVT must be a floating-point scalar type");
16051 EVT VT = Op.getValueType();
16052 if (VT.isFloatingPoint() && VT.getScalarType() != QueryVT)
16053 return false;
16054
16055 unsigned Opcode = Op.getOpcode();
16056 if (Opcode == ISD::FCANONICALIZE)
16057 return true;
16058
16059 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16060 const auto &F = CFP->getValueAPF();
16061 if (F.isNaN() && F.isSignaling())
16062 return false;
16063 if (!F.isDenormal())
16064 return true;
16065
16066 DenormalMode Mode =
16067 DAG.getMachineFunction().getDenormalMode(F.getSemantics());
16068 return Mode == DenormalMode::getIEEE();
16069 }
16070
16071 // If source is a result of another standard FP operation it is already in
16072 // canonical form.
16073 if (MaxDepth == 0)
16074 return false;
16075
16076 switch (Opcode) {
16077 // These will flush denorms if required.
16078 case ISD::FADD:
16079 case ISD::FSUB:
16080 case ISD::FMUL:
16081 case ISD::FCEIL:
16082 case ISD::FFLOOR:
16083 case ISD::FMA:
16084 case ISD::FMAD:
16085 case ISD::FSQRT:
16086 case ISD::FDIV:
16087 case ISD::FREM:
16088 case ISD::FP_ROUND:
16089 case ISD::FP_EXTEND:
16090 case ISD::FP16_TO_FP:
16091 case ISD::FP_TO_FP16:
16092 case ISD::BF16_TO_FP:
16093 case ISD::FP_TO_BF16:
16094 case ISD::FLDEXP:
16095 case AMDGPUISD::FMUL_LEGACY:
16096 case AMDGPUISD::FMAD_FTZ:
16097 case AMDGPUISD::RCP:
16098 case AMDGPUISD::RSQ:
16099 case AMDGPUISD::RSQ_CLAMP:
16100 case AMDGPUISD::RCP_LEGACY:
16101 case AMDGPUISD::RCP_IFLAG:
16102 case AMDGPUISD::LOG:
16103 case AMDGPUISD::EXP:
16104 case AMDGPUISD::DIV_SCALE:
16105 case AMDGPUISD::DIV_FMAS:
16106 case AMDGPUISD::DIV_FIXUP:
16107 case AMDGPUISD::FRACT:
16108 case AMDGPUISD::CVT_PKRTZ_F16_F32:
16109 case AMDGPUISD::CVT_F32_UBYTE0:
16110 case AMDGPUISD::CVT_F32_UBYTE1:
16111 case AMDGPUISD::CVT_F32_UBYTE2:
16112 case AMDGPUISD::CVT_F32_UBYTE3:
16113 case AMDGPUISD::FP_TO_FP16:
16114 case AMDGPUISD::SIN_HW:
16115 case AMDGPUISD::COS_HW:
16116 return true;
16117
16118 // It can/will be lowered or combined as a bit operation.
16119 // Need to check their input recursively to handle.
16120 case ISD::FNEG:
16121 case ISD::FABS:
16122 case ISD::FCOPYSIGN:
16123 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16124 MaxDepth - 1);
16125
16126 case ISD::AND:
16127 if (Op.getValueType() == MVT::i32) {
16128 // Be careful as we only know it is a bitcast floating point type. It
16129 // could be f32, v2f16, we have no way of knowing. Luckily the constant
16130 // value that we optimize for, which comes up in fp32 to bf16 conversions,
16131 // is valid to optimize for all types.
16132 if (auto *RHS = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
16133 if (RHS->getZExtValue() == 0xffff0000) {
16134 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16135 MaxDepth - 1);
16136 }
16137 }
16138 }
16139 break;
16140
16141 case ISD::FSIN:
16142 case ISD::FCOS:
16143 case ISD::FSINCOS:
16144 return Op.getValueType().getScalarType() != MVT::f16;
16145
16146 case ISD::FMINNUM:
16147 case ISD::FMAXNUM:
16148 case ISD::FMINNUM_IEEE:
16149 case ISD::FMAXNUM_IEEE:
16150 case ISD::FMINIMUM:
16151 case ISD::FMAXIMUM:
16152 case ISD::FMINIMUMNUM:
16153 case ISD::FMAXIMUMNUM:
16154 case AMDGPUISD::CLAMP:
16155 case AMDGPUISD::FMED3:
16156 case AMDGPUISD::FMAX3:
16157 case AMDGPUISD::FMIN3:
16158 case AMDGPUISD::FMAXIMUM3:
16159 case AMDGPUISD::FMINIMUM3: {
16160 // FIXME: Shouldn't treat the generic operations different based these.
16161 // However, we aren't really required to flush the result from
16162 // minnum/maxnum..
16163
16164 // snans will be quieted, so we only need to worry about denormals.
16165 if (Subtarget->supportsMinMaxDenormModes() ||
16166 // FIXME: denormalsEnabledForType is broken for dynamic
16167 denormalsEnabledForType(DAG, Op.getValueType()))
16168 return true;
16169
16170 // Flushing may be required.
16171 // In pre-GFX9 targets V_MIN_F32 and others do not flush denorms. For such
16172 // targets need to check their input recursively.
16173
16174 // FIXME: Does this apply with clamp? It's implemented with max.
16175 for (unsigned I = 0, E = Op.getNumOperands(); I != E; ++I) {
16176 if (!isCanonicalized(DAG, Op.getOperand(I), QueryVT, UserFlags,
16177 MaxDepth - 1))
16178 return false;
16179 }
16180
16181 return true;
16182 }
16183 case ISD::SELECT: {
16184 return isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16185 MaxDepth - 1) &&
16186 isCanonicalized(DAG, Op.getOperand(2), QueryVT, UserFlags,
16187 MaxDepth - 1);
16188 }
16189 case ISD::BUILD_VECTOR: {
16190 for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
16191 SDValue SrcOp = Op.getOperand(i);
16192 if (!isCanonicalized(DAG, SrcOp, QueryVT, UserFlags, MaxDepth - 1))
16193 return false;
16194 }
16195
16196 return true;
16197 }
16200 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16201 MaxDepth - 1);
16202 }
16204 return isCanonicalized(DAG, Op.getOperand(0), QueryVT, UserFlags,
16205 MaxDepth - 1) &&
16206 isCanonicalized(DAG, Op.getOperand(1), QueryVT, UserFlags,
16207 MaxDepth - 1);
16208 }
16209 case ISD::POISON:
16210 return true;
16211 case ISD::UNDEF:
16212 // Could be anything.
16213 return false;
16214
16215 case ISD::BITCAST: {
16216 // Carry QueryVT through the bitcast unchanged. The top-of-function guard
16217 // rejects a source whose FP format differs from the consumed type, so a
16218 // value canonical in one FP format is not assumed canonical in another.
16219 SDValue Src = peekThroughBitcasts(Op.getOperand(0));
16220 return isCanonicalized(DAG, Src, QueryVT, UserFlags, MaxDepth - 1);
16221 }
16222 case ISD::TRUNCATE: {
16223 // Hack round the mess we make when legalizing extract_vector_elt
16224 if (Op.getValueType() == MVT::i16) {
16225 SDValue TruncSrc = Op.getOperand(0);
16226 if (TruncSrc.getValueType() == MVT::i32 &&
16227 TruncSrc.getOpcode() == ISD::BITCAST &&
16228 TruncSrc.getOperand(0).getValueType() == MVT::v2f16) {
16229 return isCanonicalized(DAG, TruncSrc.getOperand(0), QueryVT, UserFlags,
16230 MaxDepth - 1);
16231 }
16232 }
16233 return false;
16234 }
16236 unsigned IntrinsicID = Op.getConstantOperandVal(0);
16237 // TODO: Handle more intrinsics
16238 switch (IntrinsicID) {
16239 case Intrinsic::amdgcn_cvt_pkrtz:
16240 case Intrinsic::amdgcn_cubeid:
16241 case Intrinsic::amdgcn_frexp_mant:
16242 case Intrinsic::amdgcn_fdot2:
16243 case Intrinsic::amdgcn_rcp:
16244 case Intrinsic::amdgcn_rsq:
16245 case Intrinsic::amdgcn_rsq_clamp:
16246 case Intrinsic::amdgcn_rcp_legacy:
16247 case Intrinsic::amdgcn_rsq_legacy:
16248 case Intrinsic::amdgcn_trig_preop:
16249 case Intrinsic::amdgcn_tanh:
16250 case Intrinsic::amdgcn_log:
16251 case Intrinsic::amdgcn_exp2:
16252 case Intrinsic::amdgcn_sqrt:
16253 return true;
16254 default:
16255 break;
16256 }
16257
16258 break;
16259 }
16260 default:
16261 break;
16262 }
16263
16264 // FIXME: denormalsEnabledForType is broken for dynamic
16265 return denormalsEnabledForType(DAG, Op.getValueType()) &&
16266 (UserFlags.hasNoNaNs() || DAG.isKnownNeverSNaN(Op));
16267}
16268
16270 unsigned MaxDepth) const {
16271 const MachineRegisterInfo &MRI = MF.getRegInfo();
16272 MachineInstr *MI = MRI.getVRegDef(Reg);
16273 unsigned Opcode = MI->getOpcode();
16274
16275 if (Opcode == AMDGPU::G_FCANONICALIZE)
16276 return true;
16277
16278 std::optional<FPValueAndVReg> FCR;
16279 // Constant splat (can be padded with undef) or scalar constant.
16280 if (mi_match(Reg, MRI, MIPatternMatch::m_GFCstOrSplat(FCR))) {
16281 if (FCR->Value.isSignaling())
16282 return false;
16283 if (!FCR->Value.isDenormal())
16284 return true;
16285
16286 DenormalMode Mode = MF.getDenormalMode(FCR->Value.getSemantics());
16287 return Mode == DenormalMode::getIEEE();
16288 }
16289
16290 if (MaxDepth == 0)
16291 return false;
16292
16293 switch (Opcode) {
16294 case AMDGPU::G_FADD:
16295 case AMDGPU::G_FSUB:
16296 case AMDGPU::G_FMUL:
16297 case AMDGPU::G_FCEIL:
16298 case AMDGPU::G_FFLOOR:
16299 case AMDGPU::G_FRINT:
16300 case AMDGPU::G_FNEARBYINT:
16301 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
16302 case AMDGPU::G_INTRINSIC_TRUNC:
16303 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
16304 case AMDGPU::G_FMA:
16305 case AMDGPU::G_FMAD:
16306 case AMDGPU::G_FSQRT:
16307 case AMDGPU::G_FDIV:
16308 case AMDGPU::G_FREM:
16309 case AMDGPU::G_FPOW:
16310 case AMDGPU::G_FPEXT:
16311 case AMDGPU::G_FLOG:
16312 case AMDGPU::G_FLOG2:
16313 case AMDGPU::G_FLOG10:
16314 case AMDGPU::G_FPTRUNC:
16315 case AMDGPU::G_AMDGPU_RCP_IFLAG:
16316 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
16317 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
16318 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
16319 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
16320 return true;
16321 case AMDGPU::G_FNEG:
16322 case AMDGPU::G_FABS:
16323 case AMDGPU::G_FCOPYSIGN:
16324 return isCanonicalized(MI->getOperand(1).getReg(), MF, MaxDepth - 1);
16325 case AMDGPU::G_FMINNUM:
16326 case AMDGPU::G_FMAXNUM:
16327 case AMDGPU::G_FMINNUM_IEEE:
16328 case AMDGPU::G_FMAXNUM_IEEE:
16329 case AMDGPU::G_FMINIMUM:
16330 case AMDGPU::G_FMAXIMUM:
16331 case AMDGPU::G_FMINIMUMNUM:
16332 case AMDGPU::G_FMAXIMUMNUM: {
16333 if (Subtarget->supportsMinMaxDenormModes() ||
16334 // FIXME: denormalsEnabledForType is broken for dynamic
16335 denormalsEnabledForType(MRI.getType(Reg), MF))
16336 return true;
16337
16338 [[fallthrough]];
16339 }
16340 case AMDGPU::G_BUILD_VECTOR:
16341 for (const MachineOperand &MO : llvm::drop_begin(MI->operands()))
16342 if (!isCanonicalized(MO.getReg(), MF, MaxDepth - 1))
16343 return false;
16344 return true;
16345 case AMDGPU::G_INTRINSIC:
16346 case AMDGPU::G_INTRINSIC_CONVERGENT:
16347 switch (cast<GIntrinsic>(MI)->getIntrinsicID()) {
16348 case Intrinsic::amdgcn_fmul_legacy:
16349 case Intrinsic::amdgcn_fmad_ftz:
16350 case Intrinsic::amdgcn_sqrt:
16351 case Intrinsic::amdgcn_fmed3:
16352 case Intrinsic::amdgcn_sin:
16353 case Intrinsic::amdgcn_cos:
16354 case Intrinsic::amdgcn_log:
16355 case Intrinsic::amdgcn_exp2:
16356 case Intrinsic::amdgcn_log_clamp:
16357 case Intrinsic::amdgcn_rcp:
16358 case Intrinsic::amdgcn_rcp_legacy:
16359 case Intrinsic::amdgcn_rsq:
16360 case Intrinsic::amdgcn_rsq_clamp:
16361 case Intrinsic::amdgcn_rsq_legacy:
16362 case Intrinsic::amdgcn_div_scale:
16363 case Intrinsic::amdgcn_div_fmas:
16364 case Intrinsic::amdgcn_div_fixup:
16365 case Intrinsic::amdgcn_fract:
16366 case Intrinsic::amdgcn_cvt_pkrtz:
16367 case Intrinsic::amdgcn_cubeid:
16368 case Intrinsic::amdgcn_cubema:
16369 case Intrinsic::amdgcn_cubesc:
16370 case Intrinsic::amdgcn_cubetc:
16371 case Intrinsic::amdgcn_frexp_mant:
16372 case Intrinsic::amdgcn_fdot2:
16373 case Intrinsic::amdgcn_trig_preop:
16374 case Intrinsic::amdgcn_tanh:
16375 return true;
16376 default:
16377 break;
16378 }
16379
16380 [[fallthrough]];
16381 default:
16382 return false;
16383 }
16384
16385 llvm_unreachable("invalid operation");
16386}
16387
16388// Constant fold canonicalize.
16389SDValue SITargetLowering::getCanonicalConstantFP(SelectionDAG &DAG,
16390 const SDLoc &SL, EVT VT,
16391 const APFloat &C) const {
16392 // Flush denormals to 0 if not enabled.
16393 if (C.isDenormal()) {
16394 DenormalMode Mode =
16395 DAG.getMachineFunction().getDenormalMode(C.getSemantics());
16396 if (Mode == DenormalMode::getPreserveSign()) {
16397 return DAG.getConstantFP(
16398 APFloat::getZero(C.getSemantics(), C.isNegative()), SL, VT);
16399 }
16400
16401 if (Mode != DenormalMode::getIEEE())
16402 return SDValue();
16403 }
16404
16405 if (C.isNaN()) {
16406 if (C.isSignaling()) {
16407 // Quiet a signaling NaN.
16408 return DAG.getConstantFP(C.makeQuiet(), SL, VT);
16409 }
16410 }
16411
16412 // Already canonical.
16413 return DAG.getConstantFP(C, SL, VT);
16414}
16415
16417 return Op.isUndef() || isa<ConstantFPSDNode>(Op);
16418}
16419
16420SDValue
16421SITargetLowering::performFCanonicalizeCombine(SDNode *N,
16422 DAGCombinerInfo &DCI) const {
16423 SelectionDAG &DAG = DCI.DAG;
16424 SDValue N0 = N->getOperand(0);
16425 EVT VT = N->getValueType(0);
16426
16427 // fcanonicalize undef -> qnan
16428 if (N0.isUndef()) {
16430 return DAG.getConstantFP(QNaN, SDLoc(N), VT);
16431 }
16432
16433 if (ConstantFPSDNode *CFP = isConstOrConstSplatFP(N0))
16434 return getCanonicalConstantFP(DAG, SDLoc(N), VT, CFP->getValueAPF());
16435
16436 // fcanonicalize (build_vector x, k) -> build_vector (fcanonicalize x),
16437 // (fcanonicalize k)
16438 //
16439 // fcanonicalize (build_vector x, undef) -> build_vector (fcanonicalize x), 0
16440
16441 // TODO: This could be better with wider vectors that will be split to v2f16,
16442 // and to consider uses since there aren't that many packed operations.
16443 if (N0.getOpcode() == ISD::BUILD_VECTOR && N0.getNumOperands() == 2 &&
16444 isTypeLegal(VT)) {
16445 SDLoc SL(N);
16446 SDValue NewElts[2];
16447 SDValue Lo = N0.getOperand(0);
16448 SDValue Hi = N0.getOperand(1);
16449 EVT EltVT = Lo.getValueType();
16450
16451 // Only apply this optimization if scalar canonicalize is legal for the
16452 // element type. Otherwise, scalarizing may require widening the scalar back
16453 // to a vector, adding overhead (e.g., bf16 has no scalar instructions).
16455 return SDValue();
16456
16458 for (unsigned I = 0; I != 2; ++I) {
16459 SDValue Op = N0.getOperand(I);
16460 if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op)) {
16461 NewElts[I] =
16462 getCanonicalConstantFP(DAG, SL, EltVT, CFP->getValueAPF());
16463 } else if (Op.isUndef()) {
16464 // Handled below based on what the other operand is.
16465 NewElts[I] = Op;
16466 } else {
16467 NewElts[I] = DAG.getNode(ISD::FCANONICALIZE, SL, EltVT, Op);
16468 }
16469 }
16470
16471 // If one half is undef, and one is constant, prefer a splat vector.
16472 // Otherwise, convert the undef to 0.0 since that's cheaper to use and may
16473 // be free with a packed operation.
16474 if (NewElts[0].isUndef()) {
16475 NewElts[0] = isa<ConstantFPSDNode>(NewElts[1])
16476 ? NewElts[1]
16477 : DAG.getConstantFP(0.0f, SL, EltVT);
16478 }
16479
16480 if (NewElts[1].isUndef()) {
16481 NewElts[1] = isa<ConstantFPSDNode>(NewElts[0])
16482 ? NewElts[0]
16483 : DAG.getConstantFP(0.0f, SL, EltVT);
16484 }
16485
16486 return DAG.getBuildVector(VT, SL, NewElts);
16487 }
16488 }
16489
16490 return SDValue();
16491}
16492
16493static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc) {
16494 switch (Opc) {
16495 case ISD::FMAXNUM:
16496 case ISD::FMAXNUM_IEEE:
16497 case ISD::FMAXIMUMNUM:
16498 return AMDGPUISD::FMAX3;
16499 case ISD::FMAXIMUM:
16500 return AMDGPUISD::FMAXIMUM3;
16501 case ISD::SMAX:
16502 return AMDGPUISD::SMAX3;
16503 case ISD::UMAX:
16504 return AMDGPUISD::UMAX3;
16505 case ISD::FMINNUM:
16506 case ISD::FMINNUM_IEEE:
16507 case ISD::FMINIMUMNUM:
16508 return AMDGPUISD::FMIN3;
16509 case ISD::FMINIMUM:
16510 return AMDGPUISD::FMINIMUM3;
16511 case ISD::SMIN:
16512 return AMDGPUISD::SMIN3;
16513 case ISD::UMIN:
16514 return AMDGPUISD::UMIN3;
16515 default:
16516 llvm_unreachable("Not a min/max opcode");
16517 }
16518}
16519
16520SDValue SITargetLowering::performIntMed3ImmCombine(SelectionDAG &DAG,
16521 const SDLoc &SL, SDValue Src,
16522 SDValue MinVal,
16523 SDValue MaxVal,
16524 bool Signed) const {
16525
16526 // med3 comes from
16527 // min(max(x, K0), K1), K0 < K1
16528 // max(min(x, K0), K1), K1 < K0
16529 //
16530 // "MinVal" and "MaxVal" respectively refer to the rhs of the
16531 // min/max op.
16532 ConstantSDNode *MinK = dyn_cast<ConstantSDNode>(MinVal);
16533 ConstantSDNode *MaxK = dyn_cast<ConstantSDNode>(MaxVal);
16534
16535 if (!MinK || !MaxK)
16536 return SDValue();
16537
16538 if (Signed) {
16539 if (MaxK->getAPIntValue().sge(MinK->getAPIntValue()))
16540 return SDValue();
16541 } else {
16542 if (MaxK->getAPIntValue().uge(MinK->getAPIntValue()))
16543 return SDValue();
16544 }
16545
16546 EVT VT = MinK->getValueType(0);
16547 unsigned Med3Opc = Signed ? AMDGPUISD::SMED3 : AMDGPUISD::UMED3;
16548 if (VT == MVT::i32 || (VT == MVT::i16 && Subtarget->hasMed3_16()))
16549 return DAG.getNode(Med3Opc, SL, VT, Src, MaxVal, MinVal);
16550
16551 // Note: we could also extend to i32 and use i32 med3 if i16 med3 is
16552 // not available, but this is unlikely to be profitable as constants
16553 // will often need to be materialized & extended, especially on
16554 // pre-GFX10 where VOP3 instructions couldn't take literal operands.
16555 return SDValue();
16556}
16557
16560 return C;
16561
16563 if (ConstantFPSDNode *C = BV->getConstantFPSplatNode())
16564 return C;
16565 }
16566
16567 return nullptr;
16568}
16569
16570SDValue SITargetLowering::performFPMed3ImmCombine(SelectionDAG &DAG,
16571 const SDLoc &SL, SDValue Op0,
16572 SDValue Op1,
16573 bool IsKnownNoNaNs) const {
16574 ConstantFPSDNode *K1 = getSplatConstantFP(Op1);
16575 if (!K1)
16576 return SDValue();
16577
16578 ConstantFPSDNode *K0 = getSplatConstantFP(Op0.getOperand(1));
16579 if (!K0)
16580 return SDValue();
16581
16582 // Ordered >= (although NaN inputs should have folded away by now).
16583 if (K0->getValueAPF() > K1->getValueAPF())
16584 return SDValue();
16585
16586 // med3 with a nan input acts like
16587 // v_min_f32(v_min_f32(S0.f32, S1.f32), S2.f32)
16588 //
16589 // So the result depends on whether the IEEE mode bit is enabled or not with a
16590 // signaling nan input.
16591 // ieee=1
16592 // s0 snan: yields s2
16593 // s1 snan: yields s2
16594 // s2 snan: qnan
16595
16596 // s0 qnan: min(s1, s2)
16597 // s1 qnan: min(s0, s2)
16598 // s2 qnan: min(s0, s1)
16599
16600 // ieee=0
16601 // s0 snan: min(s1, s2)
16602 // s1 snan: min(s0, s2)
16603 // s2 snan: qnan
16604
16605 // s0 qnan: min(s1, s2)
16606 // s1 qnan: min(s0, s2)
16607 // s2 qnan: min(s0, s1)
16608 const MachineFunction &MF = DAG.getMachineFunction();
16609 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
16610
16611 // TODO: Check IEEE bit enabled. We can form fmed3 with IEEE=0 regardless of
16612 // whether the input is a signaling nan if op0 is fmaximum or fmaximumnum. We
16613 // can only form if op0 is fmaxnum_ieee if IEEE=1.
16614 EVT VT = Op0.getValueType();
16615 if (Info->getMode().DX10Clamp) {
16616 // If dx10_clamp is enabled, NaNs clamp to 0.0. This is the same as the
16617 // hardware fmed3 behavior converting to a min.
16618 // FIXME: Should this be allowing -0.0?
16619 if (K1->isOne() && K0->isPosZero())
16620 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Op0.getOperand(0));
16621 }
16622
16623 // med3 for f16 is only available on gfx9+, and not available for v2f16.
16624 if (VT == MVT::f32 || (VT == MVT::f16 && Subtarget->hasMed3_16())) {
16625 // This isn't safe with signaling NaNs because in IEEE mode, min/max on a
16626 // signaling NaN gives a quiet NaN. The quiet NaN input to the min would
16627 // then give the other result, which is different from med3 with a NaN
16628 // input.
16629 SDValue Var = Op0.getOperand(0);
16630 if (!IsKnownNoNaNs && !DAG.isKnownNeverSNaN(Var))
16631 return SDValue();
16632
16633 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
16634
16635 if ((!K0->hasOneUse() || TII->isInlineConstant(K0->getValueAPF())) &&
16636 (!K1->hasOneUse() || TII->isInlineConstant(K1->getValueAPF()))) {
16637 return DAG.getNode(AMDGPUISD::FMED3, SL, K0->getValueType(0), Var,
16638 SDValue(K0, 0), SDValue(K1, 0));
16639 }
16640 }
16641
16642 return SDValue();
16643}
16644
16645/// \return true if the subtarget supports minimum3 and maximum3 with the given
16646/// base min/max opcode \p Opc for type \p VT.
16647static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc,
16648 EVT VT) {
16649 switch (Opc) {
16650 case ISD::FMINNUM:
16651 case ISD::FMAXNUM:
16652 case ISD::FMINNUM_IEEE:
16653 case ISD::FMAXNUM_IEEE:
16654 case ISD::FMINIMUMNUM:
16655 case ISD::FMAXIMUMNUM:
16656 case AMDGPUISD::FMIN_LEGACY:
16657 case AMDGPUISD::FMAX_LEGACY:
16658 return (VT == MVT::f32) || (VT == MVT::f16 && Subtarget.hasMin3Max3_16()) ||
16659 (VT == MVT::v2f16 && Subtarget.hasMin3Max3PKF16());
16660 case ISD::FMINIMUM:
16661 case ISD::FMAXIMUM:
16662 return (VT == MVT::f32 && Subtarget.hasMinimum3Maximum3F32()) ||
16663 (VT == MVT::f16 && Subtarget.hasMinimum3Maximum3F16()) ||
16664 (VT == MVT::v2f16 && Subtarget.hasMinimum3Maximum3PKF16());
16665 case ISD::SMAX:
16666 case ISD::SMIN:
16667 case ISD::UMAX:
16668 case ISD::UMIN:
16669 return (VT == MVT::i32) || (VT == MVT::i16 && Subtarget.hasMin3Max3_16());
16670 default:
16671 return false;
16672 }
16673
16674 llvm_unreachable("not a min/max opcode");
16675}
16676
16677SDValue SITargetLowering::performMinMaxCombine(SDNode *N,
16678 DAGCombinerInfo &DCI) const {
16679 SelectionDAG &DAG = DCI.DAG;
16680
16681 EVT VT = N->getValueType(0);
16682 unsigned Opc = N->getOpcode();
16683 SDValue Op0 = N->getOperand(0);
16684 SDValue Op1 = N->getOperand(1);
16685
16686 // Only do this if the inner op has one use since this will just increases
16687 // register pressure for no benefit.
16688
16689 if (supportsMin3Max3(*Subtarget, Opc, VT)) {
16690 auto IsTreeWithCombinableChildren = [Opc](SDValue Op) {
16691 return (Op.getOperand(0).getOpcode() == Opc &&
16692 Op.getOperand(0).hasOneUse()) ||
16693 (Op.getOperand(1).getOpcode() == Opc &&
16694 Op.getOperand(1).hasOneUse());
16695 };
16696
16697 bool CanTreeCombineApply = Op0.getOpcode() == Opc && Op0.hasOneUse() &&
16698 Op1.getOpcode() == Opc && Op1.hasOneUse();
16699 bool HasCombinableTreeChild =
16700 CanTreeCombineApply && (IsTreeWithCombinableChildren(Op0) ||
16701 IsTreeWithCombinableChildren(Op1));
16702
16703 // Tree reduction: when both operands are the same min/max op, restructure
16704 // to keep a 2-op node on top so higher tree levels can still combine.
16705 //
16706 // max(max(a, b), max(c, d)) -> max(max3(a, b, c), d)
16707 // min(min(a, b), min(c, d)) -> min(min3(a, b, c), d)
16708 //
16709 // Defer when either inner op is a tree node with combinable children.
16710 if (CanTreeCombineApply && !HasCombinableTreeChild) {
16711 SDLoc DL(N);
16712 SDValue Inner =
16714 Op0.getOperand(1), Op1.getOperand(0));
16715 return DAG.getNode(Opc, DL, VT, Inner, Op1.getOperand(1));
16716 }
16717
16718 // max(max(a, b), c) -> max3(a, b, c)
16719 // min(min(a, b), c) -> min3(a, b, c)
16720 // Deferred when Op0 is a tree node with combinable children.
16721 if (Op0.getOpcode() == Opc && Op0.hasOneUse() && !HasCombinableTreeChild) {
16722 SDLoc DL(N);
16723 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
16724 Op0.getOperand(0), Op0.getOperand(1), Op1);
16725 }
16726
16727 // Try commuted.
16728 // max(a, max(b, c)) -> max3(a, b, c)
16729 // min(a, min(b, c)) -> min3(a, b, c)
16730 // Deferred when Op1 is a tree node with combinable children.
16731 if (Op1.getOpcode() == Opc && Op1.hasOneUse() && !HasCombinableTreeChild) {
16732 SDLoc DL(N);
16733 return DAG.getNode(minMaxOpcToMin3Max3Opc(Opc), DL, N->getValueType(0),
16734 Op0, Op1.getOperand(0), Op1.getOperand(1));
16735 }
16736 }
16737
16738 // umin(sffbh(x), bitwidth) -> sffbh(x) if x is known to be not 0 or -1.
16739 SDValue FfbhSrc;
16740 uint64_t Clamp = 0;
16741 if (Opc == ISD::UMIN &&
16742 sd_match(Op0,
16744 sd_match(Op1, m_ConstInt(Clamp))) {
16745 unsigned BitWidth = FfbhSrc.getValueType().getScalarSizeInBits();
16746 if (Clamp >= BitWidth) {
16747 KnownBits Known = DAG.computeKnownBits(FfbhSrc);
16748 if (Known.isNonZero() && Known.Zero.getBoolValue())
16749 return Op0;
16750 }
16751 }
16752
16753 // min(max(x, K0), K1), K0 < K1 -> med3(x, K0, K1)
16754 // max(min(x, K0), K1), K1 < K0 -> med3(x, K1, K0)
16755 if (Opc == ISD::SMIN && Op0.getOpcode() == ISD::SMAX && Op0.hasOneUse()) {
16756 if (SDValue Med3 = performIntMed3ImmCombine(
16757 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), true))
16758 return Med3;
16759 }
16760 if (Opc == ISD::SMAX && Op0.getOpcode() == ISD::SMIN && Op0.hasOneUse()) {
16761 if (SDValue Med3 = performIntMed3ImmCombine(
16762 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, true))
16763 return Med3;
16764 }
16765
16766 if (Opc == ISD::UMIN && Op0.getOpcode() == ISD::UMAX && Op0.hasOneUse()) {
16767 if (SDValue Med3 = performIntMed3ImmCombine(
16768 DAG, SDLoc(N), Op0->getOperand(0), Op1, Op0->getOperand(1), false))
16769 return Med3;
16770 }
16771 if (Opc == ISD::UMAX && Op0.getOpcode() == ISD::UMIN && Op0.hasOneUse()) {
16772 if (SDValue Med3 = performIntMed3ImmCombine(
16773 DAG, SDLoc(N), Op0->getOperand(0), Op0->getOperand(1), Op1, false))
16774 return Med3;
16775 }
16776
16777 // if !is_snan(x):
16778 // fminnum(fmaxnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16779 // fminnum_ieee(fmaxnum_ieee(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16780 // fminnumnum(fmaxnumnum(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16781 // fmin_legacy(fmax_legacy(x, K0), K1), K0 < K1 -> fmed3(x, K0, K1)
16782 if (((Opc == ISD::FMINNUM && Op0.getOpcode() == ISD::FMAXNUM) ||
16785 (Opc == AMDGPUISD::FMIN_LEGACY &&
16786 Op0.getOpcode() == AMDGPUISD::FMAX_LEGACY)) &&
16787 (VT == MVT::f32 || VT == MVT::f64 ||
16788 (VT == MVT::f16 && Subtarget->has16BitInsts()) ||
16789 (VT == MVT::bf16 && Subtarget->hasBF16PackedInsts()) ||
16790 (VT == MVT::v2bf16 && Subtarget->hasBF16PackedInsts()) ||
16791 (VT == MVT::v2f16 && Subtarget->hasVOP3PInsts())) &&
16792 Op0.hasOneUse()) {
16793 if (SDValue Res = performFPMed3ImmCombine(DAG, SDLoc(N), Op0, Op1,
16794 N->getFlags().hasNoNaNs()))
16795 return Res;
16796 }
16797
16798 // Prefer fminnum_ieee over fminimum. For gfx950, minimum/maximum are legal
16799 // for some types, but at a higher cost since it's implemented with a 3
16800 // operand form.
16801 const SDNodeFlags Flags = N->getFlags();
16802 if ((Opc == ISD::FMINIMUM || Opc == ISD::FMAXIMUM) && Flags.hasNoNaNs() &&
16803 !Subtarget->hasIEEEMinimumMaximumInsts() &&
16805 unsigned NewOpc =
16807 return DAG.getNode(NewOpc, SDLoc(N), VT, Op0, Op1, Flags);
16808 }
16809
16810 return SDValue();
16811}
16812
16816 // FIXME: Should this be allowing -0.0?
16817 return (CA->isPosZero() && CB->isOne()) ||
16818 (CA->isOne() && CB->isPosZero());
16819 }
16820 }
16821
16822 return false;
16823}
16824
16825// FIXME: Should only worry about snans for version with chain.
16826SDValue SITargetLowering::performFMed3Combine(SDNode *N,
16827 DAGCombinerInfo &DCI) const {
16828 EVT VT = N->getValueType(0);
16829 // v_med3_f32 and v_max_f32 behave identically wrt denorms, exceptions and
16830 // NaNs. With a NaN input, the order of the operands may change the result.
16831
16832 SelectionDAG &DAG = DCI.DAG;
16833 SDLoc SL(N);
16834
16835 SDValue Src0 = N->getOperand(0);
16836 SDValue Src1 = N->getOperand(1);
16837 SDValue Src2 = N->getOperand(2);
16838
16839 if (isClampZeroToOne(Src0, Src1)) {
16840 // const_a, const_b, x -> clamp is safe in all cases including signaling
16841 // nans.
16842 // FIXME: Should this be allowing -0.0?
16843 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src2);
16844 }
16845
16846 const MachineFunction &MF = DAG.getMachineFunction();
16847 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
16848
16849 // FIXME: dx10_clamp behavior assumed in instcombine. Should we really bother
16850 // handling no dx10-clamp?
16851 if (Info->getMode().DX10Clamp) {
16852 // If NaNs is clamped to 0, we are free to reorder the inputs.
16853
16854 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
16855 std::swap(Src0, Src1);
16856
16857 if (isa<ConstantFPSDNode>(Src1) && !isa<ConstantFPSDNode>(Src2))
16858 std::swap(Src1, Src2);
16859
16860 if (isa<ConstantFPSDNode>(Src0) && !isa<ConstantFPSDNode>(Src1))
16861 std::swap(Src0, Src1);
16862
16863 if (isClampZeroToOne(Src1, Src2))
16864 return DAG.getNode(AMDGPUISD::CLAMP, SL, VT, Src0);
16865 }
16866
16867 return SDValue();
16868}
16869
16870SDValue SITargetLowering::performCvtPkRTZCombine(SDNode *N,
16871 DAGCombinerInfo &DCI) const {
16872 SDValue Src0 = N->getOperand(0);
16873 SDValue Src1 = N->getOperand(1);
16874 if (Src0.isUndef() && Src1.isUndef())
16875 return DCI.DAG.getUNDEF(N->getValueType(0));
16876 return SDValue();
16877}
16878
16879// Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be
16880// expanded into a set of cmp/select instructions.
16882 unsigned NumElem,
16883 bool IsDivergentIdx,
16884 const GCNSubtarget *Subtarget) {
16886 return false;
16887
16888 unsigned VecSize = EltSize * NumElem;
16889
16890 // Sub-dword vectors of size 2 dword or less have better implementation.
16891 if (VecSize <= 64 && EltSize < 32)
16892 return false;
16893
16894 // Always expand the rest of sub-dword instructions, otherwise it will be
16895 // lowered via memory.
16896 if (EltSize < 32)
16897 return true;
16898
16899 // Always do this if var-idx is divergent, otherwise it will become a loop.
16900 if (IsDivergentIdx)
16901 return true;
16902
16903 // Large vectors would yield too many compares and v_cndmask_b32 instructions.
16904 unsigned NumInsts = NumElem /* Number of compares */ +
16905 ((EltSize + 31) / 32) * NumElem /* Number of cndmasks */;
16906
16907 // On some architectures (GFX9) movrel is not available and it's better
16908 // to expand.
16909 if (Subtarget->useVGPRIndexMode())
16910 return NumInsts <= 16;
16911
16912 // If movrel is available, use it instead of expanding for vector of 8
16913 // elements.
16914 if (Subtarget->hasMovrel())
16915 return NumInsts <= 15;
16916
16917 return true;
16918}
16919
16921 SDValue Idx = N->getOperand(N->getNumOperands() - 1);
16922 if (isa<ConstantSDNode>(Idx))
16923 return false;
16924
16925 SDValue Vec = N->getOperand(0);
16926 EVT VecVT = Vec.getValueType();
16927 EVT EltVT = VecVT.getVectorElementType();
16928 unsigned EltSize = EltVT.getSizeInBits();
16929 unsigned NumElem = VecVT.getVectorNumElements();
16930
16932 EltSize, NumElem, Idx->isDivergent(), getSubtarget());
16933}
16934
16935SDValue
16936SITargetLowering::performExtractVectorEltCombine(SDNode *N,
16937 DAGCombinerInfo &DCI) const {
16938 SDValue Vec = N->getOperand(0);
16939 SelectionDAG &DAG = DCI.DAG;
16940
16941 EVT VecVT = Vec.getValueType();
16942 EVT VecEltVT = VecVT.getVectorElementType();
16943 EVT ResVT = N->getValueType(0);
16944
16945 unsigned VecSize = VecVT.getSizeInBits();
16946 unsigned VecEltSize = VecEltVT.getSizeInBits();
16947
16948 if ((Vec.getOpcode() == ISD::FNEG || Vec.getOpcode() == ISD::FABS) &&
16950 SDLoc SL(N);
16951 SDValue Idx = N->getOperand(1);
16952 SDValue Elt =
16953 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec.getOperand(0), Idx);
16954 return DAG.getNode(Vec.getOpcode(), SL, ResVT, Elt);
16955 }
16956
16957 // (extract_vector_element (and {y0, y1}, (build_vector 0x1f, 0x1f)), index)
16958 // -> (and (extract_vector_element {y0, y1}, index), 0x1f)
16959 // There are optimisations to transform 64-bit shifts into 32-bit shifts
16960 // depending on the shift operand. See e.g. performSraCombine().
16961 // This combine ensures that the optimisation is compatible with v2i32
16962 // legalised AND.
16963 if (VecVT == MVT::v2i32 && Vec->getOpcode() == ISD::AND &&
16964 Vec->getOperand(1)->getOpcode() == ISD::BUILD_VECTOR) {
16965
16967 if (!C || C->getZExtValue() != 0x1f)
16968 return SDValue();
16969
16970 SDLoc SL(N);
16971 SDValue AndMask = DAG.getConstant(0x1f, SL, MVT::i32);
16972 SDValue EVE = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32,
16973 Vec->getOperand(0), N->getOperand(1));
16974 SDValue A = DAG.getNode(ISD::AND, SL, MVT::i32, EVE, AndMask);
16975 DAG.ReplaceAllUsesWith(N, A.getNode());
16976 }
16977
16978 // ScalarRes = EXTRACT_VECTOR_ELT ((vector-BINOP Vec1, Vec2), Idx)
16979 // =>
16980 // Vec1Elt = EXTRACT_VECTOR_ELT(Vec1, Idx)
16981 // Vec2Elt = EXTRACT_VECTOR_ELT(Vec2, Idx)
16982 // ScalarRes = scalar-BINOP Vec1Elt, Vec2Elt
16983 if (Vec.hasOneUse() && DCI.isBeforeLegalize() && VecEltVT == ResVT) {
16984 SDLoc SL(N);
16985 SDValue Idx = N->getOperand(1);
16986 unsigned Opc = Vec.getOpcode();
16987
16988 switch (Opc) {
16989 default:
16990 break;
16991 // TODO: Support other binary operations.
16992 case ISD::FADD:
16993 case ISD::FSUB:
16994 case ISD::FMUL:
16995 case ISD::ADD:
16996 case ISD::UMIN:
16997 case ISD::UMAX:
16998 case ISD::SMIN:
16999 case ISD::SMAX:
17000 case ISD::FMAXNUM:
17001 case ISD::FMINNUM:
17002 case ISD::FMAXNUM_IEEE:
17003 case ISD::FMINNUM_IEEE:
17004 case ISD::FMAXIMUM:
17005 case ISD::FMINIMUM: {
17006 SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17007 Vec.getOperand(0), Idx);
17008 SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT,
17009 Vec.getOperand(1), Idx);
17010
17011 DCI.AddToWorklist(Elt0.getNode());
17012 DCI.AddToWorklist(Elt1.getNode());
17013 return DAG.getNode(Opc, SL, ResVT, Elt0, Elt1, Vec->getFlags());
17014 }
17015 }
17016 }
17017
17018 // EXTRACT_VECTOR_ELT (<n x e>, var-idx) => n x select (e, const-idx)
17020 SDLoc SL(N);
17021 SDValue Idx = N->getOperand(1);
17022 SDValue V;
17023 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17024 SDValue IC = DAG.getVectorIdxConstant(I, SL);
17025 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, ResVT, Vec, IC);
17026 if (I == 0)
17027 V = Elt;
17028 else
17029 V = DAG.getSelectCC(SL, Idx, IC, Elt, V, ISD::SETEQ);
17030 }
17031 return V;
17032 }
17033
17034 // EXTRACT_VECTOR_ELT (v2i32 bitcast (i64/f64:k), Idx)
17035 // =>
17036 // i32:Lo(k) if Idx == 0, or
17037 // i32:Hi(k) if Idx == 1
17038 auto *Idx = dyn_cast<ConstantSDNode>(N->getOperand(1));
17039 if (Vec.getOpcode() == ISD::BITCAST && VecVT == MVT::v2i32 && Idx) {
17040 SDLoc SL(N);
17041 SDValue PeekThrough = Vec.getOperand(0);
17042 auto *KImm = dyn_cast<ConstantSDNode>(PeekThrough);
17043 if (KImm && KImm->getValueType(0).getSizeInBits() == 64) {
17044 uint64_t KImmValue = KImm->getZExtValue();
17045 return DAG.getConstant(
17046 (KImmValue >> (32 * Idx->getZExtValue())) & 0xffffffff, SL, MVT::i32);
17047 }
17048 auto *KFPImm = dyn_cast<ConstantFPSDNode>(PeekThrough);
17049 if (KFPImm && KFPImm->getValueType(0).getSizeInBits() == 64) {
17050 uint64_t KFPImmValue =
17051 KFPImm->getValueAPF().bitcastToAPInt().getZExtValue();
17052 return DAG.getConstant((KFPImmValue >> (32 * Idx->getZExtValue())) &
17053 0xffffffff,
17054 SL, MVT::i32);
17055 }
17056 }
17057
17058 if (!DCI.isBeforeLegalize())
17059 return SDValue();
17060
17061 // Try to turn sub-dword accesses of vectors into accesses of the same 32-bit
17062 // elements. This exposes more load reduction opportunities by replacing
17063 // multiple small extract_vector_elements with a single 32-bit extract.
17064 if (isa<MemSDNode>(Vec) && VecEltSize <= 16 && VecEltVT.isByteSized() &&
17065 VecSize > 32 && VecSize % 32 == 0 && Idx) {
17066 EVT NewVT = getEquivalentMemType(*DAG.getContext(), VecVT);
17067
17068 unsigned BitIndex = Idx->getZExtValue() * VecEltSize;
17069 unsigned EltIdx = BitIndex / 32;
17070 unsigned LeftoverBitIdx = BitIndex % 32;
17071 SDLoc SL(N);
17072
17073 SDValue Cast = DAG.getNode(ISD::BITCAST, SL, NewVT, Vec);
17074 DCI.AddToWorklist(Cast.getNode());
17075
17076 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Cast,
17077 DAG.getConstant(EltIdx, SL, MVT::i32));
17078 DCI.AddToWorklist(Elt.getNode());
17079 SDValue Srl = DAG.getNode(ISD::SRL, SL, MVT::i32, Elt,
17080 DAG.getConstant(LeftoverBitIdx, SL, MVT::i32));
17081 DCI.AddToWorklist(Srl.getNode());
17082
17083 EVT VecEltAsIntVT = VecEltVT.changeTypeToInteger();
17084 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SL, VecEltAsIntVT, Srl);
17085 DCI.AddToWorklist(Trunc.getNode());
17086
17087 if (VecEltVT == ResVT) {
17088 return DAG.getNode(ISD::BITCAST, SL, VecEltVT, Trunc);
17089 }
17090
17091 assert(ResVT.isScalarInteger());
17092 return DAG.getAnyExtOrTrunc(Trunc, SL, ResVT);
17093 }
17094
17095 return SDValue();
17096}
17097
17098SDValue
17099SITargetLowering::performInsertVectorEltCombine(SDNode *N,
17100 DAGCombinerInfo &DCI) const {
17101 SDValue Vec = N->getOperand(0);
17102 SDValue Idx = N->getOperand(2);
17103 EVT VecVT = Vec.getValueType();
17104 EVT EltVT = VecVT.getVectorElementType();
17105
17106 // INSERT_VECTOR_ELT (<n x e>, var-idx)
17107 // => BUILD_VECTOR n x select (e, const-idx)
17109 return SDValue();
17110
17111 SelectionDAG &DAG = DCI.DAG;
17112 SDLoc SL(N);
17113 SDValue Ins = N->getOperand(1);
17114 EVT IdxVT = Idx.getValueType();
17115
17117 for (unsigned I = 0, E = VecVT.getVectorNumElements(); I < E; ++I) {
17118 SDValue IC = DAG.getConstant(I, SL, IdxVT);
17119 SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT, Vec, IC);
17120 SDValue V = DAG.getSelectCC(SL, Idx, IC, Ins, Elt, ISD::SETEQ);
17121 Ops.push_back(V);
17122 }
17123
17124 return DAG.getBuildVector(VecVT, SL, Ops);
17125}
17126
17127/// Return the source of an fp_extend from f16 to f32, or a converted FP
17128/// constant.
17130 if (Src.getOpcode() == ISD::FP_EXTEND &&
17131 Src.getOperand(0).getValueType() == MVT::f16) {
17132 return Src.getOperand(0);
17133 }
17134
17135 if (auto *CFP = dyn_cast<ConstantFPSDNode>(Src)) {
17136 APFloat Val = CFP->getValueAPF();
17137 bool LosesInfo = true;
17139 if (!LosesInfo)
17140 return DAG.getConstantFP(Val, SDLoc(Src), MVT::f16);
17141 }
17142
17143 return SDValue();
17144}
17145
17146SDValue SITargetLowering::performFPRoundCombine(SDNode *N,
17147 DAGCombinerInfo &DCI) const {
17148 assert(Subtarget->has16BitInsts() && !Subtarget->hasMed3_16() &&
17149 "combine only useful on gfx8");
17150
17151 SDValue TruncSrc = N->getOperand(0);
17152 EVT VT = N->getValueType(0);
17153 if (VT != MVT::f16)
17154 return SDValue();
17155
17156 if (TruncSrc.getOpcode() != AMDGPUISD::FMED3 ||
17157 TruncSrc.getValueType() != MVT::f32 || !TruncSrc.hasOneUse())
17158 return SDValue();
17159
17160 SelectionDAG &DAG = DCI.DAG;
17161 SDLoc SL(N);
17162
17163 // Optimize f16 fmed3 pattern performed on f32. On gfx8 there is no f16 fmed3,
17164 // and expanding it with min/max saves 1 instruction vs. casting to f32 and
17165 // casting back.
17166
17167 // fptrunc (f32 (fmed3 (fpext f16:a, fpext f16:b, fpext f16:c))) =>
17168 // fmin(fmax(a, b), fmax(fmin(a, b), c))
17169 SDValue A = strictFPExtFromF16(DAG, TruncSrc.getOperand(0));
17170 if (!A)
17171 return SDValue();
17172
17173 SDValue B = strictFPExtFromF16(DAG, TruncSrc.getOperand(1));
17174 if (!B)
17175 return SDValue();
17176
17177 SDValue C = strictFPExtFromF16(DAG, TruncSrc.getOperand(2));
17178 if (!C)
17179 return SDValue();
17180
17181 // This changes signaling nan behavior. If an input is a signaling nan, it
17182 // would have been quieted by the fpext originally. We don't care because
17183 // these are unconstrained ops. If we needed to insert quieting canonicalizes
17184 // we would be worse off than just doing the promotion.
17185 SDValue A1 = DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, A, B);
17186 SDValue B1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A, B);
17187 SDValue C1 = DAG.getNode(ISD::FMAXNUM_IEEE, SL, VT, A1, C);
17188 return DAG.getNode(ISD::FMINNUM_IEEE, SL, VT, B1, C1);
17189}
17190
17191unsigned SITargetLowering::getFusedOpcode(const SelectionDAG &DAG,
17192 const SDNode *N0,
17193 const SDNode *N1) const {
17194 EVT VT = N0->getValueType(0);
17195
17196 // Only do this if we are not trying to support denormals. v_mad_f32 does not
17197 // support denormals ever.
17198 if (((VT == MVT::f32 &&
17200 (VT == MVT::f16 && Subtarget->hasMadF16() &&
17203 return ISD::FMAD;
17204
17205 const TargetOptions &Options = DAG.getTarget().Options;
17206 if ((Options.AllowFPOpFusion == FPOpFusion::Fast ||
17207 (N0->getFlags().hasAllowContract() &&
17208 N1->getFlags().hasAllowContract())) &&
17210 return ISD::FMA;
17211 }
17212
17213 return 0;
17214}
17215
17216// For a reassociatable opcode perform:
17217// op x, (op y, z) -> op (op x, z), y, if x and z are uniform
17218SDValue SITargetLowering::reassociateScalarOps(SDNode *N,
17219 SelectionDAG &DAG) const {
17220 EVT VT = N->getValueType(0);
17221 if (VT != MVT::i32 && VT != MVT::i64)
17222 return SDValue();
17223
17224 if (DAG.isBaseWithConstantOffset(SDValue(N, 0)))
17225 return SDValue();
17226
17227 unsigned Opc = N->getOpcode();
17228 SDValue Op0 = N->getOperand(0);
17229 SDValue Op1 = N->getOperand(1);
17230
17231 if (!(Op0->isDivergent() ^ Op1->isDivergent()))
17232 return SDValue();
17233
17234 if (Op0->isDivergent())
17235 std::swap(Op0, Op1);
17236
17237 if (Op1.getOpcode() != Opc || !Op1.hasOneUse())
17238 return SDValue();
17239
17240 SDValue Op2 = Op1.getOperand(1);
17241 Op1 = Op1.getOperand(0);
17242 if (!(Op1->isDivergent() ^ Op2->isDivergent()))
17243 return SDValue();
17244
17245 if (Op1->isDivergent())
17246 std::swap(Op1, Op2);
17247
17248 SDLoc SL(N);
17249 SDValue Add1 = DAG.getNode(Opc, SL, VT, Op0, Op1);
17250 return DAG.getNode(Opc, SL, VT, Add1, Op2);
17251}
17252
17253static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT,
17254 SDValue N0, SDValue N1, SDValue N2, bool Signed) {
17256 SDVTList VTs = DAG.getVTList(MVT::i64, MVT::i1);
17257 SDValue Mad = DAG.getNode(MadOpc, SL, VTs, N0, N1, N2);
17258 return DAG.getNode(ISD::TRUNCATE, SL, VT, Mad);
17259}
17260
17261// Fold
17262// y = lshr i64 x, 32
17263// res = add (mul i64 y, Const), x where "Const" is a 64-bit constant
17264// with Const.hi == -1
17265// To
17266// res = mad_u64_u32 y.lo ,Const.lo, x.lo
17268 SDValue MulLHS, SDValue MulRHS,
17269 SDValue AddRHS) {
17270 if (MulRHS.getOpcode() == ISD::SRL)
17271 std::swap(MulLHS, MulRHS);
17272
17273 if (MulLHS.getValueType() != MVT::i64 || MulLHS.getOpcode() != ISD::SRL)
17274 return SDValue();
17275
17276 ConstantSDNode *ShiftVal = dyn_cast<ConstantSDNode>(MulLHS.getOperand(1));
17277 if (!ShiftVal || ShiftVal->getAsZExtVal() != 32 ||
17278 MulLHS.getOperand(0) != AddRHS)
17279 return SDValue();
17280
17282 if (!Const || Hi_32(Const->getZExtValue()) != uint32_t(-1))
17283 return SDValue();
17284
17285 SDValue ConstMul =
17286 DAG.getConstant(Lo_32(Const->getZExtValue()), SL, MVT::i32);
17287 return getMad64_32(DAG, SL, MVT::i64,
17288 DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS), ConstMul,
17289 DAG.getZeroExtendInReg(AddRHS, SL, MVT::i32), false);
17290}
17291
17292// Fold (add (mul x, y), z) --> (mad_[iu]64_[iu]32 x, y, z) plus high
17293// multiplies, if any.
17294//
17295// Full 64-bit multiplies that feed into an addition are lowered here instead
17296// of using the generic expansion. The generic expansion ends up with
17297// a tree of ADD nodes that prevents us from using the "add" part of the
17298// MAD instruction. The expansion produced here results in a chain of ADDs
17299// instead of a tree.
17300SDValue SITargetLowering::tryFoldToMad64_32(SDNode *N,
17301 DAGCombinerInfo &DCI) const {
17302 assert(N->isAnyAdd());
17303
17304 SelectionDAG &DAG = DCI.DAG;
17305 EVT VT = N->getValueType(0);
17306 SDLoc SL(N);
17307 SDValue LHS = N->getOperand(0);
17308 SDValue RHS = N->getOperand(1);
17309
17310 if (VT.isVector())
17311 return SDValue();
17312
17313 // S_MUL_HI_[IU]32 was added in gfx9, which allows us to keep the overall
17314 // result in scalar registers for uniform values.
17315 if (!N->isDivergent() && Subtarget->hasSMulHi())
17316 return SDValue();
17317
17318 unsigned NumBits = VT.getScalarSizeInBits();
17319 if (NumBits <= 32 || NumBits > 64)
17320 return SDValue();
17321
17322 if (LHS.getOpcode() != ISD::MUL) {
17323 assert(RHS.getOpcode() == ISD::MUL);
17324 std::swap(LHS, RHS);
17325 }
17326
17327 // Avoid the fold if it would unduly increase the number of multiplies due to
17328 // multiple uses, except on hardware with full-rate multiply-add (which is
17329 // part of full-rate 64-bit ops).
17330 if (!Subtarget->hasFullRate64Ops()) {
17331 unsigned NumUsers = 0;
17332 for (SDNode *User : LHS->users()) {
17333 // There is a use that does not feed into addition, so the multiply can't
17334 // be removed. We prefer MUL + ADD + ADDC over MAD + MUL.
17335 if (!User->isAnyAdd())
17336 return SDValue();
17337
17338 // We prefer 2xMAD over MUL + 2xADD + 2xADDC (code density), and prefer
17339 // MUL + 3xADD + 3xADDC over 3xMAD.
17340 ++NumUsers;
17341 if (NumUsers >= 3)
17342 return SDValue();
17343 }
17344 }
17345
17346 SDValue MulLHS = LHS.getOperand(0);
17347 SDValue MulRHS = LHS.getOperand(1);
17348 SDValue AddRHS = RHS;
17349
17350 if (SDValue FoldedMAD = tryFoldMADwithSRL(DAG, SL, MulLHS, MulRHS, AddRHS))
17351 return FoldedMAD;
17352
17353 // Always check whether operands are small unsigned values, since that
17354 // knowledge is useful in more cases. Check for small signed values only if
17355 // doing so can unlock a shorter code sequence.
17356 bool MulLHSUnsigned32 = numBitsUnsigned(MulLHS, DAG) <= 32;
17357 bool MulRHSUnsigned32 = numBitsUnsigned(MulRHS, DAG) <= 32;
17358
17359 bool MulSignedLo = false;
17360 if (!MulLHSUnsigned32 || !MulRHSUnsigned32) {
17361 MulSignedLo =
17362 numBitsSigned(MulLHS, DAG) <= 32 && numBitsSigned(MulRHS, DAG) <= 32;
17363 }
17364
17365 // The operands and final result all have the same number of bits. If
17366 // operands need to be extended, they can be extended with garbage. The
17367 // resulting garbage in the high bits of the mad_[iu]64_[iu]32 result is
17368 // truncated away in the end.
17369 if (VT != MVT::i64) {
17370 MulLHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulLHS);
17371 MulRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, MulRHS);
17372 AddRHS = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i64, AddRHS);
17373 }
17374
17375 // The basic code generated is conceptually straightforward. Pseudo code:
17376 //
17377 // accum = mad_64_32 lhs.lo, rhs.lo, accum
17378 // accum.hi = add (mul lhs.hi, rhs.lo), accum.hi
17379 // accum.hi = add (mul lhs.lo, rhs.hi), accum.hi
17380 //
17381 // The second and third lines are optional, depending on whether the factors
17382 // are {sign,zero}-extended or not.
17383 //
17384 // The actual DAG is noisier than the pseudo code, but only due to
17385 // instructions that disassemble values into low and high parts, and
17386 // assemble the final result.
17387 SDValue One = DAG.getConstant(1, SL, MVT::i32);
17388
17389 auto MulLHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulLHS);
17390 auto MulRHSLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, MulRHS);
17391 SDValue Accum =
17392 getMad64_32(DAG, SL, MVT::i64, MulLHSLo, MulRHSLo, AddRHS, MulSignedLo);
17393
17394 if (!MulSignedLo && (!MulLHSUnsigned32 || !MulRHSUnsigned32)) {
17395 auto [AccumLo, AccumHi] = DAG.SplitScalar(Accum, SL, MVT::i32, MVT::i32);
17396
17397 if (!MulLHSUnsigned32) {
17398 auto MulLHSHi =
17399 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulLHS, One);
17400 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSHi, MulRHSLo);
17401 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17402 }
17403
17404 if (!MulRHSUnsigned32) {
17405 auto MulRHSHi =
17406 DAG.getNode(ISD::EXTRACT_ELEMENT, SL, MVT::i32, MulRHS, One);
17407 SDValue MulHi = DAG.getNode(ISD::MUL, SL, MVT::i32, MulLHSLo, MulRHSHi);
17408 AccumHi = DAG.getNode(ISD::ADD, SL, MVT::i32, MulHi, AccumHi);
17409 }
17410
17411 Accum = DAG.getBuildVector(MVT::v2i32, SL, {AccumLo, AccumHi});
17412 Accum = DAG.getBitcast(MVT::i64, Accum);
17413 }
17414
17415 if (VT != MVT::i64)
17416 Accum = DAG.getNode(ISD::TRUNCATE, SL, VT, Accum);
17417 return Accum;
17418}
17419
17420SDValue
17421SITargetLowering::foldAddSub64WithZeroLowBitsTo32(SDNode *N,
17422 DAGCombinerInfo &DCI) const {
17423 SDValue RHS = N->getOperand(1);
17424 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
17425 if (!CRHS)
17426 return SDValue();
17427
17428 // TODO: Worth using computeKnownBits? Maybe expensive since it's so
17429 // common.
17430 uint64_t Val = CRHS->getZExtValue();
17431 if (countr_zero(Val) >= 32) {
17432 SelectionDAG &DAG = DCI.DAG;
17433 SDLoc SL(N);
17434 SDValue LHS = N->getOperand(0);
17435
17436 // Avoid carry machinery if we know the low half of the add does not
17437 // contribute to the final result.
17438 //
17439 // add i64:x, K if computeTrailingZeros(K) >= 32
17440 // => build_pair (add x.hi, K.hi), x.lo
17441
17442 // Breaking the 64-bit add here with this strange constant is unlikely
17443 // to interfere with addressing mode patterns.
17444
17445 SDValue Hi = getHiHalf64(LHS, DAG);
17446 SDValue ConstHi32 = DAG.getConstant(Hi_32(Val), SL, MVT::i32);
17447 unsigned Opcode = N->getOpcode();
17448 if (Opcode == ISD::PTRADD)
17449 Opcode = ISD::ADD;
17450 SDValue AddHi =
17451 DAG.getNode(Opcode, SL, MVT::i32, Hi, ConstHi32, N->getFlags());
17452
17453 SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
17454 return DAG.getNode(ISD::BUILD_PAIR, SL, MVT::i64, Lo, AddHi);
17455 }
17456
17457 return SDValue();
17458}
17459
17460// Collect the ultimate src of each of the mul node's operands, and confirm
17461// each operand is 8 bytes.
17462static std::optional<ByteProvider<SDValue>>
17463handleMulOperand(const SDValue &MulOperand) {
17464 auto Byte0 = calculateByteProvider(MulOperand, 0, 0);
17465 if (!Byte0 || Byte0->isConstantZero()) {
17466 return std::nullopt;
17467 }
17468 auto Byte1 = calculateByteProvider(MulOperand, 1, 0);
17469 if (Byte1 && !Byte1->isConstantZero()) {
17470 return std::nullopt;
17471 }
17472 return Byte0;
17473}
17474
17475static unsigned addPermMasks(unsigned First, unsigned Second) {
17476 unsigned FirstCs = First & 0x0c0c0c0c;
17477 unsigned SecondCs = Second & 0x0c0c0c0c;
17478 unsigned FirstNoCs = First & ~0x0c0c0c0c;
17479 unsigned SecondNoCs = Second & ~0x0c0c0c0c;
17480
17481 assert((FirstCs & 0xFF) | (SecondCs & 0xFF));
17482 assert((FirstCs & 0xFF00) | (SecondCs & 0xFF00));
17483 assert((FirstCs & 0xFF0000) | (SecondCs & 0xFF0000));
17484 assert((FirstCs & 0xFF000000) | (SecondCs & 0xFF000000));
17485
17486 return (FirstNoCs | SecondNoCs) | (FirstCs & SecondCs);
17487}
17488
17489struct DotSrc {
17491 int64_t PermMask;
17493};
17494
17498 SmallVectorImpl<DotSrc> &Src1s, int Step) {
17499
17500 assert(Src0.Src.has_value() && Src1.Src.has_value());
17501 // Src0s and Src1s are empty, just place arbitrarily.
17502 if (Step == 0) {
17503 Src0s.push_back({*Src0.Src, ((Src0.SrcOffset % 4) << 24) + 0x0c0c0c,
17504 Src0.SrcOffset / 4});
17505 Src1s.push_back({*Src1.Src, ((Src1.SrcOffset % 4) << 24) + 0x0c0c0c,
17506 Src1.SrcOffset / 4});
17507 return;
17508 }
17509
17510 for (int BPI = 0; BPI < 2; BPI++) {
17511 std::pair<ByteProvider<SDValue>, ByteProvider<SDValue>> BPP = {Src0, Src1};
17512 if (BPI == 1) {
17513 BPP = {Src1, Src0};
17514 }
17515 unsigned ZeroMask = 0x0c0c0c0c;
17516 unsigned FMask = 0xFF << (8 * (3 - Step));
17517
17518 unsigned FirstMask =
17519 (BPP.first.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17520 unsigned SecondMask =
17521 (BPP.second.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask);
17522 // Attempt to find Src vector which contains our SDValue, if so, add our
17523 // perm mask to the existing one. If we are unable to find a match for the
17524 // first SDValue, attempt to find match for the second.
17525 int FirstGroup = -1;
17526 for (int I = 0; I < 2; I++) {
17527 SmallVectorImpl<DotSrc> &Srcs = I == 0 ? Src0s : Src1s;
17528 auto MatchesFirst = [&BPP](DotSrc &IterElt) {
17529 return IterElt.SrcOp == *BPP.first.Src &&
17530 (IterElt.DWordOffset == (BPP.first.SrcOffset / 4));
17531 };
17532
17533 auto *Match = llvm::find_if(Srcs, MatchesFirst);
17534 if (Match != Srcs.end()) {
17535 Match->PermMask = addPermMasks(FirstMask, Match->PermMask);
17536 FirstGroup = I;
17537 break;
17538 }
17539 }
17540 if (FirstGroup != -1) {
17541 SmallVectorImpl<DotSrc> &Srcs = FirstGroup == 1 ? Src0s : Src1s;
17542 auto MatchesSecond = [&BPP](DotSrc &IterElt) {
17543 return IterElt.SrcOp == *BPP.second.Src &&
17544 (IterElt.DWordOffset == (BPP.second.SrcOffset / 4));
17545 };
17546 auto *Match = llvm::find_if(Srcs, MatchesSecond);
17547 if (Match != Srcs.end()) {
17548 Match->PermMask = addPermMasks(SecondMask, Match->PermMask);
17549 } else
17550 Srcs.push_back({*BPP.second.Src, SecondMask, BPP.second.SrcOffset / 4});
17551 return;
17552 }
17553 }
17554
17555 // If we have made it here, then we could not find a match in Src0s or Src1s
17556 // for either Src0 or Src1, so just place them arbitrarily.
17557
17558 unsigned ZeroMask = 0x0c0c0c0c;
17559 unsigned FMask = 0xFF << (8 * (3 - Step));
17560
17561 Src0s.push_back(
17562 {*Src0.Src,
17563 ((Src0.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17564 Src0.SrcOffset / 4});
17565 Src1s.push_back(
17566 {*Src1.Src,
17567 ((Src1.SrcOffset % 4) << (8 * (3 - Step)) | (ZeroMask & ~FMask)),
17568 Src1.SrcOffset / 4});
17569}
17570
17572 SmallVectorImpl<DotSrc> &Srcs, bool IsSigned,
17573 bool IsAny) {
17574
17575 // If we just have one source, just permute it accordingly.
17576 if (Srcs.size() == 1) {
17577 auto *Elt = Srcs.begin();
17578 auto EltOp = getDWordFromOffset(DAG, SL, Elt->SrcOp, Elt->DWordOffset);
17579
17580 // v_perm will produce the original value
17581 if (Elt->PermMask == 0x3020100)
17582 return EltOp;
17583
17584 return DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17585 DAG.getConstant(Elt->PermMask, SL, MVT::i32));
17586 }
17587
17588 auto *FirstElt = Srcs.begin();
17589 auto *SecondElt = std::next(FirstElt);
17590
17592
17593 // If we have multiple sources in the chain, combine them via perms (using
17594 // calculated perm mask) and Ors.
17595 while (true) {
17596 auto FirstMask = FirstElt->PermMask;
17597 auto SecondMask = SecondElt->PermMask;
17598
17599 unsigned FirstCs = FirstMask & 0x0c0c0c0c;
17600 unsigned FirstPlusFour = FirstMask | 0x04040404;
17601 // 0x0c + 0x04 = 0x10, so anding with 0x0F will produced 0x00 for any
17602 // original 0x0C.
17603 FirstMask = (FirstPlusFour & 0x0F0F0F0F) | FirstCs;
17604
17605 auto PermMask = addPermMasks(FirstMask, SecondMask);
17606 auto FirstVal =
17607 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17608 auto SecondVal =
17609 getDWordFromOffset(DAG, SL, SecondElt->SrcOp, SecondElt->DWordOffset);
17610
17611 Perms.push_back(DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, FirstVal,
17612 SecondVal,
17613 DAG.getConstant(PermMask, SL, MVT::i32)));
17614
17615 FirstElt = std::next(SecondElt);
17616 if (FirstElt == Srcs.end())
17617 break;
17618
17619 SecondElt = std::next(FirstElt);
17620 // If we only have a FirstElt, then just combine that into the cumulative
17621 // source node.
17622 if (SecondElt == Srcs.end()) {
17623 auto EltOp =
17624 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17625
17626 Perms.push_back(
17627 DAG.getNode(AMDGPUISD::PERM, SL, MVT::i32, EltOp, EltOp,
17628 DAG.getConstant(FirstElt->PermMask, SL, MVT::i32)));
17629 break;
17630 }
17631 }
17632
17633 assert(Perms.size() == 1 || Perms.size() == 2);
17634 return Perms.size() == 2
17635 ? DAG.getNode(ISD::OR, SL, MVT::i32, Perms[0], Perms[1])
17636 : Perms[0];
17637}
17638
17639static void fixMasks(SmallVectorImpl<DotSrc> &Srcs, unsigned ChainLength) {
17640 for (auto &[EntryVal, EntryMask, EntryOffset] : Srcs) {
17641 EntryMask = EntryMask >> ((4 - ChainLength) * 8);
17642 auto ZeroMask = ChainLength == 2 ? 0x0c0c0000 : 0x0c000000;
17643 EntryMask += ZeroMask;
17644 }
17645}
17646
17647static bool isMul(const SDValue Op) {
17648 auto Opcode = Op.getOpcode();
17649
17650 return (Opcode == ISD::MUL || Opcode == AMDGPUISD::MUL_U24 ||
17651 Opcode == AMDGPUISD::MUL_I24);
17652}
17653
17654static std::optional<bool>
17656 ByteProvider<SDValue> &Src1, const SDValue &S0Op,
17657 const SDValue &S1Op, const SelectionDAG &DAG) {
17658 // If we both ops are i8s (pre legalize-dag), then the signedness semantics
17659 // of the dot4 is irrelevant.
17660 if (S0Op.getValueSizeInBits() == 8 && S1Op.getValueSizeInBits() == 8)
17661 return false;
17662
17663 auto Known0 = DAG.computeKnownBits(S0Op, 0);
17664 bool S0IsUnsigned = Known0.countMinLeadingZeros() > 0;
17665 bool S0IsSigned = Known0.countMinLeadingOnes() > 0;
17666 auto Known1 = DAG.computeKnownBits(S1Op, 0);
17667 bool S1IsUnsigned = Known1.countMinLeadingZeros() > 0;
17668 bool S1IsSigned = Known1.countMinLeadingOnes() > 0;
17669
17670 assert(!(S0IsUnsigned && S0IsSigned));
17671 assert(!(S1IsUnsigned && S1IsSigned));
17672
17673 // There are 9 possible permutations of
17674 // {S0IsUnsigned, S0IsSigned, S1IsUnsigned, S1IsSigned}
17675
17676 // In two permutations, the sign bits are known to be the same for both Ops,
17677 // so simply return Signed / Unsigned corresponding to the MSB
17678
17679 if ((S0IsUnsigned && S1IsUnsigned) || (S0IsSigned && S1IsSigned))
17680 return S0IsSigned;
17681
17682 // In another two permutations, the sign bits are known to be opposite. In
17683 // this case return std::nullopt to indicate a bad match.
17684
17685 if ((S0IsUnsigned && S1IsSigned) || (S0IsSigned && S1IsUnsigned))
17686 return std::nullopt;
17687
17688 // In the remaining five permutations, we don't know the value of the sign
17689 // bit for at least one Op. Since we have a valid ByteProvider, we know that
17690 // the upper bits must be extension bits. Thus, the only ways for the sign
17691 // bit to be unknown is if it was sign extended from unknown value, or if it
17692 // was any extended. In either case, it is correct to use the signed
17693 // version of the signedness semantics of dot4
17694
17695 // In two of such permutations, we known the sign bit is set for
17696 // one op, and the other is unknown. It is okay to used signed version of
17697 // dot4.
17698 if ((S0IsSigned && !(S1IsSigned || S1IsUnsigned)) ||
17699 ((S1IsSigned && !(S0IsSigned || S0IsUnsigned))))
17700 return true;
17701
17702 // In one such permutation, we don't know either of the sign bits. It is okay
17703 // to used the signed version of dot4.
17704 if ((!(S1IsSigned || S1IsUnsigned) && !(S0IsSigned || S0IsUnsigned)))
17705 return true;
17706
17707 // In two of such permutations, we known the sign bit is unset for
17708 // one op, and the other is unknown. Return std::nullopt to indicate a
17709 // bad match.
17710 if ((S0IsUnsigned && !(S1IsSigned || S1IsUnsigned)) ||
17711 ((S1IsUnsigned && !(S0IsSigned || S0IsUnsigned))))
17712 return std::nullopt;
17713
17714 llvm_unreachable("Fully covered condition");
17715}
17716
17717SDValue SITargetLowering::performAddCombine(SDNode *N,
17718 DAGCombinerInfo &DCI) const {
17719 SelectionDAG &DAG = DCI.DAG;
17720 EVT VT = N->getValueType(0);
17721 SDLoc SL(N);
17722 SDValue LHS = N->getOperand(0);
17723 SDValue RHS = N->getOperand(1);
17724
17725 if (LHS.getOpcode() == ISD::MUL || RHS.getOpcode() == ISD::MUL) {
17726 if (Subtarget->hasMad64_32()) {
17727 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
17728 return Folded;
17729 }
17730 }
17731
17732 if (SDValue V = reassociateScalarOps(N, DAG)) {
17733 return V;
17734 }
17735
17736 if (VT == MVT::i64) {
17737 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
17738 return Folded;
17739 }
17740
17741 if ((isMul(LHS) || isMul(RHS)) && Subtarget->hasDot7Insts() &&
17742 (Subtarget->hasDot1Insts() || Subtarget->hasDot8Insts())) {
17743 SDValue TempNode(N, 0);
17744 std::optional<bool> IsSigned;
17748
17749 // Match the v_dot4 tree, while collecting src nodes.
17750 int ChainLength = 0;
17751 for (int I = 0; I < 4; I++) {
17752 auto MulIdx = isMul(LHS) ? 0 : isMul(RHS) ? 1 : -1;
17753 if (MulIdx == -1)
17754 break;
17755 auto Src0 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(0));
17756 if (!Src0)
17757 break;
17758 auto Src1 = handleMulOperand(TempNode->getOperand(MulIdx)->getOperand(1));
17759 if (!Src1)
17760 break;
17761
17762 auto IterIsSigned = checkDot4MulSignedness(
17763 TempNode->getOperand(MulIdx), *Src0, *Src1,
17764 TempNode->getOperand(MulIdx)->getOperand(0),
17765 TempNode->getOperand(MulIdx)->getOperand(1), DAG);
17766 if (!IterIsSigned)
17767 break;
17768 if (!IsSigned)
17769 IsSigned = *IterIsSigned;
17770 if (*IterIsSigned != *IsSigned)
17771 break;
17772 placeSources(*Src0, *Src1, Src0s, Src1s, I);
17773 auto AddIdx = 1 - MulIdx;
17774 // Allow the special case where add (add (mul24, 0), mul24) became ->
17775 // add (mul24, mul24).
17776 if (I == 2 && isMul(TempNode->getOperand(AddIdx))) {
17777 Src2s.push_back(TempNode->getOperand(AddIdx));
17778 auto Src0 =
17779 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(0));
17780 if (!Src0)
17781 break;
17782 auto Src1 =
17783 handleMulOperand(TempNode->getOperand(AddIdx)->getOperand(1));
17784 if (!Src1)
17785 break;
17786 auto IterIsSigned = checkDot4MulSignedness(
17787 TempNode->getOperand(AddIdx), *Src0, *Src1,
17788 TempNode->getOperand(AddIdx)->getOperand(0),
17789 TempNode->getOperand(AddIdx)->getOperand(1), DAG);
17790 if (!IterIsSigned)
17791 break;
17792 assert(IsSigned);
17793 if (*IterIsSigned != *IsSigned)
17794 break;
17795 placeSources(*Src0, *Src1, Src0s, Src1s, I + 1);
17796 Src2s.push_back(DAG.getConstant(0, SL, MVT::i32));
17797 ChainLength = I + 2;
17798 break;
17799 }
17800
17801 TempNode = TempNode->getOperand(AddIdx);
17802 Src2s.push_back(TempNode);
17803 ChainLength = I + 1;
17804 // The loop body treats TempNode's operands as addends.
17805 if (TempNode.getOpcode() != ISD::ADD)
17806 break;
17807 LHS = TempNode->getOperand(0);
17808 RHS = TempNode->getOperand(1);
17809 }
17810
17811 if (ChainLength < 2)
17812 return SDValue();
17813
17814 // Masks were constructed with assumption that we would find a chain of
17815 // length 4. If not, then we need to 0 out the MSB bits (via perm mask of
17816 // 0x0c) so they do not affect dot calculation.
17817 if (ChainLength < 4) {
17818 fixMasks(Src0s, ChainLength);
17819 fixMasks(Src1s, ChainLength);
17820 }
17821
17822 SDValue Src0, Src1;
17823
17824 // If we are just using a single source for both, and have permuted the
17825 // bytes consistently, we can just use the sources without permuting
17826 // (commutation).
17827 bool UseOriginalSrc = false;
17828 if (ChainLength == 4 && Src0s.size() == 1 && Src1s.size() == 1 &&
17829 Src0s.begin()->PermMask == Src1s.begin()->PermMask &&
17830 Src0s.begin()->SrcOp.getValueSizeInBits() >= 32 &&
17831 Src1s.begin()->SrcOp.getValueSizeInBits() >= 32) {
17832 SmallVector<unsigned, 4> SrcBytes;
17833 auto Src0Mask = Src0s.begin()->PermMask;
17834 SrcBytes.push_back(Src0Mask & 0xFF000000);
17835 bool UniqueEntries = true;
17836 for (auto I = 1; I < 4; I++) {
17837 auto NextByte = Src0Mask & (0xFF << ((3 - I) * 8));
17838
17839 if (is_contained(SrcBytes, NextByte)) {
17840 UniqueEntries = false;
17841 break;
17842 }
17843 SrcBytes.push_back(NextByte);
17844 }
17845
17846 if (UniqueEntries) {
17847 UseOriginalSrc = true;
17848
17849 auto *FirstElt = Src0s.begin();
17850 auto FirstEltOp =
17851 getDWordFromOffset(DAG, SL, FirstElt->SrcOp, FirstElt->DWordOffset);
17852
17853 auto *SecondElt = Src1s.begin();
17854 auto SecondEltOp = getDWordFromOffset(DAG, SL, SecondElt->SrcOp,
17855 SecondElt->DWordOffset);
17856
17857 Src0 = DAG.getBitcastedAnyExtOrTrunc(FirstEltOp, SL,
17858 MVT::getIntegerVT(32));
17859 Src1 = DAG.getBitcastedAnyExtOrTrunc(SecondEltOp, SL,
17860 MVT::getIntegerVT(32));
17861 }
17862 }
17863
17864 if (!UseOriginalSrc) {
17865 Src0 = resolveSources(DAG, SL, Src0s, false, true);
17866 Src1 = resolveSources(DAG, SL, Src1s, false, true);
17867 }
17868
17869 assert(IsSigned);
17870 SDValue Src2 =
17871 DAG.getExtOrTrunc(*IsSigned, Src2s[ChainLength - 1], SL, MVT::i32);
17872
17873 SDValue IID = DAG.getTargetConstant(*IsSigned ? Intrinsic::amdgcn_sdot4
17874 : Intrinsic::amdgcn_udot4,
17875 SL, MVT::i64);
17876
17877 assert(!VT.isVector());
17878 auto Dot = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SL, MVT::i32, IID, Src0,
17879 Src1, Src2, DAG.getTargetConstant(0, SL, MVT::i1));
17880
17881 return DAG.getExtOrTrunc(*IsSigned, Dot, SL, VT);
17882 }
17883
17884 if (VT != MVT::i32 || !DCI.isAfterLegalizeDAG())
17885 return SDValue();
17886
17887 // add x, zext (setcc) => uaddo_carry x, 0, setcc
17888 // add x, sext (setcc) => usubo_carry x, 0, setcc
17889 unsigned Opc = LHS.getOpcode();
17892 std::swap(RHS, LHS);
17893
17894 Opc = RHS.getOpcode();
17895 switch (Opc) {
17896 default:
17897 break;
17898 case ISD::ZERO_EXTEND:
17899 case ISD::SIGN_EXTEND:
17900 case ISD::ANY_EXTEND: {
17901 auto Cond = RHS.getOperand(0);
17902 // If this won't be a real VOPC output, we would still need to insert an
17903 // extra instruction anyway.
17904 if (!isBoolSGPR(Cond))
17905 break;
17906 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
17907 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
17909 return DAG.getNode(Opc, SL, VTList, Args);
17910 }
17911 case ISD::UADDO_CARRY: {
17912 // add x, (uaddo_carry y, 0, cc) => uaddo_carry x, y, cc
17913 if (!isNullConstant(RHS.getOperand(1)))
17914 break;
17915 SDValue Args[] = {LHS, RHS.getOperand(0), RHS.getOperand(2)};
17916 return DAG.getNode(ISD::UADDO_CARRY, SDLoc(N), RHS->getVTList(), Args);
17917 }
17918 }
17919 return SDValue();
17920}
17921
17922SDValue SITargetLowering::performPtrAddCombine(SDNode *N,
17923 DAGCombinerInfo &DCI) const {
17924 SelectionDAG &DAG = DCI.DAG;
17925 SDLoc DL(N);
17926 EVT VT = N->getValueType(0);
17927 SDValue N0 = N->getOperand(0);
17928 SDValue N1 = N->getOperand(1);
17929
17930 // The following folds transform PTRADDs into regular arithmetic in cases
17931 // where the PTRADD wouldn't be folded as an immediate offset into memory
17932 // instructions anyway. They are target-specific in that other targets might
17933 // prefer to not lose information about the pointer arithmetic.
17934
17935 // Fold (ptradd x, shl(0 - v, k)) -> sub(x, shl(v, k)).
17936 // Adapted from DAGCombiner::visitADDLikeCommutative.
17937 SDValue V, K;
17938 if (sd_match(N1, m_Shl(m_Neg(m_Value(V)), m_Value(K)))) {
17939 SDNodeFlags ShlFlags = N1->getFlags();
17940 // If the original shl is NUW and NSW, the first k+1 bits of 0-v are all 0,
17941 // so v is either 0 or the first k+1 bits of v are all 1 -> NSW can be
17942 // preserved.
17943 SDNodeFlags NewShlFlags =
17944 ShlFlags.hasNoUnsignedWrap() && ShlFlags.hasNoSignedWrap()
17946 : SDNodeFlags();
17947 SDValue Inner = DAG.getNode(ISD::SHL, DL, VT, V, K, NewShlFlags);
17948 DCI.AddToWorklist(Inner.getNode());
17949 return DAG.getNode(ISD::SUB, DL, VT, N0, Inner);
17950 }
17951
17952 // Fold into Mad64 if the right-hand side is a MUL. Analogous to a fold in
17953 // performAddCombine.
17954 if (N1.getOpcode() == ISD::MUL) {
17955 if (Subtarget->hasMad64_32()) {
17956 if (SDValue Folded = tryFoldToMad64_32(N, DCI))
17957 return Folded;
17958 }
17959 }
17960
17961 // If the 32 low bits of the constant are all zero, there is nothing to fold
17962 // into an immediate offset, so it's better to eliminate the unnecessary
17963 // addition for the lower 32 bits than to preserve the PTRADD.
17964 // Analogous to a fold in performAddCombine.
17965 if (VT == MVT::i64) {
17966 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
17967 return Folded;
17968 }
17969
17970 if (N1.getOpcode() != ISD::ADD || !N1.hasOneUse())
17971 return SDValue();
17972
17973 SDValue X = N0;
17974 SDValue Y = N1.getOperand(0);
17975 SDValue Z = N1.getOperand(1);
17976 bool YIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Y);
17977 bool ZIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Z);
17978
17979 if (!YIsConstant && !ZIsConstant && !X->isDivergent() &&
17980 Y->isDivergent() != Z->isDivergent()) {
17981 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, y), z) if x and
17982 // y are uniform and z isn't.
17983 // Reassociate (ptradd x, (add y, z)) -> (ptradd (ptradd x, z), y) if x and
17984 // z are uniform and y isn't.
17985 // The goal is to push uniform operands up in the computation, so that they
17986 // can be handled with scalar operations. We can't use reassociateScalarOps
17987 // for this since it requires two identical commutative operations to
17988 // reassociate.
17989 if (Y->isDivergent())
17990 std::swap(Y, Z);
17991 // If both additions in the original were NUW, reassociation preserves that.
17992 SDNodeFlags ReassocFlags =
17993 (N->getFlags() & N1->getFlags()) & SDNodeFlags::NoUnsignedWrap;
17994 SDValue UniformInner = DAG.getMemBasePlusOffset(X, Y, DL, ReassocFlags);
17995 DCI.AddToWorklist(UniformInner.getNode());
17996 return DAG.getMemBasePlusOffset(UniformInner, Z, DL, ReassocFlags);
17997 }
17998
17999 return SDValue();
18000}
18001
18002static bool isCtlzOpc(unsigned Opc) {
18003 return Opc == ISD::CTLZ || Opc == ISD::CTLZ_ZERO_POISON;
18004}
18005
18006SDValue SITargetLowering::performSubCombine(SDNode *N,
18007 DAGCombinerInfo &DCI) const {
18008 SelectionDAG &DAG = DCI.DAG;
18009 EVT VT = N->getValueType(0);
18010
18011 if (VT == MVT::i64) {
18012 if (SDValue Folded = foldAddSub64WithZeroLowBitsTo32(N, DCI))
18013 return Folded;
18014 }
18015
18016 if (VT != MVT::i32)
18017 return SDValue();
18018
18019 SDLoc SL(N);
18020 SDValue LHS = N->getOperand(0);
18021 SDValue RHS = N->getOperand(1);
18022
18023 // sub x, zext (setcc) => usubo_carry x, 0, setcc
18024 // sub x, sext (setcc) => uaddo_carry x, 0, setcc
18025 unsigned Opc = RHS.getOpcode();
18026 switch (Opc) {
18027 default:
18028 break;
18029 case ISD::ZERO_EXTEND:
18030 case ISD::SIGN_EXTEND:
18031 case ISD::ANY_EXTEND: {
18032 auto Cond = RHS.getOperand(0);
18033 // If this won't be a real VOPC output, we would still need to insert an
18034 // extra instruction anyway.
18035 if (!isBoolSGPR(Cond))
18036 break;
18037 SDVTList VTList = DAG.getVTList(MVT::i32, MVT::i1);
18038 SDValue Args[] = {LHS, DAG.getConstant(0, SL, MVT::i32), Cond};
18040 return DAG.getNode(Opc, SL, VTList, Args);
18041 }
18042 }
18043
18044 if (LHS.getOpcode() == ISD::USUBO_CARRY) {
18045 // sub (usubo_carry x, 0, cc), y => usubo_carry x, y, cc
18046 if (!isNullConstant(LHS.getOperand(1)))
18047 return SDValue();
18048 SDValue Args[] = {LHS.getOperand(0), RHS, LHS.getOperand(2)};
18049 return DAG.getNode(ISD::USUBO_CARRY, SDLoc(N), LHS->getVTList(), Args);
18050 }
18051
18052 // sub (ctlz (xor x, (sra x, 31))), 1 -> ctls x.
18053 if (isOneConstant(RHS) && isCtlzOpc(LHS.getOpcode())) {
18054 SDValue CtlzSrc = LHS.getOperand(0);
18055 // Check for xor x, (sra x, 31) pattern.
18056 if (CtlzSrc.getOpcode() == ISD::XOR) {
18057 SDValue X = CtlzSrc.getOperand(0);
18058 SDValue SignExt = CtlzSrc.getOperand(1);
18059 // Try both ordering of XOR operands.
18060 if (SignExt.getOpcode() != ISD::SRA)
18061 std::swap(X, SignExt);
18062 if (SignExt.getOpcode() == ISD::SRA && SignExt.getOperand(0) == X) {
18063 ConstantSDNode *ShiftAmt =
18065 unsigned BitWidth = X.getValueType().getScalarSizeInBits();
18066 if (ShiftAmt && ShiftAmt->getZExtValue() == BitWidth - 1)
18067 return DAG.getNode(ISD::CTLS, SL, VT, X);
18068 }
18069 }
18070 }
18071
18072 return SDValue();
18073}
18074
18075SDValue SITargetLowering::performFAddCombine(SDNode *N,
18076 DAGCombinerInfo &DCI) const {
18077 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18078 return SDValue();
18079
18080 SelectionDAG &DAG = DCI.DAG;
18081 EVT VT = N->getValueType(0);
18082
18083 SDLoc SL(N);
18084 SDValue LHS = N->getOperand(0);
18085 SDValue RHS = N->getOperand(1);
18086
18087 // These should really be instruction patterns, but writing patterns with
18088 // source modifiers is a pain.
18089
18090 // fadd (fadd (a, a), b) -> mad 2.0, a, b
18091 if (LHS.getOpcode() == ISD::FADD) {
18092 SDValue A = LHS.getOperand(0);
18093 if (A == LHS.getOperand(1)) {
18094 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18095 if (FusedOp != 0) {
18096 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18097 return DAG.getNode(FusedOp, SL, VT, A, Two, RHS);
18098 }
18099 }
18100 }
18101
18102 // fadd (b, fadd (a, a)) -> mad 2.0, a, b
18103 if (RHS.getOpcode() == ISD::FADD) {
18104 SDValue A = RHS.getOperand(0);
18105 if (A == RHS.getOperand(1)) {
18106 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18107 if (FusedOp != 0) {
18108 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18109 return DAG.getNode(FusedOp, SL, VT, A, Two, LHS);
18110 }
18111 }
18112 }
18113
18114 return SDValue();
18115}
18116
18117SDValue SITargetLowering::performFSubCombine(SDNode *N,
18118 DAGCombinerInfo &DCI) const {
18119 if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
18120 return SDValue();
18121
18122 SelectionDAG &DAG = DCI.DAG;
18123 SDLoc SL(N);
18124 EVT VT = N->getValueType(0);
18125 assert(!VT.isVector());
18126
18127 // Try to get the fneg to fold into the source modifier. This undoes generic
18128 // DAG combines and folds them into the mad.
18129 //
18130 // Only do this if we are not trying to support denormals. v_mad_f32 does
18131 // not support denormals ever.
18132 SDValue LHS = N->getOperand(0);
18133 SDValue RHS = N->getOperand(1);
18134 if (LHS.getOpcode() == ISD::FADD) {
18135 // (fsub (fadd a, a), c) -> mad 2.0, a, (fneg c)
18136 SDValue A = LHS.getOperand(0);
18137 if (A == LHS.getOperand(1)) {
18138 unsigned FusedOp = getFusedOpcode(DAG, N, LHS.getNode());
18139 if (FusedOp != 0) {
18140 const SDValue Two = DAG.getConstantFP(2.0, SL, VT);
18141 SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
18142
18143 return DAG.getNode(FusedOp, SL, VT, A, Two, NegRHS);
18144 }
18145 }
18146 }
18147
18148 if (RHS.getOpcode() == ISD::FADD) {
18149 // (fsub c, (fadd a, a)) -> mad -2.0, a, c
18150
18151 SDValue A = RHS.getOperand(0);
18152 if (A == RHS.getOperand(1)) {
18153 unsigned FusedOp = getFusedOpcode(DAG, N, RHS.getNode());
18154 if (FusedOp != 0) {
18155 const SDValue NegTwo = DAG.getConstantFP(-2.0, SL, VT);
18156 return DAG.getNode(FusedOp, SL, VT, A, NegTwo, LHS);
18157 }
18158 }
18159 }
18160
18161 return SDValue();
18162}
18163
18164SDValue SITargetLowering::performFDivCombine(SDNode *N,
18165 DAGCombinerInfo &DCI) const {
18166 SelectionDAG &DAG = DCI.DAG;
18167 SDLoc SL(N);
18168 EVT VT = N->getValueType(0);
18169
18170 if (VT != MVT::f16 && VT != MVT::bf16)
18171 return SDValue();
18172
18173 SDValue LHS = N->getOperand(0);
18174 SDValue RHS = N->getOperand(1);
18175
18176 SDNodeFlags Flags = N->getFlags();
18177 SDNodeFlags RHSFlags = RHS->getFlags();
18178 if (!Flags.hasAllowContract() || !RHSFlags.hasAllowContract() ||
18179 !RHS->hasOneUse())
18180 return SDValue();
18181
18182 if (const ConstantFPSDNode *CLHS = dyn_cast<ConstantFPSDNode>(LHS)) {
18183 bool IsNegative = false;
18184 if (CLHS->isOne() || (IsNegative = CLHS->isMinusOne())) {
18185 // fdiv contract 1.0, (sqrt contract x) -> rsq
18186 // fdiv contract -1.0, (sqrt contract x) -> fneg(rsq)
18187 if (RHS.getOpcode() == ISD::FSQRT) {
18188 // TODO: Or in RHS flags, somehow missing from SDNodeFlags
18189 SDValue SqrtOp = RHS.getOperand(0);
18190 SDValue Rsq;
18191 if (isOperationLegal(ISD::FSQRT, VT)) {
18192 // fsqrt legality correlates to rsq availability of the same type.
18193 Rsq = DAG.getNode(AMDGPUISD::RSQ, SL, VT, SqrtOp, Flags);
18194 } else if (VT == MVT::f16) {
18195 // Targets without 16-bit instructions (gfx6/gfx7) have no f16 rsq,
18196 // but v_rsq_f32 is more than accurate enough for f16. Unlike bf16,
18197 // every f16 value (including denormals) extends to a normal f32, and
18198 // an f16 rsq result is never denormal, so the f32 reciprocal square
18199 // root needs no denormal handling. Compute it in f32 and round back.
18200 SDValue Ext =
18201 DAG.getNode(ISD::FP_EXTEND, SL, MVT::f32, SqrtOp, Flags);
18202 SDValue F32Rsq =
18203 DAG.getNode(AMDGPUISD::RSQ, SL, MVT::f32, Ext, Flags);
18204 Rsq = DAG.getNode(ISD::FP_ROUND, SL, VT, F32Rsq,
18205 DAG.getTargetConstant(0, SL, MVT::i32), Flags);
18206 } else {
18207 // bf16 shares f32's exponent range, so bf16 denormals would extend to
18208 // f32 denormals that v_rsq_f32 does not handle. Leave it expanded.
18209 return SDValue();
18210 }
18211 return IsNegative ? DAG.getNode(ISD::FNEG, SL, VT, Rsq, Flags) : Rsq;
18212 }
18213 }
18214 }
18215
18216 return SDValue();
18217}
18218
18219SDValue SITargetLowering::performFMulCombine(SDNode *N,
18220 DAGCombinerInfo &DCI) const {
18221 SelectionDAG &DAG = DCI.DAG;
18222 EVT VT = N->getValueType(0);
18223 EVT ScalarVT = VT.getScalarType();
18224 EVT IntVT = VT.changeElementType(*DAG.getContext(), MVT::i32);
18225
18226 if (!N->isDivergent() && getSubtarget()->hasSALUFloatInsts() &&
18227 (ScalarVT == MVT::f32 || ScalarVT == MVT::f16)) {
18228 // Prefer to use s_mul_f16/f32 instead of v_ldexp_f16/f32.
18229 return SDValue();
18230 }
18231
18232 SDValue LHS = N->getOperand(0);
18233 SDValue RHS = N->getOperand(1);
18234
18235 // It is cheaper to realize i32 inline constants as compared against
18236 // materializing f16 or f64 (or even non-inline f32) values,
18237 // possible via ldexp usage, as shown below :
18238 //
18239 // Given : A = 2^a & B = 2^b ; where a and b are integers.
18240 // fmul x, (select y, A, B) -> ldexp( x, (select i32 y, a, b) )
18241 // fmul x, (select y, -A, -B) -> ldexp( (fneg x), (select i32 y, a, b) )
18242 if ((ScalarVT == MVT::f64 || ScalarVT == MVT::f32 || ScalarVT == MVT::f16) &&
18243 (RHS.hasOneUse() && RHS.getOpcode() == ISD::SELECT)) {
18244 const ConstantFPSDNode *TrueNode = isConstOrConstSplatFP(RHS.getOperand(1));
18245 if (!TrueNode)
18246 return SDValue();
18247 const ConstantFPSDNode *FalseNode =
18248 isConstOrConstSplatFP(RHS.getOperand(2));
18249 if (!FalseNode)
18250 return SDValue();
18251
18252 if (TrueNode->isNegative() != FalseNode->isNegative())
18253 return SDValue();
18254
18255 // For f32, only non-inline constants should be transformed.
18256 const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
18257 if (ScalarVT == MVT::f32 &&
18258 TII->isInlineConstant(TrueNode->getValueAPF()) &&
18259 TII->isInlineConstant(FalseNode->getValueAPF()))
18260 return SDValue();
18261
18262 int TrueNodeExpVal = TrueNode->getValueAPF().getExactLog2Abs();
18263 if (TrueNodeExpVal == INT_MIN)
18264 return SDValue();
18265 int FalseNodeExpVal = FalseNode->getValueAPF().getExactLog2Abs();
18266 if (FalseNodeExpVal == INT_MIN)
18267 return SDValue();
18268
18269 SDLoc SL(N);
18270 SDValue SelectNode =
18271 DAG.getNode(ISD::SELECT, SL, IntVT, RHS.getOperand(0),
18272 DAG.getSignedConstant(TrueNodeExpVal, SL, IntVT),
18273 DAG.getSignedConstant(FalseNodeExpVal, SL, IntVT));
18274
18275 LHS = TrueNode->isNegative()
18276 ? DAG.getNode(ISD::FNEG, SL, VT, LHS, LHS->getFlags())
18277 : LHS;
18278
18279 return DAG.getNode(ISD::FLDEXP, SL, VT, LHS, SelectNode, N->getFlags());
18280 }
18281
18282 return SDValue();
18283}
18284
18285SDValue SITargetLowering::performFMACombine(SDNode *N,
18286 DAGCombinerInfo &DCI) const {
18287 SelectionDAG &DAG = DCI.DAG;
18288 EVT VT = N->getValueType(0);
18289 SDLoc SL(N);
18290
18291 if (!Subtarget->hasDot10Insts() || VT != MVT::f32)
18292 return SDValue();
18293
18294 // FMA((F32)S0.x, (F32)S1. x, FMA((F32)S0.y, (F32)S1.y, (F32)z)) ->
18295 // FDOT2((V2F16)S0, (V2F16)S1, (F32)z))
18296 SDValue Op1 = N->getOperand(0);
18297 SDValue Op2 = N->getOperand(1);
18298 SDValue FMA = N->getOperand(2);
18299
18300 if (FMA.getOpcode() != ISD::FMA || Op1.getOpcode() != ISD::FP_EXTEND ||
18301 Op2.getOpcode() != ISD::FP_EXTEND)
18302 return SDValue();
18303
18304 // The fdot2 fold (fma_mix -> dot2) is only safe when both instructions agree
18305 // on how f16 subnormal inputs are handled. However, if both FMAs carry afn
18306 // the caller accepts approximate results, so any subnormal flushing
18307 // introduced by dot2 is acceptable regardless of mode.
18308 //
18309 // gfx90a (CDNA2) is the sole exception (dot2UnconditionalFlush): v_dot2c
18310 // unconditionally flushes f16 subnormal inputs to zero regardless of MODE,
18311 // while v_fma_mix_f32 preserves them when ieee=1 (the default compute kernel
18312 // mode). The fold is safe only when f32 denorm = PreserveSign, which implies
18313 // ieee=0 so both flush.
18314 //
18315 // All other GPUs: v_dot2 does NOT flush f16 subnormal inputs. v_fma_mix_f32
18316 // flushes them only when f32 denorm = PreserveSign. The fold is safe only
18317 // when f32 denorm is IEEE (both preserve the subnormal). Dynamic mode is
18318 // also rejected since the runtime value is unknown.
18319 bool AllowInaccuracy = N->getFlags().hasApproximateFuncs() &&
18320 FMA->getFlags().hasApproximateFuncs();
18321 if (!AllowInaccuracy) {
18322 const MachineFunction &MF = DAG.getMachineFunction();
18323 DenormalMode Mode = MF.getDenormalMode(APFloat::IEEEsingle());
18324 if (Subtarget->dot2UnconditionalFlush()) {
18325 // gfx90a: fold safe only when f32 denorm flushes.
18327 return SDValue();
18328 } else {
18329 // All other GPUs: fold safe only when f32 denorm is IEEE.
18330 if (Mode != DenormalMode::getIEEE())
18331 return SDValue();
18332 }
18333 }
18334
18335 // fp-contract allows reassociating the fma tree into a dot product.
18336 const TargetOptions &Options = DAG.getTarget().Options;
18337 if (Options.AllowFPOpFusion == FPOpFusion::Fast ||
18338 (N->getFlags().hasAllowContract() &&
18339 FMA->getFlags().hasAllowContract())) {
18340 Op1 = Op1.getOperand(0);
18341 Op2 = Op2.getOperand(0);
18342 if (Op1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18344 return SDValue();
18345
18346 SDValue Vec1 = Op1.getOperand(0);
18347 SDValue Idx1 = Op1.getOperand(1);
18348 SDValue Vec2 = Op2.getOperand(0);
18349
18350 SDValue FMAOp1 = FMA.getOperand(0);
18351 SDValue FMAOp2 = FMA.getOperand(1);
18352 SDValue FMAAcc = FMA.getOperand(2);
18353
18354 if (FMAOp1.getOpcode() != ISD::FP_EXTEND ||
18355 FMAOp2.getOpcode() != ISD::FP_EXTEND)
18356 return SDValue();
18357
18358 FMAOp1 = FMAOp1.getOperand(0);
18359 FMAOp2 = FMAOp2.getOperand(0);
18360 if (FMAOp1.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18362 return SDValue();
18363
18364 SDValue Vec3 = FMAOp1.getOperand(0);
18365 SDValue Vec4 = FMAOp2.getOperand(0);
18366 SDValue Idx2 = FMAOp1.getOperand(1);
18367
18368 if (Idx1 != Op2.getOperand(1) || Idx2 != FMAOp2.getOperand(1) ||
18369 // Idx1 and Idx2 cannot be the same.
18370 Idx1 == Idx2)
18371 return SDValue();
18372
18373 if (Vec1 == Vec2 || Vec3 == Vec4)
18374 return SDValue();
18375
18376 if (Vec1.getValueType() != MVT::v2f16 || Vec2.getValueType() != MVT::v2f16)
18377 return SDValue();
18378
18379 if ((Vec1 == Vec3 && Vec2 == Vec4) || (Vec1 == Vec4 && Vec2 == Vec3)) {
18380 return DAG.getNode(AMDGPUISD::FDOT2, SL, MVT::f32, Vec1, Vec2, FMAAcc,
18381 DAG.getTargetConstant(0, SL, MVT::i1));
18382 }
18383 }
18384 return SDValue();
18385}
18386
18387// Given a double-precision ordered or unordered comparison, return the
18388// condition code for an equivalent integral comparison of the operands' upper
18389// 32 bits, or `SETCC_INVALID` if not possible.
18390// For simplicity, no simplification occurs if the operands are not both known
18391// to have sign bit zero.
18392//
18393// EQ/NE:
18394// If LHS.lo32 == RHS.lo32:
18395// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18396// If LHS.lo32 != RHS.lo32:
18397// setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18398// The reduction is not possible if operands may be +0 and -0.
18399// For ordered eq / unordered ne, at most one operand may be NaN.
18400// For unordered eq / ordered ne, neither operand can be NaN.
18401//
18402// LT/GE:
18403// If LHS.lo32 >= RHS.lo32 (unsigned):
18404// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18405// If LHS.lo32 < RHS.lo32 (unsigned):
18406// setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18407// The reduction is only supported if both operands are nonnegative.
18408// For ordered lt / unordered ge, the RHS cannot be NaN.
18409// For unordered lt / ordered ge, neither operand can be NaN.
18410//
18411// LE/GT:
18412// If LHS.lo32 > RHS.lo32 (unsigned):
18413// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18414// If LHS.lo32 <= RHS.lo32 (unsigned):
18415// setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18416// The reduction is only supported if both operands are nonnegative.
18417// For unordered le / ordered gt, the LHS cannot be NaN.
18418// For ordered le / unordered gt, neither operand can be NaN.
18420 const SDValue LHS,
18421 const SDValue RHS,
18422 const SelectionDAG &DAG) {
18423 EVT VT = LHS.getValueType();
18424 assert(VT == MVT::f64 && "Incorrect operand type!");
18425
18426 const KnownBits RHSBits = DAG.computeKnownBits(RHS);
18427 // Bail if RHS sign bit is not known to be zero.
18428 if (!RHSBits.Zero.isSignBitSet())
18429 return ISD::SETCC_INVALID;
18430
18431 const KnownBits RHSKnownLo32 = RHSBits.trunc(32);
18432 const KnownFPClass RHSFPClass =
18434 const bool RHSMaybeNaN = !RHSFPClass.isKnownNeverNaN();
18435
18436 const KnownBits LHSBits = DAG.computeKnownBits(LHS);
18437 const KnownBits LHSKnownLo32 = LHSBits.trunc(32);
18438 const KnownFPClass LHSFPClass =
18440 const bool LHSMaybeNaN = !LHSFPClass.isKnownNeverNaN();
18441
18442 // Bail if LHS sign bit is not known to be zero.
18443 if (!LHSBits.Zero.isSignBitSet())
18444 return ISD::SETCC_INVALID;
18445
18446 switch (CC) {
18447 default:
18448 break;
18449 case ISD::SETEQ:
18450 case ISD::SETOEQ:
18451 case ISD::SETUEQ:
18452 case ISD::SETONE:
18453 case ISD::SETUNE: {
18454 // OEQ should be false if either operand is NaN, so it suffices that at
18455 // least one operand is not NaN.
18456 if (CC == ISD::SETOEQ && LHSMaybeNaN && RHSMaybeNaN)
18457 break;
18458 // UEQ should be true if either operand is NaN, but this cannot be checked
18459 // on underlying bits.
18460 if (CC == ISD::SETUEQ && (LHSMaybeNaN || RHSMaybeNaN))
18461 break;
18462 // ONE should be false if either operand is NaN, but this cannot be
18463 // checked on underlying bits.
18464 if (CC == ISD::SETONE && (LHSMaybeNaN || RHSMaybeNaN))
18465 break;
18466 // UNE should be true if either operand is NaN, so it suffices that they
18467 // are not both NaN.
18468 if (CC == ISD::SETUNE && LHSMaybeNaN && RHSMaybeNaN)
18469 break;
18470
18471 const std::optional<bool> KnownEq =
18472 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18473
18474 if (!KnownEq)
18475 break;
18476
18477 if (*KnownEq)
18478 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18479 ? ISD::SETEQ
18480 : ISD::SETNE;
18481
18482 return (CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ)
18484 : ISD::SETTRUE;
18485 }
18486 case ISD::SETLT:
18487 case ISD::SETOLT:
18488 case ISD::SETULT:
18489 case ISD::SETGE:
18490 case ISD::SETOGE:
18491 case ISD::SETUGE: {
18492 // OLT should be false if either operand is NaN.
18493 // Since NaNs have maximum exponent and nonzero mantissa, false positives
18494 // are only possible if the RHS is NaN. (No issue with RHS == +inf since
18495 // the inequality is strict)
18496 if (CC == ISD::SETOLT && RHSMaybeNaN)
18497 break;
18498 // ULT should be true if either operand is NaN, but this cannot be ensured
18499 // with a truncated comparison.
18500 if (CC == ISD::SETULT && (LHSMaybeNaN || RHSMaybeNaN))
18501 break;
18502 // OGE should be false if either operand is NaN, but this cannot be
18503 // ensured with a truncated comparison.
18504 if (CC == ISD::SETOGE && (LHSMaybeNaN || RHSMaybeNaN))
18505 break;
18506 // UGE should be true if either operand is NaN.
18507 // False negatives are only possible if the RHS is NaN.
18508 // (No issue with RHS == +inf since the inequality is inclusive)
18509 if (CC == ISD::SETUGE && RHSMaybeNaN)
18510 break;
18511
18512 const std::optional<bool> KnownUge =
18513 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
18514
18515 if (!KnownUge)
18516 break;
18517
18518 if (*KnownUge) {
18519 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
18520 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18521 ? ISD::SETLT
18522 : ISD::SETGE;
18523 }
18524 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
18525 return (CC == ISD::SETLT || CC == ISD::SETOLT || CC == ISD::SETULT)
18526 ? ISD::SETLE
18527 : ISD::SETGT;
18528 }
18529 case ISD::SETLE:
18530 case ISD::SETOLE:
18531 case ISD::SETULE:
18532 case ISD::SETGT:
18533 case ISD::SETOGT:
18534 case ISD::SETUGT: {
18535 // OLE should be false if either operand is NaN, but this cannot be
18536 // ensured with a truncated comparison.
18537 if (CC == ISD::SETOLE && (LHSMaybeNaN || RHSMaybeNaN))
18538 break;
18539 // ULE should be true if either operand is NaN.
18540 // False negatives are only possible if the LHS is NaN.
18541 // (No issue with LHS == +inf since the inequality is inclusive)
18542 if (CC == ISD::SETULE && LHSMaybeNaN)
18543 break;
18544 // OGT should be false if either operand is NaN.
18545 // False positives are only possible if the LHS is NaN.
18546 // (No issue with LHS == +inf since the inequality is strict)
18547 if (CC == ISD::SETOGT && LHSMaybeNaN)
18548 break;
18549 // UGT should be true if either operand is NaN, but this cannot be ensured
18550 // with a truncated comparison.
18551 if (CC == ISD::SETUGT && (LHSMaybeNaN || RHSMaybeNaN))
18552 break;
18553
18554 const std::optional<bool> KnownUle =
18555 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
18556
18557 if (!KnownUle)
18558 break;
18559
18560 if (*KnownUle) {
18561 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
18562 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18563 ? ISD::SETLE
18564 : ISD::SETGT;
18565 }
18566 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
18567 return (CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE)
18568 ? ISD::SETLT
18569 : ISD::SETGE;
18570 }
18571 }
18572
18573 return ISD::SETCC_INVALID;
18574}
18575
18576SDValue SITargetLowering::performSetCCCombine(SDNode *N,
18577 DAGCombinerInfo &DCI) const {
18578 SelectionDAG &DAG = DCI.DAG;
18579 SDLoc SL(N);
18580
18581 SDValue LHS = N->getOperand(0);
18582 SDValue RHS = N->getOperand(1);
18583 EVT VT = LHS.getValueType();
18584 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
18585
18586 auto *CRHS = dyn_cast<ConstantSDNode>(RHS);
18587 if (!CRHS) {
18589 if (CRHS) {
18590 std::swap(LHS, RHS);
18591 CC = getSetCCSwappedOperands(CC);
18592 }
18593 }
18594
18595 if (CRHS) {
18596 if (VT == MVT::i32 && LHS.getOpcode() == ISD::SIGN_EXTEND &&
18597 isBoolSGPR(LHS.getOperand(0))) {
18598 // setcc (sext from i1 cc), -1, ne|sgt|ult) => not cc => xor cc, -1
18599 // setcc (sext from i1 cc), -1, eq|sle|uge) => cc
18600 // setcc (sext from i1 cc), 0, eq|sge|ule) => not cc => xor cc, -1
18601 // setcc (sext from i1 cc), 0, ne|ugt|slt) => cc
18602 if ((CRHS->isAllOnes() &&
18603 (CC == ISD::SETNE || CC == ISD::SETGT || CC == ISD::SETULT)) ||
18604 (CRHS->isZero() &&
18605 (CC == ISD::SETEQ || CC == ISD::SETGE || CC == ISD::SETULE)))
18606 return DAG.getNode(ISD::XOR, SL, MVT::i1, LHS.getOperand(0),
18607 DAG.getAllOnesConstant(SL, MVT::i1));
18608 if ((CRHS->isAllOnes() &&
18609 (CC == ISD::SETEQ || CC == ISD::SETLE || CC == ISD::SETUGE)) ||
18610 (CRHS->isZero() &&
18611 (CC == ISD::SETNE || CC == ISD::SETUGT || CC == ISD::SETLT)))
18612 return LHS.getOperand(0);
18613 }
18614
18615 const APInt &CRHSVal = CRHS->getAPIntValue();
18616 if ((CC == ISD::SETEQ || CC == ISD::SETNE) &&
18617 LHS.getOpcode() == ISD::SELECT &&
18618 isa<ConstantSDNode>(LHS.getOperand(1)) &&
18619 isa<ConstantSDNode>(LHS.getOperand(2)) &&
18620 isBoolSGPR(LHS.getOperand(0))) {
18621 // Given CT != FT:
18622 // setcc (select cc, CT, CF), CF, eq => xor cc, -1
18623 // setcc (select cc, CT, CF), CF, ne => cc
18624 // setcc (select cc, CT, CF), CT, ne => xor cc, -1
18625 // setcc (select cc, CT, CF), CT, eq => cc
18626 const APInt &CT = LHS.getConstantOperandAPInt(1);
18627 const APInt &CF = LHS.getConstantOperandAPInt(2);
18628
18629 if (CT != CF) {
18630 if ((CF == CRHSVal && CC == ISD::SETEQ) ||
18631 (CT == CRHSVal && CC == ISD::SETNE))
18632 return DAG.getNOT(SL, LHS.getOperand(0), MVT::i1);
18633 if ((CF == CRHSVal && CC == ISD::SETNE) ||
18634 (CT == CRHSVal && CC == ISD::SETEQ))
18635 return LHS.getOperand(0);
18636 }
18637 }
18638 }
18639
18640 // Truncate 64-bit setcc to test only upper 32-bits of its operands in the
18641 // following cases where information about the lower 32-bits of its operands
18642 // is known:
18643 //
18644 // If LHS.lo32 == RHS.lo32:
18645 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, eq/ne
18646 // If LHS.lo32 != RHS.lo32:
18647 // setcc LHS, RHS, eq/ne => setcc LHS.hi32, RHS.hi32, false/true
18648 // If LHS.lo32 >= RHS.lo32 (unsigned):
18649 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]lt/ge
18650 // If LHS.lo32 > RHS.lo32 (unsigned):
18651 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]lt/ge
18652 // If LHS.lo32 <= RHS.lo32 (unsigned):
18653 // setcc LHS, RHS, [u]le/gt => LHS.hi32, RHS.hi32, [u]le/gt
18654 // If LHS.lo32 < RHS.lo32 (unsigned):
18655 // setcc LHS, RHS, [u]lt/ge => LHS.hi32, RHS.hi32, [u]le/gt
18656 if (VT == MVT::i64) {
18657 const KnownBits LHSKnownLo32 = DAG.computeKnownBits(LHS).trunc(32);
18658 const KnownBits RHSKnownLo32 = DAG.computeKnownBits(RHS).trunc(32);
18659
18660 // NewCC is valid iff we can truncate the setcc to only test the upper 32
18661 // bits
18663
18664 switch (CC) {
18665 default:
18666 break;
18667 case ISD::SETEQ: {
18668 const std::optional<bool> KnownEq =
18669 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18670 if (KnownEq)
18671 NewCC = *KnownEq ? ISD::SETEQ : ISD::SETFALSE;
18672
18673 break;
18674 }
18675 case ISD::SETNE: {
18676 const std::optional<bool> KnownEq =
18677 KnownBits::eq(LHSKnownLo32, RHSKnownLo32);
18678 if (KnownEq)
18679 NewCC = *KnownEq ? ISD::SETNE : ISD::SETTRUE;
18680
18681 break;
18682 }
18683 case ISD::SETULT:
18684 case ISD::SETUGE:
18685 case ISD::SETLT:
18686 case ISD::SETGE: {
18687 const std::optional<bool> KnownUge =
18688 KnownBits::uge(LHSKnownLo32, RHSKnownLo32);
18689 if (KnownUge) {
18690 if (*KnownUge) {
18691 // LHS.lo32 uge RHS.lo32, so LHS >= RHS iff LHS.hi32 >= RHS.hi32
18692 NewCC = CC;
18693 } else {
18694 // LHS.lo32 ult RHS.lo32, so LHS >= RHS iff LHS.hi32 > RHS.hi32
18695 NewCC = CC == ISD::SETULT ? ISD::SETULE
18696 : CC == ISD::SETUGE ? ISD::SETUGT
18697 : CC == ISD::SETLT ? ISD::SETLE
18698 : ISD::SETGT;
18699 }
18700 }
18701 break;
18702 }
18703 case ISD::SETULE:
18704 case ISD::SETUGT:
18705 case ISD::SETLE:
18706 case ISD::SETGT: {
18707 const std::optional<bool> KnownUle =
18708 KnownBits::ule(LHSKnownLo32, RHSKnownLo32);
18709 if (KnownUle) {
18710 if (*KnownUle) {
18711 // LHS.lo32 ule RHS.lo32, so LHS <= RHS iff LHS.hi32 <= RHS.hi32
18712 NewCC = CC;
18713 } else {
18714 // LHS.lo32 ugt RHS.lo32, so LHS <= RHS iff LHS.hi32 < RHS.hi32
18715 NewCC = CC == ISD::SETULE ? ISD::SETULT
18716 : CC == ISD::SETUGT ? ISD::SETUGE
18717 : CC == ISD::SETLE ? ISD::SETLT
18718 : ISD::SETGE;
18719 }
18720 }
18721 break;
18722 }
18723 }
18724
18725 if (NewCC != ISD::SETCC_INVALID)
18726 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
18727 getHiHalf64(RHS, DAG), NewCC);
18728 }
18729
18730 // Eliminate setcc by using carryout from add/sub instruction
18731
18732 // LHS = ADD i64 RHS, Z LHSlo = UADDO i32 RHSlo, Zlo
18733 // setcc LHS ult RHS -> LHSHi = UADDO_CARRY i32 RHShi, Zhi
18734 // similarly for subtraction
18735
18736 // LHS = ADD i64 Y, 1 LHSlo = UADDO i32 Ylo, 1
18737 // setcc LHS eq 0 -> LHSHi = UADDO_CARRY i32 Yhi, 0
18738
18739 if (VT == MVT::i64 && ((CC == ISD::SETULT &&
18741 (CC == ISD::SETUGT &&
18743 (CC == ISD::SETEQ && CRHS && CRHS->isZero() &&
18744 sd_match(LHS, m_Add(m_Value(), m_One()))))) {
18745 bool IsAdd = LHS.getOpcode() == ISD::ADD;
18746
18747 SDValue Op0 = LHS.getOperand(0);
18748 SDValue Op1 = LHS.getOperand(1);
18749
18750 SDValue Op0Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op0);
18751 SDValue Op1Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, Op1);
18752
18753 SDValue Op0Hi = getHiHalf64(Op0, DAG);
18754 SDValue Op1Hi = getHiHalf64(Op1, DAG);
18755
18756 SDValue NodeLo =
18757 DAG.getNode(IsAdd ? ISD::UADDO : ISD::USUBO, SL,
18758 DAG.getVTList(MVT::i32, MVT::i1), {Op0Lo, Op1Lo});
18759
18760 SDValue CarryInHi = NodeLo.getValue(1);
18761 SDValue NodeHi = DAG.getNode(IsAdd ? ISD::UADDO_CARRY : ISD::USUBO_CARRY,
18762 SL, DAG.getVTList(MVT::i32, MVT::i1),
18763 {Op0Hi, Op1Hi, CarryInHi});
18764
18765 SDValue ResultLo = NodeLo.getValue(0);
18766 SDValue ResultHi = NodeHi.getValue(0);
18767
18768 SDValue JoinedResult =
18769 DAG.getBuildVector(MVT::v2i32, SL, {ResultLo, ResultHi});
18770
18771 SDValue Result = DAG.getNode(ISD::BITCAST, SL, VT, JoinedResult);
18772 SDValue Overflow = NodeHi.getValue(1);
18773 DCI.CombineTo(LHS.getNode(), Result);
18774 return Overflow;
18775 }
18776
18777 if (VT != MVT::f32 && VT != MVT::f64 &&
18778 (!Subtarget->has16BitInsts() || VT != MVT::f16))
18779 return SDValue();
18780
18781 // Match isinf/isfinite pattern
18782 // (fcmp oeq (fabs x), inf) -> (fp_class x, (p_infinity | n_infinity))
18783 // (fcmp one (fabs x), inf) -> (fp_class x,
18784 // (p_normal | n_normal | p_subnormal | n_subnormal | p_zero | n_zero)
18785 if ((CC == ISD::SETOEQ || CC == ISD::SETONE) &&
18786 LHS.getOpcode() == ISD::FABS) {
18787 const ConstantFPSDNode *CRHS = dyn_cast<ConstantFPSDNode>(RHS);
18788 if (!CRHS)
18789 return SDValue();
18790
18791 const APFloat &APF = CRHS->getValueAPF();
18792 if (APF.isInfinity() && !APF.isNegative()) {
18793 const unsigned IsInfMask =
18795 const unsigned IsFiniteMask =
18799 unsigned Mask = CC == ISD::SETOEQ ? IsInfMask : IsFiniteMask;
18800 return DAG.getNode(AMDGPUISD::FP_CLASS, SL, MVT::i1, LHS.getOperand(0),
18801 DAG.getConstant(Mask, SL, MVT::i32));
18802 }
18803 }
18804
18805 if (VT == MVT::f64) {
18806 ISD::CondCode HiHalfCC = tryReduceF64CompareToHiHalf(CC, LHS, RHS, DAG);
18807 if (HiHalfCC != ISD::SETCC_INVALID)
18808 return DAG.getSetCC(SL, N->getValueType(0), getHiHalf64(LHS, DAG),
18809 getHiHalf64(RHS, DAG), HiHalfCC);
18810 }
18811
18812 return SDValue();
18813}
18814
18815SDValue
18816SITargetLowering::performCvtF32UByteNCombine(SDNode *N,
18817 DAGCombinerInfo &DCI) const {
18818 SelectionDAG &DAG = DCI.DAG;
18819 SDLoc SL(N);
18820 unsigned Offset = N->getOpcode() - AMDGPUISD::CVT_F32_UBYTE0;
18821
18822 SDValue Src = N->getOperand(0);
18823 SDValue Shift = N->getOperand(0);
18824
18825 // TODO: Extend type shouldn't matter (assuming legal types).
18826 if (Shift.getOpcode() == ISD::ZERO_EXTEND)
18827 Shift = Shift.getOperand(0);
18828
18829 if (Shift.getOpcode() == ISD::SRL || Shift.getOpcode() == ISD::SHL) {
18830 // cvt_f32_ubyte1 (shl x, 8) -> cvt_f32_ubyte0 x
18831 // cvt_f32_ubyte3 (shl x, 16) -> cvt_f32_ubyte1 x
18832 // cvt_f32_ubyte0 (srl x, 16) -> cvt_f32_ubyte2 x
18833 // cvt_f32_ubyte1 (srl x, 16) -> cvt_f32_ubyte3 x
18834 // cvt_f32_ubyte0 (srl x, 8) -> cvt_f32_ubyte1 x
18835 if (auto *C = dyn_cast<ConstantSDNode>(Shift.getOperand(1))) {
18836 SDValue Shifted = DAG.getZExtOrTrunc(
18837 Shift.getOperand(0), SDLoc(Shift.getOperand(0)), MVT::i32);
18838
18839 unsigned ShiftOffset = 8 * Offset;
18840 if (Shift.getOpcode() == ISD::SHL)
18841 ShiftOffset -= C->getZExtValue();
18842 else
18843 ShiftOffset += C->getZExtValue();
18844
18845 if (ShiftOffset < 32 && (ShiftOffset % 8) == 0) {
18846 return DAG.getNode(AMDGPUISD::CVT_F32_UBYTE0 + ShiftOffset / 8, SL,
18847 MVT::f32, Shifted);
18848 }
18849 }
18850 }
18851
18852 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
18853 APInt DemandedBits = APInt::getBitsSet(32, 8 * Offset, 8 * Offset + 8);
18854 if (TLI.SimplifyDemandedBits(Src, DemandedBits, DCI)) {
18855 // We simplified Src. If this node is not dead, visit it again so it is
18856 // folded properly.
18857 if (N->getOpcode() != ISD::DELETED_NODE)
18858 DCI.AddToWorklist(N);
18859 return SDValue(N, 0);
18860 }
18861
18862 // Handle (or x, (srl y, 8)) pattern when known bits are zero.
18863 if (SDValue DemandedSrc =
18864 TLI.SimplifyMultipleUseDemandedBits(Src, DemandedBits, DAG))
18865 return DAG.getNode(N->getOpcode(), SL, MVT::f32, DemandedSrc);
18866
18867 return SDValue();
18868}
18869
18870SDValue SITargetLowering::performClampCombine(SDNode *N,
18871 DAGCombinerInfo &DCI) const {
18872 ConstantFPSDNode *CSrc = dyn_cast<ConstantFPSDNode>(N->getOperand(0));
18873 if (!CSrc)
18874 return SDValue();
18875
18876 const MachineFunction &MF = DCI.DAG.getMachineFunction();
18877 const APFloat &F = CSrc->getValueAPF();
18878 APFloat Zero = APFloat::getZero(F.getSemantics());
18879 if (F < Zero ||
18880 (F.isNaN() && MF.getInfo<SIMachineFunctionInfo>()->getMode().DX10Clamp)) {
18881 return DCI.DAG.getConstantFP(Zero, SDLoc(N), N->getValueType(0));
18882 }
18883
18884 APFloat One = APFloat::getOne(F.getSemantics());
18885 if (F > One)
18886 return DCI.DAG.getConstantFP(One, SDLoc(N), N->getValueType(0));
18887
18888 return getCanonicalConstantFP(DCI.DAG, SDLoc(N), N->getValueType(0), F);
18889}
18890
18891SDValue SITargetLowering::performSelectCombine(SDNode *N,
18892 DAGCombinerInfo &DCI) const {
18893
18894 // Try to fold CMP + SELECT patterns with shared constants (both FP and
18895 // integer).
18896 // Detect when CMP and SELECT use the same constant and fold them to avoid
18897 // loading the constant twice. Specifically handles patterns like:
18898 // %cmp = icmp eq i32 %val, 4242
18899 // %sel = select i1 %cmp, i32 4242, i32 %other
18900 // It can be optimized to reuse %val instead of 4242 in select.
18901 SDValue Cond = N->getOperand(0);
18902 SDValue TrueVal = N->getOperand(1);
18903 SDValue FalseVal = N->getOperand(2);
18904
18905 // Check if condition is a comparison.
18906 if (Cond.getOpcode() != ISD::SETCC)
18907 return SDValue();
18908
18909 SDValue LHS = Cond.getOperand(0);
18910 SDValue RHS = Cond.getOperand(1);
18911 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
18912
18913 bool isFloatingPoint = LHS.getValueType().isFloatingPoint();
18914 bool isInteger = LHS.getValueType().isInteger();
18915
18916 // Handle simple floating-point and integer types only.
18917 if (!isFloatingPoint && !isInteger)
18918 return SDValue();
18919
18920 // Bare SETEQ/SETNE is the builder's NaN-impossible downgrade.
18921 bool isEquality = CC == ISD::SETEQ || (isFloatingPoint && CC == ISD::SETOEQ);
18922 bool isNonEquality =
18923 CC == ISD::SETNE || (isFloatingPoint && CC == ISD::SETONE);
18924 if (!isEquality && !isNonEquality)
18925 return SDValue();
18926
18927 SDValue ArgVal, ConstVal;
18928 if ((isFloatingPoint && isa<ConstantFPSDNode>(RHS)) ||
18929 (isInteger && isa<ConstantSDNode>(RHS))) {
18930 ConstVal = RHS;
18931 ArgVal = LHS;
18932 } else if ((isFloatingPoint && isa<ConstantFPSDNode>(LHS)) ||
18933 (isInteger && isa<ConstantSDNode>(LHS))) {
18934 ConstVal = LHS;
18935 ArgVal = RHS;
18936 } else {
18937 return SDValue();
18938 }
18939
18940 // Skip optimization for inlinable immediates.
18941 if (isFloatingPoint) {
18942 const APFloat &Val = cast<ConstantFPSDNode>(ConstVal)->getValueAPF();
18943 if (!Val.isNormal() || Subtarget->getInstrInfo()->isInlineConstant(Val))
18944 return SDValue();
18945 } else {
18946 const std::optional<int64_t> Val =
18947 cast<ConstantSDNode>(ConstVal)->getAPIntValue().trySExtValue();
18948 if (Val && AMDGPU::isInlinableIntLiteral(*Val))
18949 return SDValue();
18950 }
18951
18952 // For equality and non-equality comparisons, patterns:
18953 // select (setcc x, const), const, y -> select (setcc x, const), x, y
18954 // select (setccinv x, const), y, const -> select (setccinv x, const), y, x
18955 if (!(isEquality && TrueVal == ConstVal) &&
18956 !(isNonEquality && FalseVal == ConstVal))
18957 return SDValue();
18958
18959 // SETONE's false arm is also taken for NaN ArgVal, so require NaN excluded.
18960 if (isFloatingPoint && isNonEquality && FalseVal == ConstVal &&
18961 !Cond->getFlags().hasNoNaNs() && !DCI.DAG.isKnownNeverNaN(ArgVal))
18962 return SDValue();
18963
18964 SDValue SelectLHS = (isEquality && TrueVal == ConstVal) ? ArgVal : TrueVal;
18965 SDValue SelectRHS =
18966 (isNonEquality && FalseVal == ConstVal) ? ArgVal : FalseVal;
18967 return DCI.DAG.getNode(ISD::SELECT, SDLoc(N), N->getValueType(0), Cond,
18968 SelectLHS, SelectRHS);
18969}
18970
18972 DAGCombinerInfo &DCI) const {
18973 switch (N->getOpcode()) {
18974 case ISD::ABS:
18975 if (SDValue Res = promoteUniformUnaryOpToI32(SDValue(N, 0), DCI))
18976 return Res;
18977 break;
18978 case ISD::ADD:
18979 case ISD::SUB:
18980 case ISD::SHL:
18981 case ISD::SRL:
18982 case ISD::SRA:
18983 case ISD::AND:
18984 case ISD::OR:
18985 case ISD::XOR:
18986 case ISD::MUL:
18987 case ISD::SETCC:
18988 case ISD::SELECT:
18989 case ISD::SMIN:
18990 case ISD::SMAX:
18991 case ISD::UMIN:
18992 case ISD::UMAX:
18993 case ISD::USUBSAT:
18994 if (auto Res = promoteUniformOpToI32(SDValue(N, 0), DCI))
18995 return Res;
18996 break;
18997 default:
18998 break;
18999 }
19000
19001 if (getTargetMachine().getOptLevel() == CodeGenOptLevel::None)
19002 return SDValue();
19003
19004 switch (N->getOpcode()) {
19005 case ISD::ADD:
19006 return performAddCombine(N, DCI);
19007 case ISD::PTRADD:
19008 return performPtrAddCombine(N, DCI);
19009 case ISD::SUB:
19010 return performSubCombine(N, DCI);
19011 case ISD::FADD:
19012 return performFAddCombine(N, DCI);
19013 case ISD::FSUB:
19014 return performFSubCombine(N, DCI);
19015 case ISD::FDIV:
19016 return performFDivCombine(N, DCI);
19017 case ISD::FMUL:
19018 return performFMulCombine(N, DCI);
19019 case ISD::SETCC:
19020 return performSetCCCombine(N, DCI);
19021 case ISD::SELECT:
19022 if (auto Res = performSelectCombine(N, DCI))
19023 return Res;
19024 break;
19025 case ISD::FMAXNUM:
19026 case ISD::FMINNUM:
19027 case ISD::FMAXNUM_IEEE:
19028 case ISD::FMINNUM_IEEE:
19029 case ISD::FMAXIMUM:
19030 case ISD::FMINIMUM:
19031 case ISD::FMAXIMUMNUM:
19032 case ISD::FMINIMUMNUM:
19033 case ISD::SMAX:
19034 case ISD::SMIN:
19035 case ISD::UMAX:
19036 case ISD::UMIN:
19037 case AMDGPUISD::FMIN_LEGACY:
19038 case AMDGPUISD::FMAX_LEGACY:
19039 return performMinMaxCombine(N, DCI);
19040 case ISD::FMA:
19041 return performFMACombine(N, DCI);
19042 case ISD::AND:
19043 return performAndCombine(N, DCI);
19044 case ISD::OR:
19045 return performOrCombine(N, DCI);
19046 case ISD::FSHR: {
19048 if (N->getValueType(0) == MVT::i32 && N->isDivergent() &&
19049 TII->pseudoToMCOpcode(AMDGPU::V_PERM_B32_e64) != -1) {
19050 return matchPERM(N, DCI);
19051 }
19052 break;
19053 }
19054 case ISD::XOR:
19055 return performXorCombine(N, DCI);
19056 case ISD::ANY_EXTEND:
19057 case ISD::ZERO_EXTEND:
19058 return performZeroOrAnyExtendCombine(N, DCI);
19060 return performSignExtendInRegCombine(N, DCI);
19061 case AMDGPUISD::FP_CLASS:
19062 return performClassCombine(N, DCI);
19063 case ISD::FCANONICALIZE:
19064 return performFCanonicalizeCombine(N, DCI);
19065 case AMDGPUISD::RCP:
19066 return performRcpCombine(N, DCI);
19067 case ISD::FLDEXP:
19068 case AMDGPUISD::FRACT:
19069 case AMDGPUISD::RSQ:
19070 case AMDGPUISD::RCP_LEGACY:
19071 case AMDGPUISD::RCP_IFLAG:
19072 case AMDGPUISD::RSQ_CLAMP: {
19073 // FIXME: This is probably wrong. If src is an sNaN, it won't be quieted
19074 SDValue Src = N->getOperand(0);
19075 if (Src.isUndef())
19076 return Src;
19077 break;
19078 }
19079 case ISD::SINT_TO_FP:
19080 case ISD::UINT_TO_FP:
19081 return performUCharToFloatCombine(N, DCI);
19082 case ISD::FCOPYSIGN:
19083 return performFCopySignCombine(N, DCI);
19084 case AMDGPUISD::CVT_F32_UBYTE0:
19085 case AMDGPUISD::CVT_F32_UBYTE1:
19086 case AMDGPUISD::CVT_F32_UBYTE2:
19087 case AMDGPUISD::CVT_F32_UBYTE3:
19088 return performCvtF32UByteNCombine(N, DCI);
19089 case AMDGPUISD::FMED3:
19090 return performFMed3Combine(N, DCI);
19091 case AMDGPUISD::CVT_PKRTZ_F16_F32:
19092 return performCvtPkRTZCombine(N, DCI);
19093 case AMDGPUISD::CLAMP:
19094 return performClampCombine(N, DCI);
19095 case ISD::SCALAR_TO_VECTOR: {
19096 SelectionDAG &DAG = DCI.DAG;
19097 EVT VT = N->getValueType(0);
19098
19099 // v2i16 (scalar_to_vector i16:x) -> v2i16 (bitcast (any_extend i16:x))
19100 if (VT == MVT::v2i16 || VT == MVT::v2f16 || VT == MVT::v2bf16) {
19101 SDLoc SL(N);
19102 SDValue Src = N->getOperand(0);
19103 EVT EltVT = Src.getValueType();
19104 if (EltVT != MVT::i16)
19105 Src = DAG.getNode(ISD::BITCAST, SL, MVT::i16, Src);
19106
19107 SDValue Ext = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Src);
19108 return DAG.getNode(ISD::BITCAST, SL, VT, Ext);
19109 }
19110
19111 break;
19112 }
19114 return performExtractVectorEltCombine(N, DCI);
19116 return performInsertVectorEltCombine(N, DCI);
19117 case ISD::FP_ROUND:
19118 return performFPRoundCombine(N, DCI);
19119 case ISD::LOAD: {
19120 if (SDValue Widened = widenLoad(cast<LoadSDNode>(N), DCI))
19121 return Widened;
19122 [[fallthrough]];
19123 }
19124 default: {
19125 if (!DCI.isBeforeLegalize()) {
19126 if (MemSDNode *MemNode = dyn_cast<MemSDNode>(N))
19127 return performMemSDNodeCombine(MemNode, DCI);
19128 }
19129
19130 break;
19131 }
19132 }
19133
19135}
19136
19137/// Helper function for adjustWritemask
19138static unsigned SubIdx2Lane(unsigned Idx) {
19139 switch (Idx) {
19140 default:
19141 return ~0u;
19142 case AMDGPU::sub0:
19143 return 0;
19144 case AMDGPU::sub1:
19145 return 1;
19146 case AMDGPU::sub2:
19147 return 2;
19148 case AMDGPU::sub3:
19149 return 3;
19150 case AMDGPU::sub4:
19151 return 4; // Possible with TFE/LWE
19152 }
19153}
19154
19155/// Adjust the writemask of MIMG, VIMAGE or VSAMPLE instructions
19156SDNode *SITargetLowering::adjustWritemask(MachineSDNode *&Node,
19157 SelectionDAG &DAG) const {
19158 unsigned Opcode = Node->getMachineOpcode();
19159
19160 // Subtract 1 because the vdata output is not a MachineSDNode operand.
19161 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::d16) - 1;
19162 if (D16Idx >= 0 && Node->getConstantOperandVal(D16Idx))
19163 return Node; // not implemented for D16
19164
19165 SDNode *Users[5] = {nullptr};
19166 unsigned Lane = 0;
19167 unsigned DmaskIdx =
19168 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::dmask) - 1;
19169 unsigned OldDmask = Node->getConstantOperandVal(DmaskIdx);
19170 unsigned NewDmask = 0;
19171 unsigned TFEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::tfe) - 1;
19172 unsigned LWEIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::lwe) - 1;
19173 bool UsesTFC = (int(TFEIdx) >= 0 && Node->getConstantOperandVal(TFEIdx)) ||
19174 (int(LWEIdx) >= 0 && Node->getConstantOperandVal(LWEIdx));
19175 unsigned TFCLane = 0;
19176 bool HasChain = Node->getNumValues() > 1;
19177
19178 if (OldDmask == 0) {
19179 // These are folded out, but on the chance it happens don't assert.
19180 return Node;
19181 }
19182
19183 unsigned OldBitsSet = llvm::popcount(OldDmask);
19184 // Work out which is the TFE/LWE lane if that is enabled.
19185 if (UsesTFC) {
19186 TFCLane = OldBitsSet;
19187 }
19188
19189 // Try to figure out the used register components
19190 for (SDUse &Use : Node->uses()) {
19191
19192 // Don't look at users of the chain.
19193 if (Use.getResNo() != 0)
19194 continue;
19195
19196 SDNode *User = Use.getUser();
19197
19198 // Abort if we can't understand the usage
19199 if (!User->isMachineOpcode() ||
19200 User->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
19201 return Node;
19202
19203 // Lane means which subreg of %vgpra_vgprb_vgprc_vgprd is used.
19204 // Note that subregs are packed, i.e. Lane==0 is the first bit set
19205 // in OldDmask, so it can be any of X,Y,Z,W; Lane==1 is the second bit
19206 // set, etc.
19207 Lane = SubIdx2Lane(User->getConstantOperandVal(1));
19208 if (Lane == ~0u)
19209 return Node;
19210
19211 // Check if the use is for the TFE/LWE generated result at VGPRn+1.
19212 if (UsesTFC && Lane == TFCLane) {
19213 Users[Lane] = User;
19214 } else {
19215 // Set which texture component corresponds to the lane.
19216 unsigned Comp;
19217 for (unsigned i = 0, Dmask = OldDmask; (i <= Lane) && (Dmask != 0); i++) {
19218 Comp = llvm::countr_zero(Dmask);
19219 Dmask &= ~(1 << Comp);
19220 }
19221
19222 // Abort if we have more than one user per component.
19223 if (Users[Lane])
19224 return Node;
19225
19226 Users[Lane] = User;
19227 NewDmask |= 1 << Comp;
19228 }
19229 }
19230
19231 // Don't allow 0 dmask, as hardware assumes one channel enabled.
19232 bool NoChannels = !NewDmask;
19233 if (NoChannels) {
19234 if (!UsesTFC) {
19235 // No uses of the result and not using TFC. Then do nothing.
19236 return Node;
19237 }
19238 // If the original dmask has one channel - then nothing to do
19239 if (OldBitsSet == 1)
19240 return Node;
19241 // Use an arbitrary dmask - required for the instruction to work
19242 NewDmask = 1;
19243 }
19244 // Abort if there's no change
19245 if (NewDmask == OldDmask)
19246 return Node;
19247
19248 unsigned BitsSet = llvm::popcount(NewDmask);
19249
19250 // Check for TFE or LWE - increase the number of channels by one to account
19251 // for the extra return value
19252 // This will need adjustment for D16 if this is also included in
19253 // adjustWriteMask (this function) but at present D16 are excluded.
19254 unsigned NewChannels = BitsSet + UsesTFC;
19255
19256 int NewOpcode =
19257 AMDGPU::getMaskedMIMGOp(Node->getMachineOpcode(), NewChannels);
19258 assert(NewOpcode != -1 &&
19259 NewOpcode != static_cast<int>(Node->getMachineOpcode()) &&
19260 "failed to find equivalent MIMG op");
19261
19262 // Adjust the writemask in the node
19264 llvm::append_range(Ops, Node->ops().take_front(DmaskIdx));
19265 Ops.push_back(DAG.getTargetConstant(NewDmask, SDLoc(Node), MVT::i32));
19266 llvm::append_range(Ops, Node->ops().drop_front(DmaskIdx + 1));
19267
19268 MVT SVT = Node->getValueType(0).getVectorElementType().getSimpleVT();
19269
19270 MVT ResultVT = NewChannels == 1
19271 ? SVT
19272 : MVT::getVectorVT(SVT, NewChannels == 3 ? 4
19273 : NewChannels == 5 ? 8
19274 : NewChannels);
19275 SDVTList NewVTList =
19276 HasChain ? DAG.getVTList(ResultVT, MVT::Other) : DAG.getVTList(ResultVT);
19277
19278 MachineSDNode *NewNode =
19279 DAG.getMachineNode(NewOpcode, SDLoc(Node), NewVTList, Ops);
19280
19281 if (HasChain) {
19282 // Update chain.
19283 DAG.setNodeMemRefs(NewNode, Node->memoperands());
19284 DAG.ReplaceAllUsesOfValueWith(SDValue(Node, 1), SDValue(NewNode, 1));
19285 }
19286
19287 if (NewChannels == 1) {
19288 assert(Node->hasNUsesOfValue(1, 0));
19289 SDNode *Copy =
19290 DAG.getMachineNode(TargetOpcode::COPY, SDLoc(Node),
19291 Users[Lane]->getValueType(0), SDValue(NewNode, 0));
19292 DAG.ReplaceAllUsesWith(Users[Lane], Copy);
19293 return nullptr;
19294 }
19295
19296 // Update the users of the node with the new indices
19297 for (unsigned i = 0, Idx = AMDGPU::sub0; i < 5; ++i) {
19298 SDNode *User = Users[i];
19299 if (!User) {
19300 // Handle the special case of NoChannels. We set NewDmask to 1 above, but
19301 // Users[0] is still nullptr because channel 0 doesn't really have a use.
19302 if (i || !NoChannels)
19303 continue;
19304 } else {
19305 SDValue Op = DAG.getTargetConstant(Idx, SDLoc(User), MVT::i32);
19306 SDNode *NewUser = DAG.UpdateNodeOperands(User, SDValue(NewNode, 0), Op);
19307 if (NewUser != User) {
19308 DAG.ReplaceAllUsesWith(SDValue(User, 0), SDValue(NewUser, 0));
19309 DAG.RemoveDeadNode(User);
19310 }
19311 }
19312
19313 switch (Idx) {
19314 default:
19315 break;
19316 case AMDGPU::sub0:
19317 Idx = AMDGPU::sub1;
19318 break;
19319 case AMDGPU::sub1:
19320 Idx = AMDGPU::sub2;
19321 break;
19322 case AMDGPU::sub2:
19323 Idx = AMDGPU::sub3;
19324 break;
19325 case AMDGPU::sub3:
19326 Idx = AMDGPU::sub4;
19327 break;
19328 }
19329 }
19330
19331 DAG.RemoveDeadNode(Node);
19332 return nullptr;
19333}
19334
19336 if (Op.getOpcode() == ISD::AssertZext)
19337 Op = Op.getOperand(0);
19338
19339 return isa<FrameIndexSDNode>(Op);
19340}
19341
19342/// Legalize target independent instructions (e.g. INSERT_SUBREG)
19343/// with frame index operands.
19344/// LLVM assumes that inputs are to these instructions are registers.
19345SDNode *
19347 SelectionDAG &DAG) const {
19348 if (Node->getOpcode() == ISD::CopyToReg) {
19349 RegisterSDNode *DestReg = cast<RegisterSDNode>(Node->getOperand(1));
19350 SDValue SrcVal = Node->getOperand(2);
19351
19352 // Insert a copy to a VReg_1 virtual register so LowerI1Copies doesn't have
19353 // to try understanding copies to physical registers.
19354 if (SrcVal.getValueType() == MVT::i1 && DestReg->getReg().isPhysical()) {
19355 SDLoc SL(Node);
19357 SDValue VReg = DAG.getRegister(
19358 MRI.createVirtualRegister(&AMDGPU::VReg_1RegClass), MVT::i1);
19359
19360 SDNode *Glued = Node->getGluedNode();
19361 SDValue ToVReg = DAG.getCopyToReg(
19362 Node->getOperand(0), SL, VReg, SrcVal,
19363 SDValue(Glued, Glued ? Glued->getNumValues() - 1 : 0));
19364 SDValue ToResultReg = DAG.getCopyToReg(ToVReg, SL, SDValue(DestReg, 0),
19365 VReg, ToVReg.getValue(1));
19366 DAG.ReplaceAllUsesWith(Node, ToResultReg.getNode());
19367 DAG.RemoveDeadNode(Node);
19368 return ToResultReg.getNode();
19369 }
19370 }
19371
19373 for (unsigned i = 0; i < Node->getNumOperands(); ++i) {
19374 if (!isFrameIndexOp(Node->getOperand(i))) {
19375 Ops.push_back(Node->getOperand(i));
19376 continue;
19377 }
19378
19379 SDLoc DL(Node);
19380 Ops.push_back(SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL,
19381 Node->getOperand(i).getValueType(),
19382 Node->getOperand(i)),
19383 0));
19384 }
19385
19386 return DAG.UpdateNodeOperands(Node, Ops);
19387}
19388
19389/// Fold the instructions after selecting them.
19390/// Returns null if users were already updated.
19392 SelectionDAG &DAG) const {
19394 unsigned Opcode = Node->getMachineOpcode();
19395
19396 if (TII->isImage(Opcode) && !TII->get(Opcode).mayStore() &&
19397 !TII->isGather4(Opcode) &&
19398 AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::dmask)) {
19399 return adjustWritemask(Node, DAG);
19400 }
19401
19402 if (Opcode == AMDGPU::INSERT_SUBREG || Opcode == AMDGPU::REG_SEQUENCE) {
19404 return Node;
19405 }
19406
19407 switch (Opcode) {
19408 case AMDGPU::V_DIV_SCALE_F32_e64:
19409 case AMDGPU::V_DIV_SCALE_F64_e64: {
19410 // Satisfy the operand register constraint when one of the inputs is
19411 // undefined. Ordinarily each undef value will have its own implicit_def of
19412 // a vreg, so force these to use a single register.
19413 SDValue Src0 = Node->getOperand(1);
19414 SDValue Src1 = Node->getOperand(3);
19415 SDValue Src2 = Node->getOperand(5);
19416
19417 if ((Src0.isMachineOpcode() &&
19418 Src0.getMachineOpcode() != AMDGPU::IMPLICIT_DEF) &&
19419 (Src0 == Src1 || Src0 == Src2))
19420 break;
19421
19422 MVT VT = Src0.getValueType().getSimpleVT();
19423 const TargetRegisterClass *RC =
19424 getRegClassFor(VT, Src0.getNode()->isDivergent());
19425
19427 SDValue UndefReg = DAG.getRegister(MRI.createVirtualRegister(RC), VT);
19428
19429 SDValue ImpDef = DAG.getCopyToReg(DAG.getEntryNode(), SDLoc(Node), UndefReg,
19430 Src0, SDValue());
19431
19432 // src0 must be the same register as src1 or src2, even if the value is
19433 // undefined, so make sure we don't violate this constraint.
19434 if (Src0.isMachineOpcode() &&
19435 Src0.getMachineOpcode() == AMDGPU::IMPLICIT_DEF) {
19436 if (Src1.isMachineOpcode() &&
19437 Src1.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19438 Src0 = Src1;
19439 else if (Src2.isMachineOpcode() &&
19440 Src2.getMachineOpcode() != AMDGPU::IMPLICIT_DEF)
19441 Src0 = Src2;
19442 else {
19443 assert(Src1.getMachineOpcode() == AMDGPU::IMPLICIT_DEF);
19444 Src0 = UndefReg;
19445 Src1 = UndefReg;
19446 }
19447 } else
19448 break;
19449
19451 Ops[1] = Src0;
19452 Ops[3] = Src1;
19453 Ops[5] = Src2;
19454 Ops.push_back(ImpDef.getValue(1));
19455 return DAG.getMachineNode(Opcode, SDLoc(Node), Node->getVTList(), Ops);
19456 }
19457 default:
19458 break;
19459 }
19460
19461 return Node;
19462}
19463
19464// Any MIMG instructions that use tfe or lwe require an initialization of the
19465// result register that will be written in the case of a memory access failure.
19466// The required code is also added to tie this init code to the result of the
19467// img instruction.
19470 const SIRegisterInfo &TRI = TII->getRegisterInfo();
19471 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
19472 MachineBasicBlock &MBB = *MI.getParent();
19473
19474 int DstIdx =
19475 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
19476 unsigned InitIdx = 0;
19477
19478 if (TII->isImage(MI)) {
19479 MachineOperand *TFE = TII->getNamedOperand(MI, AMDGPU::OpName::tfe);
19480 MachineOperand *LWE = TII->getNamedOperand(MI, AMDGPU::OpName::lwe);
19481 MachineOperand *D16 = TII->getNamedOperand(MI, AMDGPU::OpName::d16);
19482
19483 if (!TFE && !LWE) // intersect_ray
19484 return;
19485
19486 unsigned TFEVal = TFE ? TFE->getImm() : 0;
19487 unsigned LWEVal = LWE ? LWE->getImm() : 0;
19488 unsigned D16Val = D16 ? D16->getImm() : 0;
19489
19490 if (!TFEVal && !LWEVal)
19491 return;
19492
19493 // At least one of TFE or LWE are non-zero
19494 // We have to insert a suitable initialization of the result value and
19495 // tie this to the dest of the image instruction.
19496
19497 // Calculate which dword we have to initialize to 0.
19498 MachineOperand *MO_Dmask = TII->getNamedOperand(MI, AMDGPU::OpName::dmask);
19499
19500 // check that dmask operand is found.
19501 assert(MO_Dmask && "Expected dmask operand in instruction");
19502
19503 unsigned dmask = MO_Dmask->getImm();
19504 // Determine the number of active lanes taking into account the
19505 // Gather4 special case
19506 unsigned ActiveLanes = TII->isGather4(MI) ? 4 : llvm::popcount(dmask);
19507
19508 bool Packed = !Subtarget->hasUnpackedD16VMem();
19509
19510 InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1;
19511
19512 // Abandon attempt if the dst size isn't large enough
19513 // - this is in fact an error but this is picked up elsewhere and
19514 // reported correctly.
19515 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
19516
19517 uint32_t DstSize = TRI.getRegSizeInBits(*DstRC) / 32;
19518 if (DstSize < InitIdx)
19519 return;
19520 } else if (TII->isMUBUF(MI) && AMDGPU::getMUBUFTfe(MI.getOpcode())) {
19521 const TargetRegisterClass *DstRC = TII->getRegClass(MI.getDesc(), DstIdx);
19522 InitIdx = TRI.getRegSizeInBits(*DstRC) / 32;
19523 } else {
19524 return;
19525 }
19526
19527 const DebugLoc &DL = MI.getDebugLoc();
19528
19529 // Create a register for the initialization value.
19530 Register PrevDst = MRI.cloneVirtualRegister(MI.getOperand(DstIdx).getReg());
19531 unsigned NewDst = 0; // Final initialized value will be in here
19532
19533 // If PRTStrictNull feature is enabled (the default) then initialize
19534 // all the result registers to 0, otherwise just the error indication
19535 // register (VGPRn+1)
19536 unsigned SizeLeft = Subtarget->usePRTStrictNull() ? InitIdx : 1;
19537 unsigned CurrIdx = Subtarget->usePRTStrictNull() ? 0 : (InitIdx - 1);
19538
19539 BuildMI(MBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), PrevDst);
19540 for (; SizeLeft; SizeLeft--, CurrIdx++) {
19541 NewDst = MRI.createVirtualRegister(TII->getOpRegClass(MI, DstIdx));
19542 // Initialize dword
19543 Register SubReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
19544 // clang-format off
19545 BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), SubReg)
19546 .addImm(0);
19547 // clang-format on
19548 // Insert into the super-reg
19549 BuildMI(MBB, MI, DL, TII->get(TargetOpcode::INSERT_SUBREG), NewDst)
19550 .addReg(PrevDst)
19551 .addReg(SubReg)
19553
19554 PrevDst = NewDst;
19555 }
19556
19557 // Add as an implicit operand
19558 MI.addOperand(MachineOperand::CreateReg(NewDst, false, true));
19559
19560 // Tie the just added implicit operand to the dst
19561 MI.tieOperands(DstIdx, MI.getNumOperands() - 1);
19562}
19563
19564/// Assign the register class depending on the number of
19565/// bits set in the writemask
19567 SDNode *Node) const {
19569
19570 MachineFunction *MF = MI.getMF();
19571 MachineRegisterInfo &MRI = MF->getRegInfo();
19572
19573 if (TII->isVOP3(MI.getOpcode())) {
19574 // Make sure constant bus requirements are respected.
19575 TII->legalizeOperandsVOP3(MRI, MI);
19576
19577 if (TII->isMAI(MI)) {
19578 // The ordinary src0, src1, src2 were legalized above.
19579 //
19580 // We have to also legalize the appended v_mfma_ld_scale_b32 operands,
19581 // as a separate instruction.
19582 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
19583 AMDGPU::OpName::scale_src0);
19584 if (Src0Idx != -1) {
19585 int Src1Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
19586 AMDGPU::OpName::scale_src1);
19587 if (TII->usesConstantBus(MRI, MI, Src0Idx) &&
19588 TII->usesConstantBus(MRI, MI, Src1Idx))
19589 TII->legalizeOpWithMove(MI, Src1Idx);
19590 }
19591 }
19592
19593 return;
19594 }
19595
19596 if (TII->isImage(MI))
19597 TII->enforceOperandRCAlignment(MI, AMDGPU::OpName::vaddr);
19598}
19599
19601 uint64_t Val) {
19602 SDValue K = DAG.getTargetConstant(Val, DL, MVT::i32);
19603 return SDValue(DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, K), 0);
19604}
19605
19607 const SDLoc &DL,
19608 SDValue Ptr) const {
19610
19611 // Build the half of the subregister with the constants before building the
19612 // full 128-bit register. If we are building multiple resource descriptors,
19613 // this will allow CSEing of the 2-component register.
19614 const SDValue Ops0[] = {
19615 DAG.getTargetConstant(AMDGPU::SGPR_64RegClassID, DL, MVT::i32),
19616 buildSMovImm32(DAG, DL, 0),
19617 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
19618 buildSMovImm32(DAG, DL, TII->getDefaultRsrcDataFormat() >> 32),
19619 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32)};
19620
19621 SDValue SubRegHi = SDValue(
19622 DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v2i32, Ops0), 0);
19623
19624 // Combine the constants and the pointer.
19625 const SDValue Ops1[] = {
19626 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32), Ptr,
19627 DAG.getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32), SubRegHi,
19628 DAG.getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32)};
19629
19630 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops1);
19631}
19632
19633/// Return a resource descriptor with the 'Add TID' bit enabled
19634/// The TID (Thread ID) is multiplied by the stride value (bits [61:48]
19635/// of the resource descriptor) to create an offset, which is added to
19636/// the resource pointer.
19638 SDValue Ptr, uint32_t RsrcDword1,
19639 uint64_t RsrcDword2And3) const {
19640 SDValue PtrLo = DAG.getTargetExtractSubreg(AMDGPU::sub0, DL, MVT::i32, Ptr);
19641 SDValue PtrHi = DAG.getTargetExtractSubreg(AMDGPU::sub1, DL, MVT::i32, Ptr);
19642 if (RsrcDword1) {
19643 PtrHi = DAG.getNode(ISD::OR, DL, MVT::i32, PtrHi,
19644 DAG.getConstant(RsrcDword1, DL, MVT::i32));
19645 }
19646
19647 SDValue DataLo =
19648 buildSMovImm32(DAG, DL, RsrcDword2And3 & UINT64_C(0xFFFFFFFF));
19649 SDValue DataHi = buildSMovImm32(DAG, DL, RsrcDword2And3 >> 32);
19650
19651 const SDValue Ops[] = {
19652 DAG.getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32),
19653 PtrLo,
19654 DAG.getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
19655 PtrHi,
19656 DAG.getTargetConstant(AMDGPU::sub1, DL, MVT::i32),
19657 DataLo,
19658 DAG.getTargetConstant(AMDGPU::sub2, DL, MVT::i32),
19659 DataHi,
19660 DAG.getTargetConstant(AMDGPU::sub3, DL, MVT::i32)};
19661
19662 return DAG.getMachineNode(AMDGPU::REG_SEQUENCE, DL, MVT::v4i32, Ops);
19663}
19664
19665//===----------------------------------------------------------------------===//
19666// SI Inline Assembly Support
19667//===----------------------------------------------------------------------===//
19668
19669std::pair<unsigned, const TargetRegisterClass *>
19671 StringRef Constraint,
19672 MVT VT) const {
19673 const SIRegisterInfo *TRI = static_cast<const SIRegisterInfo *>(TRI_);
19674
19675 const TargetRegisterClass *RC = nullptr;
19676 if (Constraint.size() == 1) {
19677 // Check if we cannot determine the bit size of the given value type. This
19678 // can happen, for example, in this situation where we have an empty struct
19679 // (size 0): `call void asm "", "v"({} poison)`-
19680 if (VT == MVT::Other)
19681 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
19682 const unsigned BitWidth = VT.getSizeInBits();
19683 switch (Constraint[0]) {
19684 default:
19685 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
19686 case 's':
19687 case 'r':
19688 switch (BitWidth) {
19689 case 16:
19690 RC = &AMDGPU::SReg_32RegClass;
19691 break;
19692 case 64:
19693 RC = &AMDGPU::SGPR_64RegClass;
19694 break;
19695 default:
19697 if (!RC)
19698 return std::pair(0U, nullptr);
19699 break;
19700 }
19701 break;
19702 case 'v':
19703 switch (BitWidth) {
19704 case 1:
19705 return std::pair(0U, nullptr);
19706 case 16:
19707 RC = Subtarget->useRealTrue16Insts() ? &AMDGPU::VGPR_16RegClass
19708 : &AMDGPU::VGPR_32_Lo256RegClass;
19709 break;
19710 default:
19711 RC = Subtarget->has1024AddressableVGPRs()
19712 ? TRI->getAlignedLo256VGPRClassForBitWidth(BitWidth)
19713 : TRI->getVGPRClassForBitWidth(BitWidth);
19714 if (!RC)
19715 return std::pair(0U, nullptr);
19716 break;
19717 }
19718 break;
19719 case 'a':
19720 if (!Subtarget->hasMAIInsts())
19721 break;
19722 switch (BitWidth) {
19723 case 1:
19724 return std::pair(0U, nullptr);
19725 case 16:
19726 RC = &AMDGPU::AGPR_32RegClass;
19727 break;
19728 default:
19729 RC = TRI->getAGPRClassForBitWidth(BitWidth);
19730 if (!RC)
19731 return std::pair(0U, nullptr);
19732 break;
19733 }
19734 break;
19735 }
19736 } else if (Constraint == "VA" && Subtarget->hasGFX90AInsts()) {
19737 const unsigned BitWidth = VT.getSizeInBits();
19738 switch (BitWidth) {
19739 case 16:
19740 RC = &AMDGPU::AV_32RegClass;
19741 break;
19742 default:
19743 RC = TRI->getVectorSuperClassForBitWidth(BitWidth);
19744 if (!RC)
19745 return std::pair(0U, nullptr);
19746 break;
19747 }
19748 }
19749
19750 // We actually support i128, i16 and f16 as inline parameters
19751 // even if they are not reported as legal
19752 if (RC && (isTypeLegal(VT) || VT.SimpleTy == MVT::i128 ||
19753 VT.SimpleTy == MVT::i16 || VT.SimpleTy == MVT::f16))
19754 return std::pair(0U, RC);
19755
19756 auto [Kind, Idx, NumRegs] = AMDGPU::parseAsmConstraintPhysReg(Constraint);
19757 if (Kind != '\0') {
19758 if (Kind == 'v') {
19759 RC = &AMDGPU::VGPR_32_Lo256RegClass;
19760 } else if (Kind == 's') {
19761 RC = &AMDGPU::SGPR_32RegClass;
19762 } else if (Kind == 'a') {
19763 RC = &AMDGPU::AGPR_32RegClass;
19764 }
19765
19766 if (RC) {
19767 if (NumRegs > 1) {
19768 if (Idx >= RC->getNumRegs() || Idx + NumRegs - 1 >= RC->getNumRegs())
19769 return std::pair(0U, nullptr);
19770
19771 uint32_t Width = NumRegs * 32;
19772 // Prohibit constraints for register ranges with a width that does not
19773 // match the required type.
19774 if (VT.SimpleTy != MVT::Other && Width != VT.getSizeInBits())
19775 return std::pair(0U, nullptr);
19776
19777 MCRegister Reg = RC->getRegister(Idx);
19779 RC = TRI->getVGPRClassForBitWidth(Width);
19780 else if (SIRegisterInfo::isSGPRClass(RC))
19781 RC = TRI->getSGPRClassForBitWidth(Width);
19782 else if (SIRegisterInfo::isAGPRClass(RC))
19783 RC = TRI->getAGPRClassForBitWidth(Width);
19784 if (RC) {
19785 Reg = TRI->getMatchingSuperReg(Reg, AMDGPU::sub0, RC);
19786 if (!Reg) {
19787 // The register class does not contain the requested register,
19788 // e.g., because it is an SGPR pair that would violate alignment
19789 // requirements.
19790 return std::pair(0U, nullptr);
19791 }
19792 return std::pair(Reg, RC);
19793 }
19794 }
19795
19796 // Reject types that do not fit a single 32-bit register: any scalar wider
19797 // than 32 bits, or a vector that is not exactly 32 bits.
19798 if (VT.SimpleTy != MVT::Other &&
19799 (VT.getSizeInBits() > 32 ||
19800 (VT.isVector() && VT.getSizeInBits() != 32)))
19801 return std::pair(0U, nullptr);
19802 if (RC && Idx < RC->getNumRegs())
19803 return std::pair(RC->getRegister(Idx), RC);
19804 return std::pair(0U, nullptr);
19805 }
19806 }
19807
19808 auto Ret = TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
19809 if (Ret.first)
19810 Ret.second = TRI->getPhysRegBaseClass(Ret.first);
19811
19812 return Ret;
19813}
19814
19815static bool isImmConstraint(StringRef Constraint) {
19816 if (Constraint.size() == 1) {
19817 switch (Constraint[0]) {
19818 default:
19819 break;
19820 case 'I':
19821 case 'J':
19822 case 'A':
19823 case 'B':
19824 case 'C':
19825 return true;
19826 }
19827 } else if (Constraint == "DA" || Constraint == "DB") {
19828 return true;
19829 }
19830 return false;
19831}
19832
19835 if (Constraint.size() == 1) {
19836 switch (Constraint[0]) {
19837 default:
19838 break;
19839 case 's':
19840 case 'v':
19841 case 'a':
19842 return C_RegisterClass;
19843 }
19844 } else if (Constraint.size() == 2) {
19845 if (Constraint == "VA")
19846 return C_RegisterClass;
19847 }
19848 if (isImmConstraint(Constraint)) {
19849 return C_Other;
19850 }
19851 return TargetLowering::getConstraintType(Constraint);
19852}
19853
19854static uint64_t clearUnusedBits(uint64_t Val, unsigned Size) {
19856 Val = Val & maskTrailingOnes<uint64_t>(Size);
19857 }
19858 return Val;
19859}
19860
19862 StringRef Constraint,
19863 std::vector<SDValue> &Ops,
19864 SelectionDAG &DAG) const {
19865 if (isImmConstraint(Constraint)) {
19866 uint64_t Val;
19867 if (getAsmOperandConstVal(Op, Val) &&
19868 checkAsmConstraintVal(Op, Constraint, Val)) {
19869 Val = clearUnusedBits(Val, Op.getScalarValueSizeInBits());
19870 Ops.push_back(DAG.getTargetConstant(Val, SDLoc(Op), MVT::i64));
19871 }
19872 } else {
19874 }
19875}
19876
19878 unsigned Size = Op.getScalarValueSizeInBits();
19879 if (Size > 64)
19880 return false;
19881
19882 if (Size == 16 && !Subtarget->has16BitInsts())
19883 return false;
19884
19886 Val = C->getSExtValue();
19887 return true;
19888 }
19890 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
19891 return true;
19892 }
19894 if (Size != 16 || Op.getNumOperands() != 2)
19895 return false;
19896 if (Op.getOperand(0).isUndef() || Op.getOperand(1).isUndef())
19897 return false;
19898 if (ConstantSDNode *C = V->getConstantSplatNode()) {
19899 Val = C->getSExtValue();
19900 return true;
19901 }
19902 if (ConstantFPSDNode *C = V->getConstantFPSplatNode()) {
19903 Val = C->getValueAPF().bitcastToAPInt().getSExtValue();
19904 return true;
19905 }
19906 }
19907
19908 return false;
19909}
19910
19912 uint64_t Val) const {
19913 if (Constraint.size() == 1) {
19914 switch (Constraint[0]) {
19915 case 'I':
19917 case 'J':
19918 return isInt<16>(Val);
19919 case 'A':
19920 return checkAsmConstraintValA(Op, Val);
19921 case 'B':
19922 return isInt<32>(Val);
19923 case 'C':
19924 return isUInt<32>(clearUnusedBits(Val, Op.getScalarValueSizeInBits())) ||
19926 default:
19927 break;
19928 }
19929 } else if (Constraint.size() == 2) {
19930 if (Constraint == "DA") {
19931 int64_t HiBits = static_cast<int32_t>(Val >> 32);
19932 int64_t LoBits = static_cast<int32_t>(Val);
19933 return checkAsmConstraintValA(Op, HiBits, 32) &&
19934 checkAsmConstraintValA(Op, LoBits, 32);
19935 }
19936 if (Constraint == "DB") {
19937 return true;
19938 }
19939 }
19940 llvm_unreachable("Invalid asm constraint");
19941}
19942
19944 unsigned MaxSize) const {
19945 unsigned Size = std::min<unsigned>(Op.getScalarValueSizeInBits(), MaxSize);
19946 bool HasInv2Pi = Subtarget->hasInv2PiInlineImm();
19947 if (Size == 16) {
19948 MVT VT = Op.getSimpleValueType();
19949 switch (VT.SimpleTy) {
19950 default:
19951 return false;
19952 case MVT::i16:
19953 return AMDGPU::isInlinableLiteralI16(Val, HasInv2Pi);
19954 case MVT::f16:
19955 return AMDGPU::isInlinableLiteralFP16(Val, HasInv2Pi);
19956 case MVT::bf16:
19957 return AMDGPU::isInlinableLiteralBF16(Val, HasInv2Pi);
19958 case MVT::v2i16:
19959 return AMDGPU::getInlineEncodingV2I16(Val).has_value();
19960 case MVT::v2f16:
19961 return AMDGPU::getInlineEncodingV2F16(Val).has_value();
19962 case MVT::v2bf16:
19963 return AMDGPU::getInlineEncodingV2BF16(Val).has_value();
19964 }
19965 }
19966 if ((Size == 32 && AMDGPU::isInlinableLiteral32(Val, HasInv2Pi)) ||
19967 (Size == 64 && AMDGPU::isInlinableLiteral64(Val, HasInv2Pi)))
19968 return true;
19969 return false;
19970}
19971
19972static int getAlignedAGPRClassID(unsigned UnalignedClassID) {
19973 switch (UnalignedClassID) {
19974 case AMDGPU::VReg_64RegClassID:
19975 return AMDGPU::VReg_64_Align2RegClassID;
19976 case AMDGPU::VReg_96RegClassID:
19977 return AMDGPU::VReg_96_Align2RegClassID;
19978 case AMDGPU::VReg_128RegClassID:
19979 return AMDGPU::VReg_128_Align2RegClassID;
19980 case AMDGPU::VReg_160RegClassID:
19981 return AMDGPU::VReg_160_Align2RegClassID;
19982 case AMDGPU::VReg_192RegClassID:
19983 return AMDGPU::VReg_192_Align2RegClassID;
19984 case AMDGPU::VReg_224RegClassID:
19985 return AMDGPU::VReg_224_Align2RegClassID;
19986 case AMDGPU::VReg_256RegClassID:
19987 return AMDGPU::VReg_256_Align2RegClassID;
19988 case AMDGPU::VReg_288RegClassID:
19989 return AMDGPU::VReg_288_Align2RegClassID;
19990 case AMDGPU::VReg_320RegClassID:
19991 return AMDGPU::VReg_320_Align2RegClassID;
19992 case AMDGPU::VReg_352RegClassID:
19993 return AMDGPU::VReg_352_Align2RegClassID;
19994 case AMDGPU::VReg_384RegClassID:
19995 return AMDGPU::VReg_384_Align2RegClassID;
19996 case AMDGPU::VReg_512RegClassID:
19997 return AMDGPU::VReg_512_Align2RegClassID;
19998 case AMDGPU::VReg_1024RegClassID:
19999 return AMDGPU::VReg_1024_Align2RegClassID;
20000 case AMDGPU::AReg_64RegClassID:
20001 return AMDGPU::AReg_64_Align2RegClassID;
20002 case AMDGPU::AReg_96RegClassID:
20003 return AMDGPU::AReg_96_Align2RegClassID;
20004 case AMDGPU::AReg_128RegClassID:
20005 return AMDGPU::AReg_128_Align2RegClassID;
20006 case AMDGPU::AReg_160RegClassID:
20007 return AMDGPU::AReg_160_Align2RegClassID;
20008 case AMDGPU::AReg_192RegClassID:
20009 return AMDGPU::AReg_192_Align2RegClassID;
20010 case AMDGPU::AReg_256RegClassID:
20011 return AMDGPU::AReg_256_Align2RegClassID;
20012 case AMDGPU::AReg_512RegClassID:
20013 return AMDGPU::AReg_512_Align2RegClassID;
20014 case AMDGPU::AReg_1024RegClassID:
20015 return AMDGPU::AReg_1024_Align2RegClassID;
20016 default:
20017 return -1;
20018 }
20019}
20020
20021// Figure out which registers should be reserved for stack access. Only after
20022// the function is legalized do we know all of the non-spill stack objects or if
20023// calls are present.
20025 MachineRegisterInfo &MRI = MF.getRegInfo();
20027 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
20028 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20029 const SIInstrInfo *TII = ST.getInstrInfo();
20030
20031 if (Info->isEntryFunction()) {
20032 // Callable functions have fixed registers used for stack access.
20034 }
20035
20036 // TODO: Move this logic to getReservedRegs()
20037 // Reserve the SGPR(s) to save/restore EXEC for WWM spill/copy handling.
20038 unsigned MaxNumSGPRs = ST.getMaxNumSGPRs(MF);
20039 Register SReg = ST.isWave32()
20040 ? AMDGPU::SGPR_32RegClass.getRegister(MaxNumSGPRs - 1)
20041 : TRI->getAlignedHighSGPRForRC(MF, /*Align=*/2,
20042 &AMDGPU::SGPR_64RegClass);
20043 Info->setSGPRForEXECCopy(SReg);
20044
20045 assert(!TRI->isSubRegister(Info->getScratchRSrcReg(),
20046 Info->getStackPtrOffsetReg()));
20047 if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
20048 MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
20049
20050 // We need to worry about replacing the default register with itself in case
20051 // of MIR testcases missing the MFI.
20052 if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
20053 MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
20054
20055 if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
20056 MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());
20057
20058 Info->limitOccupancy(MF);
20059
20060 if (ST.isWave32() && !MF.empty()) {
20061 for (auto &MBB : MF) {
20062 for (auto &MI : MBB) {
20063 TII->fixImplicitOperands(MI);
20064 }
20065 }
20066 }
20067
20068 // FIXME: This is a hack to fixup AGPR classes to use the properly aligned
20069 // classes if required. Ideally the register class constraints would differ
20070 // per-subtarget, but there's no easy way to achieve that right now. This is
20071 // not a problem for VGPRs because the correctly aligned VGPR class is implied
20072 // from using them as the register class for legal types.
20073 if (ST.needsAlignedVGPRs()) {
20074 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
20075 const Register Reg = Register::index2VirtReg(I);
20076 const TargetRegisterClass *RC = MRI.getRegClassOrNull(Reg);
20077 if (!RC)
20078 continue;
20079 int NewClassID = getAlignedAGPRClassID(RC->getID());
20080 if (NewClassID != -1)
20081 MRI.setRegClass(Reg, TRI->getRegClass(NewClassID));
20082 }
20083 }
20084
20086}
20087
20090 const APInt &DemandedElts,
20091 const SelectionDAG &DAG,
20092 unsigned Depth) const {
20093 Known.resetAll();
20094 unsigned Opc = Op.getOpcode();
20095 switch (Opc) {
20097 unsigned IID = Op.getConstantOperandVal(0);
20098 switch (IID) {
20099 case Intrinsic::amdgcn_mbcnt_lo:
20100 case Intrinsic::amdgcn_mbcnt_hi: {
20101 const GCNSubtarget &ST =
20103 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20104 // most 31 + src1.
20105 Known.Zero.setBitsFrom(
20106 IID == Intrinsic::amdgcn_mbcnt_lo ? ST.getWavefrontSizeLog2() : 5);
20107 KnownBits Known2 = DAG.computeKnownBits(Op.getOperand(2), Depth + 1);
20108 Known = KnownBits::add(Known, Known2);
20109 return;
20110 }
20111 }
20112 break;
20113 }
20114 }
20116 Op, Known, DemandedElts, DAG, Depth);
20117}
20118
20120 KnownBits &Known, const MachineFunction &MF, Align Alignment) const {
20122
20123 // Set the high bits to zero based on the maximum allowed scratch size per
20124 // wave. We can't use vaddr in MUBUF instructions if we don't know the address
20125 // calculation won't overflow, so assume the sign bit is never set.
20126 Known.Zero.setHighBits(getSubtarget()->getKnownHighZeroBitsForFrameIndex());
20127}
20128
20131 unsigned Dim) {
20132 unsigned MaxValue =
20133 ST.getMaxWorkitemID(VT.getMachineFunction().getFunction(), Dim);
20134 Known.Zero.setHighBits(llvm::countl_zero(MaxValue));
20135}
20136
20138 KnownBits &Known, const APInt &DemandedElts,
20139 unsigned BFEWidth, bool SExt, unsigned Depth) {
20141 const MachineOperand &Src1 = MI.getOperand(2);
20142
20143 unsigned Src1Cst = 0;
20144 if (Src1.isImm()) {
20145 Src1Cst = Src1.getImm();
20146 } else if (Src1.isReg()) {
20147 auto Cst = getIConstantVRegValWithLookThrough(Src1.getReg(), MRI);
20148 if (!Cst)
20149 return;
20150 Src1Cst = Cst->Value.getZExtValue();
20151 } else {
20152 return;
20153 }
20154
20155 // Offset is at bits [4:0] for 32 bit, [5:0] for 64 bit.
20156 // Width is always [22:16].
20157 const unsigned Offset =
20158 Src1Cst & maskTrailingOnes<unsigned>((BFEWidth == 32) ? 5 : 6);
20159 const unsigned Width = (Src1Cst >> 16) & maskTrailingOnes<unsigned>(6);
20160
20161 if (Width >= BFEWidth) // Ill-formed.
20162 return;
20163
20164 VT.computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, DemandedElts,
20165 Depth + 1);
20166
20167 Known = Known.extractBits(Width, Offset);
20168
20169 if (SExt)
20170 Known = Known.sext(BFEWidth);
20171 else
20172 Known = Known.zext(BFEWidth);
20173}
20174
20177 const APInt &DemandedElts, const MachineRegisterInfo &MRI,
20178 unsigned Depth) const {
20179 Known.resetAll();
20180 const MachineInstr *MI = MRI.getVRegDef(R);
20181 switch (MI->getOpcode()) {
20182 case AMDGPU::S_BFE_I32:
20183 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20184 /*SExt=*/true, Depth);
20185 case AMDGPU::S_BFE_U32:
20186 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/32,
20187 /*SExt=*/false, Depth);
20188 case AMDGPU::S_BFE_I64:
20189 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20190 /*SExt=*/true, Depth);
20191 case AMDGPU::S_BFE_U64:
20192 return knownBitsForSBFE(*MI, VT, Known, DemandedElts, /*Width=*/64,
20193 /*SExt=*/false, Depth);
20194 case AMDGPU::G_INTRINSIC:
20195 case AMDGPU::G_INTRINSIC_CONVERGENT: {
20196 Intrinsic::ID IID = cast<GIntrinsic>(MI)->getIntrinsicID();
20197 switch (IID) {
20198 case Intrinsic::amdgcn_workitem_id_x:
20200 break;
20201 case Intrinsic::amdgcn_workitem_id_y:
20203 break;
20204 case Intrinsic::amdgcn_workitem_id_z:
20206 break;
20207 case Intrinsic::amdgcn_mbcnt_lo:
20208 case Intrinsic::amdgcn_mbcnt_hi: {
20209 // Wave64 mbcnt_lo returns at most 32 + src1. Otherwise these return at
20210 // most 31 + src1.
20211 Known.Zero.setBitsFrom(IID == Intrinsic::amdgcn_mbcnt_lo
20212 ? getSubtarget()->getWavefrontSizeLog2()
20213 : 5);
20214 KnownBits Known2;
20215 VT.computeKnownBitsImpl(MI->getOperand(3).getReg(), Known2, DemandedElts,
20216 Depth + 1);
20217 Known = KnownBits::add(Known, Known2);
20218 break;
20219 }
20220 case Intrinsic::amdgcn_groupstaticsize: {
20221 // We can report everything over the maximum size as 0. We can't report
20222 // based on the actual size because we don't know if it's accurate or not
20223 // at any given point.
20224 Known.Zero.setHighBits(
20225 llvm::countl_zero(getSubtarget()->getAddressableLocalMemorySize()));
20226 break;
20227 }
20228 }
20229 break;
20230 }
20231 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
20232 Known.Zero.setHighBits(24);
20233 break;
20234 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
20235 Known.Zero.setHighBits(16);
20236 break;
20237 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
20238 // G_AMDGPU_COPY_SCC_VCC converts a uniform boolean in VCC to SGPR s32,
20239 // producing exactly 0 or 1.
20240 Known.Zero.setHighBits(Known.getBitWidth() - 1);
20241 break;
20242 case AMDGPU::G_AMDGPU_SMED3:
20243 case AMDGPU::G_AMDGPU_UMED3: {
20244 auto [Dst, Src0, Src1, Src2] = MI->getFirst4Regs();
20245
20246 KnownBits Known2;
20247 VT.computeKnownBitsImpl(Src2, Known2, DemandedElts, Depth + 1);
20248 if (Known2.isUnknown())
20249 break;
20250
20251 KnownBits Known1;
20252 VT.computeKnownBitsImpl(Src1, Known1, DemandedElts, Depth + 1);
20253 if (Known1.isUnknown())
20254 break;
20255
20256 KnownBits Known0;
20257 VT.computeKnownBitsImpl(Src0, Known0, DemandedElts, Depth + 1);
20258 if (Known0.isUnknown())
20259 break;
20260
20261 // TODO: Handle LeadZero/LeadOne from UMIN/UMAX handling.
20262 Known.Zero = Known0.Zero & Known1.Zero & Known2.Zero;
20263 Known.One = Known0.One & Known1.One & Known2.One;
20264 break;
20265 }
20266 }
20267}
20268
20271 unsigned Depth) const {
20272 const MachineInstr *MI = MRI.getVRegDef(R);
20273 if (auto *GI = dyn_cast<GIntrinsic>(MI)) {
20274 // FIXME: Can this move to generic code? What about the case where the call
20275 // site specifies a lower alignment?
20276 Intrinsic::ID IID = GI->getIntrinsicID();
20278 AttributeList Attrs =
20279 Intrinsic::getAttributes(Ctx, IID, Intrinsic::getType(Ctx, IID));
20280 if (MaybeAlign RetAlign = Attrs.getRetAlignment())
20281 return *RetAlign;
20282 }
20283 return Align(1);
20284}
20285
20288 const Align CacheLineAlign = Align(64);
20289
20290 // GFX950: Prevent an 8-byte instruction at loop header from being split by
20291 // the 32-byte instruction fetch window boundary. This avoids a significant
20292 // fetch delay after backward branch. We use 32-byte alignment with max
20293 // padding of 4 bytes (one s_nop), see getMaxPermittedBytesForAlignment().
20294 if (ML && !DisableLoopAlignment &&
20295 getSubtarget()->hasLoopHeadInstSplitSensitivity()) {
20296 const MachineBasicBlock *Header = ML->getHeader();
20297 // Respect user-specified or previously set alignment.
20298 if (Header->getAlignment() != PrefAlign)
20299 return Header->getAlignment();
20300 if (needsFetchWindowAlignment(*Header))
20301 return Align(32);
20302 }
20303
20304 // Pre-GFX10 target did not benefit from loop alignment
20305 if (!ML || DisableLoopAlignment || !getSubtarget()->hasInstPrefetch() ||
20306 getSubtarget()->hasInstFwdPrefetchBug())
20307 return PrefAlign;
20308
20309 // On GFX10 I$ is 4 x 64 bytes cache lines.
20310 // By default prefetcher keeps one cache line behind and reads two ahead.
20311 // We can modify it with S_INST_PREFETCH for larger loops to have two lines
20312 // behind and one ahead.
20313 // Therefor we can benefit from aligning loop headers if loop fits 192 bytes.
20314 // If loop fits 64 bytes it always spans no more than two cache lines and
20315 // does not need an alignment.
20316 // Else if loop is less or equal 128 bytes we do not need to modify prefetch,
20317 // Else if loop is less or equal 192 bytes we need two lines behind.
20318
20320 const MachineBasicBlock *Header = ML->getHeader();
20321 if (Header->getAlignment() != PrefAlign)
20322 return Header->getAlignment(); // Already processed.
20323
20324 unsigned LoopSize = 0;
20325 for (const MachineBasicBlock *MBB : ML->blocks()) {
20326 // If inner loop block is aligned assume in average half of the alignment
20327 // size to be added as nops.
20328 if (MBB != Header)
20329 LoopSize += MBB->getAlignment().value() / 2;
20330
20331 for (const MachineInstr &MI : *MBB) {
20332 LoopSize += TII->getInstSizeInBytes(MI);
20333 if (LoopSize > 192)
20334 return PrefAlign;
20335 }
20336 }
20337
20338 if (LoopSize <= 64)
20339 return PrefAlign;
20340
20341 if (LoopSize <= 128)
20342 return CacheLineAlign;
20343
20344 // If any of parent loops is surrounded by prefetch instructions do not
20345 // insert new for inner loop, which would reset parent's settings.
20346 for (MachineLoop *P = ML->getParentLoop(); P; P = P->getParentLoop()) {
20347 if (MachineBasicBlock *Exit = P->getExitBlock()) {
20348 auto I = Exit->getFirstNonDebugInstr();
20349 if (I != Exit->end() && I->getOpcode() == AMDGPU::S_INST_PREFETCH)
20350 return CacheLineAlign;
20351 }
20352 }
20353
20354 MachineBasicBlock *Pre = ML->getLoopPreheader();
20355 MachineBasicBlock *Exit = ML->getExitBlock();
20356
20357 if (Pre && Exit) {
20358 auto PreTerm = Pre->getFirstTerminator();
20359 if (PreTerm == Pre->begin() ||
20360 std::prev(PreTerm)->getOpcode() != AMDGPU::S_INST_PREFETCH)
20361 BuildMI(*Pre, PreTerm, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20362 .addImm(1); // prefetch 2 lines behind PC
20363
20364 auto ExitHead = Exit->getFirstNonDebugInstr();
20365 if (ExitHead == Exit->end() ||
20366 ExitHead->getOpcode() != AMDGPU::S_INST_PREFETCH)
20367 BuildMI(*Exit, ExitHead, DebugLoc(), TII->get(AMDGPU::S_INST_PREFETCH))
20368 .addImm(2); // prefetch 1 line behind PC
20369 }
20370
20371 return CacheLineAlign;
20372}
20373
20375 MachineBasicBlock *MBB) const {
20376 // GFX950: Limit padding to 4 bytes (one s_nop) for blocks where an 8-byte
20377 // instruction could be split by the 32-byte fetch window boundary.
20378 // See getPrefLoopAlignment() for context.
20379 if (needsFetchWindowAlignment(*MBB))
20380 return 4;
20382}
20383
20384bool SITargetLowering::needsFetchWindowAlignment(
20385 const MachineBasicBlock &MBB) const {
20386 if (!getSubtarget()->hasLoopHeadInstSplitSensitivity())
20387 return false;
20389 for (const MachineInstr &MI : MBB) {
20390 if (MI.isMetaInstruction())
20391 continue;
20392 // Instructions larger than 4 bytes can be split by a 32-byte boundary.
20393 return TII->getInstSizeInBytes(MI) > 4;
20394 }
20395 return false;
20396}
20397
20398[[maybe_unused]]
20399static bool isCopyFromRegOfInlineAsm(const SDNode *N) {
20400 assert(N->getOpcode() == ISD::CopyFromReg);
20401 do {
20402 // Follow the chain until we find an INLINEASM node.
20403 N = N->getOperand(0).getNode();
20404 if (N->getOpcode() == ISD::INLINEASM || N->getOpcode() == ISD::INLINEASM_BR)
20405 return true;
20406 } while (N->getOpcode() == ISD::CopyFromReg);
20407 return false;
20408}
20409
20412 UniformityInfo *UA) const {
20413 switch (N->getOpcode()) {
20414 case ISD::CopyFromReg: {
20415 const RegisterSDNode *R = cast<RegisterSDNode>(N->getOperand(1));
20416 const MachineRegisterInfo &MRI = FLI->MF->getRegInfo();
20417 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20418 Register Reg = R->getReg();
20419
20420 // FIXME: Why does this need to consider isLiveIn?
20421 if (Reg.isPhysical() || MRI.isLiveIn(Reg))
20422 return !TRI->isSGPRReg(MRI, Reg);
20423
20424 if (const Value *V = FLI->getValueFromVirtualReg(R->getReg()))
20425 return UA->isDivergentAtDef(V);
20426
20428 return !TRI->isSGPRReg(MRI, Reg);
20429 }
20430 case ISD::LOAD: {
20431 const LoadSDNode *L = cast<LoadSDNode>(N);
20432 unsigned AS = L->getAddressSpace();
20433 // A flat load may access private memory.
20435 }
20436 case ISD::CALLSEQ_END:
20437 return true;
20439 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(0));
20441 return AMDGPU::isIntrinsicSourceOfDivergence(N->getConstantOperandVal(1));
20442 case AMDGPUISD::ATOMIC_CMP_SWAP:
20443 case AMDGPUISD::BUFFER_ATOMIC_SWAP:
20444 case AMDGPUISD::BUFFER_ATOMIC_ADD:
20445 case AMDGPUISD::BUFFER_ATOMIC_SUB:
20446 case AMDGPUISD::BUFFER_ATOMIC_SMIN:
20447 case AMDGPUISD::BUFFER_ATOMIC_UMIN:
20448 case AMDGPUISD::BUFFER_ATOMIC_SMAX:
20449 case AMDGPUISD::BUFFER_ATOMIC_UMAX:
20450 case AMDGPUISD::BUFFER_ATOMIC_AND:
20451 case AMDGPUISD::BUFFER_ATOMIC_OR:
20452 case AMDGPUISD::BUFFER_ATOMIC_XOR:
20453 case AMDGPUISD::BUFFER_ATOMIC_INC:
20454 case AMDGPUISD::BUFFER_ATOMIC_DEC:
20455 case AMDGPUISD::BUFFER_ATOMIC_CMPSWAP:
20456 case AMDGPUISD::BUFFER_ATOMIC_FADD:
20457 case AMDGPUISD::BUFFER_ATOMIC_FMIN:
20458 case AMDGPUISD::BUFFER_ATOMIC_FMAX:
20459 // Target-specific read-modify-write atomics are sources of divergence.
20460 return true;
20461 default:
20462 if (auto *A = dyn_cast<AtomicSDNode>(N)) {
20463 // Generic read-modify-write atomics are sources of divergence.
20464 return A->readMem() && A->writeMem();
20465 }
20466 return false;
20467 }
20468}
20469
20471 EVT VT) const {
20472 switch (VT.getScalarType().getSimpleVT().SimpleTy) {
20473 case MVT::f32:
20475 case MVT::f64:
20476 case MVT::f16:
20478 default:
20479 return false;
20480 }
20481}
20482
20484 LLT Ty, const MachineFunction &MF) const {
20485 switch (Ty.getScalarSizeInBits()) {
20486 case 32:
20487 return !denormalModeIsFlushAllF32(MF);
20488 case 64:
20489 case 16:
20490 return !denormalModeIsFlushAllF64F16(MF);
20491 default:
20492 return false;
20493 }
20494}
20495
20497 const APInt &DemandedElts,
20498 const SelectionDAG &DAG,
20499 bool SNaN,
20500 unsigned Depth) const {
20501 if (Op.getOpcode() == AMDGPUISD::CLAMP) {
20502 const MachineFunction &MF = DAG.getMachineFunction();
20504
20505 if (Info->getMode().DX10Clamp)
20506 return true; // Clamped to 0.
20507 return DAG.isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);
20508 }
20509
20511 DAG, SNaN, Depth);
20512}
20513
20514// On older subtargets, global FP atomic instructions have a hardcoded FP mode
20515// and do not support FP32 denormals, and only support v2f16/f64 denormals.
20517 if (RMW->hasMetadata("amdgpu.ignore.denormal.mode"))
20518 return true;
20519
20520 const fltSemantics &Flt = RMW->getType()->getScalarType()->getFltSemantics();
20521 auto DenormMode = RMW->getFunction()->getDenormalMode(Flt);
20522 if (DenormMode == DenormalMode::getPreserveSign())
20523 return true;
20524
20525 // TODO: Remove this.
20526 return RMW->getFunction()
20527 ->getFnAttribute("amdgpu-unsafe-fp-atomics")
20528 .getValueAsBool();
20529}
20530
20532 LLVMContext &Ctx = RMW->getContext();
20533 StringRef MemScope =
20534 Ctx.getSyncScopeName(RMW->getSyncScopeID()).value_or("system");
20535
20536 return OptimizationRemark(DEBUG_TYPE, "Passed", RMW)
20537 << "Hardware instruction generated for atomic "
20538 << RMW->getOperationName(RMW->getOperation())
20539 << " operation at memory scope " << MemScope;
20540}
20541
20542static bool isV2F16OrV2BF16(Type *Ty) {
20543 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
20544 Type *EltTy = VT->getElementType();
20545 return VT->getNumElements() == 2 &&
20546 (EltTy->isHalfTy() || EltTy->isBFloatTy());
20547 }
20548
20549 return false;
20550}
20551
20552static bool isV2F16(Type *Ty) {
20554 return VT && VT->getNumElements() == 2 && VT->getElementType()->isHalfTy();
20555}
20556
20557static bool isV2BF16(Type *Ty) {
20559 return VT && VT->getNumElements() == 2 && VT->getElementType()->isBFloatTy();
20560}
20561
20562/// \return true if atomicrmw integer ops work for the type.
20563static bool isAtomicRMWLegalIntTy(Type *Ty) {
20564 if (auto *IT = dyn_cast<IntegerType>(Ty)) {
20565 unsigned BW = IT->getBitWidth();
20566 return BW == 32 || BW == 64;
20567 }
20568
20569 return false;
20570}
20571
20572/// \return true if this atomicrmw xchg type can be selected.
20573static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW) {
20574 Type *Ty = RMW->getType();
20575 if (isAtomicRMWLegalIntTy(Ty))
20576 return true;
20577
20578 if (PointerType *PT = dyn_cast<PointerType>(Ty)) {
20579 const DataLayout &DL = RMW->getFunction()->getParent()->getDataLayout();
20580 unsigned BW = DL.getPointerSizeInBits(PT->getAddressSpace());
20581 return BW == 32 || BW == 64;
20582 }
20583
20584 if (Ty->isFloatTy() || Ty->isDoubleTy())
20585 return true;
20586
20588 return VT->getNumElements() == 2 &&
20589 VT->getElementType()->getPrimitiveSizeInBits() == 16;
20590 }
20591
20592 return false;
20593}
20594
20595/// \returns true if it's valid to emit a native instruction for \p RMW, based
20596/// on the properties of the target memory.
20597static bool globalMemoryFPAtomicIsLegal(const GCNSubtarget &Subtarget,
20598 const AtomicRMWInst *RMW,
20599 bool HasSystemScope) {
20600 // The remote/fine-grained access logic is different from the integer
20601 // atomics. Without AgentScopeFineGrainedRemoteMemoryAtomics support,
20602 // fine-grained access does not work, even for a device local allocation.
20603 //
20604 // With AgentScopeFineGrainedRemoteMemoryAtomics, system scoped device local
20605 // allocations work.
20606 if (HasSystemScope) {
20607 if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics() &&
20608 RMW->hasMetadata("amdgpu.no.remote.memory"))
20609 return true;
20610 if (Subtarget.hasEmulatedSystemScopeAtomics())
20611 return true;
20612 } else if (Subtarget.hasAgentScopeFineGrainedRemoteMemoryAtomics())
20613 return true;
20614
20615 return RMW->hasMetadata("amdgpu.no.fine.grained.memory");
20616}
20617
20618/// \return Action to perform on AtomicRMWInsts for integer operations.
20625
20626/// Return if a flat address space atomicrmw can access private memory.
20628 const MDNode *MD = I->getMetadata(LLVMContext::MD_noalias_addrspace);
20629 return !MD ||
20631}
20632
20635 // For GAS, lower to flat atomic.
20636 return STI.hasGloballyAddressableScratch()
20639}
20640
20643 unsigned AS = RMW->getPointerAddressSpace();
20644 if (AS == AMDGPUAS::PRIVATE_ADDRESS)
20646
20647 // 64-bit flat atomics that dynamically reside in private memory will silently
20648 // be dropped.
20649 //
20650 // Note that we will emit a new copy of the original atomic in the expansion,
20651 // which will be incrementally relegalized.
20652 const DataLayout &DL = RMW->getFunction()->getDataLayout();
20653 if (AS == AMDGPUAS::FLAT_ADDRESS &&
20654 DL.getTypeSizeInBits(RMW->getType()) == 64 &&
20657
20658 auto ReportUnsafeHWInst = [=](TargetLowering::AtomicExpansionKind Kind) {
20660 ORE.emit([=]() {
20661 return emitAtomicRMWLegalRemark(RMW) << " due to an unsafe request.";
20662 });
20663 return Kind;
20664 };
20665
20666 auto SSID = RMW->getSyncScopeID();
20667 bool HasSystemScope =
20668 SSID == SyncScope::System ||
20670 getTargetMachine().getTargetTriple(), AtomicScope::System,
20671 /*OneAddressSpace=*/true));
20672
20673 auto Op = RMW->getOperation();
20674 switch (Op) {
20676 // PCIe supports add and xchg for system atomics.
20677 return isAtomicRMWLegalXChgTy(RMW)
20680 case AtomicRMWInst::Add:
20681 // PCIe supports add and xchg for system atomics.
20683 case AtomicRMWInst::Sub:
20684 case AtomicRMWInst::And:
20685 case AtomicRMWInst::Or:
20686 case AtomicRMWInst::Xor:
20687 case AtomicRMWInst::Max:
20688 case AtomicRMWInst::Min:
20695 if (Op == AtomicRMWInst::USubCond && !Subtarget->hasCondSubInsts())
20697 if (Op == AtomicRMWInst::USubSat && !Subtarget->hasSubClampInsts())
20700 auto *IT = dyn_cast<IntegerType>(RMW->getType());
20701 if (!IT || IT->getBitWidth() != 32)
20703 }
20704
20707 if (Subtarget->hasEmulatedSystemScopeAtomics())
20709
20710 // On most subtargets, for atomicrmw operations other than add/xchg,
20711 // whether or not the instructions will behave correctly depends on where
20712 // the address physically resides and what interconnect is used in the
20713 // system configuration. On some some targets the instruction will nop,
20714 // and in others synchronization will only occur at degraded device scope.
20715 //
20716 // If the allocation is known local to the device, the instructions should
20717 // work correctly.
20718 if (RMW->hasMetadata("amdgpu.no.remote.memory"))
20720
20721 // If fine-grained remote memory works at device scope, we don't need to
20722 // do anything.
20723 if (!HasSystemScope &&
20724 Subtarget->hasAgentScopeFineGrainedRemoteMemoryAtomics())
20726
20727 // If we are targeting a remote allocated address, it depends what kind of
20728 // allocation the address belongs to.
20729 //
20730 // If the allocation is fine-grained (in host memory, or in PCIe peer
20731 // device memory), the operation will fail depending on the target.
20732 //
20733 // Note fine-grained host memory access does work on APUs or if XGMI is
20734 // used, but we do not know if we are targeting an APU or the system
20735 // configuration from the ISA version/target-cpu.
20736 if (RMW->hasMetadata("amdgpu.no.fine.grained.memory"))
20738
20741 // Atomic sub/or/xor do not work over PCI express, but atomic add
20742 // does. InstCombine transforms these with 0 to or, so undo that.
20743 if (const Constant *ConstVal = dyn_cast<Constant>(RMW->getValOperand());
20744 ConstVal && ConstVal->isNullValue())
20746 }
20747
20748 // If the allocation could be in remote, fine-grained memory, the rmw
20749 // instructions may fail. cmpxchg should work, so emit that. On some
20750 // system configurations, PCIe atomics aren't supported so cmpxchg won't
20751 // even work, so you're out of luck anyway.
20752
20753 // In summary:
20754 //
20755 // Cases that may fail:
20756 // - fine-grained pinned host memory
20757 // - fine-grained migratable host memory
20758 // - fine-grained PCIe peer device
20759 //
20760 // Cases that should work, but may be treated overly conservatively.
20761 // - fine-grained host memory on an APU
20762 // - fine-grained XGMI peer device
20764 }
20765
20767 }
20768 case AtomicRMWInst::FAdd: {
20769 Type *Ty = RMW->getType();
20770
20771 // TODO: Handle REGION_ADDRESS
20772 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
20773 // DS F32 FP atomics do respect the denormal mode, but the rounding mode
20774 // is fixed to round-to-nearest-even.
20775 //
20776 // F64 / PK_F16 / PK_BF16 never flush and are also fixed to
20777 // round-to-nearest-even.
20778 //
20779 // We ignore the rounding mode problem, even in strictfp. The C++ standard
20780 // suggests it is OK if the floating-point mode may not match the calling
20781 // thread.
20782 if (Ty->isFloatTy()) {
20783 return Subtarget->hasLDSFPAtomicAddF32() ? AtomicExpansionKind::None
20785 }
20786
20787 if (Ty->isDoubleTy()) {
20788 // Ignores denormal mode, but we don't consider flushing mandatory.
20789 return Subtarget->hasLDSFPAtomicAddF64() ? AtomicExpansionKind::None
20791 }
20792
20793 if (Subtarget->hasAtomicDsPkAdd16Insts() && isV2F16OrV2BF16(Ty))
20795
20797 }
20798
20799 // LDS atomics respect the denormal mode from the mode register.
20800 //
20801 // Traditionally f32 global/buffer memory atomics would unconditionally
20802 // flush denormals, but newer targets do not flush. f64/f16/bf16 cases never
20803 // flush.
20804 //
20805 // On targets with flat atomic fadd, denormals would flush depending on
20806 // whether the target address resides in LDS or global memory. We consider
20807 // this flat-maybe-flush as will-flush.
20808 if (Ty->isFloatTy() &&
20809 !Subtarget->hasMemoryAtomicFaddF32DenormalSupport() &&
20812
20813 // FIXME: These ReportUnsafeHWInsts are imprecise. Some of these cases are
20814 // safe. The message phrasing also should be better.
20815 if (globalMemoryFPAtomicIsLegal(*Subtarget, RMW, HasSystemScope)) {
20816 if (AS == AMDGPUAS::FLAT_ADDRESS) {
20817 // gfx942, gfx12
20818 if (Subtarget->hasAtomicFlatPkAdd16Insts() && isV2F16OrV2BF16(Ty))
20819 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20820 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS)) {
20821 // gfx90a, gfx942, gfx12
20822 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
20823 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20824
20825 // gfx942, gfx12
20826 if (Subtarget->hasAtomicGlobalPkAddBF16Inst() && isV2BF16(Ty))
20827 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20828 } else if (AS == AMDGPUAS::BUFFER_FAT_POINTER) {
20829 // gfx90a, gfx942, gfx12
20830 if (Subtarget->hasAtomicBufferGlobalPkAddF16Insts() && isV2F16(Ty))
20831 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20832
20833 // While gfx90a/gfx942 supports v2bf16 for global/flat, it does not for
20834 // buffer. gfx12 does have the buffer version.
20835 if (Subtarget->hasAtomicBufferPkAddBF16Inst() && isV2BF16(Ty))
20836 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20837 }
20838
20839 // global and flat atomic fadd f64: gfx90a, gfx942.
20840 if (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() && Ty->isDoubleTy())
20841 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20842
20843 if (AS != AMDGPUAS::FLAT_ADDRESS) {
20844 if (Ty->isFloatTy()) {
20845 // global/buffer atomic fadd f32 no-rtn: gfx908, gfx90a, gfx942,
20846 // gfx11+.
20847 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
20848 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20849 // global/buffer atomic fadd f32 rtn: gfx90a, gfx942, gfx11+.
20850 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
20851 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20852 } else {
20853 // gfx908
20854 if (RMW->use_empty() &&
20855 Subtarget->hasAtomicBufferGlobalPkAddF16NoRtnInsts() &&
20856 isV2F16(Ty))
20857 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20858 }
20859 }
20860
20861 // flat atomic fadd f32: gfx942, gfx11+.
20862 if (AS == AMDGPUAS::FLAT_ADDRESS && Ty->isFloatTy()) {
20863 if (Subtarget->hasFlatAtomicFaddF32Inst())
20864 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20865
20866 // If it is in flat address space, and the type is float, we will try to
20867 // expand it, if the target supports global and lds atomic fadd. The
20868 // reason we need that is, in the expansion, we emit the check of
20869 // address space. If it is in global address space, we emit the global
20870 // atomic fadd; if it is in shared address space, we emit the LDS atomic
20871 // fadd.
20872 if (Subtarget->hasLDSFPAtomicAddF32()) {
20873 if (RMW->use_empty() && Subtarget->hasAtomicFaddNoRtnInsts())
20875 if (!RMW->use_empty() && Subtarget->hasAtomicFaddRtnInsts())
20877 }
20878 }
20879 }
20880
20882 }
20884 case AtomicRMWInst::FMax: {
20885 Type *Ty = RMW->getType();
20886
20887 // LDS float and double fmin/fmax were always supported.
20888 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
20889 return Ty->isFloatTy() || Ty->isDoubleTy() ? AtomicExpansionKind::None
20891 }
20892
20893 if (globalMemoryFPAtomicIsLegal(*Subtarget, RMW, HasSystemScope)) {
20894 // For flat and global cases:
20895 // float, double in gfx7. Manual claims denormal support.
20896 // Removed in gfx8.
20897 // float, double restored in gfx10.
20898 // double removed again in gfx11, so only f32 for gfx11/gfx12.
20899 //
20900 // For gfx9, gfx90a and gfx942 support f64 for global (same as fadd), but
20901 // no f32.
20902 if (AS == AMDGPUAS::FLAT_ADDRESS) {
20903 if (Subtarget->hasAtomicFMinFMaxF32FlatInsts() && Ty->isFloatTy())
20904 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20905 if (Subtarget->hasAtomicFMinFMaxF64FlatInsts() && Ty->isDoubleTy())
20906 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20907 } else if (AMDGPU::isExtendedGlobalAddrSpace(AS) ||
20909 if (Subtarget->hasAtomicFMinFMaxF32GlobalInsts() && Ty->isFloatTy())
20910 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20911 if (Subtarget->hasAtomicFMinFMaxF64GlobalInsts() && Ty->isDoubleTy())
20912 return ReportUnsafeHWInst(AtomicExpansionKind::None);
20913 }
20914 }
20915
20917 }
20920 default:
20922 }
20923
20924 llvm_unreachable("covered atomicrmw op switch");
20925}
20926
20933
20940
20943 const AtomicCmpXchgInst *CmpX) const {
20944 unsigned AddrSpace = CmpX->getPointerAddressSpace();
20945 if (AddrSpace == AMDGPUAS::PRIVATE_ADDRESS)
20947
20948 if (AddrSpace != AMDGPUAS::FLAT_ADDRESS || !flatInstrMayAccessPrivate(CmpX))
20950
20951 const DataLayout &DL = CmpX->getDataLayout();
20952
20953 Type *ValTy = CmpX->getNewValOperand()->getType();
20954
20955 // If a 64-bit flat atomic may alias private, we need to avoid using the
20956 // atomic in the private case.
20957 return DL.getTypeSizeInBits(ValTy) == 64 ? AtomicExpansionKind::CustomExpand
20959}
20960
20961const TargetRegisterClass *
20962SITargetLowering::getRegClassFor(MVT VT, bool isDivergent) const {
20964 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
20965 if (RC == &AMDGPU::VReg_1RegClass && !isDivergent)
20966 return Subtarget->isWave64() ? &AMDGPU::SReg_64RegClass
20967 : &AMDGPU::SReg_32RegClass;
20968 if (!TRI->isSGPRClass(RC) && !isDivergent)
20969 return TRI->getEquivalentSGPRClass(RC);
20970 if (TRI->isSGPRClass(RC) && isDivergent) {
20971 if (Subtarget->hasGFX90AInsts())
20972 return TRI->getEquivalentAVClass(RC);
20973 return TRI->getEquivalentVGPRClass(RC);
20974 }
20975
20976 return RC;
20977}
20978
20979// FIXME: This is a workaround for DivergenceAnalysis not understanding always
20980// uniform values (as produced by the mask results of control flow intrinsics)
20981// used outside of divergent blocks. The phi users need to also be treated as
20982// always uniform.
20983//
20984// FIXME: DA is no longer in-use. Does this still apply to UniformityAnalysis?
20985static bool hasCFUser(const Value *V, SmallPtrSet<const Value *, 16> &Visited,
20986 unsigned WaveSize) {
20987 // FIXME: We assume we never cast the mask results of a control flow
20988 // intrinsic.
20989 // Early exit if the type won't be consistent as a compile time hack.
20990 IntegerType *IT = dyn_cast<IntegerType>(V->getType());
20991 if (!IT || IT->getBitWidth() != WaveSize)
20992 return false;
20993
20994 if (!isa<Instruction>(V))
20995 return false;
20996 if (!Visited.insert(V).second)
20997 return false;
20998 bool Result = false;
20999 for (const auto *U : V->users()) {
21001 if (V == U->getOperand(1)) {
21002 switch (Intrinsic->getIntrinsicID()) {
21003 default:
21004 Result = false;
21005 break;
21006 case Intrinsic::amdgcn_if_break:
21007 case Intrinsic::amdgcn_if:
21008 case Intrinsic::amdgcn_else:
21009 Result = true;
21010 break;
21011 }
21012 }
21013 if (V == U->getOperand(0)) {
21014 switch (Intrinsic->getIntrinsicID()) {
21015 default:
21016 Result = false;
21017 break;
21018 case Intrinsic::amdgcn_end_cf:
21019 case Intrinsic::amdgcn_loop:
21020 Result = true;
21021 break;
21022 }
21023 }
21024 } else {
21025 Result = hasCFUser(U, Visited, WaveSize);
21026 }
21027 if (Result)
21028 break;
21029 }
21030 return Result;
21031}
21032
21034 const Value *V) const {
21035 if (const CallInst *CI = dyn_cast<CallInst>(V)) {
21036 if (CI->isInlineAsm()) {
21037 // FIXME: This cannot give a correct answer. This should only trigger in
21038 // the case where inline asm returns mixed SGPR and VGPR results, used
21039 // outside the defining block. We don't have a specific result to
21040 // consider, so this assumes if any value is SGPR, the overall register
21041 // also needs to be SGPR.
21042 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
21044 MF.getDataLayout(), Subtarget->getRegisterInfo(), *CI);
21045 for (auto &TC : TargetConstraints) {
21046 if (TC.Type == InlineAsm::isOutput) {
21048 const TargetRegisterClass *RC =
21049 getRegForInlineAsmConstraint(SIRI, TC.ConstraintCode,
21050 TC.ConstraintVT)
21051 .second;
21052 if (RC && SIRI->isSGPRClass(RC))
21053 return true;
21054 }
21055 }
21056 }
21057 }
21059 return hasCFUser(V, Visited, Subtarget->getWavefrontSize());
21060}
21061
21063 for (SDUse &Use : N->uses()) {
21065 if (getBasePtrIndex(M) == Use.getOperandNo())
21066 return true;
21067 }
21068 }
21069 return false;
21070}
21071
21073 SDValue N1) const {
21074 if (!N0.hasOneUse())
21075 return false;
21076 // Take care of the opportunity to keep N0 uniform
21077 if (N0->isDivergent() || !N1->isDivergent())
21078 return true;
21079 // Check if we have a good chance to form the memory access pattern with the
21080 // base and offset
21081 return (DAG.isBaseWithConstantOffset(N0) &&
21083}
21084
21086 Register N0, Register N1) const {
21087 return MRI.hasOneNonDBGUse(N0); // FIXME: handle regbanks
21088}
21089
21092 // Propagate metadata set by AMDGPUAnnotateUniformValues to the MMO of a load.
21094 if (I.getMetadata("amdgpu.noclobber"))
21095 Flags |= MONoClobber;
21096 if (I.getMetadata("amdgpu.last.use"))
21097 Flags |= MOLastUse;
21098 return Flags;
21099}
21100
21102 Instruction *AI) const {
21103 // Given: atomicrmw fadd ptr %addr, float %val ordering
21104 //
21105 // With this expansion we produce the following code:
21106 // [...]
21107 // %is.shared = call i1 @llvm.amdgcn.is.shared(ptr %addr)
21108 // br i1 %is.shared, label %atomicrmw.shared, label %atomicrmw.check.private
21109 //
21110 // atomicrmw.shared:
21111 // %cast.shared = addrspacecast ptr %addr to ptr addrspace(3)
21112 // %loaded.shared = atomicrmw fadd ptr addrspace(3) %cast.shared,
21113 // float %val ordering
21114 // br label %atomicrmw.phi
21115 //
21116 // atomicrmw.check.private:
21117 // %is.private = call i1 @llvm.amdgcn.is.private(ptr %int8ptr)
21118 // br i1 %is.private, label %atomicrmw.private, label %atomicrmw.global
21119 //
21120 // atomicrmw.private:
21121 // %cast.private = addrspacecast ptr %addr to ptr addrspace(5)
21122 // %loaded.private = load float, ptr addrspace(5) %cast.private
21123 // %val.new = fadd float %loaded.private, %val
21124 // store float %val.new, ptr addrspace(5) %cast.private
21125 // br label %atomicrmw.phi
21126 //
21127 // atomicrmw.global:
21128 // %cast.global = addrspacecast ptr %addr to ptr addrspace(1)
21129 // %loaded.global = atomicrmw fadd ptr addrspace(1) %cast.global,
21130 // float %val ordering
21131 // br label %atomicrmw.phi
21132 //
21133 // atomicrmw.phi:
21134 // %loaded.phi = phi float [ %loaded.shared, %atomicrmw.shared ],
21135 // [ %loaded.private, %atomicrmw.private ],
21136 // [ %loaded.global, %atomicrmw.global ]
21137 // br label %atomicrmw.end
21138 //
21139 // atomicrmw.end:
21140 // [...]
21141 //
21142 //
21143 // For 64-bit atomics which may reside in private memory, we perform a simpler
21144 // version that only inserts the private check, and uses the flat operation.
21145
21146 IRBuilder<> Builder(AI);
21147 LLVMContext &Ctx = Builder.getContext();
21148
21149 auto *RMW = dyn_cast<AtomicRMWInst>(AI);
21150 const unsigned PtrOpIdx = RMW ? AtomicRMWInst::getPointerOperandIndex()
21152 Value *Addr = AI->getOperand(PtrOpIdx);
21153
21154 /// TODO: Only need to check private, then emit flat-known-not private (no
21155 /// need for shared block, or cast to global).
21157
21158 Align Alignment;
21159 if (RMW)
21160 Alignment = RMW->getAlign();
21161 else if (CX)
21162 Alignment = CX->getAlign();
21163 else
21164 llvm_unreachable("unhandled atomic operation");
21165
21166 // FullFlatEmulation is true if we need to issue the private, shared, and
21167 // global cases.
21168 //
21169 // If this is false, we are only dealing with the flat-targeting-private case,
21170 // where we only insert a check for private and still use the flat instruction
21171 // for global and shared.
21172
21173 bool FullFlatEmulation =
21174 RMW && RMW->getOperation() == AtomicRMWInst::FAdd &&
21175 ((Subtarget->hasAtomicFaddInsts() && RMW->getType()->isFloatTy()) ||
21176 (Subtarget->hasFlatBufferGlobalAtomicFaddF64Inst() &&
21177 RMW->getType()->isDoubleTy()));
21178
21179 // If the return value isn't used, do not introduce a false use in the phi.
21180 bool ReturnValueIsUsed = !AI->use_empty();
21181
21182 BasicBlock *BB = Builder.GetInsertBlock();
21183 Function *F = BB->getParent();
21184 BasicBlock *ExitBB =
21185 BB->splitBasicBlock(Builder.GetInsertPoint(), "atomicrmw.end");
21186 BasicBlock *SharedBB = nullptr;
21187
21188 BasicBlock *CheckPrivateBB = BB;
21189 if (FullFlatEmulation) {
21190 SharedBB = BasicBlock::Create(Ctx, "atomicrmw.shared", F, ExitBB);
21191 CheckPrivateBB =
21192 BasicBlock::Create(Ctx, "atomicrmw.check.private", F, ExitBB);
21193 }
21194
21195 BasicBlock *PrivateBB =
21196 BasicBlock::Create(Ctx, "atomicrmw.private", F, ExitBB);
21197 BasicBlock *GlobalBB = BasicBlock::Create(Ctx, "atomicrmw.global", F, ExitBB);
21198 BasicBlock *PhiBB = BasicBlock::Create(Ctx, "atomicrmw.phi", F, ExitBB);
21199
21200 std::prev(BB->end())->eraseFromParent();
21201 Builder.SetInsertPoint(BB);
21202
21203 Value *LoadedShared = nullptr;
21204 if (FullFlatEmulation) {
21205 Value *IsShared = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_shared,
21206 {Addr}, nullptr, "is.shared");
21207 Builder.CreateCondBr(IsShared, SharedBB, CheckPrivateBB);
21208 Builder.SetInsertPoint(SharedBB);
21209 Value *CastToLocal = Builder.CreateAddrSpaceCast(
21211
21212 Instruction *Clone = AI->clone();
21213 Clone->insertInto(SharedBB, SharedBB->end());
21214 Clone->getOperandUse(PtrOpIdx).set(CastToLocal);
21215 LoadedShared = Clone;
21216
21217 Builder.CreateBr(PhiBB);
21218 Builder.SetInsertPoint(CheckPrivateBB);
21219 }
21220
21221 Value *IsPrivate = Builder.CreateIntrinsic(Intrinsic::amdgcn_is_private,
21222 {Addr}, nullptr, "is.private");
21223 Builder.CreateCondBr(IsPrivate, PrivateBB, GlobalBB);
21224
21225 Builder.SetInsertPoint(PrivateBB);
21226
21227 Value *CastToPrivate = Builder.CreateAddrSpaceCast(
21229
21230 Value *LoadedPrivate;
21231 if (RMW) {
21232 LoadedPrivate = Builder.CreateAlignedLoad(
21233 RMW->getType(), CastToPrivate, RMW->getAlign(), "loaded.private");
21234
21235 Value *NewVal = buildAtomicRMWValue(RMW->getOperation(), Builder,
21236 LoadedPrivate, RMW->getValOperand());
21237
21238 Builder.CreateAlignedStore(NewVal, CastToPrivate, RMW->getAlign());
21239 } else {
21240 auto [ResultLoad, Equal] =
21241 buildCmpXchgValue(Builder, CastToPrivate, CX->getCompareOperand(),
21242 CX->getNewValOperand(), CX->getAlign());
21243
21244 Value *Insert = Builder.CreateInsertValue(PoisonValue::get(CX->getType()),
21245 ResultLoad, 0);
21246 LoadedPrivate = Builder.CreateInsertValue(Insert, Equal, 1);
21247 }
21248
21249 Builder.CreateBr(PhiBB);
21250
21251 Builder.SetInsertPoint(GlobalBB);
21252
21253 // Continue using a flat instruction if we only emitted the check for private.
21254 Instruction *LoadedGlobal = AI;
21255 if (FullFlatEmulation) {
21256 Value *CastToGlobal = Builder.CreateAddrSpaceCast(
21258 AI->getOperandUse(PtrOpIdx).set(CastToGlobal);
21259 }
21260
21261 AI->removeFromParent();
21262 AI->insertInto(GlobalBB, GlobalBB->end());
21263
21264 // The new atomicrmw may go through another round of legalization later.
21265 if (!FullFlatEmulation) {
21266 // We inserted the runtime check already, make sure we do not try to
21267 // re-expand this.
21268 // TODO: Should union with any existing metadata.
21269 MDBuilder MDB(F->getContext());
21270 MDNode *RangeNotPrivate =
21273 LoadedGlobal->setMetadata(LLVMContext::MD_noalias_addrspace,
21274 RangeNotPrivate);
21275 }
21276
21277 Builder.CreateBr(PhiBB);
21278
21279 Builder.SetInsertPoint(PhiBB);
21280
21281 if (ReturnValueIsUsed) {
21282 PHINode *Loaded = Builder.CreatePHI(AI->getType(), 3);
21283 AI->replaceAllUsesWith(Loaded);
21284 if (FullFlatEmulation)
21285 Loaded->addIncoming(LoadedShared, SharedBB);
21286 Loaded->addIncoming(LoadedPrivate, PrivateBB);
21287 Loaded->addIncoming(LoadedGlobal, GlobalBB);
21288 Loaded->takeName(AI);
21289 }
21290
21291 Builder.CreateBr(ExitBB);
21292}
21293
21295 unsigned PtrOpIdx) {
21296 Value *PtrOp = I->getOperand(PtrOpIdx);
21299
21300 Type *FlatPtr = PointerType::get(I->getContext(), AMDGPUAS::FLAT_ADDRESS);
21301 Value *ASCast = CastInst::CreatePointerCast(PtrOp, FlatPtr, "scratch.ascast",
21302 I->getIterator());
21303 I->setOperand(PtrOpIdx, ASCast);
21304}
21305
21308
21311
21314 if (const auto *ConstVal = dyn_cast<Constant>(AI->getValOperand());
21315 ConstVal && ConstVal->isNullValue()) {
21316 // atomicrmw or %ptr, 0 -> atomicrmw add %ptr, 0
21318
21319 // We may still need the private-alias-flat handling below.
21320
21321 // TODO: Skip this for cases where we cannot access remote memory.
21322 }
21323 }
21324
21325 // The non-flat expansions should only perform the de-canonicalization of
21326 // identity values.
21328 return;
21329
21331}
21332
21339
21343
21345 "Expand Atomic Load only handles SCRATCH -> FLAT conversion");
21346}
21347
21349 if (SI->getPointerAddressSpace() == AMDGPUAS::PRIVATE_ADDRESS)
21350 return convertScratchAtomicToFlatAtomic(SI, SI->getPointerOperandIndex());
21351
21353 "Expand Atomic Store only handles SCRATCH -> FLAT conversion");
21354}
21355
21356LoadInst *
21358 IRBuilder<> Builder(AI);
21359 auto Order = AI->getOrdering();
21360
21361 // The optimization removes store aspect of the atomicrmw. Therefore, cache
21362 // must be flushed if the atomic ordering had a release semantics. This is
21363 // not necessary a fence, a release fence just coincides to do that flush.
21364 // Avoid replacing of an atomicrmw with a release semantics.
21365 if (isReleaseOrStronger(Order))
21366 return nullptr;
21367
21368 LoadInst *LI = Builder.CreateAlignedLoad(
21369 AI->getType(), AI->getPointerOperand(), AI->getAlign());
21370 LI->setAtomic(Order, AI->getSyncScopeID());
21371 LI->copyMetadata(*AI);
21372 LI->takeName(AI);
21373 AI->replaceAllUsesWith(LI);
21374 AI->eraseFromParent();
21375 return LI;
21376}
static bool isMul(MachineInstr *MI)
return SDValue()
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static constexpr std::pair< ImplicitArgumentMask, StringLiteral > ImplicitAttrs[]
static bool allUsesHaveSourceMods(MachineInstr &MI, MachineRegisterInfo &MRI, unsigned CostThreshold=4)
static bool isCtlzOpc(unsigned Opc)
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isNoUnsignedWrap(MachineInstr *Addr)
static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE, bool &IsTexFail)
static bool isAsyncLDSDMA(Intrinsic::ID Intr)
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI, SmallVectorImpl< Register > &PackedAddrs, unsigned ArgOffset, const AMDGPU::ImageDimIntrinsicInfo *Intr, bool IsA16, bool IsG16)
Turn a set of f16 typed registers in AddrRegs into a dword sized vector with f16 typed elements.
constexpr LLT S32
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI, const AMDGPUTargetMachine &TM, unsigned AddrSpace)
Return true if the value is a known valid address, such that a null check is not necessary.
Provides AMDGPU specific target descriptions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
Function Alias Analysis Results
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
@ 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)
static LVOptions Options
Definition LVOptions.cpp:25
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Contains matchers for matching SSA Machine Instructions.
static bool isUndef(const MachineInstr &MI)
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
uint64_t IntrinsicInst * II
#define P(N)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
Contains matchers for matching SelectionDAG nodes and values.
static void r0(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:39
static void r3(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:57
static void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:51
static void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
Definition SHA1.cpp:45
#define FP_DENORM_FLUSH_NONE
Definition SIDefines.h:1504
#define FP_DENORM_FLUSH_IN_FLUSH_OUT
Definition SIDefines.h:1501
SI Fold Operands
static void reservePrivateMemoryRegs(const TargetMachine &TM, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info)
static SDValue adjustLoadValueTypeImpl(SDValue Result, EVT LoadVT, const SDLoc &DL, SelectionDAG &DAG, bool Unpacked)
static MachineBasicBlock * emitIndirectSrc(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static bool denormalModeIsFlushAllF64F16(const MachineFunction &MF)
static bool isAtomicRMWLegalIntTy(Type *Ty)
static void knownBitsForWorkitemID(const GCNSubtarget &ST, GISelValueTracking &VT, KnownBits &Known, unsigned Dim)
static bool flatInstrMayAccessPrivate(const Instruction *I)
Return if a flat address space atomicrmw can access private memory.
static std::pair< unsigned, int > computeIndirectRegAndOffset(const SIRegisterInfo &TRI, const TargetRegisterClass *SuperRC, unsigned VecReg, int Offset)
static bool denormalModeIsFlushAllF32(const MachineFunction &MF)
static bool addresses16Bits(int Mask)
static MachineBasicBlock * expand64BitScalarArithmetic(MachineInstr &MI, MachineBasicBlock *BB)
static bool isClampZeroToOne(SDValue A, SDValue B)
static bool supportsMin3Max3(const GCNSubtarget &Subtarget, unsigned Opc, EVT VT)
static unsigned findFirstFreeSGPR(CCState &CCInfo)
static uint32_t getPermuteMask(SDValue V)
static SDValue lowerLaneOp(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static int getAlignedAGPRClassID(unsigned UnalignedClassID)
static void processPSInputArgs(SmallVectorImpl< ISD::InputArg > &Splits, CallingConv::ID CallConv, ArrayRef< ISD::InputArg > Ins, BitVector &Skipped, FunctionType *FType, SIMachineFunctionInfo *Info)
static SDValue selectSOffset(SDValue SOffset, SelectionDAG &DAG, const GCNSubtarget *Subtarget)
static SDValue getLoadExtOrTrunc(SelectionDAG &DAG, ISD::LoadExtType ExtType, SDValue Op, const SDLoc &SL, EVT VT)
static bool globalMemoryFPAtomicIsLegal(const GCNSubtarget &Subtarget, const AtomicRMWInst *RMW, bool HasSystemScope)
static std::tuple< unsigned, unsigned > getDPPOpcForWaveReduction(unsigned Opc, const GCNSubtarget &ST)
static void fixMasks(SmallVectorImpl< DotSrc > &Srcs, unsigned ChainLength)
static bool is32bitWaveReduceOperation(unsigned Opc)
static TargetLowering::AtomicExpansionKind atomicSupportedIfLegalIntType(const AtomicRMWInst *RMW)
static SDValue strictFPExtFromF16(SelectionDAG &DAG, SDValue Src)
Return the source of an fp_extend from f16 to f32, or a converted FP constant.
static bool isAtomicRMWLegalXChgTy(const AtomicRMWInst *RMW)
static bool bitOpWithConstantIsReducible(unsigned Opc, uint32_t Val)
static void convertScratchAtomicToFlatAtomic(Instruction *I, unsigned PtrOpIdx)
static bool isCopyFromRegOfInlineAsm(const SDNode *N)
static bool elementPairIsOddToEven(ArrayRef< int > Mask, int Elt)
static 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 SDValue lowerICMPIntrinsic(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static bool hasCFUser(const Value *V, SmallPtrSet< const Value *, 16 > &Visited, unsigned WaveSize)
static std::pair< Register, Register > ExtractSubRegs(MachineInstr &MI, MachineOperand &Op, const TargetRegisterClass *SrcRC, const GCNSubtarget &ST, MachineRegisterInfo &MRI)
static OptimizationRemark emitAtomicRMWLegalRemark(const AtomicRMWInst *RMW)
static unsigned SubIdx2Lane(unsigned Idx)
Helper function for adjustWritemask.
static TargetLowering::AtomicExpansionKind getPrivateAtomicExpansionKind(const GCNSubtarget &STI)
static bool addressMayBeAccessedAsPrivate(const MachineMemOperand *MMO, const SIMachineFunctionInfo &Info)
static MachineBasicBlock * lowerWaveReduce(MachineInstr &MI, MachineBasicBlock &BB, const GCNSubtarget &ST, unsigned Opc)
static bool elementPairIsContiguous(ArrayRef< int > Mask, int Elt)
static bool isV2BF16(Type *Ty)
static ArgDescriptor allocateSGPR32InputImpl(CCState &CCInfo, const TargetRegisterClass *RC, unsigned NumArgRegs)
static SDValue getMad64_32(SelectionDAG &DAG, const SDLoc &SL, EVT VT, SDValue N0, SDValue N1, SDValue N2, bool Signed)
static SDValue resolveSources(SelectionDAG &DAG, SDLoc SL, SmallVectorImpl< DotSrc > &Srcs, bool IsSigned, bool IsAny)
static bool hasNon16BitAccesses(uint64_t PermMask, SDValue &Op, SDValue &OtherOp)
static SDValue lowerWaveShuffle(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue diagnoseUnsupportedImage(SelectionDAG &DAG, SDValue Op, ArrayRef< EVT > ResultTypes, const SDLoc &DL, const Twine &Msg)
Emit a DiagnosticInfoUnsupported for an unsupported image intrinsic and return poison values of Resul...
static void placeSources(ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, SmallVectorImpl< DotSrc > &Src0s, SmallVectorImpl< DotSrc > &Src1s, int Step)
static unsigned parseSyncscopeMDArg(const CallBase &CI, unsigned ArgIdx)
static EVT memVTFromLoadIntrReturn(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static MachineBasicBlock::iterator emitLoadM0FromVGPRLoop(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB, const DebugLoc &DL, const MachineOperand &Idx, unsigned InitReg, unsigned ResultReg, unsigned PhiReg, unsigned InitSaveExecReg, int Offset, bool UseGPRIdxMode, Register &SGPRIdxReg)
static SDValue matchPERM(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isFrameIndexOp(SDValue Op)
static ConstantFPSDNode * getSplatConstantFP(SDValue Op)
static void allocateSGPR32Input(CCState &CCInfo, ArgDescriptor &Arg)
static void knownBitsForSBFE(const MachineInstr &MI, GISelValueTracking &VT, KnownBits &Known, const APInt &DemandedElts, unsigned BFEWidth, bool SExt, unsigned Depth)
static bool isExtendedFrom16Bits(SDValue &Operand)
static std::optional< bool > checkDot4MulSignedness(const SDValue &N, ByteProvider< SDValue > &Src0, ByteProvider< SDValue > &Src1, const SDValue &S0Op, const SDValue &S1Op, const SelectionDAG &DAG)
static bool vectorEltWillFoldAway(SDValue Op)
static SDValue getSPDenormModeValue(uint32_t SPDenormMode, SelectionDAG &DAG, const SIMachineFunctionInfo *Info, const GCNSubtarget *ST)
static uint32_t getConstantPermuteMask(uint32_t C)
static AtomicOrdering parseAtomicOrderingCABIArg(const CallBase &CI, unsigned ArgIdx)
static MachineBasicBlock * emitIndirectDst(MachineInstr &MI, MachineBasicBlock &MBB, const GCNSubtarget &ST)
static void setM0ToIndexFromSGPR(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static ArgDescriptor allocateVGPR32Input(CCState &CCInfo, unsigned Mask=~0u, ArgDescriptor Arg=ArgDescriptor())
static DenormalFPEnv getDenormalFPEnv(const MachineFunction &MF)
static std::pair< MachineBasicBlock *, MachineBasicBlock * > splitBlockForLoop(MachineInstr &MI, MachineBasicBlock &MBB, bool InstInLoop)
static unsigned getBasePtrIndex(const MemSDNode *N)
MemSDNode::getBasePtr() does not work for intrinsics, which needs to offset by the chain and intrinsi...
static void allocateFixedSGPRInputImpl(CCState &CCInfo, const TargetRegisterClass *RC, MCRegister Reg)
static SDValue constructRetValue(SelectionDAG &DAG, MachineSDNode *Result, ArrayRef< EVT > ResultTypes, bool IsTexFail, bool Unpacked, bool IsD16, int DMaskPop, int NumVDataDwords, bool IsAtomicPacked16Bit, const SDLoc &DL)
static std::optional< ByteProvider< SDValue > > handleMulOperand(const SDValue &MulOperand)
static ISD::CondCode tryReduceF64CompareToHiHalf(const ISD::CondCode CC, const SDValue LHS, const SDValue RHS, const SelectionDAG &DAG)
static SDValue lowerFCMPIntrinsic(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static Register getIndirectSGPRIdx(const SIInstrInfo *TII, MachineRegisterInfo &MRI, MachineInstr &MI, int Offset)
static SDValue emitNonHSAIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static EVT memVTFromLoadIntrData(const SITargetLowering &TLI, const DataLayout &DL, Type *Ty, unsigned MaxNumLanes)
static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc)
static unsigned getExtOpcodeForPromotedOp(SDValue Op)
static void expand64BitV_CNDMASK(MachineInstr &MI, MachineBasicBlock *BB)
static SDValue lowerBALLOTIntrinsic(const SITargetLowering &TLI, SDNode *N, SelectionDAG &DAG)
static SDValue buildSMovImm32(SelectionDAG &DAG, const SDLoc &DL, uint64_t Val)
static SDValue tryFoldMADwithSRL(SelectionDAG &DAG, const SDLoc &SL, SDValue MulLHS, SDValue MulRHS, SDValue AddRHS)
static unsigned getIntrMemWidth(unsigned IntrID)
static SDValue getBuildDwordsVector(SelectionDAG &DAG, SDLoc DL, ArrayRef< SDValue > Elts)
static SDNode * findUser(SDValue Value, unsigned Opcode)
Helper function for LowerBRCOND.
static unsigned addPermMasks(unsigned First, unsigned Second)
static uint64_t clearUnusedBits(uint64_t Val, unsigned Size)
static SDValue getFPTernOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue C, SDValue GlueChain, SDNodeFlags Flags)
static bool isV2F16OrV2BF16(Type *Ty)
static bool atomicIgnoresDenormalModeOrFPModeIsFTZ(const AtomicRMWInst *RMW)
static SDValue emitRemovedIntrinsicError(SelectionDAG &DAG, const SDLoc &DL, EVT VT)
static SDValue getFPBinOp(SelectionDAG &DAG, unsigned Opcode, const SDLoc &SL, EVT VT, SDValue A, SDValue B, SDValue GlueChain, SDNodeFlags Flags)
static SDValue buildPCRelGlobalAddress(SelectionDAG &DAG, const GlobalValue *GV, const SDLoc &DL, int64_t Offset, EVT PtrVT, unsigned GAFlags=SIInstrInfo::MO_NONE)
static cl::opt< bool > UseDivergentRegisterIndexing("amdgpu-use-divergent-register-indexing", cl::Hidden, cl::desc("Use indirect register addressing for divergent indexes"), cl::init(false))
static const std::optional< ByteProvider< SDValue > > calculateSrcByte(const SDValue Op, uint64_t DestByte, uint64_t SrcIndex=0, unsigned Depth=0)
static bool isV2F16(Type *Ty)
static void allocateSGPR64Input(CCState &CCInfo, ArgDescriptor &Arg)
static uint64_t getIdentityValueForWaveReduction(unsigned Opc)
SI DAG Lowering interface definition.
Interface definition for SIRegisterInfo.
const char * Msg
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
static unsigned getScalarSizeInBits(Type *Ty)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
LLVM IR instance of the generic uniformity analysis.
static constexpr int Concat[]
Value * RHS
Value * LHS
The Input class is used to parse a yaml document into in-memory structs and vectors.
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
static std::optional< uint32_t > getLDSAbsoluteAddress(const GlobalValue &GV)
unsigned getWavefrontSize() const
static unsigned numBitsSigned(SDValue Op, SelectionDAG &DAG)
SDValue SplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Split a vector load into 2 loads of half the vector.
void analyzeFormalArgumentsCompute(CCState &State, const SmallVectorImpl< ISD::InputArg > &Ins) const
The SelectionDAGBuilder will automatically promote function arguments with illegal types.
SDValue LowerF64ToF16Safe(SDValue Src, const SDLoc &DL, SelectionDAG &DAG) const
SDValue storeStackInputValue(SelectionDAG &DAG, const SDLoc &SL, SDValue Chain, SDValue ArgVal, int64_t Offset) const
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue splitBinaryBitConstantOpImpl(DAGCombinerInfo &DCI, const SDLoc &SL, unsigned Opc, SDValue LHS, uint32_t ValLo, uint32_t ValHi) const
Split the 64-bit value LHS into two 32-bit components, and perform the binary operation Opc to it wit...
SDValue lowerUnhandledCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals, StringRef Reason) const
virtual SDValue LowerGlobalAddress(AMDGPUMachineFunctionInfo *MFI, SDValue Op, SelectionDAG &DAG) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
SDValue addTokenForArgument(SDValue Chain, SelectionDAG &DAG, MachineFrameInfo &MFI, int ClobberedFI) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
static bool needsDenormHandlingF32(const SelectionDAG &DAG, SDValue Src, SDNodeFlags Flags)
uint32_t getImplicitParameterOffset(const MachineFunction &MF, const ImplicitParameter Param) const
Helper function that returns the byte offset of the given type of implicit parameter.
SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const
SDValue loadInputValue(SelectionDAG &DAG, const TargetRegisterClass *RC, EVT VT, const SDLoc &SL, const ArgDescriptor &Arg) const
AMDGPUTargetLowering(const TargetMachine &TM, const TargetSubtargetInfo &STI, const AMDGPUSubtarget &AMDGPUSTI)
static EVT getEquivalentMemType(LLVMContext &Context, EVT VT)
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
SDValue CreateLiveInRegister(SelectionDAG &DAG, const TargetRegisterClass *RC, Register Reg, EVT VT, const SDLoc &SL, bool RawReg=false) const
Helper function that adds Reg to the LiveIn list of the DAG's MachineFunction.
SDValue SplitVectorStore(SDValue Op, SelectionDAG &DAG) const
Split a vector store into 2 stores of half the vector.
std::pair< SDValue, SDValue > split64BitValue(SDValue Op, SelectionDAG &DAG) const
Return 64-bit value Op as two 32-bit integers.
static CCAssignFn * CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg)
static CCAssignFn * CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg)
Selects the correct CCAssignFn for a given CallingConvention value.
static unsigned numBitsUnsigned(SDValue Op, SelectionDAG &DAG)
static bool allowApproxFunc(const SelectionDAG &DAG, SDNodeFlags Flags)
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
SDValue performRcpCombine(SDNode *N, DAGCombinerInfo &DCI) const
SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const
static bool shouldFoldFNegIntoSrc(SDNode *FNeg, SDValue FNegSrc)
bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const override
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue WidenOrSplitVectorLoad(SDValue Op, SelectionDAG &DAG) const
Widen a suitably aligned v3 load.
SDValue getHiHalf64(SDValue Op, SelectionDAG &DAG) const
bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast between SrcAS and DestAS is a noop.
const std::array< unsigned, 3 > & getDims() const
static const LaneMaskConstants & get(const GCNSubtarget &ST)
static const fltSemantics & IEEEsingle()
Definition APFloat.h:304
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:353
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:1216
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:5934
LLVM_READONLY int getExactLog2Abs() const
Definition APFloat.h:1631
bool isNegative() const
Definition APFloat.h:1575
bool isNormal() const
Definition APFloat.h:1579
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
Definition APFloat.h:1184
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
Definition APFloat.h:1234
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition APFloat.h:1194
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition APFloat.h:1175
bool isInfinity() const
Definition APFloat.h:1572
Class for arbitrary precision integers.
Definition APInt.h:78
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
Definition APInt.h:255
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:377
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
Definition APInt.h:463
unsigned countr_zero() const
Count the number of trailing zero bits.
Definition APInt.h:1660
bool isOneBitSet(unsigned BitNo) const
Determine if this APInt Value only has the specified bit set.
Definition APInt.h:363
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
Definition APInt.h:338
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition APInt.h:293
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
Definition APInt.h:1242
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
Definition APInt.h:1226
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:333
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,...
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,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
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)
Value * getPointerOperand()
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)
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
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:407
LLVM_ABI MemoryEffects getMemoryEffects() const
LLVM_ABI bool getValueAsBool() const
Return the attribute's value as a boolean.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator end()
Definition BasicBlock.h:459
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
A "pseudo-class" with methods for operating on BUILD_VECTORs.
Represents known origin of an individual byte in combine pattern.
static ByteProvider getConstantZero()
static ByteProvider getSrc(std::optional< ISelOp > Val, int64_t ByteOffset, int64_t VectorOffset)
std::optional< ISelOp > Src
CCState - This class holds information needed while lowering arguments and return values.
MachineFunction & getMachineFunction() const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
LLVM_ABI void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
bool isAllocated(MCRegister Reg) const
isAllocated - Return true if the specified register (or an alias) is allocated.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
bool isTailCall() const
static LLVM_ABI CastInst * CreatePointerCast(Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ ICMP_NE
not equal
Definition InstrTypes.h:762
bool isSigned() const
Definition InstrTypes.h:993
static bool isFPPredicate(Predicate P)
Definition InstrTypes.h:833
static bool isIntPredicate(Predicate P)
Definition InstrTypes.h:839
const APFloat & getValueAPF() const
bool isPosZero() const
Return true if the value is positive zero.
bool isOne() const
Returns true if this value is exactly +1.0.
bool isMinusOne() const
Returns true if this value is exactly -1.0.
bool isNegative() const
Return true if the value is negative.
bool isInfinity() const
Return true if the value is an infinity.
This is the shared class of boolean and integer constants.
Definition Constants.h:87
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition Constants.h:219
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
Definition Constant.h:43
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
bool isBigEndian() const
Definition DataLayout.h:218
A debug info location.
Definition DebugLoc.h:126
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:309
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:211
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Definition Function.cpp:357
iterator_range< arg_iterator > args()
Definition Function.h:876
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:762
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:272
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:353
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
Definition Function.cpp:803
size_t arg_size() const
Definition Function.h:885
Argument * getArg(unsigned i) const
Definition Function.h:870
const SIInstrInfo * getInstrInfo() const override
bool hasMadF16() const
unsigned getInstCacheLineSize() const
Instruction cache line size in bytes (64 for pre-GFX11, 128 for GFX11+).
const SIRegisterInfo * getRegisterInfo() const override
bool hasMin3Max3_16() const
bool supportsWaveWideBPermute() const
unsigned getMaxPrivateElementSize(bool ForBufferRSrc=false) const
bool isWave64() const
bool hasPrivateSegmentBuffer() const
const MachineFunction & getMachineFunction() const
void computeKnownBitsImpl(Register R, KnownBits &Known, const APInt &DemandedElts, unsigned Depth=0)
bool isDivergentAtDef(ConstValueRefT V) const
Whether V is divergent at its definition.
LLVM_ABI unsigned getAddressSpace() const
const GlobalValue * getGlobal() const
bool hasExternalLinkage() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Definition Globals.cpp:205
Type * getValueType() const
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
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 InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes 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 void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
constexpr unsigned getScalarSizeInBits() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI SyncScope::ID getOrInsertSyncScopeID(StringRef SSN)
getOrInsertSyncScopeID - Maps synchronization scope name to synchronization scope ID.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
static unsigned getPointerOperandIndex()
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
Describe properties that are true of each instruction in the target description file.
unsigned getID() const
getID() - Return the register class ID number.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
iterator begin() const
begin/end - Return all of the registers in this class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
LLVM_ABI MDNode * createRange(const APInt &Lo, const APInt &Hi)
Return metadata describing the range [Lo, Hi).
Definition MDBuilder.cpp:96
Metadata node.
Definition Metadata.h:1069
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1426
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.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
bool hasCalls() const
Return true if the current function has any function calls.
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
bool hasStackObjects() const
Return true if there are any stack objects in this function.
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
Representation of each machine instruction.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static MachineOperand CreateImm(int64_t Val)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI bool isLiveIn(Register Reg) const
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register getLiveInVirtReg(MCRegister PReg) const
getLiveInVirtReg - If PReg is a live-in physical register, return the corresponding live-in virtual r...
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
Align getAlign() const
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
bool isInvariant() const
EVT getMemoryVT() const
Return the type of the in-memory value.
bool onlyWritesMemory() const
Whether this function only (at most) writes memory.
Definition ModRef.h:252
bool doesNotAccessMemory() const
Whether this function accesses no memory.
Definition ModRef.h:246
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
Definition ModRef.h:249
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition Module.h:320
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:911
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
LLVM_ABI const PseudoSourceValue * getConstantPool()
Return a pseudo source value referencing the constant pool.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition Register.h:72
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool isDivergent() const
bool hasOneUse() const
Return true if there is exactly one use of this node.
value_iterator value_end() const
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
op_iterator op_end() const
bool isAnyAdd() const
Returns true if the node type is ADD or PTRADD.
value_iterator value_begin() const
op_iterator op_begin() const
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isUndef() const
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
bool isMachineOpcode() const
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getMachineOpcode() const
unsigned getOpcode() const
unsigned getNumOperands() const
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
AMDGPU::ClusterDimsAttr getClusterDims() const
SIModeRegisterDefaults getMode() const
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
const AMDGPUGWSResourcePseudoSourceValue * getGWSPSV(const AMDGPUTargetMachine &TM)
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static bool isVGPRClass(const TargetRegisterClass *RC)
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
bool isTypeDesirableForOp(unsigned Op, EVT VT) const override
Return true if the target has native support for the specified value type and it is 'desirable' to us...
SDNode * PostISelFolding(MachineSDNode *N, SelectionDAG &DAG) const override
Fold the instructions after selecting them.
SDValue splitTernaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachineSDNode * wrapAddr64Rsrc(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr) const
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool requiresUniformRegister(MachineFunction &MF, const Value *V) const override
Allows target to decide about the register class of the specific value that is live outside the defin...
bool isFMADLegal(const SelectionDAG &DAG, const SDNode *N) const override
Returns true if be combined with to form an ISD::FMAD.
AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
void bundleInstWithWaitcnt(MachineInstr &MI) const
Insert MI into a BUNDLE with an S_WAITCNT 0 immediately following it.
SDValue lowerROTR(SDValue Op, SelectionDAG &DAG) const
MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override
Return the type to use for a scalar shift opcode, given the shifted amount type.
SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
MVT getPointerTy(const DataLayout &DL, unsigned AS) const override
Map address space 7 to MVT::amdgpuBufferFatPointer because that's its in-memory representation.
bool denormalsEnabledForType(const SelectionDAG &DAG, EVT VT) const
void insertCopiesSplitCSR(MachineBasicBlock *Entry, const SmallVectorImpl< MachineBasicBlock * > &Exits) const override
Insert explicit copies in entry and exit blocks.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
SDNode * legalizeTargetIndependentNode(SDNode *Node, SelectionDAG &DAG) const
Legalize target independent instructions (e.g.
bool allowsMisalignedMemoryAccessesImpl(unsigned Size, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const
TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
SDValue lowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const
const GCNSubtarget * getSubtarget() const
bool enableAggressiveFMAFusion(EVT VT) const override
Return true if target always benefits from combining into FMA for a given value type.
bool shouldEmitGOTReloc(const GlobalValue *GV) const
void CollectTargetIntrinsicOperands(const CallInst &I, SmallVectorImpl< SDValue > &Ops, SelectionDAG &DAG) const override
SDValue splitUnaryVectorOp(SDValue Op, SelectionDAG &DAG) const
SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool isCanonicalized(SelectionDAG &DAG, SDValue Op, SDNodeFlags UserFlags={}, unsigned MaxDepth=5) const
void allocateSpecialInputSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocateLDSKernelId(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const
bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const override
void allocateHSAUserSGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent) const override
Return the register class that should be used for the specified value type.
void AddMemOpInit(MachineInstr &MI) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
bool isLegalGlobalAddressingMode(const AddrMode &AM) const
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
Align getPrefLoopAlignment(MachineLoop *ML) const override
Return the preferred loop alignment.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
void emitExpandAtomicStore(StoreInst *SI) const override
Perform a atomic store using a target-specific way.
AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
Align computeKnownAlignForTargetInstr(GISelValueTracking &Analysis, Register R, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine the known alignment for the pointer value R.
bool getAsmOperandConstVal(SDValue Op, uint64_t &Val) const
bool isShuffleMaskLegal(ArrayRef< int >, EVT) const override
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
void emitExpandAtomicLoad(LoadInst *LI) const override
Perform a atomic load using a target-specific way.
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const override
Determine known bits of a pointer to a known valid stack object.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
LLT getPreferredShiftAmountTy(LLT Ty) const override
Return the preferred type to use for a shift opcode, given the shifted amount type is ShiftValueTy.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const
bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const override
True if target has some particular form of dealing with pointer arithmetic semantics for pointers wit...
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &, const CallBase &, MachineFunction &MF, unsigned IntrinsicID) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const
void allocateSpecialInputVGPRsFixed(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments in fixed registers.
LoadInst * lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *AI) const override
On some platforms, an AtomicRMW that never actually modifies the value (such as fetch_add of 0) can b...
MachineBasicBlock * emitGWSMemViolTestLoop(MachineInstr &MI, MachineBasicBlock *BB) const
bool getAddrModeArguments(const IntrinsicInst *I, SmallVectorImpl< Value * > &Ops, Type *&AccessTy) const override
CodeGenPrepare sinks address calculations into the same BB as Load/Store instructions reading the add...
bool checkAsmConstraintValA(SDValue Op, uint64_t Val, unsigned MaxSize=64) const
bool shouldEmitFixup(const GlobalValue *GV) const
MachineBasicBlock * splitKillBlock(MachineInstr &MI, MachineBasicBlock *BB) const
void emitExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) const override
Perform a cmpxchg expansion using a target-specific method.
bool canTransformPtrArithOutOfBounds(const Function &F, EVT PtrVT) const override
True if the target allows transformations of in-bounds pointer arithmetic that cause out-of-bounds in...
bool hasMemSDNodeUser(SDNode *N) const
bool isSDNodeSourceOfDivergence(const SDNode *N, FunctionLoweringInfo *FLI, UniformityInfo *UA) const override
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
bool isEligibleForTailCallOptimization(SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SmallVectorImpl< ISD::InputArg > &Ins, SelectionDAG &DAG) const
bool isMemOpHasNoClobberedMemOperand(const SDNode *N) const
bool isLegalFlatAddressingMode(const AddrMode &AM, unsigned AddrSpace) const
SDValue LowerCallResult(SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals, bool isThisReturn, SDValue ThisVal) const
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode, EVT DestVT, EVT SrcVT) const override
Return true if an fpext operation input to an Opcode operation is free (for instance,...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
Assign the register class depending on the number of bits set in the writemask.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void allocateSpecialInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
Allocate implicit function VGPR arguments at the end of allocated user arguments.
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
static bool isNonGlobalAddrSpace(unsigned AS)
void emitExpandAtomicAddrSpacePredicate(Instruction *AI) const
MachineSDNode * buildRSRC(SelectionDAG &DAG, const SDLoc &DL, SDValue Ptr, uint32_t RsrcDword1, uint64_t RsrcDword2And3) const
Return a resource descriptor with the 'Add TID' bit enabled The TID (Thread ID) is multiplied by the ...
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain targets require unusual breakdowns of certain types.
bool mayBeEmittedAsTailCall(const CallInst *) const override
Return true if the target may be able emit the call instruction as a tail call.
void passSpecialInputs(CallLoweringInfo &CLI, CCState &CCInfo, const SIMachineFunctionInfo &Info, SmallVectorImpl< std::pair< unsigned, SDValue > > &RegsToPass, SmallVectorImpl< SDValue > &MemOpChains, SDValue Chain) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool checkAsmConstraintVal(SDValue Op, StringRef Constraint, uint64_t Val) const
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN=false, unsigned Depth=0) const override
If SNaN is false,.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
static bool shouldExpandVectorDynExt(unsigned EltSize, unsigned NumElem, bool IsDivergentIdx, const GCNSubtarget *Subtarget)
Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be expanded into a set of cmp...
bool shouldUseLDSConstAddress(const GlobalValue *GV) const
bool supportSplitCSR(MachineFunction *MF) const override
Return true if the target supports that a subset of CSRs for the given machine function is handled ex...
bool isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
bool allowsMisalignedMemoryAccesses(LLT Ty, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *IsFast=nullptr) const override
LLT handling variant.
bool canMergeStoresTo(unsigned AS, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const
SITargetLowering(const TargetMachine &tm, const GCNSubtarget &STI)
void computeKnownBitsForTargetInstr(GISelValueTracking &Analysis, Register R, KnownBits &Known, const APInt &DemandedElts, const MachineRegisterInfo &MRI, unsigned Depth=0) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool isFreeAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override
Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g.
bool shouldEmitPCReloc(const GlobalValue *GV) const
AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
void initializeSplitCSR(MachineBasicBlock *Entry) const override
Perform necessary initialization to handle a subset of CSRs explicitly via copies.
void allocateSpecialEntryInputVGPRs(CCState &CCInfo, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
void allocatePreloadKernArgSGPRs(CCState &CCInfo, SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< ISD::InputArg > &Ins, MachineFunction &MF, const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const
SDValue copyToM0(SelectionDAG &DAG, SDValue Chain, const SDLoc &DL, SDValue V) const
SDValue splitBinaryVectorOp(SDValue Op, SelectionDAG &DAG) const
MachinePointerInfo getKernargSegmentPtrInfo(MachineFunction &MF) const
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
MVT getPointerMemTy(const DataLayout &DL, unsigned AS) const override
Similarly, the in-memory representation of a p7 is {p8, i32}, aka v8i32 when padding is added.
void allocateSystemSGPRs(CCState &CCInfo, MachineFunction &MF, SIMachineFunctionInfo &Info, CallingConv::ID CallConv, bool IsShader) const
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const override
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT, unsigned Opcode)
Convert Op, which must be of integer type, to the integer type VT, by either any/sign/zero-extending ...
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
LLVM_ABI SDValue getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS)
Return an AddrSpaceCastSDNode.
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 getRegister(Register Reg, EVT VT)
LLVM_ABI bool SignBitIsZeroFP(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero, for a floating-point value.
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO)
Gets a node for an atomic op, produces result (if relevant) and chain and takes 2 operands.
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by first bitcasting (from potentia...
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
const TargetMachine & getTarget() const
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getErrorMergeValues(ArrayRef< EVT > ResultTypes, SDValue Chain, const SDLoc &dl)
Return poison values for each of ResultTypes, substituting Chain for any result of type MVT::Other,...
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
const SDValue & setRoot(SDValue N)
Set the current root tag of the SelectionDAG.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
int getMaskElt(unsigned Idx) const
ArrayRef< int > getMask() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition SmallSet.h:176
bool empty() const
Definition SmallSet.h:169
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Information about stack frame layout on the target.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
TargetInstrInfo - Interface to description of machine instruction set.
Type * Ty
Same as OrigTy, or partially legalized for soft float libcalls.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual unsigned getMaxPermittedBytesForAlignment(MachineBasicBlock *MBB) const
Return the maximum amount of bytes allowed to be emitted when padding for alignment.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setHasExtractBitsInsn(bool hasExtractInsn=true)
Tells the code generator that the target has BitExtract instructions.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
virtual Align getPrefLoopAlignment(MachineLoop *ML=nullptr) const
Return the preferred loop alignment.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS=0) const
Return the in-memory pointer type for the given address space, defaults to the pointer type from the ...
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
SDValue scalarizeVectorStore(StoreSDNode *ST, SelectionDAG &DAG) const
std::vector< AsmOperandInfo > AsmOperandInfoVector
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminimumnum/fmaximumnum into multiple comparison with selects.
virtual bool isTypeDesirableForOp(unsigned, EVT VT) const
Return true if the target has native support for the specified value type and it is 'desirable' to us...
virtual void computeKnownBitsForStackObjectPointer(KnownBits &Known, const MachineFunction &MF, Align Alignment) const
Determine known bits of a pointer to a known valid stack object.
std::pair< SDValue, SDValue > scalarizeVectorLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Turn load of vector type into a load of the individual elements.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
TargetLowering(const TargetLowering &)=delete
virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
virtual AsmOperandInfoVector ParseConstraints(const DataLayout &DL, const TargetRegisterInfo *TRI, const CallBase &Call) const
Split up the constraint string from the inline assembly value into the specific constraints and their...
SDValue expandRoundInexactToOdd(EVT ResultVT, SDValue Op, const SDLoc &DL, SelectionDAG &DAG) const
Truncate Op to ResultVT.
virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, SelectionDAG *DAG=nullptr) const
Determines the constraint code and constraint type to use for the specific AsmOperandInfo,...
SDValue annotateStackObjectPointer(SDValue Ptr, SelectionDAG &DAG, const SDLoc &DL, Align Alignment) const
Annotate a stack object pointer with known-bits assertions.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
SDValue expandFMINNUM_FMAXNUM(SDNode *N, SelectionDAG &DAG) const
Expand fminnum/fmaxnum into fminnum_ieee/fmaxnum_ieee with quieted inputs.
Primary interface to the complete machine description for the target machine.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
const Triple & getTargetTriple() const
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
TargetOptions Options
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
OSType getOS() const
Get the parsed operating system type of this triple.
Definition Triple.h:521
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:343
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:309
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:368
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:273
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
LLVM_ABI const fltSemantics & getFltSemantics() const
Definition Type.cpp:106
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:36
LLVM_ABI void set(Value *Val)
Definition Value.h:874
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:255
bool hasOneUse() const
Return true if there is exactly one use of this value.
Definition Value.h:439
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
iterator_range< user_iterator > users()
Definition Value.h:426
bool use_empty() const
Definition Value.h:346
iterator_range< use_iterator > uses()
Definition Value.h:380
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:400
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
Definition TypeSize.h:176
self_iterator getIterator()
Definition ilist_node.h:123
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ STREAMOUT_REGISTER
Internal address spaces. Can be freely renumbered.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char NumVGPRs[]
Key for Kernel::CodeProps::Metadata::mNumVGPRs.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
LLVM_READONLY const MIMGG16MappingInfo * getMIMGG16MappingInfo(unsigned G)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords)
LLVM_READNONE constexpr bool isShader(CallingConv::ID CC)
bool shouldEmitConstantsToTextSection(const Triple &TT)
bool isFlatGlobalAddrSpace(unsigned AS)
const uint64_t FltRoundToHWConversionTable
bool isGFX12Plus(const MCSubtargetInfo &STI)
unsigned getNSAMaxSize(const MCSubtargetInfo &STI, bool HasSampler)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isGFX11(const MCSubtargetInfo &STI)
bool isGFX13(const MCSubtargetInfo &STI)
bool hasValueInRangeLikeMetadata(const MDNode &MD, int64_t Val)
Checks if Val is inside MD, a !range-like metadata.
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READNONE constexpr bool mayTailCallThisCC(CallingConv::ID CC)
Return true if we might ever do TCO for calls with this calling convention.
unsigned getAMDHSACodeObjectVersion(const Module &M)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool getMUBUFTfe(unsigned Opc)
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
LLVM_READONLY int32_t getVOPe64(uint32_t Opcode)
bool isGFX11Plus(const MCSubtargetInfo &STI)
std::optional< unsigned > getInlineEncodingV2F16(uint32_t Literal)
std::tuple< char, unsigned, unsigned > parseAsmConstraintPhysReg(StringRef Constraint)
Returns a valid charcode or 0 in the first entry if this is a valid physical register constraint.
bool isGFX10Plus(const MCSubtargetInfo &STI)
bool isValidWMMAScaleFmtCombination(unsigned AFmt, unsigned AScale, unsigned BFmt, unsigned BScale)
bool isUniformMMO(const MachineMemOperand *MMO)
std::optional< unsigned > getInlineEncodingV2I16(uint32_t Literal)
uint32_t decodeFltRoundToHWConversionTable(uint32_t FltRounds)
Read the hardware rounding mode equivalent of a AMDGPUFltRounds value.
bool isExtendedGlobalAddrSpace(unsigned AS)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
std::optional< unsigned > getInlineEncodingV2BF16(uint32_t Literal)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
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:829
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:261
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
Definition ISDOpcodes.h:45
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:236
@ SET_FPENV
Sets the current floating-point environment.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:275
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:602
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:789
@ 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:524
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:863
@ ATOMIC_LOAD_USUB_COND
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:520
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition ISDOpcodes.h:220
@ GlobalAddress
Definition ISDOpcodes.h:88
@ ATOMIC_CMP_SWAP_WITH_SUCCESS
Val, Success, OUTCHAIN = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) N.b.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:890
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:586
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:417
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:749
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition ISDOpcodes.h:254
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ ATOMIC_LOAD_USUB_SAT
@ CTLZ_ZERO_POISON
Definition ISDOpcodes.h:798
@ SET_ROUNDING
Set rounding mode.
Definition ISDOpcodes.h:985
@ CONVERGENCECTRL_GLUE
This does not correspond to any convergence control intrinsic.
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:667
@ 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:352
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:543
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
Definition ISDOpcodes.h:550
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:374
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:806
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
Definition ISDOpcodes.h:247
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
Definition ISDOpcodes.h:230
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:348
@ CTLS
Count leading redundant sign bits.
Definition ISDOpcodes.h:802
@ 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:980
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:706
@ 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:771
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:651
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:616
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:578
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition ISDOpcodes.h:224
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ 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:821
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:356
@ 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:898
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:729
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:988
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:815
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:328
@ 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:502
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:936
@ 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:507
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:567
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
Definition ISDOpcodes.h:797
@ ExternalSymbol
Definition ISDOpcodes.h:93
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:969
@ SPONENTRY
SPONENTRY - Represents the llvm.sponentry intrinsic.
Definition ISDOpcodes.h:122
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
Definition ISDOpcodes.h:955
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:866
@ 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:843
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ ATOMIC_LOAD_UINC_WRAP
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:536
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:365
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:213
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:558
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 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.
auto m_Value()
Match an arbitrary value and ignore it.
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(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
Offsets
Offsets in bytes from the start of the input buffer.
@ System
Synchronized with respect to all concurrently executing threads.
Definition LLVMContext.h:58
initializer< Ty > init(const Ty &Val)
constexpr double inv_pi
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Offset
Definition DWP.cpp:578
LLVM_ABI ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred)
getICmpCondCode - Return the ISD condition code corresponding to the given LLVM IR integer condition ...
Definition Analysis.cpp:237
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:1739
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:840
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.
LLVM_ABI std::pair< Value *, Value * > buildCmpXchgValue(IRBuilderBase &Builder, Value *Ptr, Value *Cmp, Value *Val, Align Alignment)
Emit IR to implement the given cmpxchg operation on values in registers, returning the new value.
@ Known
Known to have no common set bits.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Done
Definition Threading.h:60
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
Definition MathExtras.h:224
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:325
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
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:547
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
Definition ModRef.h:356
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
Definition MathExtras.h:386
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
bool isReleaseOrStronger(AtomicOrdering AO)
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
Definition MathExtras.h:358
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
Definition SIInstrInfo.h:46
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
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:332
AtomicOrderingCABI
Atomic ordering for C11 / C++11's memory models.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition bit.h:263
bool isBoolSGPR(SDValue V)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
LLVM_ABI ISD::CondCode getFCmpCondCode(FCmpInst::Predicate Pred)
getFCmpCondCode - Return the ISD condition code corresponding to the given LLVM IR floating-point con...
Definition Analysis.cpp:203
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
Definition SIInstrInfo.h:54
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI Value * buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Val)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:395
@ 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
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ NearestTiesToEven
roundTiesToEven.
unsigned M0(unsigned Val)
Definition VE.h:376
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
Definition MathExtras.h:233
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI std::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:1772
std::optional< StringRef > getAtomicScopeIRString(const Triple &T, AtomicScope S, bool IsSingleAddressSpace=false)
Returns the LLVM IR syncscope string that T uses to spell S.
Definition AtomicScope.h:34
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:50
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:201
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
constexpr RegState getUndefRegState(bool B)
@ Custom
The result value requires a custom uniformity check.
Definition Uniformity.h:31
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
int64_t DWordOffset
int64_t PermMask
std::tuple< const ArgDescriptor *, const TargetRegisterClass *, LLT > getPreloadedValue(PreloadedValue Value) const
static const AMDGPUFunctionArgInfo FixedABIFunctionInfo
static constexpr uint64_t encode(Fields... Values)
static std::tuple< typename Fields::ValueType... > decode(uint64_t Encoded)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
static ArgDescriptor createStack(unsigned Offset, unsigned Mask=~0u)
MCRegister getRegister() const
static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask)
static ArgDescriptor createRegister(Register Reg, unsigned Mask=~0u)
Helper struct shared between Function Specialization and SCCP Solver.
Definition SCCPSolver.h:42
Represents the full denormal controls for a function, including the default mode and the f32 specific...
Represent subnormal handling kind for floating point instruction inputs and outputs.
@ Dynamic
Denormals have unknown treatment.
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
Extended Value Type.
Definition ValueTypes.h:35
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition ValueTypes.h:418
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:145
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:70
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
Definition ValueTypes.h:129
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
Definition ValueTypes.h:323
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:155
ElementCount getVectorElementCount() const
Definition ValueTypes.h:373
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:266
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:501
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
Definition ValueTypes.h:435
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition ValueTypes.h:61
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
Definition ValueTypes.h:404
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:346
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
Definition ValueTypes.h:279
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
Definition ValueTypes.h:121
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
Definition ValueTypes.h:181
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
Definition ValueTypes.h:165
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
unsigned getPointerAddrSpace() const
unsigned getByValSize() const
Align getNonZeroMemAlign() const
InputArg - This struct carries flags and type information about a single incoming (formal) argument o...
MVT VT
Legalized type of this argument part.
unsigned getOrigArgIndex() const
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
static LLVM_ABI std::optional< bool > eq(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_EQ result.
bool isUnknown() const
Returns true if we don't know any bits.
Definition KnownBits.h:64
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
Definition KnownBits.h:165
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
Definition KnownBits.h:361
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
Definition KnownBits.h:262
static LLVM_ABI std::optional< bool > ule(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_ULE result.
static LLVM_ABI std::optional< bool > uge(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_UGE result.
bool isKnownNeverNaN() const
Return true if it's known this can never be a nan.
static LLVM_ABI KnownFPClass bitcast(const fltSemantics &FltSemantics, const KnownBits &Bits)
Report known values for a bitcast into a float with provided semantics.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoUnsignedWrap() const
bool hasAllowContract() const
bool hasNoSignedWrap() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
unsigned int NumVTs
DenormalMode FP64FP16Denormals
If this is set, neither input or output denormals are flushed for both f64 and f16/v2f16 instructions...
DenormalMode FP32Denormals
If this is set, neither input or output denormals are flushed for most f32 instructions.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
std::optional< unsigned > fallbackAddressSpace
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs