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 // Optimize _L to _LZ when _L is zero
186 if (const auto *LZMappingInfo =
188 if (auto *ConstantLod =
189 dyn_cast<ConstantFP>(II.getOperand(ImageDimIntr->LodIndex))) {
190 if (ConstantLod->isZero() || ConstantLod->isNegative()) {
191 const AMDGPU::ImageDimIntrinsicInfo *NewImageDimIntr =
193 ImageDimIntr->Dim);
194 return modifyIntrinsicCall(
195 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {
196 Args.erase(Args.begin() + ImageDimIntr->LodIndex);
197 });
198 }
199 }
200 }
201
202 // Optimize _mip away, when 'lod' is zero
203 if (const auto *MIPMappingInfo =
205 if (auto *ConstantMip =
206 dyn_cast<ConstantInt>(II.getOperand(ImageDimIntr->MipIndex))) {
207 if (ConstantMip->isZero()) {
208 const AMDGPU::ImageDimIntrinsicInfo *NewImageDimIntr =
209 AMDGPU::getImageDimIntrinsicByBaseOpcode(MIPMappingInfo->NONMIP,
210 ImageDimIntr->Dim);
211 return modifyIntrinsicCall(
212 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {
213 Args.erase(Args.begin() + ImageDimIntr->MipIndex);
214 });
215 }
216 }
217 }
218
219 // Optimize _bias away when 'bias' is zero
220 if (const auto *BiasMappingInfo =
222 if (auto *ConstantBias =
223 dyn_cast<ConstantFP>(II.getOperand(ImageDimIntr->BiasIndex))) {
224 if (ConstantBias->isZero()) {
225 const AMDGPU::ImageDimIntrinsicInfo *NewImageDimIntr =
226 AMDGPU::getImageDimIntrinsicByBaseOpcode(BiasMappingInfo->NoBias,
227 ImageDimIntr->Dim);
228 return modifyIntrinsicCall(
229 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {
230 Args.erase(Args.begin() + ImageDimIntr->BiasIndex);
231 ArgTys.erase(ArgTys.begin() + ImageDimIntr->BiasTyArg);
232 });
233 }
234 }
235 }
236
237 // Optimize _offset away when 'offset' is zero
238 if (const auto *OffsetMappingInfo =
240 if (auto *ConstantOffset =
241 dyn_cast<ConstantInt>(II.getOperand(ImageDimIntr->OffsetIndex))) {
242 if (ConstantOffset->isZero()) {
243 const AMDGPU::ImageDimIntrinsicInfo *NewImageDimIntr =
245 OffsetMappingInfo->NoOffset, ImageDimIntr->Dim);
246 return modifyIntrinsicCall(
247 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {
248 Args.erase(Args.begin() + ImageDimIntr->OffsetIndex);
249 });
250 }
251 }
252 }
253
254 // Try to use D16
255 if (ST->hasD16Images()) {
256
257 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
259
260 if (BaseOpcode->HasD16) {
261
262 // If the only use of image intrinsic is a fptrunc (with conversion to
263 // half) then both fptrunc and image intrinsic will be replaced with image
264 // intrinsic with D16 flag.
265 if (II.hasOneUse()) {
266 Instruction *User = II.user_back();
267
268 if (User->getOpcode() == Instruction::FPTrunc &&
270
271 return modifyIntrinsicCall(II, *User, ImageDimIntr->Intr, IC,
272 [&](auto &Args, auto &ArgTys) {
273 // Change return type of image intrinsic.
274 // Set it to return type of fptrunc.
275 ArgTys[0] = User->getType();
276 });
277 }
278 }
279
280 // Only perform D16 folding if every user of the image sample is
281 // an ExtractElementInst immediately followed by an FPTrunc to half.
283 ExtractTruncPairs;
284 bool AllHalfExtracts = true;
285
286 for (User *U : II.users()) {
287 auto *Ext = dyn_cast<ExtractElementInst>(U);
288 if (!Ext || !Ext->hasOneUse()) {
289 AllHalfExtracts = false;
290 break;
291 }
292
293 auto *Tr = dyn_cast<FPTruncInst>(*Ext->user_begin());
294 if (!Tr || !Tr->getType()->isHalfTy()) {
295 AllHalfExtracts = false;
296 break;
297 }
298
299 ExtractTruncPairs.emplace_back(Ext, Tr);
300 }
301
302 if (!ExtractTruncPairs.empty() && AllHalfExtracts) {
303 auto *VecTy = cast<VectorType>(II.getType());
304 Type *HalfVecTy =
305 VecTy->getWithNewType(Type::getHalfTy(II.getContext()));
306
307 // Obtain the original image sample intrinsic's signature
308 // and replace its return type with the half-vector for D16 folding
309 SmallVector<Type *, 8> OverloadTys;
310 if (!Intrinsic::isSignatureValid(II.getCalledFunction(), OverloadTys))
311 return std::nullopt;
312
313 OverloadTys[0] = HalfVecTy;
314 Module *M = II.getModule();
316 M, ImageDimIntr->Intr, OverloadTys);
317
318 II.mutateType(HalfVecTy);
319 II.setCalledFunction(HalfDecl);
320
321 IRBuilder<> Builder(II.getContext());
322 for (auto &[Ext, Tr] : ExtractTruncPairs) {
323 Value *Idx = Ext->getIndexOperand();
324
325 Builder.SetInsertPoint(Tr);
326
327 Value *HalfExtract = Builder.CreateExtractElement(&II, Idx);
328 HalfExtract->takeName(Tr);
329
330 Tr->replaceAllUsesWith(HalfExtract);
331 }
332
333 for (auto &[Ext, Tr] : ExtractTruncPairs) {
334 IC.eraseInstFromFunction(*Tr);
335 IC.eraseInstFromFunction(*Ext);
336 }
337
338 return &II;
339 }
340 }
341 }
342
343 // Try to use A16 or G16
344 if (!ST->hasA16() && !ST->hasG16())
345 return std::nullopt;
346
347 // Address is interpreted as float if the instruction has a sampler or as
348 // unsigned int if there is no sampler.
349 bool HasSampler =
351 bool FloatCoord = false;
352 // true means derivatives can be converted to 16 bit, coordinates not
353 bool OnlyDerivatives = false;
354
355 // Sampler-less addresses are unsigned, so a sext from i16 folds to a16 like a
356 // zext: they only disagree for a negative i16 (>= 0x8000), which is out of
357 // bounds while the max image dimension is <= 0x8000.
358 bool AllowI16SExt = !HasSampler;
359
360 for (unsigned OperandIndex = ImageDimIntr->GradientStart;
361 OperandIndex < ImageDimIntr->VAddrEnd; OperandIndex++) {
362 Value *Coord = II.getOperand(OperandIndex);
363 // If the values are not derived from 16-bit values, we cannot optimize.
364 if (!canSafelyConvertTo16Bit(*Coord, HasSampler, AllowI16SExt)) {
365 if (OperandIndex < ImageDimIntr->CoordStart ||
366 ImageDimIntr->GradientStart == ImageDimIntr->CoordStart) {
367 return std::nullopt;
368 }
369 // All gradients can be converted, so convert only them
370 OnlyDerivatives = true;
371 break;
372 }
373
374 assert(OperandIndex == ImageDimIntr->GradientStart ||
375 FloatCoord == Coord->getType()->isFloatingPointTy());
376 FloatCoord = Coord->getType()->isFloatingPointTy();
377 }
378
379 if (!OnlyDerivatives && !ST->hasA16())
380 OnlyDerivatives = true; // Only supports G16
381
382 // Check if there is a bias parameter and if it can be converted to f16
383 if (!OnlyDerivatives && ImageDimIntr->NumBiasArgs != 0) {
384 Value *Bias = II.getOperand(ImageDimIntr->BiasIndex);
385 assert(HasSampler &&
386 "Only image instructions with a sampler can have a bias");
387 if (!canSafelyConvertTo16Bit(*Bias, HasSampler))
388 OnlyDerivatives = true;
389 }
390
391 if (OnlyDerivatives && (!ST->hasG16() || ImageDimIntr->GradientStart ==
392 ImageDimIntr->CoordStart))
393 return std::nullopt;
394
395 Type *CoordType = FloatCoord ? Type::getHalfTy(II.getContext())
396 : Type::getInt16Ty(II.getContext());
397
398 return modifyIntrinsicCall(
399 II, II, II.getIntrinsicID(), IC, [&](auto &Args, auto &ArgTys) {
400 ArgTys[ImageDimIntr->GradientTyArg] = CoordType;
401 if (!OnlyDerivatives) {
402 ArgTys[ImageDimIntr->CoordTyArg] = CoordType;
403
404 // Change the bias type
405 if (ImageDimIntr->NumBiasArgs != 0)
406 ArgTys[ImageDimIntr->BiasTyArg] = Type::getHalfTy(II.getContext());
407 }
408
409 unsigned EndIndex =
410 OnlyDerivatives ? ImageDimIntr->CoordStart : ImageDimIntr->VAddrEnd;
411 for (unsigned OperandIndex = ImageDimIntr->GradientStart;
412 OperandIndex < EndIndex; OperandIndex++) {
413 Args[OperandIndex] =
414 convertTo16Bit(*II.getOperand(OperandIndex), IC.Builder);
415 }
416
417 // Convert the bias
418 if (!OnlyDerivatives && ImageDimIntr->NumBiasArgs != 0) {
419 Value *Bias = II.getOperand(ImageDimIntr->BiasIndex);
420 Args[ImageDimIntr->BiasIndex] = convertTo16Bit(*Bias, IC.Builder);
421 }
422 });
423}
424
426 const Value *Op0, const Value *Op1,
427 InstCombiner &IC) const {
428 // The legacy behaviour is that multiplying +/-0.0 by anything, even NaN or
429 // infinity, gives +0.0. If we can prove we don't have one of the special
430 // cases then we can use a normal multiply instead.
432 KnownFPClass Known0 =
434 DenormalMode Mode = I.getFunction()->getDenormalMode(APFloat::IEEEsingle());
435
436 // Bail early if Op0 may be zero and nsz is not set -- Op1 cannot help.
437 if (!Known0.isKnownNeverLogicalZero(Mode) && !I.hasNoSignedZeros())
438 return false;
439
440 KnownFPClass Known1 =
442
443 // Simplify if both operands are known non-zero.
444 if (Known0.isKnownNeverLogicalZero(Mode) &&
445 Known1.isKnownNeverLogicalZero(Mode))
446 return true;
447
448 // With nsz, two additional cases allow simplification:
449 // 1. One operand is not zero or infinity or NaN:
450 // Op0 NeverLogicalZero && NeverInfOrNaN, or symmetric for Op1.
451 // 2. Neither operand is infinity or NaN:
452 // Op0 NeverInfOrNaN && Op1 NeverInfOrNaN.
453 // The following condition captures both cases.
454 if (I.hasNoSignedZeros() &&
455 (Known0.isKnownNeverLogicalZero(Mode) || Known1.isKnownNeverInfOrNaN()) &&
456 (Known1.isKnownNeverLogicalZero(Mode) || Known0.isKnownNeverInfOrNaN()))
457 return true;
458
459 return false;
460}
461
462/// Match an fpext from half to float, or a constant we can convert.
464 Value *Src = nullptr;
465 ConstantFP *CFP = nullptr;
466 if (match(Arg, m_OneUse(m_FPExt(m_Value(Src))))) {
467 if (Src->getType()->isHalfTy())
468 return Src;
469 } else if (match(Arg, m_ConstantFP(CFP))) {
470 bool LosesInfo;
471 APFloat Val(CFP->getValueAPF());
473 if (!LosesInfo)
474 return ConstantFP::get(Type::getHalfTy(Arg->getContext()), Val);
475 }
476 return nullptr;
477}
478
479// Trim all zero components from the end of the vector \p UseV and return
480// an appropriate bitset with known elements.
482 Instruction *I) {
483 auto *VTy = cast<FixedVectorType>(UseV->getType());
484 unsigned VWidth = VTy->getNumElements();
485 APInt DemandedElts = APInt::getAllOnes(VWidth);
486
487 for (int i = VWidth - 1; i > 0; --i) {
488 auto *Elt = findScalarElement(UseV, i);
489 if (!Elt)
490 break;
491
492 if (auto *ConstElt = dyn_cast<Constant>(Elt)) {
493 if (!ConstElt->isNullValue() && !isa<UndefValue>(Elt))
494 break;
495 } else {
496 break;
497 }
498
499 DemandedElts.clearBit(i);
500 }
501
502 return DemandedElts;
503}
504
505// Trim elements of the end of the vector \p V, if they are
506// equal to the first element of the vector.
508 auto *VTy = cast<FixedVectorType>(V->getType());
509 unsigned VWidth = VTy->getNumElements();
510 APInt DemandedElts = APInt::getAllOnes(VWidth);
511 Value *FirstComponent = findScalarElement(V, 0);
512
513 SmallVector<int> ShuffleMask;
514 if (auto *SVI = dyn_cast<ShuffleVectorInst>(V))
515 SVI->getShuffleMask(ShuffleMask);
516
517 for (int I = VWidth - 1; I > 0; --I) {
518 if (ShuffleMask.empty()) {
519 auto *Elt = findScalarElement(V, I);
520 if (!Elt || (Elt != FirstComponent && !isa<UndefValue>(Elt)))
521 break;
522 } else {
523 // Detect identical elements in the shufflevector result, even though
524 // findScalarElement cannot tell us what that element is.
525 if (ShuffleMask[I] != ShuffleMask[0] && ShuffleMask[I] != PoisonMaskElem)
526 break;
527 }
528 DemandedElts.clearBit(I);
529 }
530
531 return DemandedElts;
532}
533
536 APInt DemandedElts,
537 int DMaskIdx = -1,
538 bool IsLoad = true);
539
540/// Return true if it's legal to contract llvm.amdgcn.rcp(llvm.sqrt)
541static bool canContractSqrtToRsq(const FPMathOperator *SqrtOp) {
542 return (SqrtOp->getType()->isFloatTy() &&
543 (SqrtOp->hasApproxFunc() || SqrtOp->getFPAccuracy() >= 1.0f)) ||
544 SqrtOp->getType()->isHalfTy();
545}
546
547/// Return true if we can easily prove that use U is uniform.
548static bool isTriviallyUniform(const Use &U) {
549 Value *V = U.get();
550 if (isa<Constant>(V))
551 return true;
552 if (const auto *A = dyn_cast<Argument>(V))
554 if (const auto *II = dyn_cast<IntrinsicInst>(V)) {
555 if (!AMDGPU::isIntrinsicAlwaysUniform(II->getIntrinsicID()))
556 return false;
557 // If II and U are in different blocks then there is a possibility of
558 // temporal divergence.
559 return II->getParent() == cast<Instruction>(U.getUser())->getParent();
560 }
561 return false;
562}
563
564/// Simplify a lane index operand (e.g. llvm.amdgcn.readlane src1).
565///
566/// The instruction only reads the low 5 bits for wave32, and 6 bits for wave64.
569 unsigned LaneArgIdx) const {
570 unsigned MaskBits = ST->getWavefrontSizeLog2();
571 APInt DemandedMask(32, maskTrailingOnes<unsigned>(MaskBits));
572
573 KnownBits Known(32);
574 if (IC.SimplifyDemandedBits(&II, LaneArgIdx, DemandedMask, Known))
575 return true;
576
577 if (!Known.isConstant())
578 return false;
579
580 // Out of bounds indexes may appear in wave64 code compiled for wave32.
581 // Unlike the DAG version, SimplifyDemandedBits does not change constants, so
582 // manually fix it up.
583
584 Value *LaneArg = II.getArgOperand(LaneArgIdx);
585 Constant *MaskedConst =
586 ConstantInt::get(LaneArg->getType(), Known.getConstant() & DemandedMask);
587 if (MaskedConst != LaneArg) {
588 II.getOperandUse(LaneArgIdx).set(MaskedConst);
589 return true;
590 }
591
592 return false;
593}
594
596 Function &NewCallee, ArrayRef<Value *> Ops) {
598 Old.getOperandBundlesAsDefs(OpBundles);
599
600 CallInst *NewCall = B.CreateCall(&NewCallee, Ops, OpBundles);
601 NewCall->takeName(&Old);
602 return NewCall;
603}
604
605// Return true for sequences of instructions that effectively assign
606// each lane to its thread ID
607static bool isThreadID(const GCNSubtarget &ST, Value *V) {
608 // Case 1:
609 // wave32: mbcnt_lo(-1, 0)
610 // wave64: mbcnt_hi(-1, mbcnt_lo(-1, 0))
616 if (ST.isWave32() && match(V, W32Pred))
617 return true;
618 if (ST.isWave64() && match(V, W64Pred))
619 return true;
620
621 return false;
622}
623
626 IntrinsicInst &II) const {
627 const auto IID = II.getIntrinsicID();
628 assert(IID == Intrinsic::amdgcn_readlane ||
629 IID == Intrinsic::amdgcn_readfirstlane ||
630 IID == Intrinsic::amdgcn_permlane64);
631
632 Instruction *OpInst = dyn_cast<Instruction>(II.getOperand(0));
633
634 // Only do this if both instructions are in the same block
635 // (so the exec mask won't change) and the readlane is the only user of its
636 // operand.
637 if (!OpInst || !OpInst->hasOneUser() || OpInst->getParent() != II.getParent())
638 return nullptr;
639
640 const bool IsReadLane = (IID == Intrinsic::amdgcn_readlane);
641
642 // If this is a readlane, check that the second operand is a constant, or is
643 // defined before OpInst so we know it's safe to move this intrinsic higher.
644 Value *LaneID = nullptr;
645 if (IsReadLane) {
646 LaneID = II.getOperand(1);
647
648 // readlane take an extra operand for the lane ID, so we must check if that
649 // LaneID value can be used at the point where we want to move the
650 // intrinsic.
651 if (auto *LaneIDInst = dyn_cast<Instruction>(LaneID)) {
652 if (!IC.getDominatorTree().dominates(LaneIDInst, OpInst))
653 return nullptr;
654 }
655 }
656
657 // Hoist the intrinsic (II) through OpInst.
658 //
659 // (II (OpInst x)) -> (OpInst (II x))
660 const auto DoIt = [&](unsigned OpIdx,
661 Function *NewIntrinsic) -> Instruction * {
663 if (IsReadLane)
664 Ops.push_back(LaneID);
665
666 // Rewrite the intrinsic call.
667 CallInst *NewII = rewriteCall(IC.Builder, II, *NewIntrinsic, Ops);
668
669 // Rewrite OpInst so it takes the result of the intrinsic now.
670 Instruction &NewOp = *OpInst->clone();
671 NewOp.setOperand(OpIdx, NewII);
672 return &NewOp;
673 };
674
675 // TODO(?): Should we do more with permlane64?
676 if (IID == Intrinsic::amdgcn_permlane64 && !isa<BitCastInst>(OpInst))
677 return nullptr;
678
679 if (isa<UnaryOperator>(OpInst))
680 return DoIt(0, II.getCalledFunction());
681
682 if (isa<CastInst>(OpInst)) {
683 Value *Src = OpInst->getOperand(0);
684 Type *SrcTy = Src->getType();
685 if (!isTypeLegal(SrcTy))
686 return nullptr;
687
688 Function *Remangled =
689 Intrinsic::getOrInsertDeclaration(II.getModule(), IID, {SrcTy});
690 return DoIt(0, Remangled);
691 }
692
693 // We can also hoist through binary operators if the other operand is uniform.
694 if (isa<BinaryOperator>(OpInst)) {
695 // FIXME: If we had access to UniformityInfo here we could just check
696 // if the operand is uniform.
697 if (isTriviallyUniform(OpInst->getOperandUse(0)))
698 return DoIt(1, II.getCalledFunction());
699 if (isTriviallyUniform(OpInst->getOperandUse(1)))
700 return DoIt(0, II.getCalledFunction());
701 }
702
703 return nullptr;
704}
705
706/// Evaluate V as a function of the lane ID and return its value on Lane, or
707/// std::nullopt if V is not a closed-form expression of the lane ID.
708static std::optional<unsigned> evalLaneExpr(Value *V, unsigned Lane,
709 const GCNSubtarget &ST,
710 const DataLayout &DL,
711 unsigned Depth = 0) {
713 return std::nullopt;
714
715 // Poison/undef in the index expression: bail and let InstCombine fold the
716 // intrinsic the usual way.
717 if (isa<UndefValue>(V))
718 return std::nullopt;
719
720 if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
721 return CI->getZExtValue();
722
723 if (isThreadID(ST, V))
724 return Lane;
725
727 if (!BO)
728 return std::nullopt;
729
730 std::optional<unsigned> LHS =
731 evalLaneExpr(BO->getOperand(0), Lane, ST, DL, Depth + 1);
732 if (!LHS)
733 return std::nullopt;
734 std::optional<unsigned> RHS =
735 evalLaneExpr(BO->getOperand(1), Lane, ST, DL, Depth + 1);
736 if (!RHS)
737 return std::nullopt;
738
739 Type *Ty = BO->getType();
740 Constant *Ops[] = {ConstantInt::get(Ty, *LHS), ConstantInt::get(Ty, *RHS)};
741 auto *CI =
743 return CI ? std::optional<unsigned>(CI->getZExtValue()) : std::nullopt;
744}
745
746/// Build the per-lane shuffle map by evaluating Index for every lane in the
747/// wave. Returns false if any lane index is non-constant or out of range.
748static bool tryBuildShuffleMap(Value *Index, const GCNSubtarget &ST,
750 const DataLayout &DL) {
751 unsigned WaveSize = ST.getWavefrontSize();
752 Ids.resize(WaveSize);
753 for (unsigned Lane : seq(WaveSize)) {
754 std::optional<unsigned> Val = evalLaneExpr(Index, Lane, ST, DL);
755 if (!Val || *Val >= WaveSize)
756 return false;
757 Ids[Lane] = *Val;
758 }
759 return true;
760}
761
762/// Lanes are partitioned into groups of Period; each group is a translated
763/// copy of the first: Ids[I] = Ids[I % Period] + (I & ~(Period - 1)).
764template <unsigned Period>
766 static_assert(isPowerOf2_32(Period), "Period must be a power of two");
767 for (unsigned I = Period, E = Ids.size(); I < E; ++I)
768 if (Ids[I] != Ids[I % Period] + (I & ~(Period - 1)))
769 return false;
770 return true;
771}
772
773/// Match an N-lane row pattern: each lane in [0, N) reads from a source lane
774/// in the same N-lane row, and the pattern repeats periodically across rows.
775template <unsigned N> static bool isRowPattern(ArrayRef<uint8_t> Ids) {
776 for (unsigned I = 0; I < N; ++I)
777 if (Ids[I] >= N)
778 return false;
779 return hasPeriodicLayout<N>(Ids);
780}
781
782static constexpr auto isQuadPattern = isRowPattern<4>;
783static constexpr auto isHalfRowPattern = isRowPattern<8>;
784static constexpr auto isFullRowPattern = isRowPattern<16>;
785
786/// Match a 4-lane (quad) permutation, encoded as the v_mov_b32_dpp
787/// QUAD_PERM control word: bits[1:0]=Ids[0], [3:2]=Ids[1], [5:4]=Ids[2],
788/// [7:6]=Ids[3].
789static std::optional<unsigned> matchQuadPermPattern(ArrayRef<uint8_t> Ids) {
790 if (!isQuadPattern(Ids))
791 return std::nullopt;
792 return Ids[3] << 6 | Ids[2] << 4 | Ids[1] << 2 | Ids[0];
793}
794
795/// Match an N-lane reversal (mirror) pattern.
796template <unsigned N> static bool matchMirrorPattern(ArrayRef<uint8_t> Ids) {
797 if (!isRowPattern<N>(Ids))
798 return false;
799 for (unsigned J = 0; J < N; ++J)
800 if (Ids[J] != (N - 1) - J)
801 return false;
802 return true;
803}
804
807
808/// Match a 16-lane cyclic rotation; returns the rotation amount in [1, 15].
809static std::optional<unsigned> matchRowRotatePattern(ArrayRef<uint8_t> Ids) {
810 if (Ids[0] == 0 || !isFullRowPattern(Ids))
811 return std::nullopt;
812 for (unsigned J = 1; J < 16; ++J)
813 if (Ids[J] != (Ids[0] + J) % 16)
814 return std::nullopt;
815 return 16u - Ids[0];
816}
817
818/// Match a row-share pattern: all 16 lanes of each row read the same source
819/// lane. Returns the shared source lane index in [0, 16).
820static std::optional<unsigned> matchRowSharePattern(ArrayRef<uint8_t> Ids) {
821 if (!isFullRowPattern(Ids))
822 return std::nullopt;
823 if (!all_equal(Ids.take_front(16)))
824 return std::nullopt;
825 return Ids[0];
826}
827
828/// Match an XOR mask pattern within each 16-lane row: Ids[J] == Mask ^ J,
829/// with Mask in [1, 15].
830static std::optional<unsigned> matchRowXMaskPattern(ArrayRef<uint8_t> Ids) {
831 unsigned Mask = Ids[0];
832 if (Mask == 0 || !isFullRowPattern(Ids))
833 return std::nullopt;
834 for (unsigned J = 0; J < 16; ++J)
835 if (Ids[J] != (Mask ^ J))
836 return std::nullopt;
837 return Mask;
838}
839
840/// Match an 8-lane arbitrary permutation, encoded as the v_mov_b32_dpp8
841/// 24-bit selector (three bits per output lane).
842static std::optional<unsigned> matchHalfRowPermPattern(ArrayRef<uint8_t> Ids) {
843 if (!isHalfRowPattern(Ids))
844 return std::nullopt;
845 unsigned Selector = 0;
846 for (unsigned J = 0; J < 8; ++J)
847 Selector |= Ids[J] << (J * 3);
848 return Selector;
849}
850
851/// Pack a 16-lane permutation into a single 64-bit value: four bits per output
852/// lane, lane J in bits [J*4 + 3 : J*4]. The caller splits it into the low and
853/// high 32-bit selector operands of v_permlane16 / v_permlanex16.
855 uint64_t Sel = 0;
856 for (unsigned J = 0; J < 16; ++J)
857 Sel |= static_cast<uint64_t>(Ids[J] & 0xF) << (J * 4);
858 return Sel;
859}
860
861/// Match a half-wave swap: lane J reads from lane J ^ 32. Only meaningful on
862/// wave64 targets.
864 if (Ids.size() != 64)
865 return false;
866 for (unsigned J = 0; J < 64; ++J)
867 if (Ids[J] != (J ^ 32))
868 return false;
869 return true;
870}
871
872/// Match a cross-row permutation suitable for v_permlanex16: every lane in
873/// the low 16-lane half reads from the high half of its own row, and vice
874/// versa.
876 if (!hasPeriodicLayout<32>(Ids))
877 return false;
878 for (unsigned J = 0; J < 16; ++J) {
879 if (Ids[J] < 16 || Ids[J] >= 32)
880 return false;
881 if (Ids[J + 16] != Ids[J] - 16)
882 return false;
883 }
884 return true;
885}
886
887/// Match a DS_SWIZZLE bitmask-mode permutation:
888/// dst_lane = ((src_lane & AND) | OR) ^ XOR
889/// with each mask being five bits. Returns the encoded swizzle immediate.
890/// The hardware applies the formula independently within each 32-lane group,
891/// so on wave64 the high group must replicate the low one (translated by 32).
892static std::optional<unsigned>
894 if (!hasPeriodicLayout<32>(Ids))
895 return std::nullopt;
896
897 // The formula is per-bit: output bit B depends only on input bit B. Probe
898 // each bit with src=0 and src=(1<<B); if the output bit flipped, AND[B]=1
899 // and XOR[B] carries the constant offset; otherwise it is a constant bit
900 // encoded in OR (with AND[B]=0, XOR[B]=0).
901 unsigned AndMask = 0, OrMask = 0, XorMask = 0;
902 for (unsigned B = 0; B < 5; ++B) {
903 unsigned Bit0 = (Ids[0] >> B) & 1;
904 unsigned Bit1 = (Ids[1u << B] >> B) & 1;
905 if (Bit0 != Bit1) {
906 AndMask |= 1u << B;
907 XorMask |= Bit0 << B;
908 } else {
909 OrMask |= Bit0 << B;
910 }
911 }
912
913 // The per-bit derivation assumes bit independence; verify the masks
914 // actually reproduce every lane in the 32-lane group.
915 for (unsigned I : seq(32u)) {
916 unsigned Expected = ((I & AndMask) | OrMask) ^ XorMask;
917 if (Ids[I] != Expected)
918 return std::nullopt;
919 }
920
925}
926
927/// Match a GFX9+ DS_SWIZZLE rotate-mode permutation: a cyclic left-rotation
928/// of all 32 lanes within each 32-lane group by a constant N in [0, 31],
929/// i.e. dst_lane = (src_lane + N) % 32. On wave64, hasPeriodicLayout<32>
930/// ensures both 32-lane groups rotate by the same amount.
931static std::optional<unsigned>
933 if (!hasPeriodicLayout<32>(Ids))
934 return std::nullopt;
935
936 // Determine the rotation amount from lane 0: every lane must read from
937 // lane (I + N) % 32 where N = Ids[0] and 0 <= N <= 31.
938 unsigned N = Ids[0];
939 if (N >= 32)
940 return std::nullopt;
941
942 for (unsigned I = 0; I < 32; ++I)
943 if (Ids[I] != (I + N) % 32)
944 return std::nullopt;
945
948}
949
950/// Emit v_mov_b32_dpp with the given control word, row/bank masks 0xF, and
951/// bound_ctrl=1 so out-of-bounds lanes are well-defined and the DPP mov can
952/// be folded into a consuming VALU op by GCNDPPCombine.
953static Value *createUpdateDpp(IRBuilderBase &B, Value *Val, unsigned Ctrl) {
954 Type *Ty = Val->getType();
955 return B.CreateIntrinsic(Intrinsic::amdgcn_update_dpp, {Ty},
956 {PoisonValue::get(Ty), Val, B.getInt32(Ctrl),
957 B.getInt32(0xF), B.getInt32(0xF), B.getTrue()});
958}
959
960/// Emit v_mov_b32_dpp8 with the given 24-bit lane selector.
961static Value *createMovDpp8(IRBuilderBase &B, Value *Val, unsigned Selector) {
962 return B.CreateIntrinsic(Intrinsic::amdgcn_mov_dpp8, {Val->getType()},
963 {Val, B.getInt32(Selector)});
964}
965
966/// Emit v_permlane16 with the precomputed lane-select halves.
968 uint32_t Hi) {
969 Type *Ty = Val->getType();
970 return B.CreateIntrinsic(Intrinsic::amdgcn_permlane16, {Ty},
971 {PoisonValue::get(Ty), Val, B.getInt32(Lo),
972 B.getInt32(Hi), B.getFalse(), B.getFalse()});
973}
974
975/// Emit v_permlanex16 with the precomputed lane-select halves. Each output
976/// lane reads from the other 16-lane half of the same row.
978 uint32_t Hi) {
979 Type *Ty = Val->getType();
980 return B.CreateIntrinsic(Intrinsic::amdgcn_permlanex16, {Ty},
981 {PoisonValue::get(Ty), Val, B.getInt32(Lo),
982 B.getInt32(Hi), B.getFalse(), B.getFalse()});
983}
984
985/// Emit ds_swizzle with the given immediate, bitcasting/converting between
986/// pointer/float types and i32 as required by the intrinsic signature.
988 const DataLayout &DL) {
989 Type *OrigTy = Val->getType();
990 assert(DL.getTypeSizeInBits(OrigTy) == 32 &&
991 "ds_swizzle only supports 32-bit operands");
992 IntegerType *I32Ty = B.getInt32Ty();
993 Value *Src = Val;
994 if (OrigTy->isPointerTy())
995 Src = B.CreatePtrToInt(Src, I32Ty);
996 else if (OrigTy != I32Ty)
997 Src = B.CreateBitCast(Src, I32Ty);
998 Value *Result = B.CreateIntrinsic(Intrinsic::amdgcn_ds_swizzle, {},
999 {Src, B.getInt32(Offset)});
1000 if (OrigTy->isPointerTy())
1001 return B.CreateIntToPtr(Result, OrigTy);
1002 if (OrigTy != I32Ty)
1003 return B.CreateBitCast(Result, OrigTy);
1004 return Result;
1005}
1006
1007/// Emit v_permlane64 (swap of the two 32-lane halves of a wave64).
1009 return B.CreateIntrinsic(Intrinsic::amdgcn_permlane64, {Val->getType()},
1010 {Val});
1011}
1012
1013/// Given a shuffle map, try to emit the best hardware intrinsic.
1016 const GCNSubtarget &ST,
1017 const DataLayout &DL) {
1018 // Identity shuffle (every lane reads itself) folds to the source value.
1019 if (all_of(enumerate(Ids),
1020 [](const auto &E) { return E.value() == E.index(); }))
1021 return Src;
1022
1023 // Uniform shuffle (all lanes read the same value) is handled by cheaper
1024 // broadcast/readlane intrinsics.
1025 if (all_equal(Ids))
1026 return nullptr;
1027
1028 if (std::optional<unsigned> QP = matchQuadPermPattern(Ids)) {
1029 if (ST.hasDPP())
1030 return createUpdateDpp(B, Src, *QP);
1032 }
1033
1034 if (ST.hasDPP()) {
1039 if (std::optional<unsigned> Amt = matchRowRotatePattern(Ids))
1040 return createUpdateDpp(B, Src, AMDGPU::DPP::ROW_ROR_FIRST + *Amt - 1);
1041 }
1042
1043 // row_share is supported on GFX90A and GFX10+; row_xmask is GFX10+ only.
1044 if (ST.hasDPPRowShare()) {
1045 if (std::optional<unsigned> Lane = matchRowSharePattern(Ids))
1046 return createUpdateDpp(B, Src, AMDGPU::DPP::ROW_SHARE_FIRST + *Lane);
1047 }
1048
1049 if (ST.hasDPP() && ST.hasGFX10Insts()) {
1050 if (std::optional<unsigned> Mask = matchRowXMaskPattern(Ids))
1051 return createUpdateDpp(B, Src, AMDGPU::DPP::ROW_XMASK_FIRST + *Mask);
1052 }
1053
1054 if (ST.hasDPP8()) {
1055 if (std::optional<unsigned> Sel = matchHalfRowPermPattern(Ids))
1056 return createMovDpp8(B, Src, *Sel);
1057 }
1058
1059 if (ST.hasPermlane16Insts()) {
1060 if (isFullRowPattern(Ids)) {
1062 return createPermlane16(B, Src, Lo_32(Sel), Hi_32(Sel));
1063 }
1064 // Cross-row shuffles (e.g. XOR 16..31) — covered by permlanex16.
1065 if (isCrossRowPattern(Ids)) {
1067 return createPermlaneX16(B, Src, Lo_32(Sel), Hi_32(Sel));
1068 }
1069 }
1070
1071 // Generic DS_SWIZZLE bitmask-mode fallback: handles any 32-lane shuffle that
1072 // can be expressed as dst = ((src & AND) | OR) ^ XOR with 5-bit masks. This
1073 // is available on every target that has ds_swizzle.
1074 if (std::optional<unsigned> Imm = matchDsSwizzleBitmaskPattern(Ids))
1075 return createDsSwizzle(B, Src, *Imm, DL);
1076
1077 // DS_SWIZZLE rotate mode (GFX9+): handles cyclic 32-lane rotations that
1078 // bitmask mode cannot express (e.g. +1 mod 32 requires inter-bit carry).
1079 if (ST.hasDsSwizzleRotateMode()) {
1080 if (std::optional<unsigned> Imm = matchDsSwizzleRotatePattern(Ids))
1081 return createDsSwizzle(B, Src, *Imm, DL);
1082 }
1083
1084 if (ST.hasPermLane64() && matchHalfWaveSwapPattern(Ids))
1085 return createPermlane64(B, Src);
1086
1087 return nullptr;
1088}
1089
1090/// Try to fold a wave_shuffle/ds_bpermute whose lane index is a constant
1091/// function of the lane ID into a hardware-specific lane permutation intrinsic.
1092static std::optional<Instruction *>
1094 const GCNSubtarget &ST) {
1095 const DataLayout &DL = IC.getDataLayout();
1096 if (DL.getTypeSizeInBits(II.getType()) != 32)
1097 return std::nullopt;
1098
1099 if (!ST.isWaveSizeKnown())
1100 return std::nullopt;
1101
1102 unsigned WaveSize = ST.getWavefrontSize();
1103 bool IsBpermute = II.getIntrinsicID() == Intrinsic::amdgcn_ds_bpermute;
1104 Value *Src = II.getArgOperand(IsBpermute ? 1 : 0);
1105 Value *Index = II.getArgOperand(IsBpermute ? 0 : 1);
1106
1108 if (IsBpermute) {
1109 Ids.resize(WaveSize);
1110 for (unsigned Lane : seq(WaveSize)) {
1111 std::optional<unsigned> Val = evalLaneExpr(Index, Lane, ST, DL);
1112 if (!Val || (*Val & 3) || (*Val >> 2) >= WaveSize)
1113 return std::nullopt;
1114 Ids[Lane] = *Val >> 2;
1115 }
1116 } else {
1117 if (!tryBuildShuffleMap(Index, ST, Ids, DL))
1118 return std::nullopt;
1119 }
1120
1121 Value *Result = matchShuffleToHWIntrinsic(IC.Builder, Src, Ids, ST, DL);
1122 if (!Result)
1123 return std::nullopt;
1124
1125 return IC.replaceInstUsesWith(II, Result);
1126}
1127std::optional<Instruction *>
1129 Intrinsic::ID IID = II.getIntrinsicID();
1130 switch (IID) {
1131 case Intrinsic::amdgcn_implicitarg_ptr: {
1132 if (II.getFunction()->hasFnAttribute("amdgpu-no-implicitarg-ptr"))
1133 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
1134 uint64_t ImplicitArgBytes = ST->getImplicitArgNumBytes(*II.getFunction());
1135
1136 uint64_t CurrentOrNullBytes =
1137 II.getAttributes().getRetDereferenceableOrNullBytes();
1138 if (CurrentOrNullBytes != 0) {
1139 // Refine "dereferenceable (A) meets dereferenceable_or_null(B)"
1140 // into dereferenceable(max(A, B))
1141 uint64_t NewBytes = std::max(CurrentOrNullBytes, ImplicitArgBytes);
1142 II.addRetAttr(
1143 Attribute::getWithDereferenceableBytes(II.getContext(), NewBytes));
1144 II.removeRetAttr(Attribute::DereferenceableOrNull);
1145 return &II;
1146 }
1147
1148 uint64_t CurrentBytes = II.getAttributes().getRetDereferenceableBytes();
1149 uint64_t NewBytes = std::max(CurrentBytes, ImplicitArgBytes);
1150 if (NewBytes != CurrentBytes) {
1151 II.addRetAttr(
1152 Attribute::getWithDereferenceableBytes(II.getContext(), NewBytes));
1153 return &II;
1154 }
1155
1156 return std::nullopt;
1157 }
1158 case Intrinsic::amdgcn_rcp: {
1159 Value *Src = II.getArgOperand(0);
1160 if (isa<PoisonValue>(Src))
1161 return IC.replaceInstUsesWith(II, Src);
1162
1163 // TODO: Move to ConstantFolding/InstSimplify?
1164 if (isa<UndefValue>(Src)) {
1165 Type *Ty = II.getType();
1166 auto *QNaN = ConstantFP::get(Ty, APFloat::getQNaN(Ty->getFltSemantics()));
1167 return IC.replaceInstUsesWith(II, QNaN);
1168 }
1169
1170 if (II.isStrictFP())
1171 break;
1172
1173 if (const ConstantFP *C = dyn_cast<ConstantFP>(Src)) {
1174 std::optional<APFloat> Val = AMDGPU::evaluateRcp(C->getValueAPF());
1175 if (!Val)
1176 break;
1177
1178 return IC.replaceInstUsesWith(II, ConstantFP::get(II.getContext(), *Val));
1179 }
1180
1181 FastMathFlags FMF = cast<FPMathOperator>(II).getFastMathFlags();
1182 if (!FMF.allowContract())
1183 break;
1184 auto *SrcCI = dyn_cast<IntrinsicInst>(Src);
1185 if (!SrcCI)
1186 break;
1187
1188 auto IID = SrcCI->getIntrinsicID();
1189 // llvm.amdgcn.rcp(llvm.amdgcn.sqrt(x)) -> llvm.amdgcn.rsq(x) if contractable
1190 //
1191 // llvm.amdgcn.rcp(llvm.sqrt(x)) -> llvm.amdgcn.rsq(x) if contractable and
1192 // relaxed.
1193 if (IID == Intrinsic::amdgcn_sqrt || IID == Intrinsic::sqrt) {
1194 const FPMathOperator *SqrtOp = cast<FPMathOperator>(SrcCI);
1195 FastMathFlags InnerFMF = SqrtOp->getFastMathFlags();
1196 if (!InnerFMF.allowContract() || !SrcCI->hasOneUse())
1197 break;
1198
1199 if (IID == Intrinsic::sqrt && !canContractSqrtToRsq(SqrtOp))
1200 break;
1201
1203 SrcCI->getModule(), Intrinsic::amdgcn_rsq, {SrcCI->getType()});
1204
1205 InnerFMF |= FMF;
1206 II.setFastMathFlags(InnerFMF);
1207
1208 II.setCalledFunction(NewDecl);
1209 return IC.replaceOperand(II, 0, SrcCI->getArgOperand(0));
1210 }
1211
1212 break;
1213 }
1214 case Intrinsic::amdgcn_sqrt:
1215 case Intrinsic::amdgcn_rsq:
1216 case Intrinsic::amdgcn_tanh: {
1217 Value *Src = II.getArgOperand(0);
1218 if (isa<PoisonValue>(Src))
1219 return IC.replaceInstUsesWith(II, Src);
1220
1221 // TODO: Move to ConstantFolding/InstSimplify?
1222 if (isa<UndefValue>(Src)) {
1223 Type *Ty = II.getType();
1224 auto *QNaN = ConstantFP::get(Ty, APFloat::getQNaN(Ty->getFltSemantics()));
1225 return IC.replaceInstUsesWith(II, QNaN);
1226 }
1227
1228 // f16 amdgcn.sqrt is identical to regular sqrt.
1229 if (IID == Intrinsic::amdgcn_sqrt && Src->getType()->isHalfTy()) {
1231 II.getModule(), Intrinsic::sqrt, {II.getType()});
1232 II.setCalledFunction(NewDecl);
1233 return &II;
1234 }
1235
1236 break;
1237 }
1238 case Intrinsic::amdgcn_log:
1239 case Intrinsic::amdgcn_exp2: {
1240 const bool IsLog = IID == Intrinsic::amdgcn_log;
1241 const bool IsExp = IID == Intrinsic::amdgcn_exp2;
1242 Value *Src = II.getArgOperand(0);
1243 Type *Ty = II.getType();
1244
1245 if (isa<PoisonValue>(Src))
1246 return IC.replaceInstUsesWith(II, Src);
1247
1248 if (IC.getSimplifyQuery().isUndefValue(Src))
1250
1251 if (ConstantFP *C = dyn_cast<ConstantFP>(Src)) {
1252 if (C->isInfinity()) {
1253 // exp2(+inf) -> +inf
1254 // log2(+inf) -> +inf
1255 if (!C->isNegative())
1256 return IC.replaceInstUsesWith(II, C);
1257
1258 // exp2(-inf) -> 0
1259 if (IsExp && C->isNegative())
1261 }
1262
1263 if (II.isStrictFP())
1264 break;
1265
1266 if (C->isNaN()) {
1267 Constant *Quieted = ConstantFP::get(Ty, C->getValue().makeQuiet());
1268 return IC.replaceInstUsesWith(II, Quieted);
1269 }
1270
1271 // f32 instruction doesn't handle denormals, f16 does.
1272 if (C->isZero() || (C->getValue().isDenormal() && Ty->isFloatTy())) {
1273 Constant *FoldedValue = IsLog ? ConstantFP::getInfinity(Ty, true)
1274 : ConstantFP::get(Ty, 1.0);
1275 return IC.replaceInstUsesWith(II, FoldedValue);
1276 }
1277
1278 if (IsLog && C->isNegative())
1280
1281 // TODO: Full constant folding matching hardware behavior.
1282 }
1283
1284 break;
1285 }
1286 case Intrinsic::amdgcn_frexp_mant:
1287 case Intrinsic::amdgcn_frexp_exp: {
1288 Value *Src = II.getArgOperand(0);
1289 if (const ConstantFP *C = dyn_cast<ConstantFP>(Src)) {
1290 int Exp;
1291 APFloat Significand =
1292 frexp(C->getValueAPF(), Exp, APFloat::rmNearestTiesToEven);
1293
1294 if (IID == Intrinsic::amdgcn_frexp_mant) {
1295 return IC.replaceInstUsesWith(
1296 II, ConstantFP::get(II.getContext(), Significand));
1297 }
1298
1299 // Match instruction special case behavior.
1300 if (Exp == APFloat::IEK_NaN || Exp == APFloat::IEK_Inf)
1301 Exp = 0;
1302
1303 return IC.replaceInstUsesWith(II,
1304 ConstantInt::getSigned(II.getType(), Exp));
1305 }
1306
1307 if (isa<PoisonValue>(Src))
1308 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
1309
1310 if (isa<UndefValue>(Src)) {
1311 return IC.replaceInstUsesWith(II, UndefValue::get(II.getType()));
1312 }
1313
1314 break;
1315 }
1316 case Intrinsic::amdgcn_class: {
1317 Value *Src0 = II.getArgOperand(0);
1318 Value *Src1 = II.getArgOperand(1);
1319 const ConstantInt *CMask = dyn_cast<ConstantInt>(Src1);
1320 if (CMask) {
1321 II.setCalledOperand(Intrinsic::getOrInsertDeclaration(
1322 II.getModule(), Intrinsic::is_fpclass, Src0->getType()));
1323
1324 // Clamp any excess bits, as they're illegal for the generic intrinsic.
1325 II.setArgOperand(1, ConstantInt::get(Src1->getType(),
1326 CMask->getZExtValue() & fcAllFlags));
1327 return &II;
1328 }
1329
1330 // Propagate poison.
1331 if (isa<PoisonValue>(Src0) || isa<PoisonValue>(Src1))
1332 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
1333
1334 // llvm.amdgcn.class(_, undef) -> false
1335 if (IC.getSimplifyQuery().isUndefValue(Src1))
1336 return IC.replaceInstUsesWith(II, ConstantInt::get(II.getType(), false));
1337
1338 // llvm.amdgcn.class(undef, mask) -> mask != 0
1339 if (IC.getSimplifyQuery().isUndefValue(Src0)) {
1340 Value *CmpMask = IC.Builder.CreateICmpNE(
1341 Src1, ConstantInt::getNullValue(Src1->getType()));
1342 return IC.replaceInstUsesWith(II, CmpMask);
1343 }
1344 break;
1345 }
1346 case Intrinsic::amdgcn_cvt_pkrtz: {
1347 auto foldFPTruncToF16RTZ = [](Value *Arg) -> Value * {
1348 Type *HalfTy = Type::getHalfTy(Arg->getContext());
1349
1350 if (isa<PoisonValue>(Arg))
1351 return PoisonValue::get(HalfTy);
1352 if (isa<UndefValue>(Arg))
1353 return UndefValue::get(HalfTy);
1354
1355 ConstantFP *CFP = nullptr;
1356 if (match(Arg, m_ConstantFP(CFP))) {
1357 bool LosesInfo;
1358 APFloat Val(CFP->getValueAPF());
1360 return ConstantFP::get(HalfTy, Val);
1361 }
1362
1363 Value *Src = nullptr;
1364 if (match(Arg, m_FPExt(m_Value(Src)))) {
1365 if (Src->getType()->isHalfTy())
1366 return Src;
1367 }
1368
1369 return nullptr;
1370 };
1371
1372 if (Value *Src0 = foldFPTruncToF16RTZ(II.getArgOperand(0))) {
1373 if (Value *Src1 = foldFPTruncToF16RTZ(II.getArgOperand(1))) {
1374 Value *V = PoisonValue::get(II.getType());
1375 V = IC.Builder.CreateInsertElement(V, Src0, (uint64_t)0);
1376 V = IC.Builder.CreateInsertElement(V, Src1, (uint64_t)1);
1377 return IC.replaceInstUsesWith(II, V);
1378 }
1379 }
1380
1381 break;
1382 }
1383 case Intrinsic::amdgcn_cvt_pknorm_i16:
1384 case Intrinsic::amdgcn_cvt_pknorm_u16:
1385 case Intrinsic::amdgcn_cvt_pk_i16:
1386 case Intrinsic::amdgcn_cvt_pk_u16: {
1387 Value *Src0 = II.getArgOperand(0);
1388 Value *Src1 = II.getArgOperand(1);
1389
1390 // TODO: Replace call with scalar operation if only one element is poison.
1391 if (isa<PoisonValue>(Src0) && isa<PoisonValue>(Src1))
1392 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
1393
1394 if (isa<UndefValue>(Src0) && isa<UndefValue>(Src1)) {
1395 return IC.replaceInstUsesWith(II, UndefValue::get(II.getType()));
1396 }
1397
1398 break;
1399 }
1400 case Intrinsic::amdgcn_cvt_off_f32_i4: {
1401 Value* Arg = II.getArgOperand(0);
1402 Type *Ty = II.getType();
1403
1404 if (isa<PoisonValue>(Arg))
1405 return IC.replaceInstUsesWith(II, PoisonValue::get(Ty));
1406
1407 if(IC.getSimplifyQuery().isUndefValue(Arg))
1409
1410 ConstantInt *CArg = dyn_cast<ConstantInt>(II.getArgOperand(0));
1411 if (!CArg)
1412 break;
1413
1414 // Tabulated 0.0625 * (sext (CArg & 0xf)).
1415 constexpr size_t ResValsSize = 16;
1416 static constexpr float ResVals[ResValsSize] = {
1417 0.0, 0.0625, 0.125, 0.1875, 0.25, 0.3125, 0.375, 0.4375,
1418 -0.5, -0.4375, -0.375, -0.3125, -0.25, -0.1875, -0.125, -0.0625};
1419 Constant *Res =
1420 ConstantFP::get(Ty, ResVals[CArg->getZExtValue() & (ResValsSize - 1)]);
1421 return IC.replaceInstUsesWith(II, Res);
1422 }
1423 case Intrinsic::amdgcn_ubfe:
1424 case Intrinsic::amdgcn_sbfe: {
1425 // Decompose simple cases into standard shifts.
1426 Value *Src = II.getArgOperand(0);
1427 if (isa<UndefValue>(Src)) {
1428 return IC.replaceInstUsesWith(II, Src);
1429 }
1430
1431 unsigned Width;
1432 Type *Ty = II.getType();
1433 unsigned IntSize = Ty->getIntegerBitWidth();
1434
1435 ConstantInt *CWidth = dyn_cast<ConstantInt>(II.getArgOperand(2));
1436 if (CWidth) {
1437 Width = CWidth->getZExtValue();
1438 if ((Width & (IntSize - 1)) == 0) {
1440 }
1441
1442 // Hardware ignores high bits, so remove those.
1443 if (Width >= IntSize) {
1444 return IC.replaceOperand(
1445 II, 2, ConstantInt::get(CWidth->getType(), Width & (IntSize - 1)));
1446 }
1447 }
1448
1449 unsigned Offset;
1450 ConstantInt *COffset = dyn_cast<ConstantInt>(II.getArgOperand(1));
1451 if (COffset) {
1452 Offset = COffset->getZExtValue();
1453 if (Offset >= IntSize) {
1454 return IC.replaceOperand(
1455 II, 1,
1456 ConstantInt::get(COffset->getType(), Offset & (IntSize - 1)));
1457 }
1458 }
1459
1460 bool Signed = IID == Intrinsic::amdgcn_sbfe;
1461
1462 if (!CWidth || !COffset)
1463 break;
1464
1465 // The case of Width == 0 is handled above, which makes this transformation
1466 // safe. If Width == 0, then the ashr and lshr instructions become poison
1467 // value since the shift amount would be equal to the bit size.
1468 assert(Width != 0);
1469
1470 // TODO: This allows folding to undef when the hardware has specific
1471 // behavior?
1472 if (Offset + Width < IntSize) {
1473 Value *Shl = IC.Builder.CreateShl(Src, IntSize - Offset - Width);
1474 Value *RightShift = Signed ? IC.Builder.CreateAShr(Shl, IntSize - Width)
1475 : IC.Builder.CreateLShr(Shl, IntSize - Width);
1476 RightShift->takeName(&II);
1477 return IC.replaceInstUsesWith(II, RightShift);
1478 }
1479
1480 Value *RightShift = Signed ? IC.Builder.CreateAShr(Src, Offset)
1481 : IC.Builder.CreateLShr(Src, Offset);
1482
1483 RightShift->takeName(&II);
1484 return IC.replaceInstUsesWith(II, RightShift);
1485 }
1486 case Intrinsic::amdgcn_exp:
1487 case Intrinsic::amdgcn_exp_row:
1488 case Intrinsic::amdgcn_exp_compr: {
1489 ConstantInt *En = cast<ConstantInt>(II.getArgOperand(1));
1490 unsigned EnBits = En->getZExtValue();
1491 if (EnBits == 0xf)
1492 break; // All inputs enabled.
1493
1494 bool IsCompr = IID == Intrinsic::amdgcn_exp_compr;
1495 bool Changed = false;
1496 for (int I = 0; I < (IsCompr ? 2 : 4); ++I) {
1497 if ((!IsCompr && (EnBits & (1 << I)) == 0) ||
1498 (IsCompr && ((EnBits & (0x3 << (2 * I))) == 0))) {
1499 Value *Src = II.getArgOperand(I + 2);
1500 if (!isa<PoisonValue>(Src)) {
1501 IC.replaceOperand(II, I + 2, PoisonValue::get(Src->getType()));
1502 Changed = true;
1503 }
1504 }
1505 }
1506
1507 if (Changed) {
1508 return &II;
1509 }
1510
1511 break;
1512 }
1513 case Intrinsic::amdgcn_fmed3: {
1514 Value *Src0 = II.getArgOperand(0);
1515 Value *Src1 = II.getArgOperand(1);
1516 Value *Src2 = II.getArgOperand(2);
1517
1518 for (Value *Src : {Src0, Src1, Src2}) {
1519 if (isa<PoisonValue>(Src))
1520 return IC.replaceInstUsesWith(II, Src);
1521 }
1522
1523 if (II.isStrictFP())
1524 break;
1525
1526 // med3 with a nan input acts like
1527 // v_min_f32(v_min_f32(s0, s1), s2)
1528 //
1529 // Signalingness is ignored with ieee=0, so we fold to
1530 // minimumnum/maximumnum. With ieee=1, the v_min_f32 acts like llvm.minnum
1531 // with signaling nan handling. With ieee=0, like llvm.minimumnum except a
1532 // returned signaling nan will not be quieted.
1533
1534 // ieee=1
1535 // s0 snan: s2
1536 // s1 snan: s2
1537 // s2 snan: qnan
1538
1539 // s0 qnan: min(s1, s2)
1540 // s1 qnan: min(s0, s2)
1541 // s2 qnan: min(s0, s1)
1542
1543 // ieee=0
1544 // s0 _nan: min(s1, s2)
1545 // s1 _nan: min(s0, s2)
1546 // s2 _nan: min(s0, s1)
1547
1548 // med3 behavior with infinity
1549 // s0 +inf: max(s1, s2)
1550 // s1 +inf: max(s0, s2)
1551 // s2 +inf: max(s0, s1)
1552 // s0 -inf: min(s1, s2)
1553 // s1 -inf: min(s0, s2)
1554 // s2 -inf: min(s0, s1)
1555
1556 // Checking for NaN before canonicalization provides better fidelity when
1557 // mapping other operations onto fmed3 since the order of operands is
1558 // unchanged.
1559 Value *V = nullptr;
1560 const APFloat *ConstSrc0 = nullptr;
1561 const APFloat *ConstSrc1 = nullptr;
1562 const APFloat *ConstSrc2 = nullptr;
1563
1564 if ((match(Src0, m_APFloat(ConstSrc0)) &&
1565 (ConstSrc0->isNaN() || ConstSrc0->isInfinity())) ||
1566 isa<UndefValue>(Src0)) {
1567 const bool IsPosInfinity = ConstSrc0 && ConstSrc0->isPosInfinity();
1568 switch (fpenvIEEEMode(II)) {
1569 case KnownIEEEMode::On:
1570 // TODO: If Src2 is snan, does it need quieting?
1571 if (ConstSrc0 && ConstSrc0->isNaN() && ConstSrc0->isSignaling())
1572 return IC.replaceInstUsesWith(II, Src2);
1573
1574 V = IsPosInfinity ? IC.Builder.CreateMaxNum(Src1, Src2)
1575 : IC.Builder.CreateMinNum(Src1, Src2);
1576 break;
1577 case KnownIEEEMode::Off:
1578 V = IsPosInfinity ? IC.Builder.CreateMaximumNum(Src1, Src2)
1579 : IC.Builder.CreateMinimumNum(Src1, Src2);
1580 break;
1582 break;
1583 }
1584 } else if ((match(Src1, m_APFloat(ConstSrc1)) &&
1585 (ConstSrc1->isNaN() || ConstSrc1->isInfinity())) ||
1586 isa<UndefValue>(Src1)) {
1587 const bool IsPosInfinity = ConstSrc1 && ConstSrc1->isPosInfinity();
1588 switch (fpenvIEEEMode(II)) {
1589 case KnownIEEEMode::On:
1590 // TODO: If Src2 is snan, does it need quieting?
1591 if (ConstSrc1 && ConstSrc1->isNaN() && ConstSrc1->isSignaling())
1592 return IC.replaceInstUsesWith(II, Src2);
1593
1594 V = IsPosInfinity ? IC.Builder.CreateMaxNum(Src0, Src2)
1595 : IC.Builder.CreateMinNum(Src0, Src2);
1596 break;
1597 case KnownIEEEMode::Off:
1598 V = IsPosInfinity ? IC.Builder.CreateMaximumNum(Src0, Src2)
1599 : IC.Builder.CreateMinimumNum(Src0, Src2);
1600 break;
1602 break;
1603 }
1604 } else if ((match(Src2, m_APFloat(ConstSrc2)) &&
1605 (ConstSrc2->isNaN() || ConstSrc2->isInfinity())) ||
1606 isa<UndefValue>(Src2)) {
1607 switch (fpenvIEEEMode(II)) {
1608 case KnownIEEEMode::On:
1609 if (ConstSrc2 && ConstSrc2->isNaN() && ConstSrc2->isSignaling()) {
1610 auto *Quieted = ConstantFP::get(II.getType(), ConstSrc2->makeQuiet());
1611 return IC.replaceInstUsesWith(II, Quieted);
1612 }
1613
1614 V = (ConstSrc2 && ConstSrc2->isPosInfinity())
1615 ? IC.Builder.CreateMaxNum(Src0, Src1)
1616 : IC.Builder.CreateMinNum(Src0, Src1);
1617 break;
1618 case KnownIEEEMode::Off:
1619 V = (ConstSrc2 && ConstSrc2->isPosInfinity())
1620 ? IC.Builder.CreateMaximumNum(Src0, Src1)
1621 : IC.Builder.CreateMinimumNum(Src0, Src1);
1622 break;
1624 break;
1625 }
1626 }
1627
1628 if (V) {
1629 if (auto *CI = dyn_cast<CallInst>(V)) {
1630 CI->copyFastMathFlags(&II);
1631 CI->takeName(&II);
1632 }
1633 return IC.replaceInstUsesWith(II, V);
1634 }
1635
1636 bool Swap = false;
1637 // Canonicalize constants to RHS operands.
1638 //
1639 // fmed3(c0, x, c1) -> fmed3(x, c0, c1)
1640 if (isa<Constant>(Src0) && !isa<Constant>(Src1)) {
1641 std::swap(Src0, Src1);
1642 Swap = true;
1643 }
1644
1645 if (isa<Constant>(Src1) && !isa<Constant>(Src2)) {
1646 std::swap(Src1, Src2);
1647 Swap = true;
1648 }
1649
1650 if (isa<Constant>(Src0) && !isa<Constant>(Src1)) {
1651 std::swap(Src0, Src1);
1652 Swap = true;
1653 }
1654
1655 if (Swap) {
1656 II.setArgOperand(0, Src0);
1657 II.setArgOperand(1, Src1);
1658 II.setArgOperand(2, Src2);
1659 return &II;
1660 }
1661
1662 if (const ConstantFP *C0 = dyn_cast<ConstantFP>(Src0)) {
1663 if (const ConstantFP *C1 = dyn_cast<ConstantFP>(Src1)) {
1664 if (const ConstantFP *C2 = dyn_cast<ConstantFP>(Src2)) {
1665 APFloat Result = fmed3AMDGCN(C0->getValueAPF(), C1->getValueAPF(),
1666 C2->getValueAPF());
1667 return IC.replaceInstUsesWith(II,
1668 ConstantFP::get(II.getType(), Result));
1669 }
1670 }
1671 }
1672
1673 if (!ST->hasMed3_16())
1674 break;
1675
1676 // Repeat floating-point width reduction done for minnum/maxnum.
1677 // fmed3((fpext X), (fpext Y), (fpext Z)) -> fpext (fmed3(X, Y, Z))
1678 if (Value *X = matchFPExtFromF16(Src0)) {
1679 if (Value *Y = matchFPExtFromF16(Src1)) {
1680 if (Value *Z = matchFPExtFromF16(Src2)) {
1681 Value *NewCall = IC.Builder.CreateIntrinsic(
1682 IID, {X->getType()}, {X, Y, Z}, &II, II.getName());
1683 return new FPExtInst(NewCall, II.getType());
1684 }
1685 }
1686 }
1687
1688 break;
1689 }
1690 case Intrinsic::amdgcn_icmp:
1691 case Intrinsic::amdgcn_fcmp: {
1692 const ConstantInt *CC = cast<ConstantInt>(II.getArgOperand(2));
1693 // Guard against invalid arguments.
1694 int64_t CCVal = CC->getZExtValue();
1695 bool IsInteger = IID == Intrinsic::amdgcn_icmp;
1696 if ((IsInteger && (CCVal < CmpInst::FIRST_ICMP_PREDICATE ||
1697 CCVal > CmpInst::LAST_ICMP_PREDICATE)) ||
1698 (!IsInteger && (CCVal < CmpInst::FIRST_FCMP_PREDICATE ||
1700 break;
1701
1702 Value *Src0 = II.getArgOperand(0);
1703 Value *Src1 = II.getArgOperand(1);
1704
1705 if (auto *CSrc0 = dyn_cast<Constant>(Src0)) {
1706 if (auto *CSrc1 = dyn_cast<Constant>(Src1)) {
1708 (ICmpInst::Predicate)CCVal, CSrc0, CSrc1, DL);
1709 if (CCmp && CCmp->isNullValue()) {
1710 return IC.replaceInstUsesWith(
1711 II, IC.Builder.CreateSExt(CCmp, II.getType()));
1712 }
1713
1714 // The result of V_ICMP/V_FCMP assembly instructions (which this
1715 // intrinsic exposes) is one bit per thread, masked with the EXEC
1716 // register (which contains the bitmask of live threads). So a
1717 // comparison that always returns true is the same as a read of the
1718 // EXEC register. ballot(true) reads EXEC at the wave-size width, so
1719 // zext/trunc the result to the intrinsic's return type.
1720 Type *WaveTy = IC.Builder.getIntNTy(ST->getWavefrontSize());
1721 Value *Ballot = IC.Builder.CreateIntrinsic(
1722 Intrinsic::amdgcn_ballot, WaveTy, IC.Builder.getTrue());
1723 Value *Result = IC.Builder.CreateZExtOrTrunc(Ballot, II.getType());
1724 return IC.replaceInstUsesWith(II, Result);
1725 }
1726
1727 // Canonicalize constants to RHS.
1728 CmpInst::Predicate SwapPred =
1730 II.setArgOperand(0, Src1);
1731 II.setArgOperand(1, Src0);
1732 II.setArgOperand(
1733 2, ConstantInt::get(CC->getType(), static_cast<int>(SwapPred)));
1734 return &II;
1735 }
1736
1737 if (CCVal != CmpInst::ICMP_EQ && CCVal != CmpInst::ICMP_NE)
1738 break;
1739
1740 // Canonicalize compare eq with true value to compare != 0
1741 // llvm.amdgcn.icmp(zext (i1 x), 1, eq)
1742 // -> llvm.amdgcn.icmp(zext (i1 x), 0, ne)
1743 // llvm.amdgcn.icmp(sext (i1 x), -1, eq)
1744 // -> llvm.amdgcn.icmp(sext (i1 x), 0, ne)
1745 Value *ExtSrc;
1746 if (CCVal == CmpInst::ICMP_EQ &&
1747 ((match(Src1, PatternMatch::m_One()) &&
1748 match(Src0, m_ZExt(PatternMatch::m_Value(ExtSrc)))) ||
1749 (match(Src1, PatternMatch::m_AllOnes()) &&
1750 match(Src0, m_SExt(PatternMatch::m_Value(ExtSrc))))) &&
1751 ExtSrc->getType()->isIntegerTy(1)) {
1753 IC.replaceOperand(II, 2,
1754 ConstantInt::get(CC->getType(), CmpInst::ICMP_NE));
1755 return &II;
1756 }
1757
1758 CmpPredicate SrcPred;
1759 Value *SrcLHS;
1760 Value *SrcRHS;
1761
1762 // Fold compare eq/ne with 0 from a compare result as the predicate to the
1763 // intrinsic. The typical use is a wave vote function in the library, which
1764 // will be fed from a user code condition compared with 0. Fold in the
1765 // redundant compare.
1766
1767 // llvm.amdgcn.icmp([sz]ext ([if]cmp pred a, b), 0, ne)
1768 // -> llvm.amdgcn.[if]cmp(a, b, pred)
1769 //
1770 // llvm.amdgcn.icmp([sz]ext ([if]cmp pred a, b), 0, eq)
1771 // -> llvm.amdgcn.[if]cmp(a, b, inv pred)
1772 if (match(Src1, PatternMatch::m_Zero()) &&
1774 m_Cmp(SrcPred, PatternMatch::m_Value(SrcLHS),
1775 PatternMatch::m_Value(SrcRHS))))) {
1776 if (CCVal == CmpInst::ICMP_EQ)
1777 SrcPred = CmpInst::getInversePredicate(SrcPred);
1778
1779 Intrinsic::ID NewIID = CmpInst::isFPPredicate(SrcPred)
1780 ? Intrinsic::amdgcn_fcmp
1781 : Intrinsic::amdgcn_icmp;
1782
1783 Type *Ty = SrcLHS->getType();
1784 if (auto *CmpType = dyn_cast<IntegerType>(Ty)) {
1785 // Promote to next legal integer type.
1786 unsigned Width = CmpType->getBitWidth();
1787 unsigned NewWidth = Width;
1788
1789 // Don't do anything for i1 comparisons.
1790 if (Width == 1)
1791 break;
1792
1793 if (Width <= 16)
1794 NewWidth = 16;
1795 else if (Width <= 32)
1796 NewWidth = 32;
1797 else if (Width <= 64)
1798 NewWidth = 64;
1799 else
1800 break; // Can't handle this.
1801
1802 if (Width != NewWidth) {
1803 IntegerType *CmpTy = IC.Builder.getIntNTy(NewWidth);
1804 if (CmpInst::isSigned(SrcPred)) {
1805 SrcLHS = IC.Builder.CreateSExt(SrcLHS, CmpTy);
1806 SrcRHS = IC.Builder.CreateSExt(SrcRHS, CmpTy);
1807 } else {
1808 SrcLHS = IC.Builder.CreateZExt(SrcLHS, CmpTy);
1809 SrcRHS = IC.Builder.CreateZExt(SrcRHS, CmpTy);
1810 }
1811 }
1812 } else if (!Ty->isFloatTy() && !Ty->isDoubleTy() && !Ty->isHalfTy())
1813 break;
1814
1815 Value *Args[] = {SrcLHS, SrcRHS,
1816 ConstantInt::get(CC->getType(), SrcPred)};
1817 Value *NewCall = IC.Builder.CreateIntrinsic(
1818 NewIID, {II.getType(), SrcLHS->getType()}, Args);
1819 NewCall->takeName(&II);
1820 return IC.replaceInstUsesWith(II, NewCall);
1821 }
1822
1823 break;
1824 }
1825 case Intrinsic::amdgcn_mbcnt_hi:
1826 // exec_hi is all 0, so this is just a copy.
1827 if (ST->isWave32())
1828 return IC.replaceInstUsesWith(II, II.getArgOperand(1));
1829 [[fallthrough]];
1830 case Intrinsic::amdgcn_mbcnt_lo: {
1831 ConstantRange AccRange =
1832 computeConstantRange(II.getArgOperand(1),
1833 /*ForSigned=*/false, IC.getSimplifyQuery());
1834 if (AccRange.isFullSet())
1835 return nullptr;
1836
1837 // TODO: Can raise lower bound by inspecting first argument.
1838 ConstantRange MbcntRange(APInt(32, 0), APInt(32, 32 + 1));
1839 ConstantRange ComputedRange = AccRange.add(MbcntRange);
1840 if (ComputedRange.isFullSet())
1841 return nullptr;
1842
1843 if (std::optional<ConstantRange> ExistingRange = II.getRange()) {
1844 ComputedRange = ComputedRange.intersectWith(*ExistingRange);
1845 if (ComputedRange == *ExistingRange)
1846 return nullptr;
1847 }
1848
1849 II.addRangeRetAttr(ComputedRange);
1850 return nullptr;
1851 }
1852 case Intrinsic::amdgcn_ballot: {
1853 Value *Arg = II.getArgOperand(0);
1854 if (isa<PoisonValue>(Arg))
1855 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
1856
1857 if (auto *Src = dyn_cast<ConstantInt>(Arg)) {
1858 if (Src->isZero()) {
1859 // amdgcn.ballot(i1 0) is zero.
1860 return IC.replaceInstUsesWith(II, Constant::getNullValue(II.getType()));
1861 }
1862 }
1863 if (ST->isWave32() && II.getType()->getIntegerBitWidth() == 64) {
1864 // %b64 = call i64 ballot.i64(...)
1865 // =>
1866 // %b32 = call i32 ballot.i32(...)
1867 // %b64 = zext i32 %b32 to i64
1869 IC.Builder.CreateIntrinsic(Intrinsic::amdgcn_ballot,
1870 {IC.Builder.getInt32Ty()},
1871 {II.getArgOperand(0)}),
1872 II.getType());
1873 Call->takeName(&II);
1874 return IC.replaceInstUsesWith(II, Call);
1875 }
1876 break;
1877 }
1878 case Intrinsic::amdgcn_wavefrontsize: {
1879 if (ST->isWaveSizeKnown())
1880 return IC.replaceInstUsesWith(
1881 II, ConstantInt::get(II.getType(), ST->getWavefrontSize()));
1882 break;
1883 }
1884 case Intrinsic::amdgcn_wqm_vote: {
1885 // wqm_vote is identity when the argument is constant.
1886 if (!isa<Constant>(II.getArgOperand(0)))
1887 break;
1888
1889 return IC.replaceInstUsesWith(II, II.getArgOperand(0));
1890 }
1891 case Intrinsic::amdgcn_kill: {
1892 const ConstantInt *C = dyn_cast<ConstantInt>(II.getArgOperand(0));
1893 if (!C || !C->getZExtValue())
1894 break;
1895
1896 // amdgcn.kill(i1 1) is a no-op
1897 return IC.eraseInstFromFunction(II);
1898 }
1899 case Intrinsic::amdgcn_s_sendmsg:
1900 case Intrinsic::amdgcn_s_sendmsghalt: {
1901 // The second operand is copied to m0, but is only actually used for
1902 // certain message types. For message types that are known to not use m0,
1903 // fold it to poison.
1904 using namespace AMDGPU::SendMsg;
1905
1906 Value *M0Val = II.getArgOperand(1);
1907 if (isa<PoisonValue>(M0Val))
1908 break;
1909
1910 auto *MsgImm = cast<ConstantInt>(II.getArgOperand(0));
1911 uint16_t MsgId, OpId, StreamId;
1912 decodeMsg(MsgImm->getZExtValue(), MsgId, OpId, StreamId, *ST);
1913
1914 if (!msgDoesNotUseM0(MsgId, *ST))
1915 break;
1916
1917 // Drop UB-implying attributes since we're replacing with poison.
1918 II.dropUBImplyingAttrsAndMetadata();
1919 IC.replaceOperand(II, 1, PoisonValue::get(M0Val->getType()));
1920 return nullptr;
1921 }
1922 case Intrinsic::amdgcn_update_dpp: {
1923 Value *Old = II.getArgOperand(0);
1924
1925 auto *BC = cast<ConstantInt>(II.getArgOperand(5));
1926 auto *RM = cast<ConstantInt>(II.getArgOperand(3));
1927 auto *BM = cast<ConstantInt>(II.getArgOperand(4));
1928 if (BC->isNullValue() || RM->getZExtValue() != 0xF ||
1929 BM->getZExtValue() != 0xF || isa<PoisonValue>(Old))
1930 break;
1931
1932 // If bound_ctrl = 1, row mask = bank mask = 0xf we can omit old value.
1933 return IC.replaceOperand(II, 0, PoisonValue::get(Old->getType()));
1934 }
1935 case Intrinsic::amdgcn_permlane16:
1936 case Intrinsic::amdgcn_permlane16_var:
1937 case Intrinsic::amdgcn_permlanex16:
1938 case Intrinsic::amdgcn_permlanex16_var: {
1939 // Discard vdst_in if it's not going to be read.
1940 Value *VDstIn = II.getArgOperand(0);
1941 if (isa<PoisonValue>(VDstIn))
1942 break;
1943
1944 // FetchInvalid operand idx.
1945 unsigned int FiIdx = (IID == Intrinsic::amdgcn_permlane16 ||
1946 IID == Intrinsic::amdgcn_permlanex16)
1947 ? 4 /* for permlane16 and permlanex16 */
1948 : 3; /* for permlane16_var and permlanex16_var */
1949
1950 // BoundCtrl operand idx.
1951 // For permlane16 and permlanex16 it should be 5
1952 // For Permlane16_var and permlanex16_var it should be 4
1953 unsigned int BcIdx = FiIdx + 1;
1954
1955 ConstantInt *FetchInvalid = cast<ConstantInt>(II.getArgOperand(FiIdx));
1956 ConstantInt *BoundCtrl = cast<ConstantInt>(II.getArgOperand(BcIdx));
1957 if (!FetchInvalid->getZExtValue() && !BoundCtrl->getZExtValue())
1958 break;
1959
1960 return IC.replaceOperand(II, 0, PoisonValue::get(VDstIn->getType()));
1961 }
1962 case Intrinsic::amdgcn_wave_shuffle:
1963 return tryOptimizeShufflePattern(IC, II, *ST);
1964 case Intrinsic::amdgcn_permlane64:
1965 case Intrinsic::amdgcn_readfirstlane:
1966 case Intrinsic::amdgcn_readlane:
1967 case Intrinsic::amdgcn_ds_bpermute: {
1968 // If the data argument is uniform these intrinsics return it unchanged.
1969 unsigned SrcIdx = IID == Intrinsic::amdgcn_ds_bpermute ? 1 : 0;
1970 const Use &Src = II.getArgOperandUse(SrcIdx);
1971 if (isTriviallyUniform(Src))
1972 return IC.replaceInstUsesWith(II, Src.get());
1973
1974 if (IID == Intrinsic::amdgcn_readlane &&
1976 return &II;
1977
1978 // If the lane argument of bpermute is uniform, change it to readlane. This
1979 // generates better code and can enable further optimizations because
1980 // readlane is AlwaysUniform.
1981 if (IID == Intrinsic::amdgcn_ds_bpermute) {
1982 const Use &Lane = II.getArgOperandUse(0);
1983 if (isTriviallyUniform(Lane)) {
1984 Value *NewLane = IC.Builder.CreateLShr(Lane, 2);
1986 II.getModule(), Intrinsic::amdgcn_readlane, II.getType());
1987 II.setCalledFunction(NewDecl);
1988 II.setOperand(0, Src);
1989 II.setOperand(1, NewLane);
1990 return &II;
1991 }
1992 }
1993
1994 if (IID == Intrinsic::amdgcn_ds_bpermute)
1995 return tryOptimizeShufflePattern(IC, II, *ST);
1996
1998 return Res;
1999
2000 return std::nullopt;
2001 }
2002 case Intrinsic::amdgcn_writelane: {
2003 // TODO: Fold bitcast like readlane.
2004 if (simplifyDemandedLaneMaskArg(IC, II, 1))
2005 return &II;
2006 return std::nullopt;
2007 }
2008 case Intrinsic::amdgcn_trig_preop: {
2009 // The intrinsic is declared with name mangling, but currently the
2010 // instruction only exists for f64
2011 if (!II.getType()->isDoubleTy())
2012 break;
2013
2014 Value *Src = II.getArgOperand(0);
2015 Value *Segment = II.getArgOperand(1);
2016 if (isa<PoisonValue>(Src) || isa<PoisonValue>(Segment))
2017 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
2018
2019 if (isa<UndefValue>(Segment))
2020 return IC.replaceInstUsesWith(II, ConstantFP::getZero(II.getType()));
2021
2022 // Sign bit is not used.
2023 Value *StrippedSign = InstCombiner::stripSignOnlyFPOps(Src);
2024 if (StrippedSign != Src)
2025 return IC.replaceOperand(II, 0, StrippedSign);
2026
2027 if (II.isStrictFP())
2028 break;
2029
2030 const ConstantFP *CSrc = dyn_cast<ConstantFP>(Src);
2031 if (!CSrc && !isa<UndefValue>(Src))
2032 break;
2033
2034 // The instruction ignores special cases, and literally just extracts the
2035 // exponents. Fold undef to nan, and index the table as normal.
2036 APInt FSrcInt = CSrc ? CSrc->getValueAPF().bitcastToAPInt()
2037 : APFloat::getQNaN(II.getType()->getFltSemantics())
2038 .bitcastToAPInt();
2039
2040 const ConstantInt *Cseg = dyn_cast<ConstantInt>(Segment);
2041 if (!Cseg) {
2042 if (isa<UndefValue>(Src))
2043 return IC.replaceInstUsesWith(II, ConstantFP::getZero(II.getType()));
2044 break;
2045 }
2046
2047 unsigned Exponent = FSrcInt.extractBitsAsZExtValue(11, 52);
2048 unsigned SegmentVal = Cseg->getValue().trunc(5).getZExtValue();
2049 unsigned Shift = SegmentVal * 53;
2050 if (Exponent > 1077)
2051 Shift += Exponent - 1077;
2052
2053 // 2.0/PI table.
2054 static const uint32_t TwoByPi[] = {
2055 0xa2f9836e, 0x4e441529, 0xfc2757d1, 0xf534ddc0, 0xdb629599, 0x3c439041,
2056 0xfe5163ab, 0xdebbc561, 0xb7246e3a, 0x424dd2e0, 0x06492eea, 0x09d1921c,
2057 0xfe1deb1c, 0xb129a73e, 0xe88235f5, 0x2ebb4484, 0xe99c7026, 0xb45f7e41,
2058 0x3991d639, 0x835339f4, 0x9c845f8b, 0xbdf9283b, 0x1ff897ff, 0xde05980f,
2059 0xef2f118b, 0x5a0a6d1f, 0x6d367ecf, 0x27cb09b7, 0x4f463f66, 0x9e5fea2d,
2060 0x7527bac7, 0xebe5f17b, 0x3d0739f7, 0x8a5292ea, 0x6bfb5fb1, 0x1f8d5d08,
2061 0x56033046};
2062
2063 // Return 0 for outbound segment (hardware behavior).
2064 unsigned Idx = Shift >> 5;
2065 if (Idx + 2 >= std::size(TwoByPi)) {
2066 APFloat Zero = APFloat::getZero(II.getType()->getFltSemantics());
2067 return IC.replaceInstUsesWith(II, ConstantFP::get(II.getType(), Zero));
2068 }
2069
2070 unsigned BShift = Shift & 0x1f;
2071 uint64_t Thi = Make_64(TwoByPi[Idx], TwoByPi[Idx + 1]);
2072 uint64_t Tlo = Make_64(TwoByPi[Idx + 2], 0);
2073 if (BShift)
2074 Thi = (Thi << BShift) | (Tlo >> (64 - BShift));
2075 Thi = Thi >> 11;
2076 APFloat Result = APFloat((double)Thi);
2077
2078 int Scale = -53 - Shift;
2079 if (Exponent >= 1968)
2080 Scale += 128;
2081
2082 Result = scalbn(Result, Scale, RoundingMode::NearestTiesToEven);
2083 return IC.replaceInstUsesWith(II, ConstantFP::get(Src->getType(), Result));
2084 }
2085 case Intrinsic::amdgcn_fmul_legacy: {
2086 Value *Op0 = II.getArgOperand(0);
2087 Value *Op1 = II.getArgOperand(1);
2088
2089 for (Value *Src : {Op0, Op1}) {
2090 if (isa<PoisonValue>(Src))
2091 return IC.replaceInstUsesWith(II, Src);
2092 }
2093
2094 // The legacy behaviour is that multiplying +/-0.0 by anything, even NaN or
2095 // infinity, gives +0.0.
2096 // TODO: Move to InstSimplify?
2097 if (match(Op0, PatternMatch::m_AnyZeroFP()) ||
2099 return IC.replaceInstUsesWith(II, ConstantFP::getZero(II.getType()));
2100
2101 // If we can prove we don't have one of the special cases then we can use a
2102 // normal fmul instruction instead.
2103 if (canSimplifyLegacyMulToMul(II, Op0, Op1, IC)) {
2104 auto *FMul = IC.Builder.CreateFMulFMF(Op0, Op1, &II);
2105 FMul->takeName(&II);
2106 return IC.replaceInstUsesWith(II, FMul);
2107 }
2108 break;
2109 }
2110 case Intrinsic::amdgcn_fma_legacy: {
2111 Value *Op0 = II.getArgOperand(0);
2112 Value *Op1 = II.getArgOperand(1);
2113 Value *Op2 = II.getArgOperand(2);
2114
2115 for (Value *Src : {Op0, Op1, Op2}) {
2116 if (isa<PoisonValue>(Src))
2117 return IC.replaceInstUsesWith(II, Src);
2118 }
2119
2120 // The legacy behaviour is that multiplying +/-0.0 by anything, even NaN or
2121 // infinity, gives +0.0.
2122 // TODO: Move to InstSimplify?
2123 if (match(Op0, PatternMatch::m_AnyZeroFP()) ||
2125 // It's tempting to just return Op2 here, but that would give the wrong
2126 // result if Op2 was -0.0.
2127 auto *Zero = ConstantFP::getZero(II.getType());
2128 auto *FAdd = IC.Builder.CreateFAddFMF(Zero, Op2, &II);
2129 FAdd->takeName(&II);
2130 return IC.replaceInstUsesWith(II, FAdd);
2131 }
2132
2133 // If we can prove we don't have one of the special cases then we can use a
2134 // normal fma instead.
2135 if (canSimplifyLegacyMulToMul(II, Op0, Op1, IC)) {
2136 II.setCalledOperand(Intrinsic::getOrInsertDeclaration(
2137 II.getModule(), Intrinsic::fma, II.getType()));
2138 return &II;
2139 }
2140 break;
2141 }
2142 case Intrinsic::amdgcn_is_shared:
2143 case Intrinsic::amdgcn_is_private: {
2144 Value *Src = II.getArgOperand(0);
2145 if (isa<PoisonValue>(Src))
2146 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
2147 if (isa<UndefValue>(Src))
2148 return IC.replaceInstUsesWith(II, UndefValue::get(II.getType()));
2149
2150 if (isa<ConstantPointerNull>(II.getArgOperand(0)))
2151 return IC.replaceInstUsesWith(II, ConstantInt::getFalse(II.getType()));
2152 break;
2153 }
2154 case Intrinsic::amdgcn_make_buffer_rsrc: {
2155 Value *Src = II.getArgOperand(0);
2156 if (isa<PoisonValue>(Src))
2157 return IC.replaceInstUsesWith(II, PoisonValue::get(II.getType()));
2158 return std::nullopt;
2159 }
2160 case Intrinsic::amdgcn_raw_buffer_store_format:
2161 case Intrinsic::amdgcn_struct_buffer_store_format:
2162 case Intrinsic::amdgcn_raw_tbuffer_store:
2163 case Intrinsic::amdgcn_struct_tbuffer_store:
2164 case Intrinsic::amdgcn_image_store_1d:
2165 case Intrinsic::amdgcn_image_store_1darray:
2166 case Intrinsic::amdgcn_image_store_2d:
2167 case Intrinsic::amdgcn_image_store_2darray:
2168 case Intrinsic::amdgcn_image_store_2darraymsaa:
2169 case Intrinsic::amdgcn_image_store_2dmsaa:
2170 case Intrinsic::amdgcn_image_store_3d:
2171 case Intrinsic::amdgcn_image_store_cube:
2172 case Intrinsic::amdgcn_image_store_mip_1d:
2173 case Intrinsic::amdgcn_image_store_mip_1darray:
2174 case Intrinsic::amdgcn_image_store_mip_2d:
2175 case Intrinsic::amdgcn_image_store_mip_2darray:
2176 case Intrinsic::amdgcn_image_store_mip_3d:
2177 case Intrinsic::amdgcn_image_store_mip_cube: {
2178 if (!isa<FixedVectorType>(II.getArgOperand(0)->getType()))
2179 break;
2180
2181 APInt DemandedElts;
2182 if (ST->hasDefaultComponentBroadcast())
2183 DemandedElts = defaultComponentBroadcast(II.getArgOperand(0));
2184 else if (ST->hasDefaultComponentZero())
2185 DemandedElts = trimTrailingZerosInVector(IC, II.getArgOperand(0), &II);
2186 else
2187 break;
2188
2189 int DMaskIdx = getAMDGPUImageDMaskIntrinsic(II.getIntrinsicID()) ? 1 : -1;
2190 if (simplifyAMDGCNMemoryIntrinsicDemanded(IC, II, DemandedElts, DMaskIdx,
2191 false)) {
2192 return IC.eraseInstFromFunction(II);
2193 }
2194
2195 break;
2196 }
2197 case Intrinsic::amdgcn_prng_b32: {
2198 auto *Src = II.getArgOperand(0);
2199 if (isa<UndefValue>(Src)) {
2200 return IC.replaceInstUsesWith(II, Src);
2201 }
2202 return std::nullopt;
2203 }
2204 case Intrinsic::amdgcn_mfma_scale_f32_16x16x128_f8f6f4:
2205 case Intrinsic::amdgcn_mfma_scale_f32_32x32x64_f8f6f4: {
2206 Value *Src0 = II.getArgOperand(0);
2207 Value *Src1 = II.getArgOperand(1);
2208 uint64_t CBSZ = cast<ConstantInt>(II.getArgOperand(3))->getZExtValue();
2209 uint64_t BLGP = cast<ConstantInt>(II.getArgOperand(4))->getZExtValue();
2210 auto *Src0Ty = cast<FixedVectorType>(Src0->getType());
2211 auto *Src1Ty = cast<FixedVectorType>(Src1->getType());
2212
2213 auto getFormatNumRegs = [](unsigned FormatVal) {
2214 switch (FormatVal) {
2217 return 6u;
2219 return 4u;
2222 return 8u;
2223 default:
2224 llvm_unreachable("invalid format value");
2225 }
2226 };
2227
2228 bool MadeChange = false;
2229 unsigned Src0NumElts = getFormatNumRegs(CBSZ);
2230 unsigned Src1NumElts = getFormatNumRegs(BLGP);
2231
2232 // Depending on the used format, fewer registers are required so shrink the
2233 // vector type.
2234 if (Src0Ty->getNumElements() > Src0NumElts) {
2235 Src0 = IC.Builder.CreateExtractVector(
2236 FixedVectorType::get(Src0Ty->getElementType(), Src0NumElts), Src0,
2237 uint64_t(0));
2238 MadeChange = true;
2239 }
2240
2241 if (Src1Ty->getNumElements() > Src1NumElts) {
2242 Src1 = IC.Builder.CreateExtractVector(
2243 FixedVectorType::get(Src1Ty->getElementType(), Src1NumElts), Src1,
2244 uint64_t(0));
2245 MadeChange = true;
2246 }
2247
2248 if (!MadeChange)
2249 return std::nullopt;
2250
2251 SmallVector<Value *, 10> Args(II.args());
2252 Args[0] = Src0;
2253 Args[1] = Src1;
2254
2255 Value *NewII = IC.Builder.CreateIntrinsic(
2256 IID, {Src0->getType(), Src1->getType()}, Args, &II);
2257 NewII->takeName(&II);
2258 return IC.replaceInstUsesWith(II, NewII);
2259 }
2260 case Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4:
2261 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
2262 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
2263 Value *Src0 = II.getArgOperand(1);
2264 Value *Src1 = II.getArgOperand(3);
2265 unsigned FmtA = cast<ConstantInt>(II.getArgOperand(0))->getZExtValue();
2266 uint64_t FmtB = cast<ConstantInt>(II.getArgOperand(2))->getZExtValue();
2267 auto *Src0Ty = cast<FixedVectorType>(Src0->getType());
2268 auto *Src1Ty = cast<FixedVectorType>(Src1->getType());
2269
2270 bool MadeChange = false;
2271 unsigned Src0NumElts = AMDGPU::wmmaScaleF8F6F4FormatToNumRegs(FmtA);
2272 unsigned Src1NumElts = AMDGPU::wmmaScaleF8F6F4FormatToNumRegs(FmtB);
2273
2274 // Depending on the used format, fewer registers are required so shrink the
2275 // vector type.
2276 if (Src0Ty->getNumElements() > Src0NumElts) {
2277 Src0 = IC.Builder.CreateExtractVector(
2278 FixedVectorType::get(Src0Ty->getElementType(), Src0NumElts), Src0,
2279 IC.Builder.getInt64(0));
2280 MadeChange = true;
2281 }
2282
2283 if (Src1Ty->getNumElements() > Src1NumElts) {
2284 Src1 = IC.Builder.CreateExtractVector(
2285 FixedVectorType::get(Src1Ty->getElementType(), Src1NumElts), Src1,
2286 IC.Builder.getInt64(0));
2287 MadeChange = true;
2288 }
2289
2290 if (!MadeChange)
2291 return std::nullopt;
2292
2293 SmallVector<Value *, 13> Args(II.args());
2294 Args[1] = Src0;
2295 Args[3] = Src1;
2296
2297 Value *NewII = IC.Builder.CreateIntrinsic(
2298 IID, {II.getArgOperand(5)->getType(), Src0->getType(), Src1->getType()},
2299 Args, &II);
2300 NewII->takeName(&II);
2301 return IC.replaceInstUsesWith(II, NewII);
2302 }
2303 }
2304 if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr =
2305 AMDGPU::getImageDimIntrinsicInfo(II.getIntrinsicID())) {
2306 return simplifyAMDGCNImageIntrinsic(ST, ImageDimIntr, II, IC);
2307 }
2308 return std::nullopt;
2309}
2310
2311/// Implement SimplifyDemandedVectorElts for amdgcn buffer and image intrinsics.
2312///
2313/// The result of simplifying amdgcn image and buffer store intrinsics is updating
2314/// definitions of the intrinsics vector argument, not Uses of the result like
2315/// image and buffer loads.
2316/// Note: This only supports non-TFE/LWE image intrinsic calls; those have
2317/// struct returns.
2320 APInt DemandedElts,
2321 int DMaskIdx, bool IsLoad) {
2322
2323 auto *IIVTy = cast<FixedVectorType>(IsLoad ? II.getType()
2324 : II.getOperand(0)->getType());
2325 unsigned VWidth = IIVTy->getNumElements();
2326 if (VWidth == 1)
2327 return nullptr;
2328 Type *EltTy = IIVTy->getElementType();
2329
2332
2333 // Assume the arguments are unchanged and later override them, if needed.
2334 SmallVector<Value *, 16> Args(II.args());
2335
2336 if (DMaskIdx < 0) {
2337 // Buffer case.
2338
2339 const unsigned ActiveBits = DemandedElts.getActiveBits();
2340 const unsigned UnusedComponentsAtFront = DemandedElts.countr_zero();
2341
2342 // Start assuming the prefix of elements is demanded, but possibly clear
2343 // some other bits if there are trailing zeros (unused components at front)
2344 // and update offset.
2345 DemandedElts = (1 << ActiveBits) - 1;
2346
2347 if (UnusedComponentsAtFront > 0) {
2348 static const unsigned InvalidOffsetIdx = 0xf;
2349
2350 unsigned OffsetIdx;
2351 switch (II.getIntrinsicID()) {
2352 case Intrinsic::amdgcn_raw_buffer_load:
2353 case Intrinsic::amdgcn_raw_ptr_buffer_load:
2354 OffsetIdx = 1;
2355 break;
2356 case Intrinsic::amdgcn_s_buffer_load:
2357 case Intrinsic::amdgcn_ptr_s_buffer_load:
2358 // If resulting type is vec3, there is no point in trimming the
2359 // load with updated offset, as the vec3 would most likely be widened to
2360 // vec4 anyway during lowering.
2361 if (ActiveBits == 4 && UnusedComponentsAtFront == 1)
2362 OffsetIdx = InvalidOffsetIdx;
2363 else
2364 OffsetIdx = 1;
2365 break;
2366 case Intrinsic::amdgcn_struct_buffer_load:
2367 case Intrinsic::amdgcn_struct_ptr_buffer_load:
2368 OffsetIdx = 2;
2369 break;
2370 default:
2371 // TODO: handle tbuffer* intrinsics.
2372 OffsetIdx = InvalidOffsetIdx;
2373 break;
2374 }
2375
2376 if (OffsetIdx != InvalidOffsetIdx) {
2377 // Clear demanded bits and update the offset.
2378 DemandedElts &= ~((1 << UnusedComponentsAtFront) - 1);
2379 auto *Offset = Args[OffsetIdx];
2380 unsigned SingleComponentSizeInBits =
2381 IC.getDataLayout().getTypeSizeInBits(EltTy);
2382 unsigned OffsetAdd =
2383 UnusedComponentsAtFront * SingleComponentSizeInBits / 8;
2384 auto *OffsetAddVal = ConstantInt::get(Offset->getType(), OffsetAdd);
2385 Args[OffsetIdx] = IC.Builder.CreateAdd(Offset, OffsetAddVal);
2386 }
2387 }
2388 } else {
2389 // Image case.
2390
2391 ConstantInt *DMask = cast<ConstantInt>(Args[DMaskIdx]);
2392 unsigned DMaskVal = DMask->getZExtValue() & 0xf;
2393
2394 // dmask 0 has special semantics, do not simplify.
2395 if (DMaskVal == 0)
2396 return nullptr;
2397
2398 if (!IsLoad && !isMask_32(DMaskVal))
2399 return nullptr;
2400
2401 // Mask off values that are undefined because the dmask doesn't cover them
2402 DemandedElts &= (1 << llvm::popcount(DMaskVal)) - 1;
2403
2404 unsigned NewDMaskVal = 0;
2405 unsigned OrigLdStIdx = 0;
2406 for (unsigned SrcIdx = 0; SrcIdx < 4; ++SrcIdx) {
2407 const unsigned Bit = 1 << SrcIdx;
2408 if (!!(DMaskVal & Bit)) {
2409 if (!!DemandedElts[OrigLdStIdx])
2410 NewDMaskVal |= Bit;
2411 OrigLdStIdx++;
2412 }
2413 }
2414
2415 if (DMaskVal != NewDMaskVal)
2416 Args[DMaskIdx] = ConstantInt::get(DMask->getType(), NewDMaskVal);
2417 }
2418
2419 unsigned NewNumElts = DemandedElts.popcount();
2420 if (!NewNumElts)
2421 return PoisonValue::get(IIVTy);
2422
2423 if (NewNumElts >= VWidth && DemandedElts.isMask()) {
2424 if (DMaskIdx >= 0)
2425 II.setArgOperand(DMaskIdx, Args[DMaskIdx]);
2426 return nullptr;
2427 }
2428
2429 // Validate function argument and return types, extracting overloaded types
2430 // along the way.
2431 SmallVector<Type *, 6> OverloadTys;
2432 if (!Intrinsic::isSignatureValid(II.getCalledFunction(), OverloadTys))
2433 return nullptr;
2434
2435 Type *NewTy =
2436 (NewNumElts == 1) ? EltTy : FixedVectorType::get(EltTy, NewNumElts);
2437 OverloadTys[0] = NewTy;
2438
2439 if (!IsLoad) {
2440 SmallVector<int, 8> EltMask;
2441 for (unsigned OrigStoreIdx = 0; OrigStoreIdx < VWidth; ++OrigStoreIdx)
2442 if (DemandedElts[OrigStoreIdx])
2443 EltMask.push_back(OrigStoreIdx);
2444
2445 if (NewNumElts == 1)
2446 Args[0] = IC.Builder.CreateExtractElement(II.getOperand(0), EltMask[0]);
2447 else
2448 Args[0] = IC.Builder.CreateShuffleVector(II.getOperand(0), EltMask);
2449 }
2450
2452 II.getIntrinsicID(), OverloadTys, Args);
2453 NewCall->takeName(&II);
2454 NewCall->copyMetadata(II);
2455 AttributeList OldAttrList = II.getAttributes();
2456 NewCall->setAttributes(OldAttrList);
2457
2458 if (IsLoad) {
2459 if (NewNumElts == 1) {
2460 return IC.Builder.CreateInsertElement(PoisonValue::get(IIVTy), NewCall,
2461 DemandedElts.countr_zero());
2462 }
2463
2464 SmallVector<int, 8> EltMask;
2465 unsigned NewLoadIdx = 0;
2466 for (unsigned OrigLoadIdx = 0; OrigLoadIdx < VWidth; ++OrigLoadIdx) {
2467 if (!!DemandedElts[OrigLoadIdx])
2468 EltMask.push_back(NewLoadIdx++);
2469 else
2470 EltMask.push_back(NewNumElts);
2471 }
2472
2473 auto *Shuffle = IC.Builder.CreateShuffleVector(NewCall, EltMask);
2474
2475 return Shuffle;
2476 }
2477
2478 return NewCall;
2479}
2480
2482 InstCombiner &IC, IntrinsicInst &II, const APInt &DemandedElts,
2483 APInt &UndefElts) const {
2484 auto *VT = dyn_cast<FixedVectorType>(II.getType());
2485 if (!VT)
2486 return nullptr;
2487
2488 const unsigned FirstElt = DemandedElts.countr_zero();
2489 const unsigned LastElt = DemandedElts.getActiveBits() - 1;
2490 const unsigned MaskLen = LastElt - FirstElt + 1;
2491
2492 unsigned OldNumElts = VT->getNumElements();
2493 if (MaskLen == OldNumElts && MaskLen != 1)
2494 return nullptr;
2495
2496 Type *EltTy = VT->getElementType();
2497 Type *NewVT = MaskLen == 1 ? EltTy : FixedVectorType::get(EltTy, MaskLen);
2498
2499 // Theoretically we should support these intrinsics for any legal type. Avoid
2500 // introducing cases that aren't direct register types like v3i16.
2501 if (!isTypeLegal(NewVT))
2502 return nullptr;
2503
2504 Value *Src = II.getArgOperand(0);
2505
2506 // Make sure convergence tokens are preserved.
2507 // TODO: CreateIntrinsic should allow directly copying bundles
2509 II.getOperandBundlesAsDefs(OpBundles);
2510
2512 Function *Remangled =
2513 Intrinsic::getOrInsertDeclaration(M, II.getIntrinsicID(), {NewVT});
2514
2515 if (MaskLen == 1) {
2516 Value *Extract = IC.Builder.CreateExtractElement(Src, FirstElt);
2517
2518 // TODO: Preserve callsite attributes?
2519 CallInst *NewCall = IC.Builder.CreateCall(Remangled, {Extract}, OpBundles);
2520
2521 return IC.Builder.CreateInsertElement(PoisonValue::get(II.getType()),
2522 NewCall, FirstElt);
2523 }
2524
2525 SmallVector<int> ExtractMask(MaskLen, -1);
2526 for (unsigned I = 0; I != MaskLen; ++I) {
2527 if (DemandedElts[FirstElt + I])
2528 ExtractMask[I] = FirstElt + I;
2529 }
2530
2531 Value *Extract = IC.Builder.CreateShuffleVector(Src, ExtractMask);
2532
2533 // TODO: Preserve callsite attributes?
2534 CallInst *NewCall = IC.Builder.CreateCall(Remangled, {Extract}, OpBundles);
2535
2536 SmallVector<int> InsertMask(OldNumElts, -1);
2537 for (unsigned I = 0; I != MaskLen; ++I) {
2538 if (DemandedElts[FirstElt + I])
2539 InsertMask[FirstElt + I] = I;
2540 }
2541
2542 // FIXME: If the call has a convergence bundle, we end up leaving the dead
2543 // call behind.
2544 return IC.Builder.CreateShuffleVector(NewCall, InsertMask);
2545}
2546
2548 InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts,
2549 APInt &UndefElts2, APInt &UndefElts3,
2550 std::function<void(Instruction *, unsigned, APInt, APInt &)>
2551 SimplifyAndSetOp) const {
2552 switch (II.getIntrinsicID()) {
2553 case Intrinsic::amdgcn_readfirstlane:
2554 SimplifyAndSetOp(&II, 0, DemandedElts, UndefElts);
2555 return simplifyAMDGCNLaneIntrinsicDemanded(IC, II, DemandedElts, UndefElts);
2556 case Intrinsic::amdgcn_raw_buffer_load:
2557 case Intrinsic::amdgcn_raw_ptr_buffer_load:
2558 case Intrinsic::amdgcn_raw_buffer_load_format:
2559 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:
2560 case Intrinsic::amdgcn_raw_tbuffer_load:
2561 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:
2562 case Intrinsic::amdgcn_s_buffer_load:
2563 case Intrinsic::amdgcn_ptr_s_buffer_load:
2564 case Intrinsic::amdgcn_struct_buffer_load:
2565 case Intrinsic::amdgcn_struct_ptr_buffer_load:
2566 case Intrinsic::amdgcn_struct_buffer_load_format:
2567 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:
2568 case Intrinsic::amdgcn_struct_tbuffer_load:
2569 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
2570 return simplifyAMDGCNMemoryIntrinsicDemanded(IC, II, DemandedElts);
2571 default: {
2572 if (getAMDGPUImageDMaskIntrinsic(II.getIntrinsicID())) {
2573 return simplifyAMDGCNMemoryIntrinsicDemanded(IC, II, DemandedElts, 0);
2574 }
2575 break;
2576 }
2577 }
2578 return std::nullopt;
2579}
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
MachineInstr unsigned OpIdx
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:5929
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 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.