LLVM 24.0.0git
AMDGPUInstCombineIntrinsic.cpp
Go to the documentation of this file.
1//===- AMDGPInstCombineIntrinsic.cpp - AMDGPU specific InstCombine pass ---===//
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// This file implements a TargetTransformInfo analysis pass specific to the
11// AMDGPU target machine. It uses the target's detailed information to provide
12// more precise answers to certain TTI queries, while letting the target
13// independent and default TTI implementations handle the rest.
14//
15//===----------------------------------------------------------------------===//
16
17#include "AMDGPUInstrInfo.h"
19#include "GCNSubtarget.h"
20#include "SIDefines.h"
22#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/Sequence.h"
26#include "llvm/IR/Constants.h"
27#include "llvm/IR/Dominators.h"
28#include "llvm/IR/IntrinsicsAMDGPU.h"
31#include <optional>
32
33using namespace llvm;
34using namespace llvm::PatternMatch;
35
36#define DEBUG_TYPE "AMDGPUtti"
37
38namespace {
39
40struct AMDGPUImageDMaskIntrinsic {
41 unsigned Intr;
42};
43
44#define GET_AMDGPUImageDMaskIntrinsicTable_IMPL
45#include "AMDGPUGenSearchableTables.inc"
46
47} // end anonymous namespace
48
49// Constant fold llvm.amdgcn.fmed3 intrinsics for standard inputs.
50//
51// A single NaN input is folded to minnum, so we rely on that folding for
52// handling NaNs.
53static APFloat fmed3AMDGCN(const APFloat &Src0, const APFloat &Src1,
54 const APFloat &Src2) {
55 assert(!Src0.isNaN() && !Src1.isNaN() && !Src2.isNaN() &&
56 "nans handled separately");
57 APFloat Max3 = maxnum(maxnum(Src0, Src1), Src2);
58
59 if (Max3.bitwiseIsEqual(Src0))
60 return maxnum(Src1, Src2);
61
62 if (Max3.bitwiseIsEqual(Src1))
63 return maxnum(Src0, Src2);
64
65 return maxnum(Src0, Src1);
66}
67
68// Check if a value can be converted to a 16-bit value without losing precision.
69// The value is expected to be either a float (IsFloat = true) or an unsigned
70// integer (IsFloat = false). When AllowI16SExt is set, a sext from i16 is also
71// accepted: for unsigned addresses sext and zext only differ for a negative
72// i16, which is out of bounds anyway (see caller).
73static bool canSafelyConvertTo16Bit(Value &V, bool IsFloat,
74 bool AllowI16SExt = false) {
75 Type *VTy = V.getType();
76 if (VTy->isHalfTy() || VTy->isIntegerTy(16)) {
77 // The value is already 16-bit, so we don't want to convert to 16-bit again!
78 return false;
79 }
80 if (IsFloat) {
81 if (ConstantFP *ConstFloat = dyn_cast<ConstantFP>(&V)) {
82 // We need to check that if we cast the index down to a half, we do not
83 // lose precision.
84 APFloat FloatValue(ConstFloat->getValueAPF());
85 bool LosesInfo = true;
87 &LosesInfo);
88 return !LosesInfo;
89 }
90 } else {
91 if (ConstantInt *ConstInt = dyn_cast<ConstantInt>(&V)) {
92 // We need to check that if we cast the index down to an i16, we do not
93 // lose precision.
94 APInt IntValue(ConstInt->getValue());
95 return IntValue.getActiveBits() <= 16;
96 }
97 }
98
99 // Coordinates may arrive as extractelement((s|z|fp)ext Vec), Idx. The
100 // widening cast has one use per lane, so it is never sunk into the extract;
101 // strip the extract here so the cast check below is common to scalar and
102 // vector coords.
103 Value *CastCandidate;
104 if (!match(&V, m_ExtractElt(m_Value(CastCandidate), m_Value())))
105 CastCandidate = &V;
106
107 Value *CastSrc;
108 bool IsExt = IsFloat ? match(CastCandidate, m_FPExt(m_Value(CastSrc)))
109 : match(CastCandidate, m_ZExt(m_Value(CastSrc)));
110 if (!IsExt && !IsFloat && AllowI16SExt)
111 IsExt = match(CastCandidate, m_SExt(m_Value(CastSrc)));
112 if (IsExt) {
113 Type *CastSrcTy = CastSrc->getType()->getScalarType();
114 if (CastSrcTy->isHalfTy() || CastSrcTy->isIntegerTy(16))
115 return true;
116 }
117
118 return false;
119}
120
121// Convert a value to 16-bit.
123 Type *VTy = V.getType();
125 return cast<Instruction>(&V)->getOperand(0);
126 // Vector form: extractelement((s|z|fp)ext Vec), Idx -> extractelement(Vec,
127 // Idx), taking the narrow lane directly so the widening cast can be removed.
128 Instruction *VecCast;
129 Value *Idx;
130 if (match(&V, m_ExtractElt(m_Instruction(VecCast), m_Value(Idx))) &&
132 return Builder.CreateExtractElement(VecCast->getOperand(0), Idx);
133 if (VTy->isIntegerTy())
134 return Builder.CreateIntCast(&V, Type::getInt16Ty(V.getContext()), false);
135 if (VTy->isFloatingPointTy())
136 return Builder.CreateFPCast(&V, Type::getHalfTy(V.getContext()));
137
138 llvm_unreachable("Should never be called!");
139}
140
141/// Applies Func(OldIntr.Args, OldIntr.ArgTys), creates intrinsic call with
142/// modified arguments (based on OldIntr) and replaces InstToReplace with
143/// this newly created intrinsic call.
144static std::optional<Instruction *> modifyIntrinsicCall(
145 IntrinsicInst &OldIntr, Instruction &InstToReplace, unsigned NewIntr,
146 InstCombiner &IC,
147 std::function<void(SmallVectorImpl<Value *> &, SmallVectorImpl<Type *> &)>
148 Func) {
149 SmallVector<Type *, 4> OverloadTys;
150 if (!Intrinsic::isSignatureValid(OldIntr.getCalledFunction(), OverloadTys))
151 return std::nullopt;
152
153 SmallVector<Value *, 8> Args(OldIntr.args());
154
155 // Modify arguments and types
156 Func(Args, OverloadTys);
157
158 CallInst *NewCall =
159 IC.Builder.CreateIntrinsicWithoutFolding(NewIntr, OverloadTys, Args);
160 NewCall->takeName(&OldIntr);
161 NewCall->copyMetadata(OldIntr);
162 if (isa<FPMathOperator>(NewCall))
163 NewCall->copyFastMathFlags(&OldIntr);
164 // Copy attributes
165 AttributeList OldAttrList = OldIntr.getAttributes();
166 NewCall->setAttributes(OldAttrList);
167
168 // Erase and replace uses
169 if (!InstToReplace.getType()->isVoidTy())
170 IC.replaceInstUsesWith(InstToReplace, NewCall);
171
172 bool RemoveOldIntr = &OldIntr != &InstToReplace;
173
174 auto *RetValue = IC.eraseInstFromFunction(InstToReplace);
175 if (RemoveOldIntr)
176 IC.eraseInstFromFunction(OldIntr);
177
178 return RetValue;
179}
180
181static std::optional<Instruction *>
183 const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr,
185 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
187
188 // Optimize _L to _LZ when _L is zero
189 if (const auto *LZMappingInfo =
191 if (auto *ConstantLod =
192 dyn_cast<ConstantFP>(II.getOperand(ImageDimIntr->LodIndex))) {
193 if (ConstantLod->isZero() || ConstantLod->isNegative()) {
194 const AMDGPU::ImageDimIntrinsicInfo *NewImageDimIntr =
196 ImageDimIntr->Dim);
197 return modifyIntrinsicCall(
198 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {
199 Args.erase(Args.begin() + ImageDimIntr->LodIndex);
200 });
201 }
202 }
203 }
204
205 // Optimize _mip away, when 'lod' is zero
206 if (const auto *MIPMappingInfo =
208 if (auto *ConstantMip =
209 dyn_cast<ConstantInt>(II.getOperand(ImageDimIntr->MipIndex))) {
210 if (ConstantMip->isZero()) {
211 const AMDGPU::ImageDimIntrinsicInfo *NewImageDimIntr =
212 AMDGPU::getImageDimIntrinsicByBaseOpcode(MIPMappingInfo->NONMIP,
213 ImageDimIntr->Dim);
214 return modifyIntrinsicCall(
215 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {
216 Args.erase(Args.begin() + ImageDimIntr->MipIndex);
217 });
218 }
219 }
220 }
221
222 // Optimize _bias away when 'bias' is zero
223 if (const auto *BiasMappingInfo =
225 if (auto *ConstantBias =
226 dyn_cast<ConstantFP>(II.getOperand(ImageDimIntr->BiasIndex))) {
227 if (ConstantBias->isZero()) {
228 const AMDGPU::ImageDimIntrinsicInfo *NewImageDimIntr =
229 AMDGPU::getImageDimIntrinsicByBaseOpcode(BiasMappingInfo->NoBias,
230 ImageDimIntr->Dim);
231 return modifyIntrinsicCall(
232 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {
233 Args.erase(Args.begin() + ImageDimIntr->BiasIndex);
234 ArgTys.erase(ArgTys.begin() + ImageDimIntr->BiasTyArg);
235 });
236 }
237 }
238 }
239
240 // Optimize _offset away when 'offset' is zero
241 if (const auto *OffsetMappingInfo =
243 if (auto *ConstantOffset =
244 dyn_cast<ConstantInt>(II.getOperand(ImageDimIntr->OffsetIndex))) {
245 if (ConstantOffset->isZero()) {
246 const AMDGPU::ImageDimIntrinsicInfo *NewImageDimIntr =
248 OffsetMappingInfo->NoOffset, ImageDimIntr->Dim);
249 return modifyIntrinsicCall(
250 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {
251 Args.erase(Args.begin() + ImageDimIntr->OffsetIndex);
252 });
253 }
254 }
255 }
256
257 // Optimize the arrayed dim away when the array slice is zero, since slice 0
258 // is the base layer. Restricted to non-atomic, non-sampled image loads and
259 // stores for now.
260 const AMDGPU::MIMGDimInfo *DimInfo =
261 AMDGPU::getMIMGDimInfo(ImageDimIntr->Dim);
262 if (!BaseOpcode->Atomic && !BaseOpcode->Sampler && BaseOpcode->Coordinates &&
263 DimInfo->NonArrayDim != ImageDimIntr->Dim) {
264 // Address is [coords..., slice, (fragid)] plus an optional mip operand.
265 // The slice is the last coordinate, so index it from CoordStart.
266 unsigned SliceIndex = ImageDimIntr->CoordStart + DimInfo->NumCoords - 1 -
267 (DimInfo->MSAA ? 1 : 0);
268 auto *ConstantSlice = dyn_cast<ConstantInt>(II.getOperand(SliceIndex));
269 if (ConstantSlice && ConstantSlice->isZero()) {
270 if (const AMDGPU::ImageDimIntrinsicInfo *NewImageDimIntr =
272 DimInfo->NonArrayDim)) {
273 return modifyIntrinsicCall(II, II, NewImageDimIntr->Intr, IC,
274 [&](auto &Args, auto &ArgTys) {
275 Args.erase(Args.begin() + SliceIndex);
276 });
277 }
278 }
279 }
280
281 // Try to use D16
282 if (ST->hasD16Images()) {
283 if (BaseOpcode->HasD16) {
284
285 // If the only use of image intrinsic is a fptrunc (with conversion to
286 // half) then both fptrunc and image intrinsic will be replaced with image
287 // intrinsic with D16 flag.
288 if (II.hasOneUse()) {
289 Instruction *User = II.user_back();
290
291 if (User->getOpcode() == Instruction::FPTrunc &&
293
294 return modifyIntrinsicCall(II, *User, ImageDimIntr->Intr, IC,
295 [&](auto &Args, auto &ArgTys) {
296 // Change return type of image intrinsic.
297 // Set it to return type of fptrunc.
298 ArgTys[0] = User->getType();
299 });
300 }
301 }
302
303 // Only perform D16 folding if every user of the image sample is
304 // an ExtractElementInst immediately followed by an FPTrunc to half.
306 ExtractTruncPairs;
307 bool AllHalfExtracts = true;
308
309 for (User *U : II.users()) {
310 auto *Ext = dyn_cast<ExtractElementInst>(U);
311 if (!Ext || !Ext->hasOneUse()) {
312 AllHalfExtracts = false;
313 break;
314 }
315
316 auto *Tr = dyn_cast<FPTruncInst>(*Ext->user_begin());
317 if (!Tr || !Tr->getType()->isHalfTy()) {
318 AllHalfExtracts = false;
319 break;
320 }
321
322 ExtractTruncPairs.emplace_back(Ext, Tr);
323 }
324
325 if (!ExtractTruncPairs.empty() && AllHalfExtracts) {
326 auto *VecTy = cast<VectorType>(II.getType());
327 Type *HalfVecTy =
328 VecTy->getWithNewType(Type::getHalfTy(II.getContext()));
329
330 // Obtain the original image sample intrinsic's signature
331 // and replace its return type with the half-vector for D16 folding
332 SmallVector<Type *, 8> OverloadTys;
333 if (!Intrinsic::isSignatureValid(II.getCalledFunction(), OverloadTys))
334 return std::nullopt;
335
336 OverloadTys[0] = HalfVecTy;
337 Module *M = II.getModule();
339 M, ImageDimIntr->Intr, OverloadTys);
340
341 II.mutateType(HalfVecTy);
342 II.setCalledFunction(HalfDecl);
343
344 IRBuilder<> Builder(II.getContext());
345 for (auto &[Ext, Tr] : ExtractTruncPairs) {
346 Value *Idx = Ext->getIndexOperand();
347
348 Builder.SetInsertPoint(Tr);
349
350 Value *HalfExtract = Builder.CreateExtractElement(&II, Idx);
351 HalfExtract->takeName(Tr);
352
353 Tr->replaceAllUsesWith(HalfExtract);
354 }
355
356 for (auto &[Ext, Tr] : ExtractTruncPairs) {
357 IC.eraseInstFromFunction(*Tr);
358 IC.eraseInstFromFunction(*Ext);
359 }
360
361 return &II;
362 }
363 }
364 }
365
366 // Try to use A16 or G16
367 if (!ST->hasA16() && !ST->hasG16())
368 return std::nullopt;
369
370 // Address is interpreted as float if the instruction has a sampler or as
371 // unsigned int if there is no sampler.
372 bool HasSampler = BaseOpcode->Sampler;
373 bool FloatCoord = false;
374 // true means derivatives can be converted to 16 bit, coordinates not
375 bool OnlyDerivatives = false;
376
377 // Sampler-less addresses are unsigned, so a sext from i16 folds to a16 like a
378 // zext: they only disagree for a negative i16 (>= 0x8000), which is out of
379 // bounds while the max image dimension is <= 0x8000.
380 bool AllowI16SExt = !HasSampler;
381
382 for (unsigned OperandIndex = ImageDimIntr->GradientStart;
383 OperandIndex < ImageDimIntr->VAddrEnd; OperandIndex++) {
384 Value *Coord = II.getOperand(OperandIndex);
385 // If the values are not derived from 16-bit values, we cannot optimize.
386 if (!canSafelyConvertTo16Bit(*Coord, HasSampler, AllowI16SExt)) {
387 if (OperandIndex < ImageDimIntr->CoordStart ||
388 ImageDimIntr->GradientStart == ImageDimIntr->CoordStart) {
389 return std::nullopt;
390 }
391 // All gradients can be converted, so convert only them
392 OnlyDerivatives = true;
393 break;
394 }
395
396 assert(OperandIndex == ImageDimIntr->GradientStart ||
397 FloatCoord == Coord->getType()->isFloatingPointTy());
398 FloatCoord = Coord->getType()->isFloatingPointTy();
399 }
400
401 if (!OnlyDerivatives && !ST->hasA16())
402 OnlyDerivatives = true; // Only supports G16
403
404 // Check if there is a bias parameter and if it can be converted to f16
405 if (!OnlyDerivatives && ImageDimIntr->NumBiasArgs != 0) {
406 Value *Bias = II.getOperand(ImageDimIntr->BiasIndex);
407 assert(HasSampler &&
408 "Only image instructions with a sampler can have a bias");
409 if (!canSafelyConvertTo16Bit(*Bias, HasSampler))
410 OnlyDerivatives = true;
411 }
412
413 if (OnlyDerivatives && (!ST->hasG16() || ImageDimIntr->GradientStart ==
414 ImageDimIntr->CoordStart))
415 return std::nullopt;
416
417 Type *CoordType = FloatCoord ? Type::getHalfTy(II.getContext())
418 : Type::getInt16Ty(II.getContext());
419
420 return modifyIntrinsicCall(
421 II, II, II.getIntrinsicID(), IC, [&](auto &Args, auto &ArgTys) {
422 ArgTys[ImageDimIntr->GradientTyArg] = CoordType;
423 if (!OnlyDerivatives) {
424 ArgTys[ImageDimIntr->CoordTyArg] = CoordType;
425
426 // Change the bias type
427 if (ImageDimIntr->NumBiasArgs != 0)
428 ArgTys[ImageDimIntr->BiasTyArg] = Type::getHalfTy(II.getContext());
429 }
430
431 unsigned EndIndex =
432 OnlyDerivatives ? ImageDimIntr->CoordStart : ImageDimIntr->VAddrEnd;
433 for (unsigned OperandIndex = ImageDimIntr->GradientStart;
434 OperandIndex < EndIndex; OperandIndex++) {
435 Args[OperandIndex] =
436 convertTo16Bit(*II.getOperand(OperandIndex), IC.Builder);
437 }
438
439 // Convert the bias
440 if (!OnlyDerivatives && ImageDimIntr->NumBiasArgs != 0) {
441 Value *Bias = II.getOperand(ImageDimIntr->BiasIndex);
442 Args[ImageDimIntr->BiasIndex] = convertTo16Bit(*Bias, IC.Builder);
443 }
444 });
445}
446
448 const Value *Op0, const Value *Op1,
449 InstCombiner &IC) const {
450 // The legacy behaviour is that multiplying +/-0.0 by anything, even NaN or
451 // infinity, gives +0.0. If we can prove we don't have one of the special
452 // cases then we can use a normal multiply instead.
454 KnownFPClass Known0 =
456 DenormalMode Mode = I.getFunction()->getDenormalMode(APFloat::IEEEsingle());
457
458 // Bail early if Op0 may be zero and nsz is not set -- Op1 cannot help.
459 if (!Known0.isKnownNeverLogicalZero(Mode) && !I.hasNoSignedZeros())
460 return false;
461
462 KnownFPClass Known1 =
464
465 // Simplify if both operands are known non-zero.
466 if (Known0.isKnownNeverLogicalZero(Mode) &&
467 Known1.isKnownNeverLogicalZero(Mode))
468 return true;
469
470 // With nsz, two additional cases allow simplification:
471 // 1. One operand is not zero or infinity or NaN:
472 // Op0 NeverLogicalZero && NeverInfOrNaN, or symmetric for Op1.
473 // 2. Neither operand is infinity or NaN:
474 // Op0 NeverInfOrNaN && Op1 NeverInfOrNaN.
475 // The following condition captures both cases.
476 if (I.hasNoSignedZeros() &&
477 (Known0.isKnownNeverLogicalZero(Mode) || Known1.isKnownNeverInfOrNaN()) &&
478 (Known1.isKnownNeverLogicalZero(Mode) || Known0.isKnownNeverInfOrNaN()))
479 return true;
480
481 return false;
482}
483
484/// Match an fpext from half to float, or a constant we can convert.
486 Value *Src = nullptr;
487 ConstantFP *CFP = nullptr;
488 if (match(Arg, m_OneUse(m_FPExt(m_Value(Src))))) {
489 if (Src->getType()->isHalfTy())
490 return Src;
491 } else if (match(Arg, m_ConstantFP(CFP))) {
492 bool LosesInfo;
493 APFloat Val(CFP->getValueAPF());
495 if (!LosesInfo)
496 return ConstantFP::get(Type::getHalfTy(Arg->getContext()), Val);
497 }
498 return nullptr;
499}
500
501// Trim all zero components from the end of the vector \p UseV and return
502// an appropriate bitset with known elements.
504 Instruction *I) {
505 auto *VTy = cast<FixedVectorType>(UseV->getType());
506 unsigned VWidth = VTy->getNumElements();
507 APInt DemandedElts = APInt::getAllOnes(VWidth);
508
509 for (int i = VWidth - 1; i > 0; --i) {
510 auto *Elt = findScalarElement(UseV, i);
511 if (!Elt)
512 break;
513
514 if (auto *ConstElt = dyn_cast<Constant>(Elt)) {
515 if (!ConstElt->isNullValue() && !isa<UndefValue>(Elt))
516 break;
517 } else {
518 break;
519 }
520
521 DemandedElts.clearBit(i);
522 }
523
524 return DemandedElts;
525}
526
527// Trim elements of the end of the vector \p V, if they are
528// equal to the first element of the vector.
530 auto *VTy = cast<FixedVectorType>(V->getType());
531 unsigned VWidth = VTy->getNumElements();
532 APInt DemandedElts = APInt::getAllOnes(VWidth);
533 Value *FirstComponent = findScalarElement(V, 0);
534
535 SmallVector<int> ShuffleMask;
536 if (auto *SVI = dyn_cast<ShuffleVectorInst>(V))
537 SVI->getShuffleMask(ShuffleMask);
538
539 for (int I = VWidth - 1; I > 0; --I) {
540 if (ShuffleMask.empty()) {
541 auto *Elt = findScalarElement(V, I);
542 if (!Elt || (Elt != FirstComponent && !isa<UndefValue>(Elt)))
543 break;
544 } else {
545 // Detect identical elements in the shufflevector result, even though
546 // findScalarElement cannot tell us what that element is.
547 if (ShuffleMask[I] != ShuffleMask[0] && ShuffleMask[I] != PoisonMaskElem)
548 break;
549 }
550 DemandedElts.clearBit(I);
551 }
552
553 return DemandedElts;
554}
555
558 APInt DemandedElts,
559 int DMaskIdx = -1,
560 bool IsLoad = true);
561
562/// Return true if it's legal to contract llvm.amdgcn.rcp(llvm.sqrt)
563static bool canContractSqrtToRsq(const FPMathOperator *SqrtOp) {
564 return (SqrtOp->getType()->isFloatTy() &&
565 (SqrtOp->hasApproxFunc() || SqrtOp->getFPAccuracy() >= 1.0f)) ||
566 SqrtOp->getType()->isHalfTy();
567}
568
569/// Return true if we can easily prove that use U is uniform.
570static bool isTriviallyUniform(const Use &U) {
571 Value *V = U.get();
572 if (isa<Constant>(V))
573 return true;
574 if (const auto *A = dyn_cast<Argument>(V))
576 if (const auto *II = dyn_cast<IntrinsicInst>(V)) {
577 if (!AMDGPU::isIntrinsicAlwaysUniform(II->getIntrinsicID()))
578 return false;
579 // If II and U are in different blocks then there is a possibility of
580 // temporal divergence.
581 return II->getParent() == cast<Instruction>(U.getUser())->getParent();
582 }
583 return false;
584}
585
586/// Simplify a lane index operand (e.g. llvm.amdgcn.readlane src1).
587///
588/// The instruction only reads the low 5 bits for wave32, and 6 bits for wave64.
591 unsigned LaneArgIdx) const {
592 unsigned MaskBits = ST->getWavefrontSizeLog2();
593 APInt DemandedMask(32, maskTrailingOnes<unsigned>(MaskBits));
594
595 KnownBits Known(32);
596 if (IC.SimplifyDemandedBits(&II, LaneArgIdx, DemandedMask, Known))
597 return true;
598
599 if (!Known.isConstant())
600 return false;
601
602 // Out of bounds indexes may appear in wave64 code compiled for wave32.
603 // Unlike the DAG version, SimplifyDemandedBits does not change constants, so
604 // manually fix it up.
605
606 Value *LaneArg = II.getArgOperand(LaneArgIdx);
607 Constant *MaskedConst =
608 ConstantInt::get(LaneArg->getType(), Known.getConstant() & DemandedMask);
609 if (MaskedConst != LaneArg) {
610 II.getOperandUse(LaneArgIdx).set(MaskedConst);
611 return true;
612 }
613
614 return false;
615}
616
618 Function &NewCallee, ArrayRef<Value *> Ops) {
620 Old.getOperandBundlesAsDefs(OpBundles);
621
622 CallInst *NewCall = B.CreateCall(&NewCallee, Ops, OpBundles);
623 NewCall->takeName(&Old);
624 return NewCall;
625}
626
627// Return true for sequences of instructions that effectively assign
628// each lane to its thread ID
629static bool isThreadID(const GCNSubtarget &ST, Value *V) {
630 // Case 1:
631 // wave32: mbcnt_lo(-1, 0)
632 // wave64: mbcnt_hi(-1, mbcnt_lo(-1, 0))
638 if (ST.isWave32() && match(V, W32Pred))
639 return true;
640 if (ST.isWave64() && match(V, W64Pred))
641 return true;
642
643 return false;
644}
645
648 IntrinsicInst &II) const {
649 const auto IID = II.getIntrinsicID();
650 assert(IID == Intrinsic::amdgcn_readlane ||
651 IID == Intrinsic::amdgcn_readfirstlane ||
652 IID == Intrinsic::amdgcn_permlane64);
653
654 Instruction *OpInst = dyn_cast<Instruction>(II.getOperand(0));
655
656 // Only do this if both instructions are in the same block
657 // (so the exec mask won't change) and the readlane is the only user of its
658 // operand.
659 if (!OpInst || !OpInst->hasOneUser() || OpInst->getParent() != II.getParent())
660 return nullptr;
661
662 const bool IsReadLane = (IID == Intrinsic::amdgcn_readlane);
663
664 // If this is a readlane, check that the second operand is a constant, or is
665 // defined before OpInst so we know it's safe to move this intrinsic higher.
666 Value *LaneID = nullptr;
667 if (IsReadLane) {
668 LaneID = II.getOperand(1);
669
670 // readlane take an extra operand for the lane ID, so we must check if that
671 // LaneID value can be used at the point where we want to move the
672 // intrinsic.
673 if (auto *LaneIDInst = dyn_cast<Instruction>(LaneID)) {
674 if (!IC.getDominatorTree().dominates(LaneIDInst, OpInst))
675 return nullptr;
676 }
677 }
678
679 // Hoist the intrinsic (II) through OpInst.
680 //
681 // (II (OpInst x)) -> (OpInst (II x))
682 const auto DoIt = [&](unsigned OpIdx,
683 Function *NewIntrinsic) -> Instruction * {
684 SmallVector<Value *, 2> Ops{OpInst->getOperand(OpIdx)};
685 if (IsReadLane)
686 Ops.push_back(LaneID);
687
688 // Rewrite the intrinsic call.
689 CallInst *NewII = rewriteCall(IC.Builder, II, *NewIntrinsic, Ops);
690
691 // Rewrite OpInst so it takes the result of the intrinsic now.
692 Instruction &NewOp = *OpInst->clone();
693 NewOp.setOperand(OpIdx, NewII);
694 return &NewOp;
695 };
696
697 // TODO(?): Should we do more with permlane64?
698 if (IID == Intrinsic::amdgcn_permlane64 && !isa<BitCastInst>(OpInst))
699 return nullptr;
700
701 if (isa<UnaryOperator>(OpInst))
702 return DoIt(0, II.getCalledFunction());
703
704 if (isa<CastInst>(OpInst)) {
705 Value *Src = OpInst->getOperand(0);
706 Type *SrcTy = Src->getType();
707 if (!isTypeLegal(SrcTy))
708 return nullptr;
709
710 Function *Remangled =
711 Intrinsic::getOrInsertDeclaration(II.getModule(), IID, {SrcTy});
712 return DoIt(0, Remangled);
713 }
714
715 // We can also hoist through binary operators if the other operand is uniform.
716 if (isa<BinaryOperator>(OpInst)) {
717 // FIXME: If we had access to UniformityInfo here we could just check
718 // if the operand is uniform.
719 if (isTriviallyUniform(OpInst->getOperandUse(0)))
720 return DoIt(1, II.getCalledFunction());
721 if (isTriviallyUniform(OpInst->getOperandUse(1)))
722 return DoIt(0, II.getCalledFunction());
723 }
724
725 return nullptr;
726}
727
728/// Evaluate V as a function of the lane ID and return its value on Lane, or
729/// std::nullopt if V is not a closed-form expression of the lane ID.
730static std::optional<unsigned> evalLaneExpr(Value *V, unsigned Lane,
731 const GCNSubtarget &ST,
732 const DataLayout &DL,
733 unsigned Depth = 0) {
735 return std::nullopt;
736
737 // Poison/undef in the index expression: bail and let InstCombine fold the
738 // intrinsic the usual way.
739 if (isa<UndefValue>(V))
740 return std::nullopt;
741
742 if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
743 return CI->getZExtValue();
744
745 if (isThreadID(ST, V))
746 return Lane;
747
749 if (!BO)
750 return std::nullopt;
751
752 std::optional<unsigned> LHS =
753 evalLaneExpr(BO->getOperand(0), Lane, ST, DL, Depth + 1);
754 if (!LHS)
755 return std::nullopt;
756 std::optional<unsigned> RHS =
757 evalLaneExpr(BO->getOperand(1), Lane, ST, DL, Depth + 1);
758 if (!RHS)
759 return std::nullopt;
760
761 Type *Ty = BO->getType();
762 Constant *Ops[] = {ConstantInt::get(Ty, *LHS), ConstantInt::get(Ty, *RHS)};
763 auto *CI =
765 return CI ? std::optional<unsigned>(CI->getZExtValue()) : std::nullopt;
766}
767
768/// Build the per-lane shuffle map by evaluating Index for every lane in the
769/// wave. Returns false if any lane index is non-constant or out of range.
770static bool tryBuildShuffleMap(Value *Index, const GCNSubtarget &ST,
772 const DataLayout &DL) {
773 unsigned WaveSize = ST.getWavefrontSize();
774 Ids.resize(WaveSize);
775 for (unsigned Lane : seq(WaveSize)) {
776 std::optional<unsigned> Val = evalLaneExpr(Index, Lane, ST, DL);
777 if (!Val || *Val >= WaveSize)
778 return false;
779 Ids[Lane] = *Val;
780 }
781 return true;
782}
783
784/// Lanes are partitioned into groups of Period; each group is a translated
785/// copy of the first: Ids[I] = Ids[I % Period] + (I & ~(Period - 1)).
786template <unsigned Period>
788 static_assert(isPowerOf2_32(Period), "Period must be a power of two");
789 for (unsigned I = Period, E = Ids.size(); I < E; ++I)
790 if (Ids[I] != Ids[I % Period] + (I & ~(Period - 1)))
791 return false;
792 return true;
793}
794
795/// Match an N-lane row pattern: each lane in [0, N) reads from a source lane
796/// in the same N-lane row, and the pattern repeats periodically across rows.
797template <unsigned N> static bool isRowPattern(ArrayRef<uint8_t> Ids) {
798 for (unsigned I = 0; I < N; ++I)
799 if (Ids[I] >= N)
800 return false;
801 return hasPeriodicLayout<N>(Ids);
802}
803
804static constexpr auto isQuadPattern = isRowPattern<4>;
805static constexpr auto isHalfRowPattern = isRowPattern<8>;
806static constexpr auto isFullRowPattern = isRowPattern<16>;
807
808/// Match a 4-lane (quad) permutation, encoded as the v_mov_b32_dpp
809/// QUAD_PERM control word: bits[1:0]=Ids[0], [3:2]=Ids[1], [5:4]=Ids[2],
810/// [7:6]=Ids[3].
811static std::optional<unsigned> matchQuadPermPattern(ArrayRef<uint8_t> Ids) {
812 if (!isQuadPattern(Ids))
813 return std::nullopt;
814 return Ids[3] << 6 | Ids[2] << 4 | Ids[1] << 2 | Ids[0];
815}
816
817/// Match an N-lane reversal (mirror) pattern.
818template <unsigned N> static bool matchMirrorPattern(ArrayRef<uint8_t> Ids) {
819 if (!isRowPattern<N>(Ids))
820 return false;
821 for (unsigned J = 0; J < N; ++J)
822 if (Ids[J] != (N - 1) - J)
823 return false;
824 return true;
825}
826
829
830/// Match a 16-lane cyclic rotation; returns the rotation amount in [1, 15].
831static std::optional<unsigned> matchRowRotatePattern(ArrayRef<uint8_t> Ids) {
832 if (Ids[0] == 0 || !isFullRowPattern(Ids))
833 return std::nullopt;
834 for (unsigned J = 1; J < 16; ++J)
835 if (Ids[J] != (Ids[0] + J) % 16)
836 return std::nullopt;
837 return 16u - Ids[0];
838}
839
840/// Match a row-share pattern: all 16 lanes of each row read the same source
841/// lane. Returns the shared source lane index in [0, 16).
842static std::optional<unsigned> matchRowSharePattern(ArrayRef<uint8_t> Ids) {
843 if (!isFullRowPattern(Ids))
844 return std::nullopt;
845 if (!all_equal(Ids.take_front(16)))
846 return std::nullopt;
847 return Ids[0];
848}
849
850/// Match an XOR mask pattern within each 16-lane row: Ids[J] == Mask ^ J,
851/// with Mask in [1, 15].
852static std::optional<unsigned> matchRowXMaskPattern(ArrayRef<uint8_t> Ids) {
853 unsigned Mask = Ids[0];
854 if (Mask == 0 || !isFullRowPattern(Ids))
855 return std::nullopt;
856 for (unsigned J = 0; J < 16; ++J)
857 if (Ids[J] != (Mask ^ J))
858 return std::nullopt;
859 return Mask;
860}
861
862/// Match an 8-lane arbitrary permutation, encoded as the v_mov_b32_dpp8
863/// 24-bit selector (three bits per output lane).
864static std::optional<unsigned> matchHalfRowPermPattern(ArrayRef<uint8_t> Ids) {
865 if (!isHalfRowPattern(Ids))
866 return std::nullopt;
867 unsigned Selector = 0;
868 for (unsigned J = 0; J < 8; ++J)
869 Selector |= Ids[J] << (J * 3);
870 return Selector;
871}
872
873/// Pack a 16-lane permutation into a single 64-bit value: four bits per output
874/// lane, lane J in bits [J*4 + 3 : J*4]. The caller splits it into the low and
875/// high 32-bit selector operands of v_permlane16 / v_permlanex16.
877 uint64_t Sel = 0;
878 for (unsigned J = 0; J < 16; ++J)
879 Sel |= static_cast<uint64_t>(Ids[J] & 0xF) << (J * 4);
880 return Sel;
881}
882
883/// Match a half-wave swap: lane J reads from lane J ^ 32. Only meaningful on
884/// wave64 targets.
886 if (Ids.size() != 64)
887 return false;
888 for (unsigned J = 0; J < 64; ++J)
889 if (Ids[J] != (J ^ 32))
890 return false;
891 return true;
892}
893
894/// Match a cross-row permutation suitable for v_permlanex16: every lane in
895/// the low 16-lane half reads from the high half of its own row, and vice
896/// versa.
898 if (!hasPeriodicLayout<32>(Ids))
899 return false;
900 for (unsigned J = 0; J < 16; ++J) {
901 if (Ids[J] < 16 || Ids[J] >= 32)
902 return false;
903 if (Ids[J + 16] != Ids[J] - 16)
904 return false;
905 }
906 return true;
907}
908
909/// Match a DS_SWIZZLE bitmask-mode permutation:
910/// dst_lane = ((src_lane & AND) | OR) ^ XOR
911/// with each mask being five bits. Returns the encoded swizzle immediate.
912/// The hardware applies the formula independently within each 32-lane group,
913/// so on wave64 the high group must replicate the low one (translated by 32).
914static std::optional<unsigned>
916 if (!hasPeriodicLayout<32>(Ids))
917 return std::nullopt;
918
919 // The formula is per-bit: output bit B depends only on input bit B. Probe
920 // each bit with src=0 and src=(1<<B); if the output bit flipped, AND[B]=1
921 // and XOR[B] carries the constant offset; otherwise it is a constant bit
922 // encoded in OR (with AND[B]=0, XOR[B]=0).
923 unsigned AndMask = 0, OrMask = 0, XorMask = 0;
924 for (unsigned B = 0; B < 5; ++B) {
925 unsigned Bit0 = (Ids[0] >> B) & 1;
926 unsigned Bit1 = (Ids[1u << B] >> B) & 1;
927 if (Bit0 != Bit1) {
928 AndMask |= 1u << B;
929 XorMask |= Bit0 << B;
930 } else {
931 OrMask |= Bit0 << B;
932 }
933 }
934
935 // The per-bit derivation assumes bit independence; verify the masks
936 // actually reproduce every lane in the 32-lane group.
937 for (unsigned I : seq(32u)) {
938 unsigned Expected = ((I & AndMask) | OrMask) ^ XorMask;
939 if (Ids[I] != Expected)
940 return std::nullopt;
941 }
942
947}
948
949/// Match a GFX9+ DS_SWIZZLE rotate-mode permutation: a cyclic left-rotation
950/// of all 32 lanes within each 32-lane group by a constant N in [0, 31],
951/// i.e. dst_lane = (src_lane + N) % 32. On wave64, hasPeriodicLayout<32>
952/// ensures both 32-lane groups rotate by the same amount.
953static std::optional<unsigned>
955 if (!hasPeriodicLayout<32>(Ids))
956 return std::nullopt;
957
958 // Determine the rotation amount from lane 0: every lane must read from
959 // lane (I + N) % 32 where N = Ids[0] and 0 <= N <= 31.
960 unsigned N = Ids[0];
961 if (N >= 32)
962 return std::nullopt;
963
964 for (unsigned I = 0; I < 32; ++I)
965 if (Ids[I] != (I + N) % 32)
966 return std::nullopt;
967
970}
971
972/// Emit v_mov_b32_dpp with the given control word, row/bank masks 0xF, and
973/// bound_ctrl=1 so out-of-bounds lanes are well-defined and the DPP mov can
974/// be folded into a consuming VALU op by GCNDPPCombine.
975static Value *createUpdateDpp(IRBuilderBase &B, Value *Val, unsigned Ctrl) {
976 Type *Ty = Val->getType();
977 return B.CreateIntrinsic(Intrinsic::amdgcn_update_dpp, {Ty},
978 {PoisonValue::get(Ty), Val, B.getInt32(Ctrl),
979 B.getInt32(0xF), B.getInt32(0xF), B.getTrue()});
980}
981
982/// Emit v_mov_b32_dpp8 with the given 24-bit lane selector.
983static Value *createMovDpp8(IRBuilderBase &B, Value *Val, unsigned Selector) {
984 return B.CreateIntrinsic(Intrinsic::amdgcn_mov_dpp8, {Val->getType()},
985 {Val, B.getInt32(Selector)});
986}
987
988/// Emit v_permlane16 with the precomputed lane-select halves.
990 uint32_t Hi) {
991 Type *Ty = Val->getType();
992 return B.CreateIntrinsic(Intrinsic::amdgcn_permlane16, {Ty},
993 {PoisonValue::get(Ty), Val, B.getInt32(Lo),
994 B.getInt32(Hi), B.getFalse(), B.getFalse()});
995}
996
997/// Emit v_permlanex16 with the precomputed lane-select halves. Each output
998/// lane reads from the other 16-lane half of the same row.
1000 uint32_t Hi) {
1001 Type *Ty = Val->getType();
1002 return B.CreateIntrinsic(Intrinsic::amdgcn_permlanex16, {Ty},
1003 {PoisonValue::get(Ty), Val, B.getInt32(Lo),
1004 B.getInt32(Hi), B.getFalse(), B.getFalse()});
1005}
1006
1007/// Emit ds_swizzle with the given immediate, bitcasting/converting between
1008/// pointer/float types and i32 as required by the intrinsic signature.
1010 const DataLayout &DL) {
1011 Type *OrigTy = Val->getType();
1012 assert(DL.getTypeSizeInBits(OrigTy) == 32 &&
1013 "ds_swizzle only supports 32-bit operands");
1014 IntegerType *I32Ty = B.getInt32Ty();
1015 Value *Src = Val;
1016 if (OrigTy->isPointerTy())
1017 Src = B.CreatePtrToInt(Src, I32Ty);
1018 else if (OrigTy != I32Ty)
1019 Src = B.CreateBitCast(Src, I32Ty);
1020 Value *Result = B.CreateIntrinsic(Intrinsic::amdgcn_ds_swizzle, {},
1021 {Src, B.getInt32(Offset)});
1022 if (OrigTy->isPointerTy())
1023 return B.CreateIntToPtr(Result, OrigTy);
1024 if (OrigTy != I32Ty)
1025 return B.CreateBitCast(Result, OrigTy);
1026 return Result;
1027}
1028
1029/// Emit v_permlane64 (swap of the two 32-lane halves of a wave64).
1031 return B.CreateIntrinsic(Intrinsic::amdgcn_permlane64, {Val->getType()},
1032 {Val});
1033}
1034
1035/// Given a shuffle map, try to emit the best hardware intrinsic.
1038 const GCNSubtarget &ST,
1039 const DataLayout &DL) {
1040 // Identity shuffle (every lane reads itself) folds to the source value.
1041 if (all_of(enumerate(Ids),
1042 [](const auto &E) { return E.value() == E.index(); }))
1043 return Src;
1044
1045 // Uniform shuffle (all lanes read the same value) is handled by cheaper
1046 // broadcast/readlane intrinsics.
1047 if (all_equal(Ids))
1048 return nullptr;
1049
1050 if (std::optional<unsigned> QP = matchQuadPermPattern(Ids)) {
1051 if (ST.hasDPP())
1052 return createUpdateDpp(B, Src, *QP);
1054 }
1055
1056 if (ST.hasDPP()) {
1061 if (std::optional<unsigned> Amt = matchRowRotatePattern(Ids))
1062 return createUpdateDpp(B, Src, AMDGPU::DPP::ROW_ROR_FIRST + *Amt - 1);
1063 }
1064
1065 // row_share is supported on GFX90A and GFX10+; row_xmask is GFX10+ only.
1066 if (ST.hasDPPRowShare()) {
1067 if (std::optional<unsigned> Lane = matchRowSharePattern(Ids))
1068 return createUpdateDpp(B, Src, AMDGPU::DPP::ROW_SHARE_FIRST + *Lane);
1069 }
1070
1071 if (ST.hasDPP() && ST.hasGFX10Insts()) {
1072 if (std::optional<unsigned> Mask = matchRowXMaskPattern(Ids))
1073 return createUpdateDpp(B, Src, AMDGPU::DPP::ROW_XMASK_FIRST + *Mask);
1074 }
1075
1076 if (ST.hasDPP8()) {
1077 if (std::optional<unsigned> Sel = matchHalfRowPermPattern(Ids))
1078 return createMovDpp8(B, Src, *Sel);
1079 }
1080
1081 if (ST.hasPermlane16Insts()) {
1082 if (isFullRowPattern(Ids)) {
1084 return createPermlane16(B, Src, Lo_32(Sel), Hi_32(Sel));
1085 }
1086 // Cross-row shuffles (e.g. XOR 16..31) — covered by permlanex16.
1087 if (isCrossRowPattern(Ids)) {
1089 return createPermlaneX16(B, Src, Lo_32(Sel), Hi_32(Sel));
1090 }
1091 }
1092
1093 // Generic DS_SWIZZLE bitmask-mode fallback: handles any 32-lane shuffle that
1094 // can be expressed as dst = ((src & AND) | OR) ^ XOR with 5-bit masks. This
1095 // is available on every target that has ds_swizzle.
1096 if (std::optional<unsigned> Imm = matchDsSwizzleBitmaskPattern(Ids))
1097 return createDsSwizzle(B, Src, *Imm, DL);
1098
1099 // DS_SWIZZLE rotate mode (GFX9+): handles cyclic 32-lane rotations that
1100 // bitmask mode cannot express (e.g. +1 mod 32 requires inter-bit carry).
1101 if (ST.hasDsSwizzleRotateMode()) {
1102 if (std::optional<unsigned> Imm = matchDsSwizzleRotatePattern(Ids))
1103 return createDsSwizzle(B, Src, *Imm, DL);
1104 }
1105
1106 if (ST.hasPermLane64() && matchHalfWaveSwapPattern(Ids))
1107 return createPermlane64(B, Src);
1108
1109 return nullptr;
1110}
1111
1112/// Try to fold a wave_shuffle/ds_bpermute whose lane index is a constant
1113/// function of the lane ID into a hardware-specific lane permutation intrinsic.
1114static std::optional<Instruction *>
1116 const GCNSubtarget &ST) {
1117 const DataLayout &DL = IC.getDataLayout();
1118 if (DL.getTypeSizeInBits(II.getType()) != 32)
1119 return std::nullopt;
1120
1121 if (!ST.isWaveSizeKnown())
1122 return std::nullopt;
1123
1124 unsigned WaveSize = ST.getWavefrontSize();
1125 bool IsBpermute = II.getIntrinsicID() == Intrinsic::amdgcn_ds_bpermute;
1126 Value *Src = II.getArgOperand(IsBpermute ? 1 : 0);
1127 Value *Index = II.getArgOperand(IsBpermute ? 0 : 1);
1128
1130 if (IsBpermute) {
1131 Ids.resize(WaveSize);
1132 for (unsigned Lane : seq(WaveSize)) {
1133 std::optional<unsigned> Val = evalLaneExpr(Index, Lane, ST, DL);
1134 if (!Val || (*Val & 3) || (*Val >> 2) >= WaveSize)
1135 return std::nullopt;
1136 Ids[Lane] = *Val >> 2;
1137 }
1138 } else {
1139 if (!tryBuildShuffleMap(Index, ST, Ids, DL))
1140 return std::nullopt;
1141 }
1142
1143 Value *Result = matchShuffleToHWIntrinsic(IC.Builder, Src, Ids, ST, DL);
1144 if (!Result)
1145 return std::nullopt;
1146
1147 return IC.replaceInstUsesWith(II, Result);
1148}
1149std::optional<Instruction *>
1151 Intrinsic::ID IID = II.getIntrinsicID();
1152 switch (IID) {
1153 case Intrinsic::amdgcn_implicitarg_ptr: {
1154 if (II.getFunction()->hasFnAttribute("amdgpu-no-implicitarg-ptr"))
1155 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
1156 uint64_t ImplicitArgBytes = ST->getImplicitArgNumBytes(*II.getFunction());
1157
1158 uint64_t CurrentOrNullBytes =
1159 II.getAttributes().getRetDereferenceableOrNullBytes();
1160 if (CurrentOrNullBytes != 0) {
1161 // Refine "dereferenceable (A) meets dereferenceable_or_null(B)"
1162 // into dereferenceable(max(A, B))
1163 uint64_t NewBytes = std::max(CurrentOrNullBytes, ImplicitArgBytes);
1164 II.addRetAttr(
1165 Attribute::getWithDereferenceableBytes(II.getContext(), NewBytes));
1166 II.removeRetAttr(Attribute::DereferenceableOrNull);
1167 return &II;
1168 }
1169
1170 uint64_t CurrentBytes = II.getAttributes().getRetDereferenceableBytes();
1171 uint64_t NewBytes = std::max(CurrentBytes, ImplicitArgBytes);
1172 if (NewBytes != CurrentBytes) {
1173 II.addRetAttr(
1174 Attribute::getWithDereferenceableBytes(II.getContext(), NewBytes));
1175 return &II;
1176 }
1177
1178 return std::nullopt;
1179 }
1180 case Intrinsic::amdgcn_rcp: {
1181 Value *Src = II.getArgOperand(0);
1182 if (isa<PoisonValue>(Src))
1183 return IC.replaceInstUsesWith(II, Src);
1184
1185 // TODO: Move to ConstantFolding/InstSimplify?
1186 if (isa<UndefValue>(Src)) {
1187 Type *Ty = II.getType();
1188 auto *QNaN = ConstantFP::get(Ty, APFloat::getQNaN(Ty->getFltSemantics()));
1189 return IC.replaceInstUsesWith(II, QNaN);
1190 }
1191
1192 if (II.isStrictFP())
1193 break;
1194
1195 if (const ConstantFP *C = dyn_cast<ConstantFP>(Src)) {
1196 std::optional<APFloat> Val = AMDGPU::evaluateRcp(C->getValueAPF());
1197 if (!Val)
1198 break;
1199
1200 return IC.replaceInstUsesWith(II, ConstantFP::get(II.getContext(), *Val));
1201 }
1202
1203 FastMathFlags FMF = cast<FPMathOperator>(II).getFastMathFlags();
1204 if (!FMF.allowContract())
1205 break;
1206 auto *SrcCI = dyn_cast<IntrinsicInst>(Src);
1207 if (!SrcCI)
1208 break;
1209
1210 auto IID = SrcCI->getIntrinsicID();
1211 // llvm.amdgcn.rcp(llvm.amdgcn.sqrt(x)) -> llvm.amdgcn.rsq(x) if contractable
1212 //
1213 // llvm.amdgcn.rcp(llvm.sqrt(x)) -> llvm.amdgcn.rsq(x) if contractable and
1214 // relaxed.
1215 if (IID == Intrinsic::amdgcn_sqrt || IID == Intrinsic::sqrt) {
1216 const FPMathOperator *SqrtOp = cast<FPMathOperator>(SrcCI);
1217 FastMathFlags InnerFMF = SqrtOp->getFastMathFlags();
1218 if (!InnerFMF.allowContract() || !SrcCI->hasOneUse())
1219 break;
1220
1221 if (IID == Intrinsic::sqrt && !canContractSqrtToRsq(SqrtOp))
1222 break;
1223
1225 SrcCI->getModule(), Intrinsic::amdgcn_rsq, {SrcCI->getType()});
1226
1227 InnerFMF |= FMF;
1228 II.setFastMathFlags(InnerFMF);
1229
1230 II.setCalledFunction(NewDecl);
1231 return IC.replaceOperand(II, 0, SrcCI->getArgOperand(0));
1232 }
1233
1234 break;
1235 }
1236 case Intrinsic::amdgcn_sqrt:
1237 case Intrinsic::amdgcn_rsq:
1238 case Intrinsic::amdgcn_tanh: {
1239 Value *Src = II.getArgOperand(0);
1240 if (isa<PoisonValue>(Src))
1241 return IC.replaceInstUsesWith(II, Src);
1242
1243 // TODO: Move to ConstantFolding/InstSimplify?
1244 if (isa<UndefValue>(Src)) {
1245 Type *Ty = II.getType();
1246 auto *QNaN = ConstantFP::get(Ty, APFloat::getQNaN(Ty->getFltSemantics()));
1247 return IC.replaceInstUsesWith(II, QNaN);
1248 }
1249
1250 // f16 amdgcn.sqrt is identical to regular sqrt.
1251 if (IID == Intrinsic::amdgcn_sqrt && Src->getType()->isHalfTy()) {
1253 II.getModule(), Intrinsic::sqrt, {II.getType()});
1254 II.setCalledFunction(NewDecl);
1255 return &II;
1256 }
1257
1258 break;
1259 }
1260 case Intrinsic::amdgcn_log:
1261 case Intrinsic::amdgcn_exp2: {
1262 const bool IsLog = IID == Intrinsic::amdgcn_log;
1263 const bool IsExp = IID == Intrinsic::amdgcn_exp2;
1264 Value *Src = II.getArgOperand(0);
1265 Type *Ty = II.getType();
1266
1267 if (isa<PoisonValue>(Src))
1268 return IC.replaceInstUsesWith(II, Src);
1269
1270 if (IC.getSimplifyQuery().isUndefValue(Src))
1272
1273 if (ConstantFP *C = dyn_cast<ConstantFP>(Src)) {
1274 if (C->isInfinity()) {
1275 // exp2(+inf) -> +inf
1276 // log2(+inf) -> +inf
1277 if (!C->isNegative())
1278 return IC.replaceInstUsesWith(II, C);
1279
1280 // exp2(-inf) -> 0
1281 if (IsExp && C->isNegative())
1283 }
1284
1285 if (II.isStrictFP())
1286 break;
1287
1288 if (C->isNaN()) {
1289 Constant *Quieted = ConstantFP::get(Ty, C->getValue().makeQuiet());
1290 return IC.replaceInstUsesWith(II, Quieted);
1291 }
1292
1293 // f32 instruction doesn't handle denormals, f16 does.
1294 if (C->isZero() || (C->getValue().isDenormal() && Ty->isFloatTy())) {
1295 Constant *FoldedValue = IsLog ? ConstantFP::getInfinity(Ty, true)
1296 : ConstantFP::get(Ty, 1.0);
1297 return IC.replaceInstUsesWith(II, FoldedValue);
1298 }
1299
1300 if (IsLog && C->isNegative())
1302
1303 // TODO: Full constant folding matching hardware behavior.
1304 }
1305
1306 break;
1307 }
1308 case Intrinsic::amdgcn_frexp_mant:
1309 case Intrinsic::amdgcn_frexp_exp: {
1310 Value *Src = II.getArgOperand(0);
1311 if (const ConstantFP *C = dyn_cast<ConstantFP>(Src)) {
1312 int Exp;
1313 APFloat Significand =
1314 frexp(C->getValueAPF(), Exp, APFloat::rmNearestTiesToEven);
1315
1316 if (IID == Intrinsic::amdgcn_frexp_mant) {
1317 return IC.replaceInstUsesWith(
1318 II, ConstantFP::get(II.getContext(), Significand));
1319 }
1320
1321 // Match instruction special case behavior.
1322 if (Exp == APFloat::IEK_NaN || Exp == APFloat::IEK_Inf)
1323 Exp = 0;
1324
1325 return IC.replaceInstUsesWith(II,
1326 ConstantInt::getSigned(II.getType(), Exp));
1327 }
1328
1329 if (isa<PoisonValue>(Src))
1330 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
1331
1332 if (isa<UndefValue>(Src)) {
1333 return IC.replaceInstUsesWith(II, UndefValue::get(II.getType()));
1334 }
1335
1336 break;
1337 }
1338 case Intrinsic::amdgcn_class: {
1339 Value *Src0 = II.getArgOperand(0);
1340 Value *Src1 = II.getArgOperand(1);
1341 const ConstantInt *CMask = dyn_cast<ConstantInt>(Src1);
1342 if (CMask) {
1343 II.setCalledOperand(Intrinsic::getOrInsertDeclaration(
1344 II.getModule(), Intrinsic::is_fpclass, Src0->getType()));
1345
1346 // Clamp any excess bits, as they're illegal for the generic intrinsic.
1347 II.setArgOperand(1, ConstantInt::get(Src1->getType(),
1348 CMask->getZExtValue() & fcAllFlags));
1349 return &II;
1350 }
1351
1352 // Propagate poison.
1353 if (isa<PoisonValue>(Src0) || isa<PoisonValue>(Src1))
1354 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
1355
1356 // llvm.amdgcn.class(_, undef) -> false
1357 if (IC.getSimplifyQuery().isUndefValue(Src1))
1358 return IC.replaceInstUsesWith(II, ConstantInt::get(II.getType(), false));
1359
1360 // llvm.amdgcn.class(undef, mask) -> mask != 0
1361 if (IC.getSimplifyQuery().isUndefValue(Src0)) {
1362 Value *CmpMask = IC.Builder.CreateICmpNE(
1363 Src1, ConstantInt::getNullValue(Src1->getType()));
1364 return IC.replaceInstUsesWith(II, CmpMask);
1365 }
1366 break;
1367 }
1368 case Intrinsic::amdgcn_cvt_pkrtz: {
1369 auto foldFPTruncToF16RTZ = [](Value *Arg) -> Value * {
1370 Type *HalfTy = Type::getHalfTy(Arg->getContext());
1371
1372 if (isa<PoisonValue>(Arg))
1373 return PoisonValue::get(HalfTy);
1374 if (isa<UndefValue>(Arg))
1375 return UndefValue::get(HalfTy);
1376
1377 ConstantFP *CFP = nullptr;
1378 if (match(Arg, m_ConstantFP(CFP))) {
1379 bool LosesInfo;
1380 APFloat Val(CFP->getValueAPF());
1382 return ConstantFP::get(HalfTy, Val);
1383 }
1384
1385 Value *Src = nullptr;
1386 if (match(Arg, m_FPExt(m_Value(Src)))) {
1387 if (Src->getType()->isHalfTy())
1388 return Src;
1389 }
1390
1391 return nullptr;
1392 };
1393
1394 if (Value *Src0 = foldFPTruncToF16RTZ(II.getArgOperand(0))) {
1395 if (Value *Src1 = foldFPTruncToF16RTZ(II.getArgOperand(1))) {
1396 Value *V = PoisonValue::get(II.getType());
1397 V = IC.Builder.CreateInsertElement(V, Src0, (uint64_t)0);
1398 V = IC.Builder.CreateInsertElement(V, Src1, (uint64_t)1);
1399 return IC.replaceInstUsesWith(II, V);
1400 }
1401 }
1402
1403 break;
1404 }
1405 case Intrinsic::amdgcn_cvt_pknorm_i16:
1406 case Intrinsic::amdgcn_cvt_pknorm_u16:
1407 case Intrinsic::amdgcn_cvt_pk_i16:
1408 case Intrinsic::amdgcn_cvt_pk_u16: {
1409 Value *Src0 = II.getArgOperand(0);
1410 Value *Src1 = II.getArgOperand(1);
1411
1412 // TODO: Replace call with scalar operation if only one element is poison.
1413 if (isa<PoisonValue>(Src0) && isa<PoisonValue>(Src1))
1414 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
1415
1416 if (isa<UndefValue>(Src0) && isa<UndefValue>(Src1)) {
1417 return IC.replaceInstUsesWith(II, UndefValue::get(II.getType()));
1418 }
1419
1420 break;
1421 }
1422 case Intrinsic::amdgcn_cvt_off_f32_i4: {
1423 Value* Arg = II.getArgOperand(0);
1424 Type *Ty = II.getType();
1425
1426 if (isa<PoisonValue>(Arg))
1427 return IC.replaceInstUsesWith(II, PoisonValue::get(Ty));
1428
1429 if(IC.getSimplifyQuery().isUndefValue(Arg))
1431
1432 ConstantInt *CArg = dyn_cast<ConstantInt>(II.getArgOperand(0));
1433 if (!CArg)
1434 break;
1435
1436 // Tabulated 0.0625 * (sext (CArg & 0xf)).
1437 constexpr size_t ResValsSize = 16;
1438 static constexpr float ResVals[ResValsSize] = {
1439 0.0, 0.0625, 0.125, 0.1875, 0.25, 0.3125, 0.375, 0.4375,
1440 -0.5, -0.4375, -0.375, -0.3125, -0.25, -0.1875, -0.125, -0.0625};
1441 Constant *Res =
1442 ConstantFP::get(Ty, ResVals[CArg->getZExtValue() & (ResValsSize - 1)]);
1443 return IC.replaceInstUsesWith(II, Res);
1444 }
1445 case Intrinsic::amdgcn_ubfe:
1446 case Intrinsic::amdgcn_sbfe: {
1447 // Decompose simple cases into standard shifts.
1448 Value *Src = II.getArgOperand(0);
1449 if (isa<UndefValue>(Src)) {
1450 return IC.replaceInstUsesWith(II, Src);
1451 }
1452
1453 unsigned Width;
1454 Type *Ty = II.getType();
1455 unsigned IntSize = Ty->getIntegerBitWidth();
1456
1457 ConstantInt *CWidth = dyn_cast<ConstantInt>(II.getArgOperand(2));
1458 if (CWidth) {
1459 Width = CWidth->getZExtValue();
1460 if ((Width & (IntSize - 1)) == 0) {
1462 }
1463
1464 // Hardware ignores high bits, so remove those.
1465 if (Width >= IntSize) {
1466 return IC.replaceOperand(
1467 II, 2, ConstantInt::get(CWidth->getType(), Width & (IntSize - 1)));
1468 }
1469 }
1470
1471 unsigned Offset;
1472 ConstantInt *COffset = dyn_cast<ConstantInt>(II.getArgOperand(1));
1473 if (COffset) {
1474 Offset = COffset->getZExtValue();
1475 if (Offset >= IntSize) {
1476 return IC.replaceOperand(
1477 II, 1,
1478 ConstantInt::get(COffset->getType(), Offset & (IntSize - 1)));
1479 }
1480 }
1481
1482 bool Signed = IID == Intrinsic::amdgcn_sbfe;
1483
1484 if (!CWidth || !COffset)
1485 break;
1486
1487 // The case of Width == 0 is handled above, which makes this transformation
1488 // safe. If Width == 0, then the ashr and lshr instructions become poison
1489 // value since the shift amount would be equal to the bit size.
1490 assert(Width != 0);
1491
1492 // TODO: This allows folding to undef when the hardware has specific
1493 // behavior?
1494 if (Offset + Width < IntSize) {
1495 Value *Shl = IC.Builder.CreateShl(Src, IntSize - Offset - Width);
1496 Value *RightShift = Signed ? IC.Builder.CreateAShr(Shl, IntSize - Width)
1497 : IC.Builder.CreateLShr(Shl, IntSize - Width);
1498 RightShift->takeName(&II);
1499 return IC.replaceInstUsesWith(II, RightShift);
1500 }
1501
1502 Value *RightShift = Signed ? IC.Builder.CreateAShr(Src, Offset)
1503 : IC.Builder.CreateLShr(Src, Offset);
1504
1505 RightShift->takeName(&II);
1506 return IC.replaceInstUsesWith(II, RightShift);
1507 }
1508 case Intrinsic::amdgcn_exp:
1509 case Intrinsic::amdgcn_exp_row:
1510 case Intrinsic::amdgcn_exp_compr: {
1511 ConstantInt *En = cast<ConstantInt>(II.getArgOperand(1));
1512 unsigned EnBits = En->getZExtValue();
1513 if (EnBits == 0xf)
1514 break; // All inputs enabled.
1515
1516 bool IsCompr = IID == Intrinsic::amdgcn_exp_compr;
1517 bool Changed = false;
1518 for (int I = 0; I < (IsCompr ? 2 : 4); ++I) {
1519 if ((!IsCompr && (EnBits & (1 << I)) == 0) ||
1520 (IsCompr && ((EnBits & (0x3 << (2 * I))) == 0))) {
1521 Value *Src = II.getArgOperand(I + 2);
1522 if (!isa<PoisonValue>(Src)) {
1523 IC.replaceOperand(II, I + 2, PoisonValue::get(Src->getType()));
1524 Changed = true;
1525 }
1526 }
1527 }
1528
1529 if (Changed) {
1530 return &II;
1531 }
1532
1533 break;
1534 }
1535 case Intrinsic::amdgcn_fmed3: {
1536 Value *Src0 = II.getArgOperand(0);
1537 Value *Src1 = II.getArgOperand(1);
1538 Value *Src2 = II.getArgOperand(2);
1539
1540 for (Value *Src : {Src0, Src1, Src2}) {
1541 if (isa<PoisonValue>(Src))
1542 return IC.replaceInstUsesWith(II, Src);
1543 }
1544
1545 if (II.isStrictFP())
1546 break;
1547
1548 // med3 with a nan input acts like
1549 // v_min_f32(v_min_f32(s0, s1), s2)
1550 //
1551 // Signalingness is ignored with ieee=0, so we fold to
1552 // minimumnum/maximumnum. With ieee=1, the v_min_f32 acts like llvm.minnum
1553 // with signaling nan handling. With ieee=0, like llvm.minimumnum except a
1554 // returned signaling nan will not be quieted.
1555
1556 // ieee=1
1557 // s0 snan: s2
1558 // s1 snan: s2
1559 // s2 snan: qnan
1560
1561 // s0 qnan: min(s1, s2)
1562 // s1 qnan: min(s0, s2)
1563 // s2 qnan: min(s0, s1)
1564
1565 // ieee=0
1566 // s0 _nan: min(s1, s2)
1567 // s1 _nan: min(s0, s2)
1568 // s2 _nan: min(s0, s1)
1569
1570 // med3 behavior with infinity
1571 // s0 +inf: max(s1, s2)
1572 // s1 +inf: max(s0, s2)
1573 // s2 +inf: max(s0, s1)
1574 // s0 -inf: min(s1, s2)
1575 // s1 -inf: min(s0, s2)
1576 // s2 -inf: min(s0, s1)
1577
1578 // Checking for NaN before canonicalization provides better fidelity when
1579 // mapping other operations onto fmed3 since the order of operands is
1580 // unchanged.
1581 Value *V = nullptr;
1582 const APFloat *ConstSrc0 = nullptr;
1583 const APFloat *ConstSrc1 = nullptr;
1584 const APFloat *ConstSrc2 = nullptr;
1585
1586 if ((match(Src0, m_APFloat(ConstSrc0)) &&
1587 (ConstSrc0->isNaN() || ConstSrc0->isInfinity())) ||
1588 isa<UndefValue>(Src0)) {
1589 const bool IsPosInfinity = ConstSrc0 && ConstSrc0->isPosInfinity();
1590 switch (fpenvIEEEMode(II)) {
1591 case KnownIEEEMode::On:
1592 // TODO: If Src2 is snan, does it need quieting?
1593 if (ConstSrc0 && ConstSrc0->isNaN() && ConstSrc0->isSignaling())
1594 return IC.replaceInstUsesWith(II, Src2);
1595
1596 V = IsPosInfinity ? IC.Builder.CreateMaxNum(Src1, Src2)
1597 : IC.Builder.CreateMinNum(Src1, Src2);
1598 break;
1599 case KnownIEEEMode::Off:
1600 V = IsPosInfinity ? IC.Builder.CreateMaximumNum(Src1, Src2)
1601 : IC.Builder.CreateMinimumNum(Src1, Src2);
1602 break;
1604 break;
1605 }
1606 } else if ((match(Src1, m_APFloat(ConstSrc1)) &&
1607 (ConstSrc1->isNaN() || ConstSrc1->isInfinity())) ||
1608 isa<UndefValue>(Src1)) {
1609 const bool IsPosInfinity = ConstSrc1 && ConstSrc1->isPosInfinity();
1610 switch (fpenvIEEEMode(II)) {
1611 case KnownIEEEMode::On:
1612 // TODO: If Src2 is snan, does it need quieting?
1613 if (ConstSrc1 && ConstSrc1->isNaN() && ConstSrc1->isSignaling())
1614 return IC.replaceInstUsesWith(II, Src2);
1615
1616 V = IsPosInfinity ? IC.Builder.CreateMaxNum(Src0, Src2)
1617 : IC.Builder.CreateMinNum(Src0, Src2);
1618 break;
1619 case KnownIEEEMode::Off:
1620 V = IsPosInfinity ? IC.Builder.CreateMaximumNum(Src0, Src2)
1621 : IC.Builder.CreateMinimumNum(Src0, Src2);
1622 break;
1624 break;
1625 }
1626 } else if ((match(Src2, m_APFloat(ConstSrc2)) &&
1627 (ConstSrc2->isNaN() || ConstSrc2->isInfinity())) ||
1628 isa<UndefValue>(Src2)) {
1629 switch (fpenvIEEEMode(II)) {
1630 case KnownIEEEMode::On:
1631 if (ConstSrc2 && ConstSrc2->isNaN() && ConstSrc2->isSignaling()) {
1632 auto *Quieted = ConstantFP::get(II.getType(), ConstSrc2->makeQuiet());
1633 return IC.replaceInstUsesWith(II, Quieted);
1634 }
1635
1636 V = (ConstSrc2 && ConstSrc2->isPosInfinity())
1637 ? IC.Builder.CreateMaxNum(Src0, Src1)
1638 : IC.Builder.CreateMinNum(Src0, Src1);
1639 break;
1640 case KnownIEEEMode::Off:
1641 V = (ConstSrc2 && ConstSrc2->isPosInfinity())
1642 ? IC.Builder.CreateMaximumNum(Src0, Src1)
1643 : IC.Builder.CreateMinimumNum(Src0, Src1);
1644 break;
1646 break;
1647 }
1648 }
1649
1650 if (V) {
1651 if (auto *CI = dyn_cast<CallInst>(V)) {
1652 CI->copyFastMathFlags(&II);
1653 CI->takeName(&II);
1654 }
1655 return IC.replaceInstUsesWith(II, V);
1656 }
1657
1658 bool Swap = false;
1659 // Canonicalize constants to RHS operands.
1660 //
1661 // fmed3(c0, x, c1) -> fmed3(x, c0, c1)
1662 if (isa<Constant>(Src0) && !isa<Constant>(Src1)) {
1663 std::swap(Src0, Src1);
1664 Swap = true;
1665 }
1666
1667 if (isa<Constant>(Src1) && !isa<Constant>(Src2)) {
1668 std::swap(Src1, Src2);
1669 Swap = true;
1670 }
1671
1672 if (isa<Constant>(Src0) && !isa<Constant>(Src1)) {
1673 std::swap(Src0, Src1);
1674 Swap = true;
1675 }
1676
1677 if (Swap) {
1678 II.setArgOperand(0, Src0);
1679 II.setArgOperand(1, Src1);
1680 II.setArgOperand(2, Src2);
1681 return &II;
1682 }
1683
1684 if (const ConstantFP *C0 = dyn_cast<ConstantFP>(Src0)) {
1685 if (const ConstantFP *C1 = dyn_cast<ConstantFP>(Src1)) {
1686 if (const ConstantFP *C2 = dyn_cast<ConstantFP>(Src2)) {
1687 APFloat Result = fmed3AMDGCN(C0->getValueAPF(), C1->getValueAPF(),
1688 C2->getValueAPF());
1689 return IC.replaceInstUsesWith(II,
1690 ConstantFP::get(II.getType(), Result));
1691 }
1692 }
1693 }
1694
1695 if (!ST->hasMed3_16())
1696 break;
1697
1698 // Repeat floating-point width reduction done for minnum/maxnum.
1699 // fmed3((fpext X), (fpext Y), (fpext Z)) -> fpext (fmed3(X, Y, Z))
1700 if (Value *X = matchFPExtFromF16(Src0)) {
1701 if (Value *Y = matchFPExtFromF16(Src1)) {
1702 if (Value *Z = matchFPExtFromF16(Src2)) {
1703 Value *NewCall = IC.Builder.CreateIntrinsic(
1704 IID, {X->getType()}, {X, Y, Z}, &II, II.getName());
1705 return new FPExtInst(NewCall, II.getType());
1706 }
1707 }
1708 }
1709
1710 break;
1711 }
1712 case Intrinsic::amdgcn_icmp:
1713 case Intrinsic::amdgcn_fcmp: {
1714 const ConstantInt *CC = cast<ConstantInt>(II.getArgOperand(2));
1715 // Guard against invalid arguments.
1716 int64_t CCVal = CC->getZExtValue();
1717 bool IsInteger = IID == Intrinsic::amdgcn_icmp;
1718 if ((IsInteger && (CCVal < CmpInst::FIRST_ICMP_PREDICATE ||
1719 CCVal > CmpInst::LAST_ICMP_PREDICATE)) ||
1720 (!IsInteger && (CCVal < CmpInst::FIRST_FCMP_PREDICATE ||
1722 break;
1723
1724 Value *Src0 = II.getArgOperand(0);
1725 Value *Src1 = II.getArgOperand(1);
1726
1727 if (auto *CSrc0 = dyn_cast<Constant>(Src0)) {
1728 if (auto *CSrc1 = dyn_cast<Constant>(Src1)) {
1730 (ICmpInst::Predicate)CCVal, CSrc0, CSrc1, DL);
1731 if (CCmp && CCmp->isNullValue()) {
1732 return IC.replaceInstUsesWith(
1733 II, IC.Builder.CreateSExt(CCmp, II.getType()));
1734 }
1735
1736 // The result of V_ICMP/V_FCMP assembly instructions (which this
1737 // intrinsic exposes) is one bit per thread, masked with the EXEC
1738 // register (which contains the bitmask of live threads). So a
1739 // comparison that always returns true is the same as a read of the
1740 // EXEC register. ballot(true) reads EXEC at the wave-size width, so
1741 // zext/trunc the result to the intrinsic's return type.
1742 Type *WaveTy = IC.Builder.getIntNTy(ST->getWavefrontSize());
1743 Value *Ballot = IC.Builder.CreateIntrinsic(
1744 Intrinsic::amdgcn_ballot, WaveTy, IC.Builder.getTrue());
1745 Value *Result = IC.Builder.CreateZExtOrTrunc(Ballot, II.getType());
1746 return IC.replaceInstUsesWith(II, Result);
1747 }
1748
1749 // Canonicalize constants to RHS.
1750 CmpInst::Predicate SwapPred =
1752 II.setArgOperand(0, Src1);
1753 II.setArgOperand(1, Src0);
1754 II.setArgOperand(
1755 2, ConstantInt::get(CC->getType(), static_cast<int>(SwapPred)));
1756 return &II;
1757 }
1758
1759 if (CCVal != CmpInst::ICMP_EQ && CCVal != CmpInst::ICMP_NE)
1760 break;
1761
1762 // Canonicalize compare eq with true value to compare != 0
1763 // llvm.amdgcn.icmp(zext (i1 x), 1, eq)
1764 // -> llvm.amdgcn.icmp(zext (i1 x), 0, ne)
1765 // llvm.amdgcn.icmp(sext (i1 x), -1, eq)
1766 // -> llvm.amdgcn.icmp(sext (i1 x), 0, ne)
1767 Value *ExtSrc;
1768 if (CCVal == CmpInst::ICMP_EQ &&
1769 ((match(Src1, PatternMatch::m_One()) &&
1770 match(Src0, m_ZExt(PatternMatch::m_Value(ExtSrc)))) ||
1771 (match(Src1, PatternMatch::m_AllOnes()) &&
1772 match(Src0, m_SExt(PatternMatch::m_Value(ExtSrc))))) &&
1773 ExtSrc->getType()->isIntegerTy(1)) {
1775 IC.replaceOperand(II, 2,
1776 ConstantInt::get(CC->getType(), CmpInst::ICMP_NE));
1777 return &II;
1778 }
1779
1780 CmpPredicate SrcPred;
1781 Value *SrcLHS;
1782 Value *SrcRHS;
1783
1784 // Fold compare eq/ne with 0 from a compare result as the predicate to the
1785 // intrinsic. The typical use is a wave vote function in the library, which
1786 // will be fed from a user code condition compared with 0. Fold in the
1787 // redundant compare.
1788
1789 // llvm.amdgcn.icmp([sz]ext ([if]cmp pred a, b), 0, ne)
1790 // -> llvm.amdgcn.[if]cmp(a, b, pred)
1791 //
1792 // llvm.amdgcn.icmp([sz]ext ([if]cmp pred a, b), 0, eq)
1793 // -> llvm.amdgcn.[if]cmp(a, b, inv pred)
1794 if (match(Src1, PatternMatch::m_Zero()) &&
1796 m_Cmp(SrcPred, PatternMatch::m_Value(SrcLHS),
1797 PatternMatch::m_Value(SrcRHS))))) {
1798 if (CCVal == CmpInst::ICMP_EQ)
1799 SrcPred = CmpInst::getInversePredicate(SrcPred);
1800
1801 Intrinsic::ID NewIID = CmpInst::isFPPredicate(SrcPred)
1802 ? Intrinsic::amdgcn_fcmp
1803 : Intrinsic::amdgcn_icmp;
1804
1805 Type *Ty = SrcLHS->getType();
1806 if (auto *CmpType = dyn_cast<IntegerType>(Ty)) {
1807 // Promote to next legal integer type.
1808 unsigned Width = CmpType->getBitWidth();
1809 unsigned NewWidth = Width;
1810
1811 // Don't do anything for i1 comparisons.
1812 if (Width == 1)
1813 break;
1814
1815 if (Width <= 16)
1816 NewWidth = 16;
1817 else if (Width <= 32)
1818 NewWidth = 32;
1819 else if (Width <= 64)
1820 NewWidth = 64;
1821 else
1822 break; // Can't handle this.
1823
1824 if (Width != NewWidth) {
1825 IntegerType *CmpTy = IC.Builder.getIntNTy(NewWidth);
1826 if (CmpInst::isSigned(SrcPred)) {
1827 SrcLHS = IC.Builder.CreateSExt(SrcLHS, CmpTy);
1828 SrcRHS = IC.Builder.CreateSExt(SrcRHS, CmpTy);
1829 } else {
1830 SrcLHS = IC.Builder.CreateZExt(SrcLHS, CmpTy);
1831 SrcRHS = IC.Builder.CreateZExt(SrcRHS, CmpTy);
1832 }
1833 }
1834 } else if (!Ty->isFloatTy() && !Ty->isDoubleTy() && !Ty->isHalfTy())
1835 break;
1836
1837 Value *Args[] = {SrcLHS, SrcRHS,
1838 ConstantInt::get(CC->getType(), SrcPred)};
1839 Value *NewCall = IC.Builder.CreateIntrinsic(
1840 NewIID, {II.getType(), SrcLHS->getType()}, Args);
1841 NewCall->takeName(&II);
1842 return IC.replaceInstUsesWith(II, NewCall);
1843 }
1844
1845 break;
1846 }
1847 case Intrinsic::amdgcn_mbcnt_hi:
1848 // exec_hi is all 0, so this is just a copy.
1849 if (ST->isWave32())
1850 return IC.replaceInstUsesWith(II, II.getArgOperand(1));
1851 [[fallthrough]];
1852 case Intrinsic::amdgcn_mbcnt_lo: {
1853 ConstantRange AccRange =
1854 computeConstantRange(II.getArgOperand(1),
1855 /*ForSigned=*/false, IC.getSimplifyQuery());
1856 if (AccRange.isFullSet())
1857 return nullptr;
1858
1859 // TODO: Can raise lower bound by inspecting first argument.
1860 ConstantRange MbcntRange(APInt(32, 0), APInt(32, 32 + 1));
1861 ConstantRange ComputedRange = AccRange.add(MbcntRange);
1862 if (ComputedRange.isFullSet())
1863 return nullptr;
1864
1865 if (std::optional<ConstantRange> ExistingRange = II.getRange()) {
1866 ComputedRange = ComputedRange.intersectWith(*ExistingRange);
1867 if (ComputedRange == *ExistingRange)
1868 return nullptr;
1869 }
1870
1871 II.addRangeRetAttr(ComputedRange);
1872 return nullptr;
1873 }
1874 case Intrinsic::amdgcn_ballot: {
1875 Value *Arg = II.getArgOperand(0);
1876 if (isa<PoisonValue>(Arg))
1877 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
1878
1879 if (auto *Src = dyn_cast<ConstantInt>(Arg)) {
1880 if (Src->isZero()) {
1881 // amdgcn.ballot(i1 0) is zero.
1882 return IC.replaceInstUsesWith(II, Constant::getNullValue(II.getType()));
1883 }
1884 }
1885 if (ST->isWave32() && II.getType()->getIntegerBitWidth() == 64) {
1886 // %b64 = call i64 ballot.i64(...)
1887 // =>
1888 // %b32 = call i32 ballot.i32(...)
1889 // %b64 = zext i32 %b32 to i64
1891 IC.Builder.CreateIntrinsic(Intrinsic::amdgcn_ballot,
1892 {IC.Builder.getInt32Ty()},
1893 {II.getArgOperand(0)}),
1894 II.getType());
1895 Call->takeName(&II);
1896 return IC.replaceInstUsesWith(II, Call);
1897 }
1898 break;
1899 }
1900 case Intrinsic::amdgcn_wavefrontsize: {
1901 if (ST->isWaveSizeKnown())
1902 return IC.replaceInstUsesWith(
1903 II, ConstantInt::get(II.getType(), ST->getWavefrontSize()));
1904 break;
1905 }
1906 case Intrinsic::amdgcn_wqm_vote: {
1907 // wqm_vote is identity when the argument is constant.
1908 if (!isa<Constant>(II.getArgOperand(0)))
1909 break;
1910
1911 return IC.replaceInstUsesWith(II, II.getArgOperand(0));
1912 }
1913 case Intrinsic::amdgcn_kill: {
1914 const ConstantInt *C = dyn_cast<ConstantInt>(II.getArgOperand(0));
1915 if (!C || !C->getZExtValue())
1916 break;
1917
1918 // amdgcn.kill(i1 1) is a no-op
1919 return IC.eraseInstFromFunction(II);
1920 }
1921 case Intrinsic::amdgcn_s_sendmsg:
1922 case Intrinsic::amdgcn_s_sendmsghalt: {
1923 // The second operand is copied to m0, but is only actually used for
1924 // certain message types. For message types that are known to not use m0,
1925 // fold it to poison.
1926 using namespace AMDGPU::SendMsg;
1927
1928 Value *M0Val = II.getArgOperand(1);
1929 if (isa<PoisonValue>(M0Val))
1930 break;
1931
1932 auto *MsgImm = cast<ConstantInt>(II.getArgOperand(0));
1933 uint16_t MsgId, OpId, StreamId;
1934 decodeMsg(MsgImm->getZExtValue(), MsgId, OpId, StreamId, *ST);
1935
1936 if (!msgDoesNotUseM0(MsgId, *ST))
1937 break;
1938
1939 // Drop UB-implying attributes since we're replacing with poison.
1940 II.dropUBImplyingAttrsAndMetadata();
1941 IC.replaceOperand(II, 1, PoisonValue::get(M0Val->getType()));
1942 return nullptr;
1943 }
1944 case Intrinsic::amdgcn_update_dpp: {
1945 Value *Old = II.getArgOperand(0);
1946
1947 auto *BC = cast<ConstantInt>(II.getArgOperand(5));
1948 auto *RM = cast<ConstantInt>(II.getArgOperand(3));
1949 auto *BM = cast<ConstantInt>(II.getArgOperand(4));
1950 if (BC->isNullValue() || RM->getZExtValue() != 0xF ||
1951 BM->getZExtValue() != 0xF || isa<PoisonValue>(Old))
1952 break;
1953
1954 // If bound_ctrl = 1, row mask = bank mask = 0xf we can omit old value.
1955 return IC.replaceOperand(II, 0, PoisonValue::get(Old->getType()));
1956 }
1957 case Intrinsic::amdgcn_permlane16:
1958 case Intrinsic::amdgcn_permlane16_var:
1959 case Intrinsic::amdgcn_permlanex16:
1960 case Intrinsic::amdgcn_permlanex16_var: {
1961 // Discard vdst_in if it's not going to be read.
1962 Value *VDstIn = II.getArgOperand(0);
1963 if (isa<PoisonValue>(VDstIn))
1964 break;
1965
1966 // FetchInvalid operand idx.
1967 unsigned int FiIdx = (IID == Intrinsic::amdgcn_permlane16 ||
1968 IID == Intrinsic::amdgcn_permlanex16)
1969 ? 4 /* for permlane16 and permlanex16 */
1970 : 3; /* for permlane16_var and permlanex16_var */
1971
1972 // BoundCtrl operand idx.
1973 // For permlane16 and permlanex16 it should be 5
1974 // For Permlane16_var and permlanex16_var it should be 4
1975 unsigned int BcIdx = FiIdx + 1;
1976
1977 ConstantInt *FetchInvalid = cast<ConstantInt>(II.getArgOperand(FiIdx));
1978 ConstantInt *BoundCtrl = cast<ConstantInt>(II.getArgOperand(BcIdx));
1979 if (!FetchInvalid->getZExtValue() && !BoundCtrl->getZExtValue())
1980 break;
1981
1982 return IC.replaceOperand(II, 0, PoisonValue::get(VDstIn->getType()));
1983 }
1984 case Intrinsic::amdgcn_wave_shuffle:
1985 return tryOptimizeShufflePattern(IC, II, *ST);
1986 case Intrinsic::amdgcn_permlane64:
1987 case Intrinsic::amdgcn_readfirstlane:
1988 case Intrinsic::amdgcn_readlane:
1989 case Intrinsic::amdgcn_ds_bpermute: {
1990 // If the data argument is uniform these intrinsics return it unchanged.
1991 unsigned SrcIdx = IID == Intrinsic::amdgcn_ds_bpermute ? 1 : 0;
1992 const Use &Src = II.getArgOperandUse(SrcIdx);
1993 if (isTriviallyUniform(Src))
1994 return IC.replaceInstUsesWith(II, Src.get());
1995
1996 if (IID == Intrinsic::amdgcn_readlane &&
1998 return &II;
1999
2000 // If the lane argument of bpermute is uniform, change it to readlane. This
2001 // generates better code and can enable further optimizations because
2002 // readlane is AlwaysUniform.
2003 if (IID == Intrinsic::amdgcn_ds_bpermute) {
2004 const Use &Lane = II.getArgOperandUse(0);
2005 if (isTriviallyUniform(Lane)) {
2006 Value *NewLane = IC.Builder.CreateLShr(Lane, 2);
2008 II.getModule(), Intrinsic::amdgcn_readlane, II.getType());
2009 II.setCalledFunction(NewDecl);
2010 II.setOperand(0, Src);
2011 II.setOperand(1, NewLane);
2012 return &II;
2013 }
2014 }
2015
2016 if (IID == Intrinsic::amdgcn_ds_bpermute)
2017 return tryOptimizeShufflePattern(IC, II, *ST);
2018
2020 return Res;
2021
2022 return std::nullopt;
2023 }
2024 case Intrinsic::amdgcn_writelane: {
2025 // TODO: Fold bitcast like readlane.
2026 if (simplifyDemandedLaneMaskArg(IC, II, 1))
2027 return &II;
2028 return std::nullopt;
2029 }
2030 case Intrinsic::amdgcn_trig_preop: {
2031 // The intrinsic is declared with name mangling, but currently the
2032 // instruction only exists for f64
2033 if (!II.getType()->isDoubleTy())
2034 break;
2035
2036 Value *Src = II.getArgOperand(0);
2037 Value *Segment = II.getArgOperand(1);
2038 if (isa<PoisonValue>(Src) || isa<PoisonValue>(Segment))
2039 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
2040
2041 if (isa<UndefValue>(Segment))
2042 return IC.replaceInstUsesWith(II, ConstantFP::getZero(II.getType()));
2043
2044 // Sign bit is not used.
2045 Value *StrippedSign = InstCombiner::stripSignOnlyFPOps(Src);
2046 if (StrippedSign != Src)
2047 return IC.replaceOperand(II, 0, StrippedSign);
2048
2049 if (II.isStrictFP())
2050 break;
2051
2052 const ConstantFP *CSrc = dyn_cast<ConstantFP>(Src);
2053 if (!CSrc && !isa<UndefValue>(Src))
2054 break;
2055
2056 // The instruction ignores special cases, and literally just extracts the
2057 // exponents. Fold undef to nan, and index the table as normal.
2058 APInt FSrcInt = CSrc ? CSrc->getValueAPF().bitcastToAPInt()
2059 : APFloat::getQNaN(II.getType()->getFltSemantics())
2060 .bitcastToAPInt();
2061
2062 const ConstantInt *Cseg = dyn_cast<ConstantInt>(Segment);
2063 if (!Cseg) {
2064 if (isa<UndefValue>(Src))
2065 return IC.replaceInstUsesWith(II, ConstantFP::getZero(II.getType()));
2066 break;
2067 }
2068
2069 unsigned Exponent = FSrcInt.extractBitsAsZExtValue(11, 52);
2070 unsigned SegmentVal = Cseg->getValue().trunc(5).getZExtValue();
2071 unsigned Shift = SegmentVal * 53;
2072 if (Exponent > 1077)
2073 Shift += Exponent - 1077;
2074
2075 // 2.0/PI table.
2076 static const uint32_t TwoByPi[] = {
2077 0xa2f9836e, 0x4e441529, 0xfc2757d1, 0xf534ddc0, 0xdb629599, 0x3c439041,
2078 0xfe5163ab, 0xdebbc561, 0xb7246e3a, 0x424dd2e0, 0x06492eea, 0x09d1921c,
2079 0xfe1deb1c, 0xb129a73e, 0xe88235f5, 0x2ebb4484, 0xe99c7026, 0xb45f7e41,
2080 0x3991d639, 0x835339f4, 0x9c845f8b, 0xbdf9283b, 0x1ff897ff, 0xde05980f,
2081 0xef2f118b, 0x5a0a6d1f, 0x6d367ecf, 0x27cb09b7, 0x4f463f66, 0x9e5fea2d,
2082 0x7527bac7, 0xebe5f17b, 0x3d0739f7, 0x8a5292ea, 0x6bfb5fb1, 0x1f8d5d08,
2083 0x56033046};
2084
2085 // Return 0 for outbound segment (hardware behavior).
2086 unsigned Idx = Shift >> 5;
2087 if (Idx + 2 >= std::size(TwoByPi)) {
2088 APFloat Zero = APFloat::getZero(II.getType()->getFltSemantics());
2089 return IC.replaceInstUsesWith(II, ConstantFP::get(II.getType(), Zero));
2090 }
2091
2092 unsigned BShift = Shift & 0x1f;
2093 uint64_t Thi = Make_64(TwoByPi[Idx], TwoByPi[Idx + 1]);
2094 uint64_t Tlo = Make_64(TwoByPi[Idx + 2], 0);
2095 if (BShift)
2096 Thi = (Thi << BShift) | (Tlo >> (64 - BShift));
2097 Thi = Thi >> 11;
2098 APFloat Result = APFloat((double)Thi);
2099
2100 int Scale = -53 - Shift;
2101 if (Exponent >= 1968)
2102 Scale += 128;
2103
2104 Result = scalbn(Result, Scale, RoundingMode::NearestTiesToEven);
2105 return IC.replaceInstUsesWith(II, ConstantFP::get(Src->getType(), Result));
2106 }
2107 case Intrinsic::amdgcn_fmul_legacy: {
2108 Value *Op0 = II.getArgOperand(0);
2109 Value *Op1 = II.getArgOperand(1);
2110
2111 for (Value *Src : {Op0, Op1}) {
2112 if (isa<PoisonValue>(Src))
2113 return IC.replaceInstUsesWith(II, Src);
2114 }
2115
2116 // The legacy behaviour is that multiplying +/-0.0 by anything, even NaN or
2117 // infinity, gives +0.0.
2118 // TODO: Move to InstSimplify?
2119 if (match(Op0, PatternMatch::m_AnyZeroFP()) ||
2121 return IC.replaceInstUsesWith(II, ConstantFP::getZero(II.getType()));
2122
2123 // If we can prove we don't have one of the special cases then we can use a
2124 // normal fmul instruction instead.
2125 if (canSimplifyLegacyMulToMul(II, Op0, Op1, IC)) {
2126 auto *FMul = IC.Builder.CreateFMulFMF(Op0, Op1, &II);
2127 FMul->takeName(&II);
2128 return IC.replaceInstUsesWith(II, FMul);
2129 }
2130 break;
2131 }
2132 case Intrinsic::amdgcn_fma_legacy: {
2133 Value *Op0 = II.getArgOperand(0);
2134 Value *Op1 = II.getArgOperand(1);
2135 Value *Op2 = II.getArgOperand(2);
2136
2137 for (Value *Src : {Op0, Op1, Op2}) {
2138 if (isa<PoisonValue>(Src))
2139 return IC.replaceInstUsesWith(II, Src);
2140 }
2141
2142 // The legacy behaviour is that multiplying +/-0.0 by anything, even NaN or
2143 // infinity, gives +0.0.
2144 // TODO: Move to InstSimplify?
2145 if (match(Op0, PatternMatch::m_AnyZeroFP()) ||
2147 // It's tempting to just return Op2 here, but that would give the wrong
2148 // result if Op2 was -0.0.
2149 auto *Zero = ConstantFP::getZero(II.getType());
2150 auto *FAdd = IC.Builder.CreateFAddFMF(Zero, Op2, &II);
2151 FAdd->takeName(&II);
2152 return IC.replaceInstUsesWith(II, FAdd);
2153 }
2154
2155 // If we can prove we don't have one of the special cases then we can use a
2156 // normal fma instead.
2157 if (canSimplifyLegacyMulToMul(II, Op0, Op1, IC)) {
2158 II.setCalledOperand(Intrinsic::getOrInsertDeclaration(
2159 II.getModule(), Intrinsic::fma, II.getType()));
2160 return &II;
2161 }
2162 break;
2163 }
2164 case Intrinsic::amdgcn_is_shared:
2165 case Intrinsic::amdgcn_is_private: {
2166 Value *Src = II.getArgOperand(0);
2167 if (isa<PoisonValue>(Src))
2168 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
2169 if (isa<UndefValue>(Src))
2170 return IC.replaceInstUsesWith(II, UndefValue::get(II.getType()));
2171
2172 if (isa<ConstantPointerNull>(II.getArgOperand(0)))
2173 return IC.replaceInstUsesWith(II, ConstantInt::getFalse(II.getType()));
2174 break;
2175 }
2176 case Intrinsic::amdgcn_make_buffer_rsrc: {
2177 Value *Src = II.getArgOperand(0);
2178 if (isa<PoisonValue>(Src))
2179 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
2180 return std::nullopt;
2181 }
2182 case Intrinsic::amdgcn_raw_buffer_store_format:
2183 case Intrinsic::amdgcn_struct_buffer_store_format:
2184 case Intrinsic::amdgcn_raw_tbuffer_store:
2185 case Intrinsic::amdgcn_struct_tbuffer_store:
2186 case Intrinsic::amdgcn_image_store_1d:
2187 case Intrinsic::amdgcn_image_store_1darray:
2188 case Intrinsic::amdgcn_image_store_2d:
2189 case Intrinsic::amdgcn_image_store_2darray:
2190 case Intrinsic::amdgcn_image_store_2darraymsaa:
2191 case Intrinsic::amdgcn_image_store_2dmsaa:
2192 case Intrinsic::amdgcn_image_store_3d:
2193 case Intrinsic::amdgcn_image_store_cube:
2194 case Intrinsic::amdgcn_image_store_mip_1d:
2195 case Intrinsic::amdgcn_image_store_mip_1darray:
2196 case Intrinsic::amdgcn_image_store_mip_2d:
2197 case Intrinsic::amdgcn_image_store_mip_2darray:
2198 case Intrinsic::amdgcn_image_store_mip_3d:
2199 case Intrinsic::amdgcn_image_store_mip_cube: {
2200 if (!isa<FixedVectorType>(II.getArgOperand(0)->getType()))
2201 break;
2202
2203 APInt DemandedElts;
2204 if (ST->hasDefaultComponentBroadcast())
2205 DemandedElts = defaultComponentBroadcast(II.getArgOperand(0));
2206 else if (ST->hasDefaultComponentZero())
2207 DemandedElts = trimTrailingZerosInVector(IC, II.getArgOperand(0), &II);
2208 else
2209 break;
2210
2211 int DMaskIdx = getAMDGPUImageDMaskIntrinsic(II.getIntrinsicID()) ? 1 : -1;
2212 if (simplifyAMDGCNMemoryIntrinsicDemanded(IC, II, DemandedElts, DMaskIdx,
2213 false)) {
2214 return IC.eraseInstFromFunction(II);
2215 }
2216
2217 break;
2218 }
2219 case Intrinsic::amdgcn_prng_b32: {
2220 auto *Src = II.getArgOperand(0);
2221 if (isa<UndefValue>(Src)) {
2222 return IC.replaceInstUsesWith(II, Src);
2223 }
2224 return std::nullopt;
2225 }
2226 case Intrinsic::amdgcn_mfma_scale_f32_16x16x128_f8f6f4:
2227 case Intrinsic::amdgcn_mfma_scale_f32_32x32x64_f8f6f4: {
2228 Value *Src0 = II.getArgOperand(0);
2229 Value *Src1 = II.getArgOperand(1);
2230 uint64_t CBSZ = cast<ConstantInt>(II.getArgOperand(3))->getZExtValue();
2231 uint64_t BLGP = cast<ConstantInt>(II.getArgOperand(4))->getZExtValue();
2232 auto *Src0Ty = cast<FixedVectorType>(Src0->getType());
2233 auto *Src1Ty = cast<FixedVectorType>(Src1->getType());
2234
2235 auto getFormatNumRegs = [](unsigned FormatVal) {
2236 switch (FormatVal) {
2239 return 6u;
2241 return 4u;
2244 return 8u;
2245 default:
2246 llvm_unreachable("invalid format value");
2247 }
2248 };
2249
2250 bool MadeChange = false;
2251 unsigned Src0NumElts = getFormatNumRegs(CBSZ);
2252 unsigned Src1NumElts = getFormatNumRegs(BLGP);
2253
2254 // Depending on the used format, fewer registers are required so shrink the
2255 // vector type.
2256 if (Src0Ty->getNumElements() > Src0NumElts) {
2257 Src0 = IC.Builder.CreateExtractVector(
2258 FixedVectorType::get(Src0Ty->getElementType(), Src0NumElts), Src0,
2259 uint64_t(0));
2260 MadeChange = true;
2261 }
2262
2263 if (Src1Ty->getNumElements() > Src1NumElts) {
2264 Src1 = IC.Builder.CreateExtractVector(
2265 FixedVectorType::get(Src1Ty->getElementType(), Src1NumElts), Src1,
2266 uint64_t(0));
2267 MadeChange = true;
2268 }
2269
2270 if (!MadeChange)
2271 return std::nullopt;
2272
2273 SmallVector<Value *, 10> Args(II.args());
2274 Args[0] = Src0;
2275 Args[1] = Src1;
2276
2277 Value *NewII = IC.Builder.CreateIntrinsic(
2278 IID, {Src0->getType(), Src1->getType()}, Args, &II);
2279 NewII->takeName(&II);
2280 return IC.replaceInstUsesWith(II, NewII);
2281 }
2282 case Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4:
2283 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
2284 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
2285 Value *Src0 = II.getArgOperand(1);
2286 Value *Src1 = II.getArgOperand(3);
2287 unsigned FmtA = cast<ConstantInt>(II.getArgOperand(0))->getZExtValue();
2288 uint64_t FmtB = cast<ConstantInt>(II.getArgOperand(2))->getZExtValue();
2289 auto *Src0Ty = cast<FixedVectorType>(Src0->getType());
2290 auto *Src1Ty = cast<FixedVectorType>(Src1->getType());
2291
2292 bool MadeChange = false;
2293 unsigned Src0NumElts = AMDGPU::wmmaScaleF8F6F4FormatToNumRegs(FmtA);
2294 unsigned Src1NumElts = AMDGPU::wmmaScaleF8F6F4FormatToNumRegs(FmtB);
2295
2296 // Depending on the used format, fewer registers are required so shrink the
2297 // vector type.
2298 if (Src0Ty->getNumElements() > Src0NumElts) {
2299 Src0 = IC.Builder.CreateExtractVector(
2300 FixedVectorType::get(Src0Ty->getElementType(), Src0NumElts), Src0,
2301 IC.Builder.getInt64(0));
2302 MadeChange = true;
2303 }
2304
2305 if (Src1Ty->getNumElements() > Src1NumElts) {
2306 Src1 = IC.Builder.CreateExtractVector(
2307 FixedVectorType::get(Src1Ty->getElementType(), Src1NumElts), Src1,
2308 IC.Builder.getInt64(0));
2309 MadeChange = true;
2310 }
2311
2312 if (!MadeChange)
2313 return std::nullopt;
2314
2315 SmallVector<Value *, 13> Args(II.args());
2316 Args[1] = Src0;
2317 Args[3] = Src1;
2318
2319 Value *NewII = IC.Builder.CreateIntrinsic(
2320 IID, {II.getArgOperand(5)->getType(), Src0->getType(), Src1->getType()},
2321 Args, &II);
2322 NewII->takeName(&II);
2323 return IC.replaceInstUsesWith(II, NewII);
2324 }
2325 }
2326 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
2327 AMDGPU::getImageDimIntrinsicInfo(II.getIntrinsicID())) {
2328 return simplifyAMDGCNImageIntrinsic(ST, ImageDimIntr, II, IC);
2329 }
2330 return std::nullopt;
2331}
2332
2333/// Implement SimplifyDemandedVectorElts for amdgcn buffer and image intrinsics.
2334///
2335/// The result of simplifying amdgcn image and buffer store intrinsics is updating
2336/// definitions of the intrinsics vector argument, not Uses of the result like
2337/// image and buffer loads.
2338/// Note: This only supports non-TFE/LWE image intrinsic calls; those have
2339/// struct returns.
2342 APInt DemandedElts,
2343 int DMaskIdx, bool IsLoad) {
2344
2345 auto *IIVTy = cast<FixedVectorType>(IsLoad ? II.getType()
2346 : II.getOperand(0)->getType());
2347 unsigned VWidth = IIVTy->getNumElements();
2348 if (VWidth == 1)
2349 return nullptr;
2350 Type *EltTy = IIVTy->getElementType();
2351
2354
2355 // Assume the arguments are unchanged and later override them, if needed.
2356 SmallVector<Value *, 16> Args(II.args());
2357
2358 if (DMaskIdx < 0) {
2359 // Buffer case.
2360
2361 const unsigned ActiveBits = DemandedElts.getActiveBits();
2362 const unsigned UnusedComponentsAtFront = DemandedElts.countr_zero();
2363
2364 // Start assuming the prefix of elements is demanded, but possibly clear
2365 // some other bits if there are trailing zeros (unused components at front)
2366 // and update offset.
2367 DemandedElts = (1 << ActiveBits) - 1;
2368
2369 if (UnusedComponentsAtFront > 0) {
2370 static const unsigned InvalidOffsetIdx = 0xf;
2371
2372 unsigned OffsetIdx;
2373 switch (II.getIntrinsicID()) {
2374 case Intrinsic::amdgcn_raw_buffer_load:
2375 case Intrinsic::amdgcn_raw_ptr_buffer_load:
2376 OffsetIdx = 1;
2377 break;
2378 case Intrinsic::amdgcn_s_buffer_load:
2379 case Intrinsic::amdgcn_ptr_s_buffer_load:
2380 // If resulting type is vec3, there is no point in trimming the
2381 // load with updated offset, as the vec3 would most likely be widened to
2382 // vec4 anyway during lowering.
2383 if (ActiveBits == 4 && UnusedComponentsAtFront == 1)
2384 OffsetIdx = InvalidOffsetIdx;
2385 else
2386 OffsetIdx = 1;
2387 break;
2388 case Intrinsic::amdgcn_struct_buffer_load:
2389 case Intrinsic::amdgcn_struct_ptr_buffer_load:
2390 OffsetIdx = 2;
2391 break;
2392 default:
2393 // TODO: handle tbuffer* intrinsics.
2394 OffsetIdx = InvalidOffsetIdx;
2395 break;
2396 }
2397
2398 if (OffsetIdx != InvalidOffsetIdx) {
2399 // Clear demanded bits and update the offset.
2400 DemandedElts &= ~((1 << UnusedComponentsAtFront) - 1);
2401 auto *Offset = Args[OffsetIdx];
2402 unsigned SingleComponentSizeInBits =
2403 IC.getDataLayout().getTypeSizeInBits(EltTy);
2404 unsigned OffsetAdd =
2405 UnusedComponentsAtFront * SingleComponentSizeInBits / 8;
2406 auto *OffsetAddVal = ConstantInt::get(Offset->getType(), OffsetAdd);
2407 Args[OffsetIdx] = IC.Builder.CreateAdd(Offset, OffsetAddVal);
2408 }
2409 }
2410 } else {
2411 // Image case.
2412
2413 ConstantInt *DMask = cast<ConstantInt>(Args[DMaskIdx]);
2414 unsigned DMaskVal = DMask->getZExtValue() & 0xf;
2415
2416 // dmask 0 has special semantics, do not simplify.
2417 if (DMaskVal == 0)
2418 return nullptr;
2419
2420 if (!IsLoad && !isMask_32(DMaskVal))
2421 return nullptr;
2422
2423 // Mask off values that are undefined because the dmask doesn't cover them
2424 DemandedElts &= (1 << llvm::popcount(DMaskVal)) - 1;
2425
2426 unsigned NewDMaskVal = 0;
2427 unsigned OrigLdStIdx = 0;
2428 for (unsigned SrcIdx = 0; SrcIdx < 4; ++SrcIdx) {
2429 const unsigned Bit = 1 << SrcIdx;
2430 if (!!(DMaskVal & Bit)) {
2431 if (!!DemandedElts[OrigLdStIdx])
2432 NewDMaskVal |= Bit;
2433 OrigLdStIdx++;
2434 }
2435 }
2436
2437 if (DMaskVal != NewDMaskVal)
2438 Args[DMaskIdx] = ConstantInt::get(DMask->getType(), NewDMaskVal);
2439 }
2440
2441 unsigned NewNumElts = DemandedElts.popcount();
2442 if (!NewNumElts)
2443 return PoisonValue::get(IIVTy);
2444
2445 if (NewNumElts >= VWidth && DemandedElts.isMask()) {
2446 if (DMaskIdx >= 0)
2447 II.setArgOperand(DMaskIdx, Args[DMaskIdx]);
2448 return nullptr;
2449 }
2450
2451 // Validate function argument and return types, extracting overloaded types
2452 // along the way.
2453 SmallVector<Type *, 6> OverloadTys;
2454 if (!Intrinsic::isSignatureValid(II.getCalledFunction(), OverloadTys))
2455 return nullptr;
2456
2457 Type *NewTy =
2458 (NewNumElts == 1) ? EltTy : FixedVectorType::get(EltTy, NewNumElts);
2459 OverloadTys[0] = NewTy;
2460
2461 if (!IsLoad) {
2462 SmallVector<int, 8> EltMask;
2463 for (unsigned OrigStoreIdx = 0; OrigStoreIdx < VWidth; ++OrigStoreIdx)
2464 if (DemandedElts[OrigStoreIdx])
2465 EltMask.push_back(OrigStoreIdx);
2466
2467 if (NewNumElts == 1)
2468 Args[0] = IC.Builder.CreateExtractElement(II.getOperand(0), EltMask[0]);
2469 else
2470 Args[0] = IC.Builder.CreateShuffleVector(II.getOperand(0), EltMask);
2471 }
2472
2474 II.getIntrinsicID(), OverloadTys, Args);
2475 NewCall->takeName(&II);
2476 NewCall->copyMetadata(II);
2477 AttributeList OldAttrList = II.getAttributes();
2478 NewCall->setAttributes(OldAttrList);
2479
2480 if (IsLoad) {
2481 if (NewNumElts == 1) {
2482 return IC.Builder.CreateInsertElement(PoisonValue::get(IIVTy), NewCall,
2483 DemandedElts.countr_zero());
2484 }
2485
2486 SmallVector<int, 8> EltMask;
2487 unsigned NewLoadIdx = 0;
2488 for (unsigned OrigLoadIdx = 0; OrigLoadIdx < VWidth; ++OrigLoadIdx) {
2489 if (!!DemandedElts[OrigLoadIdx])
2490 EltMask.push_back(NewLoadIdx++);
2491 else
2492 EltMask.push_back(NewNumElts);
2493 }
2494
2495 auto *Shuffle = IC.Builder.CreateShuffleVector(NewCall, EltMask);
2496
2497 return Shuffle;
2498 }
2499
2500 return NewCall;
2501}
2502
2504 InstCombiner &IC, IntrinsicInst &II, const APInt &DemandedElts,
2505 APInt &UndefElts) const {
2506 auto *VT = dyn_cast<FixedVectorType>(II.getType());
2507 if (!VT)
2508 return nullptr;
2509
2510 const unsigned FirstElt = DemandedElts.countr_zero();
2511 const unsigned LastElt = DemandedElts.getActiveBits() - 1;
2512 const unsigned MaskLen = LastElt - FirstElt + 1;
2513
2514 unsigned OldNumElts = VT->getNumElements();
2515 if (MaskLen == OldNumElts && MaskLen != 1)
2516 return nullptr;
2517
2518 Type *EltTy = VT->getElementType();
2519 Type *NewVT = MaskLen == 1 ? EltTy : FixedVectorType::get(EltTy, MaskLen);
2520
2521 // Theoretically we should support these intrinsics for any legal type. Avoid
2522 // introducing cases that aren't direct register types like v3i16.
2523 if (!isTypeLegal(NewVT))
2524 return nullptr;
2525
2526 Value *Src = II.getArgOperand(0);
2527
2528 // Make sure convergence tokens are preserved.
2529 // TODO: CreateIntrinsic should allow directly copying bundles
2531 II.getOperandBundlesAsDefs(OpBundles);
2532
2534 Function *Remangled =
2535 Intrinsic::getOrInsertDeclaration(M, II.getIntrinsicID(), {NewVT});
2536
2537 if (MaskLen == 1) {
2538 Value *Extract = IC.Builder.CreateExtractElement(Src, FirstElt);
2539
2540 // TODO: Preserve callsite attributes?
2541 CallInst *NewCall = IC.Builder.CreateCall(Remangled, {Extract}, OpBundles);
2542
2543 return IC.Builder.CreateInsertElement(PoisonValue::get(II.getType()),
2544 NewCall, FirstElt);
2545 }
2546
2547 SmallVector<int> ExtractMask(MaskLen, -1);
2548 for (unsigned I = 0; I != MaskLen; ++I) {
2549 if (DemandedElts[FirstElt + I])
2550 ExtractMask[I] = FirstElt + I;
2551 }
2552
2553 Value *Extract = IC.Builder.CreateShuffleVector(Src, ExtractMask);
2554
2555 // TODO: Preserve callsite attributes?
2556 CallInst *NewCall = IC.Builder.CreateCall(Remangled, {Extract}, OpBundles);
2557
2558 SmallVector<int> InsertMask(OldNumElts, -1);
2559 for (unsigned I = 0; I != MaskLen; ++I) {
2560 if (DemandedElts[FirstElt + I])
2561 InsertMask[FirstElt + I] = I;
2562 }
2563
2564 // FIXME: If the call has a convergence bundle, we end up leaving the dead
2565 // call behind.
2566 return IC.Builder.CreateShuffleVector(NewCall, InsertMask);
2567}
2568
2570 InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts,
2571 APInt &UndefElts2, APInt &UndefElts3,
2572 std::function<void(Instruction *, unsigned, APInt, APInt &)>
2573 SimplifyAndSetOp) const {
2574 switch (II.getIntrinsicID()) {
2575 case Intrinsic::amdgcn_readfirstlane:
2576 SimplifyAndSetOp(&II, 0, DemandedElts, UndefElts);
2577 return simplifyAMDGCNLaneIntrinsicDemanded(IC, II, DemandedElts, UndefElts);
2578 case Intrinsic::amdgcn_raw_buffer_load:
2579 case Intrinsic::amdgcn_raw_ptr_buffer_load:
2580 case Intrinsic::amdgcn_raw_buffer_load_format:
2581 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
2582 case Intrinsic::amdgcn_raw_tbuffer_load:
2583 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
2584 case Intrinsic::amdgcn_s_buffer_load:
2585 case Intrinsic::amdgcn_ptr_s_buffer_load:
2586 case Intrinsic::amdgcn_struct_buffer_load:
2587 case Intrinsic::amdgcn_struct_ptr_buffer_load:
2588 case Intrinsic::amdgcn_struct_buffer_load_format:
2589 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
2590 case Intrinsic::amdgcn_struct_tbuffer_load:
2591 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
2592 return simplifyAMDGCNMemoryIntrinsicDemanded(IC, II, DemandedElts);
2593 default: {
2594 if (getAMDGPUImageDMaskIntrinsic(II.getIntrinsicID())) {
2595 return simplifyAMDGCNMemoryIntrinsicDemanded(IC, II, DemandedElts, 0);
2596 }
2597 break;
2598 }
2599 }
2600 return std::nullopt;
2601}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Value * createPermlane16(IRBuilderBase &B, Value *Val, uint32_t Lo, uint32_t Hi)
Emit v_permlane16 with the precomputed lane-select halves.
static std::optional< unsigned > matchRowSharePattern(ArrayRef< uint8_t > Ids)
Match a row-share pattern: all 16 lanes of each row read the same source lane.
static bool matchMirrorPattern(ArrayRef< uint8_t > Ids)
Match an N-lane reversal (mirror) pattern.
static bool canSafelyConvertTo16Bit(Value &V, bool IsFloat, bool AllowI16SExt=false)
static bool tryBuildShuffleMap(Value *Index, const GCNSubtarget &ST, SmallVectorImpl< uint8_t > &Ids, const DataLayout &DL)
Build the per-lane shuffle map by evaluating Index for every lane in the wave.
static std::optional< unsigned > matchQuadPermPattern(ArrayRef< uint8_t > Ids)
Match a 4-lane (quad) permutation, encoded as the v_mov_b32_dpp QUAD_PERM control word: bits[1:0]=Ids...
static std::optional< unsigned > matchDsSwizzleRotatePattern(ArrayRef< uint8_t > Ids)
Match a GFX9+ DS_SWIZZLE rotate-mode permutation: a cyclic left-rotation of all 32 lanes within each ...
static std::optional< unsigned > matchHalfRowPermPattern(ArrayRef< uint8_t > Ids)
Match an 8-lane arbitrary permutation, encoded as the v_mov_b32_dpp8 24-bit selector (three bits per ...
static std::optional< unsigned > matchRowXMaskPattern(ArrayRef< uint8_t > Ids)
Match an XOR mask pattern within each 16-lane row: Ids[J] == Mask ^ J, with Mask in [1,...
static constexpr auto matchHalfRowMirrorPattern
static Value * createPermlaneX16(IRBuilderBase &B, Value *Val, uint32_t Lo, uint32_t Hi)
Emit v_permlanex16 with the precomputed lane-select halves.
static bool isRowPattern(ArrayRef< uint8_t > Ids)
Match an N-lane row pattern: each lane in [0, N) reads from a source lane in the same N-lane row,...
static bool canContractSqrtToRsq(const FPMathOperator *SqrtOp)
Return true if it's legal to contract llvm.amdgcn.rcp(llvm.sqrt)
static bool isTriviallyUniform(const Use &U)
Return true if we can easily prove that use U is uniform.
static CallInst * rewriteCall(IRBuilderBase &B, CallInst &Old, Function &NewCallee, ArrayRef< Value * > Ops)
static Value * convertTo16Bit(Value &V, InstCombiner::BuilderTy &Builder)
static constexpr auto isFullRowPattern
static constexpr auto isQuadPattern
static APInt trimTrailingZerosInVector(InstCombiner &IC, Value *UseV, Instruction *I)
static uint64_t computePermlane16Masks(ArrayRef< uint8_t > Ids)
Pack a 16-lane permutation into a single 64-bit value: four bits per output lane, lane J in bits [J*4...
static bool matchHalfWaveSwapPattern(ArrayRef< uint8_t > Ids)
Match a half-wave swap: lane J reads from lane J ^ 32.
static bool hasPeriodicLayout(ArrayRef< uint8_t > Ids)
Lanes are partitioned into groups of Period; each group is a translated copy of the first: Ids[I] = I...
static std::optional< Instruction * > tryOptimizeShufflePattern(InstCombiner &IC, IntrinsicInst &II, const GCNSubtarget &ST)
Try to fold a wave_shuffle/ds_bpermute whose lane index is a constant function of the lane ID into a ...
static constexpr auto isHalfRowPattern
static APInt defaultComponentBroadcast(Value *V)
static std::optional< unsigned > matchDsSwizzleBitmaskPattern(ArrayRef< uint8_t > Ids)
Match a DS_SWIZZLE bitmask-mode permutation: dst_lane = ((src_lane & AND) | OR) ^ XOR with each mask ...
static Value * createDsSwizzle(IRBuilderBase &B, Value *Val, unsigned Offset, const DataLayout &DL)
Emit ds_swizzle with the given immediate, bitcasting/converting between pointer/float types and i32 a...
static std::optional< Instruction * > modifyIntrinsicCall(IntrinsicInst &OldIntr, Instruction &InstToReplace, unsigned NewIntr, InstCombiner &IC, std::function< void(SmallVectorImpl< Value * > &, SmallVectorImpl< Type * > &)> Func)
Applies Func(OldIntr.Args, OldIntr.ArgTys), creates intrinsic call with modified arguments (based on ...
static Value * matchShuffleToHWIntrinsic(IRBuilderBase &B, Value *Src, ArrayRef< uint8_t > Ids, const GCNSubtarget &ST, const DataLayout &DL)
Given a shuffle map, try to emit the best hardware intrinsic.
static std::optional< unsigned > matchRowRotatePattern(ArrayRef< uint8_t > Ids)
Match a 16-lane cyclic rotation; returns the rotation amount in [1, 15].
static bool isCrossRowPattern(ArrayRef< uint8_t > Ids)
Match a cross-row permutation suitable for v_permlanex16: every lane in the low 16-lane half reads fr...
static bool isThreadID(const GCNSubtarget &ST, Value *V)
static Value * createUpdateDpp(IRBuilderBase &B, Value *Val, unsigned Ctrl)
Emit v_mov_b32_dpp with the given control word, row/bank masks 0xF, and bound_ctrl=1 so out-of-bounds...
static APFloat fmed3AMDGCN(const APFloat &Src0, const APFloat &Src1, const APFloat &Src2)
static Value * simplifyAMDGCNMemoryIntrinsicDemanded(InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, int DMaskIdx=-1, bool IsLoad=true)
Implement SimplifyDemandedVectorElts for amdgcn buffer and image intrinsics.
static std::optional< Instruction * > simplifyAMDGCNImageIntrinsic(const GCNSubtarget *ST, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr, IntrinsicInst &II, InstCombiner &IC)
static Value * createMovDpp8(IRBuilderBase &B, Value *Val, unsigned Selector)
Emit v_mov_b32_dpp8 with the given 24-bit lane selector.
static Value * matchFPExtFromF16(Value *Arg)
Match an fpext from half to float, or a constant we can convert.
static constexpr auto matchFullRowMirrorPattern
static std::optional< unsigned > evalLaneExpr(Value *V, unsigned Lane, const GCNSubtarget &ST, const DataLayout &DL, unsigned Depth=0)
Evaluate V as a function of the lane ID and return its value on Lane, or std::nullopt if V is not a c...
static Value * createPermlane64(IRBuilderBase &B, Value *Val)
Emit v_permlane64 (swap of the two 32-lane halves of a wave64).
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
This file a TargetTransformInfoImplBase conforming object specific to the AMDGPU target machine.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
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")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Utilities for dealing with flags related to floating point properties and mode controls.
AMD GCN specific subclass of TargetSubtarget.
This file provides the interface for the instcombine pass implementation.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
if(PassOpts->AAPipeline)
This file contains some templates that are useful if you are working with the STL at all.
Provides some synthesis utilities to produce sequences of values.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
Value * RHS
Value * LHS
static const fltSemantics & IEEEsingle()
Definition APFloat.h:304
static constexpr roundingMode rmTowardZero
Definition APFloat.h:357
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
bool bitwiseIsEqual(const APFloat &RHS) const
Definition APFloat.h:1540
bool isPosInfinity() const
Definition APFloat.h:1588
APFloat makeQuiet() const
Assuming this is an IEEE-754 NaN value, quiet its signaling bit.
Definition APFloat.h:1412
bool isNaN() const
Definition APFloat.h:1573
bool isSignaling() const
Definition APFloat.h:1577
APInt bitcastToAPInt() const
Definition APFloat.h:1467
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 getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition APInt.h:235
void clearBit(unsigned BitPosition)
Set a given bit to 0.
Definition APInt.h:1431
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1565
unsigned popcount() const
Count the number of bits set.
Definition APInt.h:1695
LLVM_ABI uint64_t extractBitsAsZExtValue(unsigned numBits, unsigned bitPosition) const
Definition APInt.cpp:521
unsigned getActiveBits() const
Compute the number of active bits in the value.
Definition APInt.h:1537
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
Definition APInt.cpp:968
unsigned countr_zero() const
Count the number of trailing zero bits.
Definition APInt.h:1664
bool isMask(unsigned numBits) const
Definition APInt.h:489
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition ArrayRef.h:218
size_t size() const
Get the array size.
Definition ArrayRef.h:141
static LLVM_ABI Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)
LLVM_ABI const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
bool isTypeLegal(Type *Ty) const override
LLVM_ABI void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
void setAttributes(AttributeList A)
Set the attributes for this call.
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
AttributeList getAttributes() const
Return the attributes for this call.
This class represents a function call, abstracting a target machine's calling convention.
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
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition InstrTypes.h:890
bool isFPPredicate() const
Definition InstrTypes.h:845
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition InstrTypes.h:852
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:420
const APFloat & getValueAPF() const
Definition Constants.h:463
static LLVM_ABI ConstantFP * getZero(Type *Ty, bool Negative=false)
static LLVM_ABI ConstantFP * getNaN(Type *Ty, bool Negative=false, uint64_t Payload=0)
static LLVM_ABI ConstantFP * getInfinity(Type *Ty, bool Negative=false)
This is the shared class of boolean and integer constants.
Definition Constants.h:87
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
Definition Constants.h:135
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
This class represents a range of values.
LLVM_ABI ConstantRange add(const ConstantRange &Other) const
Return a new range representing the possible values resulting from an addition of a value in this ran...
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
LLVM_ABI ConstantRange intersectWith(const ConstantRange &CR, PreferredRangeType Type=Smallest) const
Return the range that results from the intersection of this range with another range.
This is an important base class in LLVM.
Definition Constant.h:43
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Definition Constant.h:64
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
Definition DataLayout.h:791
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Tagged union holding either a T or a Error.
Definition Error.h:485
This class represents an extension of floating point types.
Utility class for floating point operations which can have information about relaxed accuracy require...
Definition Operator.h:202
FastMathFlags getFastMathFlags() const
Convenience function for getting all the fast-math flags.
Definition Operator.h:291
bool hasApproxFunc() const
Test if this operation allows approximations of math library functions or intrinsics.
Definition Operator.h:288
LLVM_ABI float getFPAccuracy() const
Get the maximum error permitted by this operation in ULPs.
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
bool allowContract() const
Definition FMF.h:69
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:867
bool simplifyDemandedLaneMaskArg(InstCombiner &IC, IntrinsicInst &II, unsigned LaneAgIdx) const
Simplify a lane index operand (e.g.
std::optional< Instruction * > instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override
Instruction * hoistLaneIntrinsicThroughOperand(InstCombiner &IC, IntrinsicInst &II) const
std::optional< Value * > simplifyDemandedVectorEltsIntrinsic(InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3, std::function< void(Instruction *, unsigned, APInt, APInt &)> SimplifyAndSetOp) const override
KnownIEEEMode fpenvIEEEMode(const Instruction &I) const
Return KnownIEEEMode::On if we know if the use context can assume "amdgpu-ieee"="true" and KnownIEEEM...
Value * simplifyAMDGCNLaneIntrinsicDemanded(InstCombiner &IC, IntrinsicInst &II, const APInt &DemandedElts, APInt &UndefElts) const
bool canSimplifyLegacyMulToMul(const Instruction &I, const Value *Op0, const Value *Op1, InstCombiner &IC) const
Common base class shared among various IRBuilders.
Definition IRBuilder.h:114
LLVM_ABI CallInst * CreateIntrinsicWithoutFolding(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={})
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2662
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2650
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Definition IRBuilder.h:547
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
Definition IRBuilder.h:2139
ConstantInt * getTrue()
Get the constant value for i1 true.
Definition IRBuilder.h:457
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2133
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1532
Value * CreateExtractVector(Type *DstType, Value *SrcVec, Value *Idx, const Twine &Name="")
Create a call to the vector.extract intrinsic.
Definition IRBuilder.h:1112
BasicBlock * GetInsertBlock() const
Definition IRBuilder.h:175
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2379
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Definition IRBuilder.h:482
Value * CreateMaxNum(Value *LHS, Value *RHS, FMFSource FMFSource={}, const Twine &Name="")
Create call to the maxnum intrinsic.
Definition IRBuilder.h:1043
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1511
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Definition IRBuilder.h:2121
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Definition IRBuilder.h:2684
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
Value * CreateMaximumNum(Value *LHS, Value *RHS, const Twine &Name="")
Create call to the maximum intrinsic.
Definition IRBuilder.h:1071
Value * CreateMinNum(Value *LHS, Value *RHS, FMFSource FMFSource={}, const Twine &Name="")
Create call to the minnum intrinsic.
Definition IRBuilder.h:1031
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1422
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2554
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition IRBuilder.h:181
Value * CreateFAddFMF(Value *L, Value *R, FMFSource FMFSource, const Twine &Name="", MDNode *FPMD=nullptr)
Definition IRBuilder.h:1641
Value * CreateMinimumNum(Value *LHS, Value *RHS, const Twine &Name="")
Create call to the minimumnum intrinsic.
Definition IRBuilder.h:1065
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1551
Value * CreateFMulFMF(Value *L, Value *R, FMFSource FMFSource, const Twine &Name="", MDNode *FPMD=nullptr)
Definition IRBuilder.h:1679
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
The core instruction combiner logic.
const DataLayout & getDataLayout() const
virtual Instruction * eraseInstFromFunction(Instruction &I)=0
Combiner aware instruction erasure.
DominatorTree & getDominatorTree() const
Instruction * replaceInstUsesWith(Instruction &I, Value *V)
A combiner-aware RAUW-like routine.
virtual bool SimplifyDemandedBits(Instruction *I, unsigned OpNo, const APInt &DemandedMask, KnownBits &Known, const SimplifyQuery &Q, unsigned Depth=0)=0
IRBuilder< TargetFolder, IRBuilderInstCombineInserter > BuilderTy
An IRBuilder that automatically inserts new instructions into the worklist.
static Value * stripSignOnlyFPOps(Value *Val)
Ignore all operations which only change the sign of a value, returning the underlying magnitude value...
Instruction * replaceOperand(Instruction &I, unsigned OpNum, Value *V)
Replace operand of instruction and add old operand to the worklist.
const SimplifyQuery & getSimplifyQuery() const
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI void copyFastMathFlags(FastMathFlags FMF)
Convenience function for transferring all fast-math flag values to this instruction,...
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
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.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition Type.h:155
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:368
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
Definition Type.cpp:308
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition Type.h:144
LLVM_ABI Type * getWithNewType(Type *EltTy) const
Given vector type, change the element type, whilst keeping the old number of elements.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Definition Type.cpp:284
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
const Use & getOperandUse(unsigned i) const
Definition User.h:220
void setOperand(unsigned i, Value *Val)
Definition User.h:212
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
LLVM_ABI bool hasOneUser() const
Return true if there is exactly one user of this value.
Definition Value.cpp:163
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:400
const ParentTy * getParent() const
Definition ilist_node.h:34
CallInst * Call
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_READONLY const MIMGOffsetMappingInfo * getMIMGOffsetMappingInfo(unsigned Offset)
uint8_t wmmaScaleF8F6F4FormatToNumRegs(unsigned Fmt)
const ImageDimIntrinsicInfo * getImageDimIntrinsicByBaseOpcode(unsigned BaseOpcode, unsigned Dim)
LLVM_READONLY const MIMGMIPMappingInfo * getMIMGMIPMappingInfo(unsigned MIP)
bool isArgPassedInSGPR(const Argument *A)
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY const MIMGBiasMappingInfo * getMIMGBiasMappingInfo(unsigned Bias)
std::optional< APFloat > evaluateRcp(const APFloat &Val)
Evaluate the constant-folded result of v_rcp for Val, accounting for the hardware's denormal flushing...
LLVM_READONLY const MIMGLZMappingInfo * getMIMGLZMappingInfo(unsigned L)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI bool isSignatureValid(Intrinsic::ID ID, FunctionType *FT, SmallVectorImpl< Type * > &OverloadTys, raw_ostream &OS=nulls())
Returns true if FT is a valid function type for intrinsic ID.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
auto m_Cmp()
Matches any compare instruction and ignore it.
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
cstfp_pred_ty< is_any_zero_fp > m_AnyZeroFP()
Match a floating-point negative zero or positive zero.
ap_match< APFloat > m_APFloat(const APFloat *&Res)
Match a ConstantFP or splatted ConstantVector, binding the specified pointer to the contained APFloat...
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
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.
CastInst_match< OpTy, FPExtInst > m_FPExt(const OpTy &Op)
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
auto m_ConstantFP()
Match an arbitrary ConstantFP and ignore it.
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
LLVM_ABI KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, const SimplifyQuery &SQ, unsigned Depth=0)
Determine which floating-point classes are valid for V, and return them in KnownFPClass bit sets.
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
@ Known
Known to have no common set bits.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
Definition MathExtras.h:256
LLVM_ABI Constant * ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, const Instruction *I=nullptr)
Attempt to constant fold a compare instruction (icmp/fcmp) with the specified operands.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM)
Equivalent of C standard library function.
Definition APFloat.h:1705
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
LLVM_READONLY APFloat maxnum(const APFloat &A, const APFloat &B)
Implements IEEE-754 2008 maxNum semantics.
Definition APFloat.h:1748
constexpr unsigned MaxAnalysisRecursionDepth
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM)
Returns: X * 2^Exp for integral exponents.
Definition APFloat.h:1693
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
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
constexpr int PoisonMaskElem
@ FMul
Product of floats.
@ FAdd
Sum of floats.
LLVM_ABI Value * findScalarElement(Value *V, unsigned EltNo)
Given a vector and an element number, see if the scalar value is already around as a register,...
@ NearestTiesToEven
roundTiesToEven.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
Definition STLExtras.h:2166
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
LLVM_ABI Constant * ConstantFoldInstOperands(const Instruction *I, ArrayRef< Constant * > Ops, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, bool AllowNonDeterministic=true)
ConstantFoldInstOperands - Attempt to constant fold an instruction with the specified operands.
constexpr uint64_t Make_64(uint32_t High, uint32_t Low)
Make a 64-bit integer from a high / low pair of 32-bit integers.
Definition MathExtras.h:161
LLVM_ABI ConstantRange computeConstantRange(const Value *V, bool ForSigned, const SimplifyQuery &SQ, unsigned Depth=0)
Determine the possible constant range of an integer or vector of integer value.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
Represent subnormal handling kind for floating point instruction inputs and outputs.
bool isKnownNeverInfOrNaN() const
Return true if it's known this can never be an infinity or nan.
LLVM_ABI bool isKnownNeverLogicalZero(DenormalMode Mode) const
Return true if it's known this can never be interpreted as a zero.
SimplifyQuery getWithInstruction(const Instruction *I) const
LLVM_ABI bool isUndefValue(Value *V) const
If CanUseUndef is true, returns whether V is undef.