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