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