LLVM 24.0.0git
VectorCombine.cpp
Go to the documentation of this file.
1//===------- VectorCombine.cpp - Optimize partial vector operations -------===//
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// This pass optimizes scalar/vector interactions using target cost models. The
10// transforms implemented here may not fit in traditional loop-based or SLP
11// vectorization passes.
12//
13//===----------------------------------------------------------------------===//
14
16#include "llvm/ADT/DenseMap.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/ScopeExit.h"
21#include "llvm/ADT/Statistic.h"
26#include "llvm/Analysis/Loads.h"
31#include "llvm/IR/Dominators.h"
32#include "llvm/IR/Function.h"
33#include "llvm/IR/IRBuilder.h"
42#include <numeric>
43#include <optional>
44#include <queue>
45#include <set>
46
47#define DEBUG_TYPE "vector-combine"
49
50using namespace llvm;
51using namespace llvm::PatternMatch;
52
53STATISTIC(NumVecLoad, "Number of vector loads formed");
54STATISTIC(NumVecCmp, "Number of vector compares formed");
55STATISTIC(NumVecBO, "Number of vector binops formed");
56STATISTIC(NumVecCmpBO, "Number of vector compare + binop formed");
57STATISTIC(NumShufOfBitcast, "Number of shuffles moved after bitcast");
58STATISTIC(NumScalarOps, "Number of scalar unary + binary ops formed");
59STATISTIC(NumScalarCmp, "Number of scalar compares formed");
60STATISTIC(NumScalarIntrinsic, "Number of scalar intrinsic calls formed");
61
63 "disable-vector-combine", cl::init(false), cl::Hidden,
64 cl::desc("Disable all vector combine transforms"));
65
67 "disable-binop-extract-shuffle", cl::init(false), cl::Hidden,
68 cl::desc("Disable binop extract to shuffle transforms"));
69
71 "vector-combine-max-scan-instrs", cl::init(30), cl::Hidden,
72 cl::desc("Max number of instructions to scan for vector combining."));
73
74static const unsigned InvalidIndex = std::numeric_limits<unsigned>::max();
75
76namespace {
77class VectorCombine {
78public:
79 VectorCombine(Function &F, const TargetTransformInfo &TTI,
82 bool TryEarlyFoldsOnly)
83 : F(F), Builder(*F.getParent(), InstSimplifyFolder(*DL)), TTI(TTI),
84 DT(DT), AA(AA), DL(DL), CostKind(CostKind),
85 SQ(*DL, /*TLI=*/nullptr, &DT, &AC),
86 TryEarlyFoldsOnly(TryEarlyFoldsOnly) {}
87
88 bool run();
89
90private:
91 Function &F;
93 const TargetTransformInfo &TTI;
94 const DominatorTree &DT;
95 AAResults &AA;
96 const DataLayout *DL;
97 TTI::TargetCostKind CostKind;
98 const SimplifyQuery SQ;
99
100 /// If true, only perform beneficial early IR transforms. Do not introduce new
101 /// vector operations.
102 bool TryEarlyFoldsOnly;
103
104 InstructionWorklist Worklist;
105
106 /// Next instruction to iterate. It will be updated when it is erased by
107 /// RecursivelyDeleteTriviallyDeadInstructions.
108 Instruction *NextInst;
109
110 // TODO: Direct calls from the top-level "run" loop use a plain "Instruction"
111 // parameter. That should be updated to specific sub-classes because the
112 // run loop was changed to dispatch on opcode.
113 bool vectorizeLoadInsert(Instruction &I);
114 bool widenSubvectorLoad(Instruction &I);
115 ExtractElementInst *getShuffleExtract(ExtractElementInst *Ext0,
116 ExtractElementInst *Ext1,
117 unsigned PreferredExtractIndex) const;
118 bool isExtractExtractCheap(ExtractElementInst *Ext0, ExtractElementInst *Ext1,
119 const Instruction &I,
120 ExtractElementInst *&ConvertToShuffle,
121 unsigned PreferredExtractIndex);
122 Value *foldExtExtCmp(Value *V0, Value *V1, Value *ExtIndex, Instruction &I);
123 Value *foldExtExtBinop(Value *V0, Value *V1, Value *ExtIndex, Instruction &I);
124 bool foldExtractExtract(Instruction &I);
125 bool foldInsExtFNeg(Instruction &I);
126 bool foldInsExtBinop(Instruction &I);
127 bool foldInsExtVectorToShuffle(Instruction &I);
128 bool foldInsertScalarPartsToShuffle(Instruction &I);
129 bool foldBitOpOfCastops(Instruction &I);
130 bool foldBitOpOfCastConstant(Instruction &I);
131 bool foldBitcastShuffle(Instruction &I);
132 bool scalarizeOpOrCmp(Instruction &I);
133 bool foldExtractedCmps(Instruction &I);
134 bool foldSelectsFromBitcast(Instruction &I);
135 bool foldBinopOfReductions(Instruction &I);
136 bool foldInsertElementsToStores(Instruction &I);
137 bool scalarizeLoad(Instruction &I);
138 bool scalarizeLoadExtract(LoadInst *LI, VectorType *VecTy, Value *Ptr);
139 bool scalarizeLoadBitcast(LoadInst *LI, VectorType *VecTy, Value *Ptr);
140 bool scalarizeExtExtract(Instruction &I);
141 bool foldConcatOfBoolMasks(Instruction &I);
142 bool foldPermuteOfBinops(Instruction &I);
143 bool foldShuffleOfBinops(Instruction &I);
144 bool foldShuffleOfSelects(Instruction &I);
145 bool foldShuffleOfCastops(Instruction &I);
146 bool foldShuffleOfShuffles(Instruction &I);
147 bool foldPermuteOfIntrinsic(Instruction &I);
148 bool foldShufflesOfLengthChangingShuffles(Instruction &I);
149 bool foldShuffleOfIntrinsics(Instruction &I);
150 bool foldShuffleToIdentity(Instruction &I);
151 bool foldShuffleFromReductions(Instruction &I);
152 bool foldShuffleChainsToReduce(Instruction &I);
153 bool foldCastFromReductions(Instruction &I);
154 bool foldSignBitReductionCmp(Instruction &I);
155 bool foldReductionZeroTest(Instruction &I);
156 bool foldICmpEqZeroVectorReduce(Instruction &I);
157 bool foldEquivalentReductionCmp(Instruction &I);
158 bool foldReduceAddCmpZero(Instruction &I);
159 bool foldSelectShuffle(Instruction &I, bool FromReduction = false);
160 bool foldInterleaveIntrinsics(Instruction &I);
161 bool foldDeinterleaveIntrinsics(Instruction &I);
162 bool foldBitcastOfVPLoad(Instruction &I);
163 bool foldBitOrderReverseAndSwap(Instruction &I);
164 bool shrinkType(Instruction &I);
165 bool shrinkLoadForShuffles(Instruction &I);
166 bool shrinkPhiOfShuffles(Instruction &I);
167 bool foldInterleaveOfDeinterleaveChains(Instruction &I);
168
169 void replaceValue(Instruction &Old, Value &New, bool Erase = true) {
170 LLVM_DEBUG(dbgs() << "VC: Replacing: " << Old << '\n');
171 LLVM_DEBUG(dbgs() << " With: " << New << '\n');
172 Old.replaceAllUsesWith(&New);
173 if (auto *NewI = dyn_cast<Instruction>(&New)) {
174 New.takeName(&Old);
175 Worklist.pushUsersToWorkList(*NewI);
176 Worklist.pushValue(NewI);
177 }
178 if (Erase && isInstructionTriviallyDead(&Old)) {
179 eraseInstruction(Old);
180 } else {
181 Worklist.push(&Old);
182 }
183 }
184
185 void eraseInstruction(Instruction &I) {
186 LLVM_DEBUG(dbgs() << "VC: Erasing: " << I << '\n');
187 SmallVector<Value *> Ops(I.operands());
188 Worklist.remove(&I);
189 I.eraseFromParent();
190
191 // Push remaining users of the operands and then the operand itself - allows
192 // further folds that were hindered by OneUse limits.
193 SmallPtrSet<Value *, 4> Visited;
194 for (Value *Op : Ops) {
195 if (!Visited.contains(Op)) {
196 if (auto *OpI = dyn_cast<Instruction>(Op)) {
198 OpI, nullptr, nullptr, [&](Value *V) {
199 if (auto *I = dyn_cast<Instruction>(V)) {
200 LLVM_DEBUG(dbgs() << "VC: Erased: " << *I << '\n');
201 Worklist.remove(I);
202 if (I == NextInst)
203 NextInst = NextInst->getNextNode();
204 Visited.insert(I);
205 }
206 }))
207 continue;
208 Worklist.pushUsersToWorkList(*OpI);
209 Worklist.pushValue(OpI);
210 }
211 }
212 }
213 }
214};
215} // namespace
216
217/// Return the source operand of a potentially bitcasted value. If there is no
218/// bitcast, return the input value itself.
220 while (auto *BitCast = dyn_cast<BitCastInst>(V))
221 V = BitCast->getOperand(0);
222 return V;
223}
224
225/// Helper to peek through bitcasts to the same value.
226static bool isEquivBitcast(Value *X, Value *Y) {
227 return X->getType() == Y->getType() &&
229}
230
232 // Do not widen load if atomic/volatile or under asan/hwasan/memtag/tsan.
233 // The widened load may load data from dirty regions or create data races
234 // non-existent in the source.
235 if (!Load || !Load->isSimple() || !Load->hasOneUse() ||
236 Load->getFunction()->hasFnAttribute(Attribute::SanitizeMemTag) ||
238 return false;
239
240 // We are potentially transforming byte-sized (8-bit) memory accesses, so make
241 // sure we have all of our type-based constraints in place for this target.
242 Type *ScalarTy = Load->getType()->getScalarType();
243 uint64_t ScalarSize = ScalarTy->getPrimitiveSizeInBits();
244 unsigned MinVectorSize = TTI.getMinVectorRegisterBitWidth();
245 if (!ScalarSize || !MinVectorSize || MinVectorSize % ScalarSize != 0 ||
246 ScalarSize % 8 != 0)
247 return false;
248
249 return true;
250}
251
252bool VectorCombine::vectorizeLoadInsert(Instruction &I) {
253 // Match insert into fixed vector of scalar value.
254 // TODO: Handle non-zero insert index.
255 Value *Scalar;
256 if (!match(&I,
258 return false;
259
260 // Optionally match an extract from another vector.
261 Value *X;
262 bool HasExtract = match(Scalar, m_ExtractElt(m_Value(X), m_ZeroInt()));
263 if (!HasExtract)
264 X = Scalar;
265
266 auto *Load = dyn_cast<LoadInst>(X);
267 if (!canWidenLoad(Load, TTI))
268 return false;
269
270 Type *ScalarTy = Scalar->getType();
271 uint64_t ScalarSize = ScalarTy->getPrimitiveSizeInBits();
272 unsigned MinVectorSize = TTI.getMinVectorRegisterBitWidth();
273
274 // Check safety of replacing the scalar load with a larger vector load.
275 // We use minimal alignment (maximum flexibility) because we only care about
276 // the dereferenceable region. When calculating cost and creating a new op,
277 // we may use a larger value based on alignment attributes.
278 Value *SrcPtr = Load->getPointerOperand()->stripPointerCasts();
279 assert(isa<PointerType>(SrcPtr->getType()) && "Expected a pointer type");
280
281 unsigned MinVecNumElts = MinVectorSize / ScalarSize;
282 auto *MinVecTy = VectorType::get(ScalarTy, MinVecNumElts, false);
283 unsigned OffsetEltIndex = 0;
284 Align Alignment = Load->getAlign();
285 // Ignore frees because the existing load proves that the object has not been
286 // freed. Allocations cannot shrink, so this is sufficient.
287 if (!isSafeToLoadUnconditionally(SrcPtr, MinVecTy, Align(1),
289 /*IgnoreFree=*/true)) {
290 // It is not safe to load directly from the pointer, but we can still peek
291 // through gep offsets and check if it safe to load from a base address with
292 // updated alignment. If it is, we can shuffle the element(s) into place
293 // after loading.
294 unsigned OffsetBitWidth = DL->getIndexTypeSizeInBits(SrcPtr->getType());
295 APInt Offset(OffsetBitWidth, 0);
297
298 // We want to shuffle the result down from a high element of a vector, so
299 // the offset must be positive.
300 if (Offset.isNegative())
301 return false;
302
303 // The offset must be a multiple of the scalar element to shuffle cleanly
304 // in the element's size.
305 uint64_t ScalarSizeInBytes = ScalarSize / 8;
306 if (Offset.urem(ScalarSizeInBytes) != 0)
307 return false;
308
309 // If we load MinVecNumElts, will our target element still be loaded?
310 APInt OffsetEltIndexAP = Offset.udiv(ScalarSizeInBytes);
311 if (OffsetEltIndexAP.uge(MinVecNumElts))
312 return false;
313 OffsetEltIndex = OffsetEltIndexAP.getZExtValue();
314
315 if (!isSafeToLoadUnconditionally(SrcPtr, MinVecTy, Align(1),
317 /*IgnoreFree=*/true))
318 return false;
319
320 // Update alignment with offset value. Note that the offset could be negated
321 // to more accurately represent "(new) SrcPtr - Offset = (old) SrcPtr", but
322 // negation does not change the result of the alignment calculation.
323 Alignment = commonAlignment(Alignment, Offset.getZExtValue());
324 }
325
326 // Original pattern: insertelt undef, load [free casts of] PtrOp, 0
327 // Use the greater of the alignment on the load or its source pointer.
328 Alignment = std::max(SrcPtr->getPointerAlignment(*DL), Alignment);
329 Type *LoadTy = Load->getType();
330 unsigned AS = Load->getPointerAddressSpace();
331 InstructionCost OldCost =
332 TTI.getMemoryOpCost(Instruction::Load, LoadTy, Alignment, AS, CostKind);
333 APInt DemandedElts = APInt::getOneBitSet(MinVecNumElts, 0);
334 OldCost +=
335 TTI.getScalarizationOverhead(MinVecTy, DemandedElts,
336 /* Insert */ true, HasExtract, CostKind);
337
338 // New pattern: load VecPtr
339 InstructionCost NewCost =
340 TTI.getMemoryOpCost(Instruction::Load, MinVecTy, Alignment, AS, CostKind);
341 // Optionally, we are shuffling the loaded vector element(s) into place.
342 // For the mask set everything but element 0 to undef to prevent poison from
343 // propagating from the extra loaded memory. This will also optionally
344 // shrink/grow the vector from the loaded size to the output size.
345 // We assume this operation has no cost in codegen if there was no offset.
346 // Note that we could use freeze to avoid poison problems, but then we might
347 // still need a shuffle to change the vector size.
348 auto *Ty = cast<FixedVectorType>(I.getType());
349 unsigned OutputNumElts = Ty->getNumElements();
350 SmallVector<int, 16> Mask(OutputNumElts, PoisonMaskElem);
351 assert(OffsetEltIndex < MinVecNumElts && "Address offset too big");
352 Mask[0] = OffsetEltIndex;
353 if (OffsetEltIndex)
354 NewCost += TTI.getShuffleCost(TTI::SK_PermuteSingleSrc, Ty, MinVecTy,
355 CostKind, Mask);
356
357 // We can aggressively convert to the vector form because the backend can
358 // invert this transform if it does not result in a performance win.
359 if (OldCost < NewCost || !NewCost.isValid())
360 return false;
361
362 // It is safe and potentially profitable to load a vector directly:
363 // inselt undef, load Scalar, 0 --> load VecPtr
364 IRBuilder<> Builder(Load);
365 Value *CastedPtr =
366 Builder.CreatePointerBitCastOrAddrSpaceCast(SrcPtr, Builder.getPtrTy(AS));
367 Value *VecLd = Builder.CreateAlignedLoad(MinVecTy, CastedPtr, Alignment);
368 VecLd = Builder.CreateShuffleVector(VecLd, Mask);
369
370 replaceValue(I, *VecLd);
371 ++NumVecLoad;
372 return true;
373}
374
375/// If we are loading a vector and then inserting it into a larger vector with
376/// undefined elements, try to load the larger vector and eliminate the insert.
377/// This removes a shuffle in IR and may allow combining of other loaded values.
378bool VectorCombine::widenSubvectorLoad(Instruction &I) {
379 // Match subvector insert of fixed vector.
380 auto *Shuf = cast<ShuffleVectorInst>(&I);
381 if (!Shuf->isIdentityWithPadding())
382 return false;
383
384 // Allow a non-canonical shuffle mask that is choosing elements from op1.
385 unsigned NumOpElts =
386 cast<FixedVectorType>(Shuf->getOperand(0)->getType())->getNumElements();
387 unsigned OpIndex = any_of(Shuf->getShuffleMask(), [&NumOpElts](int M) {
388 return M >= (int)(NumOpElts);
389 });
390
391 auto *Load = dyn_cast<LoadInst>(Shuf->getOperand(OpIndex));
392 if (!canWidenLoad(Load, TTI))
393 return false;
394
395 // We use minimal alignment (maximum flexibility) because we only care about
396 // the dereferenceable region. When calculating cost and creating a new op,
397 // we may use a larger value based on alignment attributes.
398 auto *Ty = cast<FixedVectorType>(I.getType());
399 Value *SrcPtr = Load->getPointerOperand()->stripPointerCasts();
400 assert(isa<PointerType>(SrcPtr->getType()) && "Expected a pointer type");
401 Align Alignment = Load->getAlign();
402 // Ignore frees because the existing load proves that the object has not been
403 // freed. Allocations cannot shrink, so this is sufficient.
404 if (!isSafeToLoadUnconditionally(SrcPtr, Ty, Align(1),
406 /*IgnoreFree=*/true))
407 return false;
408
409 Alignment = std::max(SrcPtr->getPointerAlignment(*DL), Alignment);
410 Type *LoadTy = Load->getType();
411 unsigned AS = Load->getPointerAddressSpace();
412
413 // Original pattern: insert_subvector (load PtrOp)
414 // This conservatively assumes that the cost of a subvector insert into an
415 // undef value is 0. We could add that cost if the cost model accurately
416 // reflects the real cost of that operation.
417 InstructionCost OldCost =
418 TTI.getMemoryOpCost(Instruction::Load, LoadTy, Alignment, AS, CostKind);
419
420 // New pattern: load PtrOp
421 InstructionCost NewCost =
422 TTI.getMemoryOpCost(Instruction::Load, Ty, Alignment, AS, CostKind);
423
424 // We can aggressively convert to the vector form because the backend can
425 // invert this transform if it does not result in a performance win.
426 if (OldCost < NewCost || !NewCost.isValid())
427 return false;
428
429 IRBuilder<> Builder(Load);
430 Value *CastedPtr =
431 Builder.CreatePointerBitCastOrAddrSpaceCast(SrcPtr, Builder.getPtrTy(AS));
432 Value *VecLd = Builder.CreateAlignedLoad(Ty, CastedPtr, Alignment);
433 replaceValue(I, *VecLd);
434 ++NumVecLoad;
435 return true;
436}
437
438/// Determine which, if any, of the inputs should be replaced by a shuffle
439/// followed by extract from a different index.
440ExtractElementInst *VectorCombine::getShuffleExtract(
441 ExtractElementInst *Ext0, ExtractElementInst *Ext1,
442 unsigned PreferredExtractIndex = InvalidIndex) const {
443 auto *Index0C = dyn_cast<ConstantInt>(Ext0->getIndexOperand());
444 auto *Index1C = dyn_cast<ConstantInt>(Ext1->getIndexOperand());
445 assert(Index0C && Index1C && "Expected constant extract indexes");
446
447 unsigned Index0 = Index0C->getZExtValue();
448 unsigned Index1 = Index1C->getZExtValue();
449
450 // If the extract indexes are identical, no shuffle is needed.
451 if (Index0 == Index1)
452 return nullptr;
453
454 Type *VecTy = Ext0->getVectorOperand()->getType();
455 assert(VecTy == Ext1->getVectorOperand()->getType() && "Need matching types");
456 InstructionCost Cost0 =
457 TTI.getVectorInstrCost(*Ext0, VecTy, CostKind, Index0);
458 InstructionCost Cost1 =
459 TTI.getVectorInstrCost(*Ext1, VecTy, CostKind, Index1);
460
461 // If both costs are invalid no shuffle is needed
462 if (!Cost0.isValid() && !Cost1.isValid())
463 return nullptr;
464
465 // We are extracting from 2 different indexes, so one operand must be shuffled
466 // before performing a vector operation and/or extract. The more expensive
467 // extract will be replaced by a shuffle.
468 if (Cost0 > Cost1)
469 return Ext0;
470 if (Cost1 > Cost0)
471 return Ext1;
472
473 // If the costs are equal and there is a preferred extract index, shuffle the
474 // opposite operand.
475 if (PreferredExtractIndex == Index0)
476 return Ext1;
477 if (PreferredExtractIndex == Index1)
478 return Ext0;
479
480 // Otherwise, replace the extract with the higher index.
481 return Index0 > Index1 ? Ext0 : Ext1;
482}
483
484/// Compare the relative costs of 2 extracts followed by scalar operation vs.
485/// vector operation(s) followed by extract. Return true if the existing
486/// instructions are cheaper than a vector alternative. Otherwise, return false
487/// and if one of the extracts should be transformed to a shufflevector, set
488/// \p ConvertToShuffle to that extract instruction.
489bool VectorCombine::isExtractExtractCheap(ExtractElementInst *Ext0,
490 ExtractElementInst *Ext1,
491 const Instruction &I,
492 ExtractElementInst *&ConvertToShuffle,
493 unsigned PreferredExtractIndex) {
494 auto *Ext0IndexC = dyn_cast<ConstantInt>(Ext0->getIndexOperand());
495 auto *Ext1IndexC = dyn_cast<ConstantInt>(Ext1->getIndexOperand());
496 assert(Ext0IndexC && Ext1IndexC && "Expected constant extract indexes");
497
498 unsigned Opcode = I.getOpcode();
499 Value *Ext0Src = Ext0->getVectorOperand();
500 Value *Ext1Src = Ext1->getVectorOperand();
501 Type *ScalarTy = Ext0->getType();
502 auto *VecTy = cast<VectorType>(Ext0Src->getType());
503 InstructionCost ScalarOpCost, VectorOpCost;
504
505 // Get cost estimates for scalar and vector versions of the operation.
506 bool IsBinOp = Instruction::isBinaryOp(Opcode);
507 if (IsBinOp) {
508 ScalarOpCost = TTI.getArithmeticInstrCost(Opcode, ScalarTy, CostKind);
509 VectorOpCost = TTI.getArithmeticInstrCost(Opcode, VecTy, CostKind);
510 } else {
511 assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
512 "Expected a compare");
513 CmpInst::Predicate Pred = cast<CmpInst>(I).getPredicate();
514 ScalarOpCost = TTI.getCmpSelInstrCost(
515 Opcode, ScalarTy, CmpInst::makeCmpResultType(ScalarTy), Pred, CostKind);
516 VectorOpCost = TTI.getCmpSelInstrCost(
517 Opcode, VecTy, CmpInst::makeCmpResultType(VecTy), Pred, CostKind);
518 }
519
520 // Get cost estimates for the extract elements. These costs will factor into
521 // both sequences.
522 unsigned Ext0Index = Ext0IndexC->getZExtValue();
523 unsigned Ext1Index = Ext1IndexC->getZExtValue();
524
525 InstructionCost Extract0Cost =
526 TTI.getVectorInstrCost(*Ext0, VecTy, CostKind, Ext0Index);
527 InstructionCost Extract1Cost =
528 TTI.getVectorInstrCost(*Ext1, VecTy, CostKind, Ext1Index);
529
530 // A more expensive extract will always be replaced by a splat shuffle.
531 // For example, if Ext0 is more expensive:
532 // opcode (extelt V0, Ext0), (ext V1, Ext1) -->
533 // extelt (opcode (splat V0, Ext0), V1), Ext1
534 // TODO: Evaluate whether that always results in lowest cost. Alternatively,
535 // check the cost of creating a broadcast shuffle and shuffling both
536 // operands to element 0.
537 unsigned BestExtIndex = Extract0Cost > Extract1Cost ? Ext0Index : Ext1Index;
538 unsigned BestInsIndex = Extract0Cost > Extract1Cost ? Ext1Index : Ext0Index;
539 InstructionCost CheapExtractCost = std::min(Extract0Cost, Extract1Cost);
540
541 // Extra uses of the extracts mean that we include those costs in the
542 // vector total because those instructions will not be eliminated.
543 InstructionCost OldCost, NewCost;
544 if (Ext0Src == Ext1Src && Ext0Index == Ext1Index) {
545 // Handle a special case. If the 2 extracts are identical, adjust the
546 // formulas to account for that. The extra use charge allows for either the
547 // CSE'd pattern or an unoptimized form with identical values:
548 // opcode (extelt V, C), (extelt V, C) --> extelt (opcode V, V), C
549 bool HasUseTax = Ext0 == Ext1 ? !Ext0->hasNUses(2)
550 : !Ext0->hasOneUse() || !Ext1->hasOneUse();
551 OldCost = CheapExtractCost + ScalarOpCost;
552 NewCost = VectorOpCost + CheapExtractCost + HasUseTax * CheapExtractCost;
553 } else {
554 // Handle the general case. Each extract is actually a different value:
555 // opcode (extelt V0, C0), (extelt V1, C1) --> extelt (opcode V0, V1), C
556 OldCost = Extract0Cost + Extract1Cost + ScalarOpCost;
557 NewCost = VectorOpCost + CheapExtractCost +
558 !Ext0->hasOneUse() * Extract0Cost +
559 !Ext1->hasOneUse() * Extract1Cost;
560 }
561
562 ConvertToShuffle = getShuffleExtract(Ext0, Ext1, PreferredExtractIndex);
563 if (ConvertToShuffle) {
564 if (IsBinOp && DisableBinopExtractShuffle)
565 return true;
566
567 // If we are extracting from 2 different indexes, then one operand must be
568 // shuffled before performing the vector operation. The shuffle mask is
569 // poison except for 1 lane that is being translated to the remaining
570 // extraction lane. Therefore, it is a splat shuffle. Ex:
571 // ShufMask = { poison, poison, 0, poison }
572 // TODO: The cost model has an option for a "broadcast" shuffle
573 // (splat-from-element-0), but no option for a more general splat.
574 if (auto *FixedVecTy = dyn_cast<FixedVectorType>(VecTy)) {
575 SmallVector<int> ShuffleMask(FixedVecTy->getNumElements(),
577 ShuffleMask[BestInsIndex] = BestExtIndex;
579 VecTy, VecTy, CostKind, ShuffleMask, 0,
580 nullptr, {ConvertToShuffle});
581 } else {
583 VecTy, VecTy, CostKind, {}, 0, nullptr,
584 {ConvertToShuffle});
585 }
586 }
587
588 LLVM_DEBUG(dbgs() << "Found a binop of extractions: " << I << "\n OldCost: "
589 << OldCost << " vs NewCost: " << NewCost << "\n");
590
591 // Aggressively form a vector op if the cost is equal because the transform
592 // may enable further optimization.
593 // Codegen can reverse this transform (scalarize) if it was not profitable.
594 return OldCost < NewCost;
595}
596
597/// Create a shuffle that translates (shifts) 1 element from the input vector
598/// to a new element location.
599static Value *createShiftShuffle(Value *Vec, unsigned OldIndex,
600 unsigned NewIndex, IRBuilderBase &Builder) {
601 // The shuffle mask is poison except for 1 lane that is being translated
602 // to the new element index. Example for OldIndex == 2 and NewIndex == 0:
603 // ShufMask = { 2, poison, poison, poison }
604 auto *VecTy = cast<FixedVectorType>(Vec->getType());
605 SmallVector<int, 32> ShufMask(VecTy->getNumElements(), PoisonMaskElem);
606 ShufMask[NewIndex] = OldIndex;
607 return Builder.CreateShuffleVector(Vec, ShufMask, "shift");
608}
609
610/// Given an extract element instruction with constant index operand, shuffle
611/// the source vector (shift the scalar element) to a NewIndex for extraction.
612/// Return null if the input can be constant folded, so that we are not creating
613/// unnecessary instructions.
614static Value *translateExtract(ExtractElementInst *ExtElt, unsigned NewIndex,
615 IRBuilderBase &Builder) {
616 // Shufflevectors can only be created for fixed-width vectors.
617 Value *X = ExtElt->getVectorOperand();
618 if (!isa<FixedVectorType>(X->getType()))
619 return nullptr;
620
621 // If the extract can be constant-folded, this code is unsimplified. Defer
622 // to other passes to handle that.
623 Value *C = ExtElt->getIndexOperand();
624 assert(isa<ConstantInt>(C) && "Expected a constant index operand");
625 if (isa<Constant>(X))
626 return nullptr;
627
628 Value *Shuf = createShiftShuffle(X, cast<ConstantInt>(C)->getZExtValue(),
629 NewIndex, Builder);
630 return Shuf;
631}
632
633/// Try to reduce extract element costs by converting scalar compares to vector
634/// compares followed by extract.
635/// cmp (ext0 V0, ExtIndex), (ext1 V1, ExtIndex)
636Value *VectorCombine::foldExtExtCmp(Value *V0, Value *V1, Value *ExtIndex,
637 Instruction &I) {
638 assert(isa<CmpInst>(&I) && "Expected a compare");
639
640 // cmp Pred (extelt V0, ExtIndex), (extelt V1, ExtIndex)
641 // --> extelt (cmp Pred V0, V1), ExtIndex
642 ++NumVecCmp;
643 CmpInst::Predicate Pred = cast<CmpInst>(&I)->getPredicate();
644 Value *VecCmp = Builder.CreateCmp(Pred, V0, V1);
645 return Builder.CreateExtractElement(VecCmp, ExtIndex, "foldExtExtCmp");
646}
647
648/// Try to reduce extract element costs by converting scalar binops to vector
649/// binops followed by extract.
650/// bo (ext0 V0, ExtIndex), (ext1 V1, ExtIndex)
651Value *VectorCombine::foldExtExtBinop(Value *V0, Value *V1, Value *ExtIndex,
652 Instruction &I) {
653 assert(isa<BinaryOperator>(&I) && "Expected a binary operator");
654
655 // bo (extelt V0, ExtIndex), (extelt V1, ExtIndex)
656 // --> extelt (bo V0, V1), ExtIndex
657 ++NumVecBO;
658 Value *VecBO = Builder.CreateBinOp(cast<BinaryOperator>(&I)->getOpcode(), V0,
659 V1, "foldExtExtBinop");
660
661 // All IR flags are safe to back-propagate because any potential poison
662 // created in unused vector elements is discarded by the extract.
663 if (auto *VecBOInst = dyn_cast<Instruction>(VecBO))
664 VecBOInst->copyIRFlags(&I);
665
666 return Builder.CreateExtractElement(VecBO, ExtIndex, "foldExtExtBinop");
667}
668
669/// Match an instruction with extracted vector operands.
670bool VectorCombine::foldExtractExtract(Instruction &I) {
671 // It is not safe to transform things like div, urem, etc. because we may
672 // create undefined behavior when executing those on unknown vector elements.
674 return false;
675
676 Instruction *I0, *I1;
677 CmpPredicate Pred = CmpInst::BAD_ICMP_PREDICATE;
678 if (!match(&I, m_Cmp(Pred, m_Instruction(I0), m_Instruction(I1))) &&
680 return false;
681
682 Value *V0, *V1;
683 uint64_t C0, C1;
684 if (!match(I0, m_ExtractElt(m_Value(V0), m_ConstantInt(C0))) ||
686 V0->getType() != V1->getType())
687 return false;
688
689 // For fixed-width vectors, reject out-of-bounds extract indexes
690 if (auto *FixedVecTy = dyn_cast<FixedVectorType>(V0->getType())) {
691 unsigned NumElts = FixedVecTy->getNumElements();
692 if (C0 >= NumElts || C1 >= NumElts)
693 return false;
694 }
695
696 // If the scalar value 'I' is going to be re-inserted into a vector, then try
697 // to create an extract to that same element. The extract/insert can be
698 // reduced to a "select shuffle".
699 // TODO: If we add a larger pattern match that starts from an insert, this
700 // probably becomes unnecessary.
701 auto *Ext0 = cast<ExtractElementInst>(I0);
702 auto *Ext1 = cast<ExtractElementInst>(I1);
703 uint64_t InsertIndex = InvalidIndex;
704 if (I.hasOneUse())
705 match(I.user_back(),
706 m_InsertElt(m_Value(), m_Value(), m_ConstantInt(InsertIndex)));
707
708 ExtractElementInst *ExtractToChange;
709 if (isExtractExtractCheap(Ext0, Ext1, I, ExtractToChange, InsertIndex))
710 return false;
711
712 Value *ExtOp0 = Ext0->getVectorOperand();
713 Value *ExtOp1 = Ext1->getVectorOperand();
714
715 if (ExtractToChange) {
716 unsigned CheapExtractIdx = ExtractToChange == Ext0 ? C1 : C0;
717 Value *NewExtOp =
718 translateExtract(ExtractToChange, CheapExtractIdx, Builder);
719 if (!NewExtOp)
720 return false;
721 if (ExtractToChange == Ext0)
722 ExtOp0 = NewExtOp;
723 else
724 ExtOp1 = NewExtOp;
725 }
726
727 Value *ExtIndex = ExtractToChange == Ext0 ? Ext1->getIndexOperand()
728 : Ext0->getIndexOperand();
729 Value *NewExt = Pred != CmpInst::BAD_ICMP_PREDICATE
730 ? foldExtExtCmp(ExtOp0, ExtOp1, ExtIndex, I)
731 : foldExtExtBinop(ExtOp0, ExtOp1, ExtIndex, I);
732 Worklist.push(Ext0);
733 Worklist.push(Ext1);
734 replaceValue(I, *NewExt);
735 return true;
736}
737
738/// Try to replace an extract + scalar fneg + insert with a vector fneg +
739/// shuffle.
740bool VectorCombine::foldInsExtFNeg(Instruction &I) {
741 // Match an insert (op (extract)) pattern.
742 Value *DstVec;
743 uint64_t ExtIdx, InsIdx;
744 Instruction *FNeg;
745 if (!match(&I, m_InsertElt(m_Value(DstVec), m_OneUse(m_Instruction(FNeg)),
746 m_ConstantInt(InsIdx))))
747 return false;
748
749 // Note: This handles the canonical fneg instruction and "fsub -0.0, X".
750 Value *SrcVec;
751 Instruction *Extract;
752 if (!match(FNeg, m_FNeg(m_CombineAnd(
753 m_Instruction(Extract),
754 m_ExtractElt(m_Value(SrcVec), m_ConstantInt(ExtIdx))))))
755 return false;
756
757 auto *DstVecTy = cast<FixedVectorType>(DstVec->getType());
758 auto *DstVecScalarTy = DstVecTy->getScalarType();
759 auto *SrcVecTy = dyn_cast<FixedVectorType>(SrcVec->getType());
760 if (!SrcVecTy || DstVecScalarTy != SrcVecTy->getScalarType())
761 return false;
762
763 // Ignore if insert/extract index is out of bounds or destination vector has
764 // one element
765 unsigned NumDstElts = DstVecTy->getNumElements();
766 unsigned NumSrcElts = SrcVecTy->getNumElements();
767 if (ExtIdx > NumSrcElts || InsIdx >= NumDstElts || NumDstElts == 1)
768 return false;
769
770 // We are inserting the negated element into the same lane that we extracted
771 // from. This is equivalent to a select-shuffle that chooses all but the
772 // negated element from the destination vector.
773 SmallVector<int> Mask(NumDstElts);
774 std::iota(Mask.begin(), Mask.end(), 0);
775 Mask[InsIdx] = (ExtIdx % NumDstElts) + NumDstElts;
776 InstructionCost OldCost =
777 TTI.getArithmeticInstrCost(Instruction::FNeg, DstVecScalarTy, CostKind) +
778 TTI.getVectorInstrCost(I, DstVecTy, CostKind, InsIdx);
779
780 // If the extract has one use, it will be eliminated, so count it in the
781 // original cost. If it has more than one use, ignore the cost because it will
782 // be the same before/after.
783 if (Extract->hasOneUse())
784 OldCost += TTI.getVectorInstrCost(*Extract, SrcVecTy, CostKind, ExtIdx);
785
786 InstructionCost NewCost =
787 TTI.getArithmeticInstrCost(Instruction::FNeg, SrcVecTy, CostKind) +
789 DstVecTy, CostKind, Mask);
790
791 bool NeedLenChg = SrcVecTy->getNumElements() != NumDstElts;
792 // If the lengths of the two vectors are not equal,
793 // we need to add a length-change vector. Add this cost.
794 SmallVector<int> SrcMask;
795 if (NeedLenChg) {
796 SrcMask.assign(NumDstElts, PoisonMaskElem);
797 SrcMask[ExtIdx % NumDstElts] = ExtIdx;
799 DstVecTy, SrcVecTy, CostKind, SrcMask);
800 }
801
802 LLVM_DEBUG(dbgs() << "Found an insertion of (extract)fneg : " << I
803 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
804 << "\n");
805 if (NewCost > OldCost)
806 return false;
807
808 Value *NewShuf, *LenChgShuf = nullptr;
809 // insertelt DstVec, (fneg (extractelt SrcVec, Index)), Index
810 Value *VecFNeg = Builder.CreateFNegFMF(SrcVec, FNeg);
811 if (NeedLenChg) {
812 // shuffle DstVec, (shuffle (fneg SrcVec), poison, SrcMask), Mask
813 LenChgShuf = Builder.CreateShuffleVector(VecFNeg, SrcMask);
814 NewShuf = Builder.CreateShuffleVector(DstVec, LenChgShuf, Mask);
815 Worklist.pushValue(LenChgShuf);
816 } else {
817 // shuffle DstVec, (fneg SrcVec), Mask
818 NewShuf = Builder.CreateShuffleVector(DstVec, VecFNeg, Mask);
819 }
820
821 Worklist.pushValue(VecFNeg);
822 replaceValue(I, *NewShuf);
823 return true;
824}
825
826/// Try to fold insert(binop(x,y),binop(a,b),idx)
827/// --> binop(insert(x,a,idx),insert(y,b,idx))
828bool VectorCombine::foldInsExtBinop(Instruction &I) {
829 BinaryOperator *VecBinOp, *SclBinOp;
831 if (!match(&I,
832 m_InsertElt(m_OneUse(m_BinOp(VecBinOp)),
833 m_OneUse(m_BinOp(SclBinOp)), m_ConstantInt(Index))))
834 return false;
835
836 // TODO: Add support for addlike etc.
837 Instruction::BinaryOps BinOpcode = VecBinOp->getOpcode();
838 if (BinOpcode != SclBinOp->getOpcode())
839 return false;
840
841 auto *ResultTy = dyn_cast<FixedVectorType>(I.getType());
842 if (!ResultTy)
843 return false;
844
845 // TODO: Attempt to detect m_ExtractElt for scalar operands and convert to
846 // shuffle?
847
849 TTI.getInstructionCost(VecBinOp, CostKind) +
851 InstructionCost NewCost =
852 TTI.getArithmeticInstrCost(BinOpcode, ResultTy, CostKind) +
853 TTI.getVectorInstrCost(Instruction::InsertElement, ResultTy, CostKind,
854 Index, VecBinOp->getOperand(0),
855 SclBinOp->getOperand(0)) +
856 TTI.getVectorInstrCost(Instruction::InsertElement, ResultTy, CostKind,
857 Index, VecBinOp->getOperand(1),
858 SclBinOp->getOperand(1));
859
860 LLVM_DEBUG(dbgs() << "Found an insertion of two binops: " << I
861 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
862 << "\n");
863 if (NewCost > OldCost)
864 return false;
865
866 Value *NewIns0 = Builder.CreateInsertElement(VecBinOp->getOperand(0),
867 SclBinOp->getOperand(0), Index);
868 Value *NewIns1 = Builder.CreateInsertElement(VecBinOp->getOperand(1),
869 SclBinOp->getOperand(1), Index);
870 Value *NewBO = Builder.CreateBinOp(BinOpcode, NewIns0, NewIns1);
871
872 // Intersect flags from the old binops.
873 if (auto *NewInst = dyn_cast<Instruction>(NewBO)) {
874 NewInst->copyIRFlags(VecBinOp);
875 NewInst->andIRFlags(SclBinOp);
876 }
877
878 Worklist.pushValue(NewIns0);
879 Worklist.pushValue(NewIns1);
880 replaceValue(I, *NewBO);
881 return true;
882}
883
884/// Match: bitop(castop(x), castop(y)) -> castop(bitop(x, y))
885/// Supports: bitcast, trunc, sext, zext
886bool VectorCombine::foldBitOpOfCastops(Instruction &I) {
887 // Check if this is a bitwise logic operation
888 auto *BinOp = dyn_cast<BinaryOperator>(&I);
889 if (!BinOp || !BinOp->isBitwiseLogicOp())
890 return false;
891
892 // Get the cast instructions
893 auto *LHSCast = dyn_cast<CastInst>(BinOp->getOperand(0));
894 auto *RHSCast = dyn_cast<CastInst>(BinOp->getOperand(1));
895 if (!LHSCast || !RHSCast) {
896 LLVM_DEBUG(dbgs() << " One or both operands are not cast instructions\n");
897 return false;
898 }
899
900 // Both casts must be the same type
901 Instruction::CastOps CastOpcode = LHSCast->getOpcode();
902 if (CastOpcode != RHSCast->getOpcode())
903 return false;
904
905 // Only handle supported cast operations
906 switch (CastOpcode) {
907 case Instruction::BitCast:
908 case Instruction::Trunc:
909 case Instruction::SExt:
910 case Instruction::ZExt:
911 break;
912 default:
913 return false;
914 }
915
916 Value *LHSSrc = LHSCast->getOperand(0);
917 Value *RHSSrc = RHSCast->getOperand(0);
918
919 // Source types must match
920 if (LHSSrc->getType() != RHSSrc->getType())
921 return false;
922
923 auto *SrcTy = LHSSrc->getType();
924 auto *DstTy = I.getType();
925 // Bitcasts can handle scalar/vector mixes, such as i16 -> <16 x i1>.
926 // Other casts only handle vector types with integer elements.
927 if (CastOpcode != Instruction::BitCast &&
928 (!isa<FixedVectorType>(SrcTy) || !isa<FixedVectorType>(DstTy)))
929 return false;
930
931 // Only integer scalar/vector values are legal for bitwise logic operations.
932 if (!SrcTy->getScalarType()->isIntegerTy() ||
933 !DstTy->getScalarType()->isIntegerTy())
934 return false;
935
936 // Cost Check :
937 // OldCost = bitlogic + 2*casts
938 // NewCost = bitlogic + cast
939
940 // Calculate specific costs for each cast with instruction context
942 CastOpcode, DstTy, SrcTy, TTI::CastContextHint::None, CostKind, LHSCast);
944 CastOpcode, DstTy, SrcTy, TTI::CastContextHint::None, CostKind, RHSCast);
945
946 InstructionCost OldCost =
947 TTI.getArithmeticInstrCost(BinOp->getOpcode(), DstTy, CostKind) +
948 LHSCastCost + RHSCastCost;
949
950 // For new cost, we can't provide an instruction (it doesn't exist yet)
951 InstructionCost GenericCastCost = TTI.getCastInstrCost(
952 CastOpcode, DstTy, SrcTy, TTI::CastContextHint::None, CostKind);
953
954 InstructionCost NewCost =
955 TTI.getArithmeticInstrCost(BinOp->getOpcode(), SrcTy, CostKind) +
956 GenericCastCost;
957
958 // Account for multi-use casts using specific costs
959 if (!LHSCast->hasOneUse())
960 NewCost += LHSCastCost;
961 if (!RHSCast->hasOneUse())
962 NewCost += RHSCastCost;
963
964 LLVM_DEBUG(dbgs() << "foldBitOpOfCastops: OldCost=" << OldCost
965 << " NewCost=" << NewCost << "\n");
966
967 if (NewCost > OldCost)
968 return false;
969
970 // Create the operation on the source type
971 Value *NewOp = Builder.CreateBinOp(BinOp->getOpcode(), LHSSrc, RHSSrc,
972 BinOp->getName() + ".inner");
973 if (auto *NewBinOp = dyn_cast<BinaryOperator>(NewOp))
974 NewBinOp->copyIRFlags(BinOp);
975
976 Worklist.pushValue(NewOp);
977
978 // Create the cast operation directly to ensure we get a new instruction
979 Instruction *NewCast = CastInst::Create(CastOpcode, NewOp, I.getType());
980
981 // Preserve cast instruction flags
982 NewCast->copyIRFlags(LHSCast);
983 NewCast->andIRFlags(RHSCast);
984
985 // Insert the new instruction
986 Value *Result = Builder.Insert(NewCast);
987
988 replaceValue(I, *Result);
989 return true;
990}
991
992/// Match:
993// bitop(castop(x), C) ->
994// bitop(castop(x), castop(InvC)) ->
995// castop(bitop(x, InvC))
996// Supports: bitcast
997bool VectorCombine::foldBitOpOfCastConstant(Instruction &I) {
999 Constant *C;
1000
1001 // Check if this is a bitwise logic operation
1003 return false;
1004
1005 // Get the cast instructions
1006 auto *LHSCast = dyn_cast<CastInst>(LHS);
1007 if (!LHSCast)
1008 return false;
1009
1010 Instruction::CastOps CastOpcode = LHSCast->getOpcode();
1011
1012 // Only handle supported cast operations
1013 switch (CastOpcode) {
1014 case Instruction::BitCast:
1015 case Instruction::ZExt:
1016 case Instruction::SExt:
1017 case Instruction::Trunc:
1018 break;
1019 default:
1020 return false;
1021 }
1022
1023 Value *LHSSrc = LHSCast->getOperand(0);
1024
1025 auto *SrcTy = LHSSrc->getType();
1026 auto *DstTy = I.getType();
1027 // Bitcasts can handle scalar/vector mixes, such as i16 -> <16 x i1>.
1028 // Other casts only handle vector types with integer elements.
1029 if (CastOpcode != Instruction::BitCast &&
1030 (!isa<FixedVectorType>(SrcTy) || !isa<FixedVectorType>(DstTy)))
1031 return false;
1032
1033 // Only integer scalar/vector values are legal for bitwise logic operations.
1034 if (!SrcTy->getScalarType()->isIntegerTy() ||
1035 !DstTy->getScalarType()->isIntegerTy())
1036 return false;
1037
1038 // Find the constant InvC, such that castop(InvC) equals to C.
1039 PreservedCastFlags RHSFlags;
1040 Constant *InvC = getLosslessInvCast(C, SrcTy, CastOpcode, *DL, &RHSFlags);
1041 if (!InvC)
1042 return false;
1043
1044 // Cost Check :
1045 // OldCost = bitlogic + cast
1046 // NewCost = bitlogic + cast
1047
1048 // Calculate specific costs for each cast with instruction context
1049 InstructionCost LHSCastCost = TTI.getCastInstrCost(
1050 CastOpcode, DstTy, SrcTy, TTI::CastContextHint::None, CostKind, LHSCast);
1051
1052 InstructionCost OldCost =
1053 TTI.getArithmeticInstrCost(I.getOpcode(), DstTy, CostKind) + LHSCastCost;
1054
1055 // For new cost, we can't provide an instruction (it doesn't exist yet)
1056 InstructionCost GenericCastCost = TTI.getCastInstrCost(
1057 CastOpcode, DstTy, SrcTy, TTI::CastContextHint::None, CostKind);
1058
1059 InstructionCost NewCost =
1060 TTI.getArithmeticInstrCost(I.getOpcode(), SrcTy, CostKind) +
1061 GenericCastCost;
1062
1063 // Account for multi-use casts using specific costs
1064 if (!LHSCast->hasOneUse())
1065 NewCost += LHSCastCost;
1066
1067 LLVM_DEBUG(dbgs() << "foldBitOpOfCastConstant: OldCost=" << OldCost
1068 << " NewCost=" << NewCost << "\n");
1069
1070 if (NewCost > OldCost)
1071 return false;
1072
1073 // Create the operation on the source type
1074 Value *NewOp = Builder.CreateBinOp((Instruction::BinaryOps)I.getOpcode(),
1075 LHSSrc, InvC, I.getName() + ".inner");
1076 if (auto *NewBinOp = dyn_cast<BinaryOperator>(NewOp))
1077 NewBinOp->copyIRFlags(&I);
1078
1079 Worklist.pushValue(NewOp);
1080
1081 // Create the cast operation directly to ensure we get a new instruction
1082 Instruction *NewCast = CastInst::Create(CastOpcode, NewOp, I.getType());
1083
1084 // Preserve cast instruction flags
1085 if (RHSFlags.NNeg)
1086 NewCast->setNonNeg();
1087 if (RHSFlags.NUW)
1088 NewCast->setHasNoUnsignedWrap();
1089 if (RHSFlags.NSW)
1090 NewCast->setHasNoSignedWrap();
1091
1092 NewCast->andIRFlags(LHSCast);
1093
1094 // Insert the new instruction
1095 Value *Result = Builder.Insert(NewCast);
1096
1097 replaceValue(I, *Result);
1098 return true;
1099}
1100
1101/// If this is a bitcast of a shuffle, try to bitcast the source vector to the
1102/// destination type followed by shuffle. This can enable further transforms by
1103/// moving bitcasts or shuffles together.
1104bool VectorCombine::foldBitcastShuffle(Instruction &I) {
1105 Value *V0, *V1;
1106 ArrayRef<int> Mask;
1107 if (!match(&I, m_BitCast(m_OneUse(
1108 m_Shuffle(m_Value(V0), m_Value(V1), m_Mask(Mask))))))
1109 return false;
1110
1111 // 1) Do not fold bitcast shuffle for scalable type. First, shuffle cost for
1112 // scalable type is unknown; Second, we cannot reason if the narrowed shuffle
1113 // mask for scalable type is a splat or not.
1114 // 2) Disallow non-vector casts.
1115 // TODO: We could allow any shuffle.
1116 auto *DestTy = dyn_cast<FixedVectorType>(I.getType());
1117 auto *SrcTy = dyn_cast<FixedVectorType>(V0->getType());
1118 if (!DestTy || !SrcTy)
1119 return false;
1120
1121 unsigned DestEltSize = DestTy->getScalarSizeInBits();
1122 unsigned SrcEltSize = SrcTy->getScalarSizeInBits();
1123 if (SrcTy->getPrimitiveSizeInBits() % DestEltSize != 0)
1124 return false;
1125
1126 bool IsUnary = isa<UndefValue>(V1);
1127
1128 // For binary shuffles, only fold bitcast(shuffle(X,Y))
1129 // if it won't increase the number of bitcasts.
1130 if (!IsUnary) {
1133 if (!(BCTy0 && BCTy0->getElementType() == DestTy->getElementType()) &&
1134 !(BCTy1 && BCTy1->getElementType() == DestTy->getElementType()))
1135 return false;
1136 }
1137
1138 SmallVector<int, 16> NewMask;
1139 if (DestEltSize <= SrcEltSize) {
1140 // The bitcast is from wide to narrow/equal elements. The shuffle mask can
1141 // always be expanded to the equivalent form choosing narrower elements.
1142 if (SrcEltSize % DestEltSize != 0)
1143 return false;
1144 unsigned ScaleFactor = SrcEltSize / DestEltSize;
1145 narrowShuffleMaskElts(ScaleFactor, Mask, NewMask);
1146 } else {
1147 // The bitcast is from narrow elements to wide elements. The shuffle mask
1148 // must choose consecutive elements to allow casting first.
1149 if (DestEltSize % SrcEltSize != 0)
1150 return false;
1151 unsigned ScaleFactor = DestEltSize / SrcEltSize;
1152 if (!widenShuffleMaskElts(ScaleFactor, Mask, NewMask))
1153 return false;
1154 }
1155
1156 // Bitcast the shuffle src - keep its original width but using the destination
1157 // scalar type.
1158 unsigned NumSrcElts = SrcTy->getPrimitiveSizeInBits() / DestEltSize;
1159 auto *NewShuffleTy =
1160 FixedVectorType::get(DestTy->getScalarType(), NumSrcElts);
1161 auto *OldShuffleTy =
1162 FixedVectorType::get(SrcTy->getScalarType(), Mask.size());
1163 unsigned NumOps = IsUnary ? 1 : 2;
1164
1165 // The new shuffle must not cost more than the old shuffle.
1169
1170 InstructionCost NewCost =
1171 TTI.getShuffleCost(SK, DestTy, NewShuffleTy, CostKind, NewMask) +
1172 (NumOps * TTI.getCastInstrCost(Instruction::BitCast, NewShuffleTy, SrcTy,
1173 TargetTransformInfo::CastContextHint::None,
1174 CostKind));
1175 InstructionCost OldCost =
1176 TTI.getShuffleCost(SK, OldShuffleTy, SrcTy, CostKind, Mask) +
1177 TTI.getCastInstrCost(Instruction::BitCast, DestTy, OldShuffleTy,
1178 TargetTransformInfo::CastContextHint::None,
1179 CostKind);
1180
1181 LLVM_DEBUG(dbgs() << "Found a bitcasted shuffle: " << I << "\n OldCost: "
1182 << OldCost << " vs NewCost: " << NewCost << "\n");
1183
1184 if (NewCost > OldCost || !NewCost.isValid())
1185 return false;
1186
1187 // bitcast (shuf V0, V1, MaskC) --> shuf (bitcast V0), (bitcast V1), MaskC'
1188 ++NumShufOfBitcast;
1189 Value *CastV0 = Builder.CreateBitCast(peekThroughBitcasts(V0), NewShuffleTy);
1190 Value *CastV1 = Builder.CreateBitCast(peekThroughBitcasts(V1), NewShuffleTy);
1191 Value *Shuf = Builder.CreateShuffleVector(CastV0, CastV1, NewMask);
1192 replaceValue(I, *Shuf);
1193 return true;
1194}
1195
1196/// Match a vector op/compare/intrinsic with at least one
1197/// inserted scalar operand and convert to scalar op/cmp/intrinsic followed
1198/// by insertelement.
1199bool VectorCombine::scalarizeOpOrCmp(Instruction &I) {
1200 auto *UO = dyn_cast<UnaryOperator>(&I);
1201 auto *BO = dyn_cast<BinaryOperator>(&I);
1202 auto *CI = dyn_cast<CmpInst>(&I);
1203 auto *II = dyn_cast<IntrinsicInst>(&I);
1204 if (!UO && !BO && !CI && !II)
1205 return false;
1206
1207 // TODO: Allow intrinsics with different argument types
1208 if (II) {
1209 if (!isTriviallyVectorizable(II->getIntrinsicID()))
1210 return false;
1211 for (auto [Idx, Arg] : enumerate(II->args()))
1212 if (Arg->getType() != II->getType() &&
1213 !isVectorIntrinsicWithScalarOpAtArg(II->getIntrinsicID(), Idx, &TTI))
1214 return false;
1215 }
1216
1217 // Do not convert the vector condition of a vector select into a scalar
1218 // condition. That may cause problems for codegen because of differences in
1219 // boolean formats and register-file transfers.
1220 // TODO: Can we account for that in the cost model?
1221 if (CI)
1222 for (User *U : I.users())
1223 if (match(U, m_Select(m_Specific(&I), m_Value(), m_Value())))
1224 return false;
1225
1226 // Match constant vectors or scalars being inserted into constant vectors:
1227 // vec_op [VecC0 | (inselt VecC0, V0, Index)], ...
1228 SmallVector<Value *> VecCs, ScalarOps;
1229 std::optional<uint64_t> Index;
1230
1231 auto Ops = II ? II->args() : I.operands();
1232 for (auto [OpNum, Op] : enumerate(Ops)) {
1233 Constant *VecC;
1234 Value *V;
1235 uint64_t InsIdx = 0;
1236 if (match(Op.get(), m_InsertElt(m_Constant(VecC), m_Value(V),
1237 m_ConstantInt(InsIdx)))) {
1238 // Bail if any inserts are out of bounds.
1239 VectorType *OpTy = cast<VectorType>(Op->getType());
1240 if (OpTy->getElementCount().getKnownMinValue() <= InsIdx)
1241 return false;
1242 // All inserts must have the same index.
1243 // TODO: Deal with mismatched index constants and variable indexes?
1244 if (!Index)
1245 Index = InsIdx;
1246 else if (InsIdx != *Index)
1247 return false;
1248 VecCs.push_back(VecC);
1249 ScalarOps.push_back(V);
1250 } else if (II && isVectorIntrinsicWithScalarOpAtArg(II->getIntrinsicID(),
1251 OpNum, &TTI)) {
1252 VecCs.push_back(Op.get());
1253 ScalarOps.push_back(Op.get());
1254 } else if (match(Op.get(), m_Constant(VecC))) {
1255 VecCs.push_back(VecC);
1256 ScalarOps.push_back(nullptr);
1257 } else {
1258 return false;
1259 }
1260 }
1261
1262 // Bail if all operands are constant.
1263 if (!Index.has_value())
1264 return false;
1265
1266 VectorType *VecTy = cast<VectorType>(I.getType());
1267 Type *ScalarTy = VecTy->getScalarType();
1268 assert(VecTy->isVectorTy() &&
1269 (ScalarTy->isIntegerTy() || ScalarTy->isFloatingPointTy() ||
1270 ScalarTy->isPointerTy()) &&
1271 "Unexpected types for insert element into binop or cmp");
1272
1273 unsigned Opcode = I.getOpcode();
1274 InstructionCost ScalarOpCost, VectorOpCost;
1275 if (CI) {
1276 CmpInst::Predicate Pred = CI->getPredicate();
1277 ScalarOpCost = TTI.getCmpSelInstrCost(
1278 Opcode, ScalarTy, CmpInst::makeCmpResultType(ScalarTy), Pred, CostKind);
1279 VectorOpCost = TTI.getCmpSelInstrCost(
1280 Opcode, VecTy, CmpInst::makeCmpResultType(VecTy), Pred, CostKind);
1281 } else if (UO || BO) {
1282 ScalarOpCost = TTI.getArithmeticInstrCost(Opcode, ScalarTy, CostKind);
1283 VectorOpCost = TTI.getArithmeticInstrCost(Opcode, VecTy, CostKind);
1284 } else {
1285 IntrinsicCostAttributes ScalarICA(
1286 II->getIntrinsicID(), ScalarTy,
1287 SmallVector<Type *>(II->arg_size(), ScalarTy));
1288 ScalarOpCost = TTI.getIntrinsicInstrCost(ScalarICA, CostKind);
1289 IntrinsicCostAttributes VectorICA(
1290 II->getIntrinsicID(), VecTy,
1291 SmallVector<Type *>(II->arg_size(), VecTy));
1292 VectorOpCost = TTI.getIntrinsicInstrCost(VectorICA, CostKind);
1293 }
1294
1295 // Fold the vector constants in the original vectors into a new base vector to
1296 // get more accurate cost modelling.
1297 Value *NewVecC = nullptr;
1298 if (CI)
1299 NewVecC = simplifyCmpInst(CI->getPredicate(), VecCs[0], VecCs[1], SQ);
1300 else if (UO)
1301 NewVecC =
1302 simplifyUnOp(UO->getOpcode(), VecCs[0], UO->getFastMathFlags(), SQ);
1303 else if (BO)
1304 NewVecC = simplifyBinOp(BO->getOpcode(), VecCs[0], VecCs[1], SQ);
1305 else if (II)
1306 NewVecC = simplifyCall(II, II->getCalledOperand(), VecCs, SQ);
1307
1308 if (!NewVecC)
1309 return false;
1310
1311 // Get cost estimate for the insert element. This cost will factor into
1312 // both sequences.
1313 InstructionCost OldCost = VectorOpCost;
1314 InstructionCost NewCost =
1315 ScalarOpCost + TTI.getVectorInstrCost(Instruction::InsertElement, VecTy,
1316 CostKind, *Index, NewVecC);
1317
1318 for (auto [Idx, Op, VecC, Scalar] : enumerate(Ops, VecCs, ScalarOps)) {
1319 if (!Scalar || (II && isVectorIntrinsicWithScalarOpAtArg(
1320 II->getIntrinsicID(), Idx, &TTI)))
1321 continue;
1323 Instruction::InsertElement, VecTy, CostKind, *Index, VecC, Scalar);
1324 OldCost += InsertCost;
1325 NewCost += !Op->hasOneUse() * InsertCost;
1326 }
1327
1328 // We want to scalarize unless the vector variant actually has lower cost.
1329 if (OldCost < NewCost || !NewCost.isValid())
1330 return false;
1331
1332 // vec_op (inselt VecC0, V0, Index), (inselt VecC1, V1, Index) -->
1333 // inselt NewVecC, (scalar_op V0, V1), Index
1334 if (CI)
1335 ++NumScalarCmp;
1336 else if (UO || BO)
1337 ++NumScalarOps;
1338 else
1339 ++NumScalarIntrinsic;
1340
1341 // For constant cases, extract the scalar element, this should constant fold.
1342 for (auto [OpIdx, Scalar, VecC] : enumerate(ScalarOps, VecCs))
1343 if (!Scalar)
1344 ScalarOps[OpIdx] = ConstantExpr::getExtractElement(
1345 cast<Constant>(VecC), Builder.getInt64(*Index));
1346
1347 Value *Scalar;
1348 // We need to pass the flags during the creation of instrucitons. Constant
1349 // folding might remove the instructions, so post setting the flags might
1350 // pollute the later instructions.
1351 if (CI) {
1352 if (FPMathOperator *FPMO = dyn_cast<FPMathOperator>(&I)) {
1353 Scalar = Builder.CreateFCmpFMF(CI->getPredicate(), ScalarOps[0],
1354 ScalarOps[1], FPMO->getFastMathFlags(),
1355 CI->getName() + ".scalar");
1356 } else {
1357 Scalar = Builder.CreateICmp(CI->getPredicate(), ScalarOps[0],
1358 ScalarOps[1], CI->getName() + ".scalar");
1359 }
1360 } else if (UO) {
1361 Scalar = Builder.CreateUnOpFMF(UO->getOpcode(), ScalarOps[0], UO,
1362 UO->getName() + ".scalar");
1363 } else if (BO) {
1364 if (OverflowingBinaryOperator *OBO =
1366 Scalar = Builder.CreateNoWrapBinOp(
1367 BO->getOpcode(), ScalarOps[0], ScalarOps[1], OBO->hasNoUnsignedWrap(),
1368 OBO->hasNoSignedWrap(), BO->getName() + ".scalar");
1369 } else if (PossiblyDisjointInst *PDI = dyn_cast<PossiblyDisjointInst>(&I)) {
1370 Scalar = Builder.CreateOr(ScalarOps[0], ScalarOps[1],
1371 BO->getName() + ".scalar", PDI->isDisjoint());
1372 } else if (PossiblyExactOperator *PEO =
1374 Scalar =
1375 Builder.CreateExactBinOp(BO->getOpcode(), ScalarOps[0], ScalarOps[1],
1376 PEO->isExact(), BO->getName() + ".scalar");
1377 } else if (FPMathOperator *FPMO = dyn_cast<FPMathOperator>(&I)) {
1378 Scalar = Builder.CreateBinOpFMF(BO->getOpcode(), ScalarOps[0],
1379 ScalarOps[1], FPMO->getFastMathFlags(),
1380 BO->getName() + ".scalar");
1381 } else {
1382 Scalar = Builder.CreateBinOp(BO->getOpcode(), ScalarOps[0], ScalarOps[1],
1383 BO->getName() + ".scalar");
1384 }
1385 } else {
1386 FastMathFlags FMF;
1387 if (auto *FPMO = dyn_cast<FPMathOperator>(&I))
1388 FMF = FPMO->getFastMathFlags();
1389 Scalar = Builder.CreateIntrinsic(ScalarTy, II->getIntrinsicID(), ScalarOps,
1390 FMF, II->getName() + ".scalar");
1391 }
1392
1393 Value *Insert = Builder.CreateInsertElement(NewVecC, Scalar, *Index);
1394 replaceValue(I, *Insert);
1395 return true;
1396}
1397
1398/// Try to combine a scalar binop + 2 scalar compares of extracted elements of
1399/// a vector into vector operations followed by extract. Note: The SLP pass
1400/// may miss this pattern because of implementation problems.
1401bool VectorCombine::foldExtractedCmps(Instruction &I) {
1402 auto *BI = dyn_cast<BinaryOperator>(&I);
1403
1404 // We are looking for a scalar binop of booleans.
1405 // binop i1 (cmp Pred I0, C0), (cmp Pred I1, C1)
1406 if (!BI || !I.getType()->isIntegerTy(1))
1407 return false;
1408
1409 // The compare predicates should match, and each compare should have a
1410 // constant operand.
1411 Value *B0 = I.getOperand(0), *B1 = I.getOperand(1);
1412 Instruction *I0, *I1;
1413 Constant *C0, *C1;
1414 CmpPredicate P0, P1;
1415 if (!match(B0, m_Cmp(P0, m_Instruction(I0), m_Constant(C0))) ||
1416 !match(B1, m_Cmp(P1, m_Instruction(I1), m_Constant(C1))))
1417 return false;
1418
1419 auto MatchingPred = CmpPredicate::getMatching(P0, P1);
1420 if (!MatchingPred)
1421 return false;
1422
1423 // The compare operands must be extracts of the same vector with constant
1424 // extract indexes.
1425 Value *X;
1426 uint64_t Index0, Index1;
1427 if (!match(I0, m_ExtractElt(m_Value(X), m_ConstantInt(Index0))) ||
1428 !match(I1, m_ExtractElt(m_Specific(X), m_ConstantInt(Index1))))
1429 return false;
1430
1431 auto *Ext0 = cast<ExtractElementInst>(I0);
1432 auto *Ext1 = cast<ExtractElementInst>(I1);
1433 ExtractElementInst *ConvertToShuf = getShuffleExtract(Ext0, Ext1, CostKind);
1434 if (!ConvertToShuf)
1435 return false;
1436 assert((ConvertToShuf == Ext0 || ConvertToShuf == Ext1) &&
1437 "Unknown ExtractElementInst");
1438
1439 // The original scalar pattern is:
1440 // binop i1 (cmp Pred (ext X, Index0), C0), (cmp Pred (ext X, Index1), C1)
1441 CmpInst::Predicate Pred = *MatchingPred;
1442 unsigned CmpOpcode =
1443 CmpInst::isFPPredicate(Pred) ? Instruction::FCmp : Instruction::ICmp;
1444 auto *VecTy = dyn_cast<FixedVectorType>(X->getType());
1445 if (!VecTy)
1446 return false;
1447
1448 if (Index0 >= VecTy->getNumElements() || Index1 >= VecTy->getNumElements())
1449 return false;
1450
1451 InstructionCost Ext0Cost =
1452 TTI.getVectorInstrCost(*Ext0, VecTy, CostKind, Index0);
1453 InstructionCost Ext1Cost =
1454 TTI.getVectorInstrCost(*Ext1, VecTy, CostKind, Index1);
1456 CmpOpcode, I0->getType(), CmpInst::makeCmpResultType(I0->getType()), Pred,
1457 CostKind);
1458
1459 InstructionCost OldCost =
1460 Ext0Cost + Ext1Cost + CmpCost * 2 +
1461 TTI.getArithmeticInstrCost(I.getOpcode(), I.getType(), CostKind);
1462
1463 // The proposed vector pattern is:
1464 // vcmp = cmp Pred X, VecC
1465 // ext (binop vNi1 vcmp, (shuffle vcmp, Index1)), Index0
1466 int CheapIndex = ConvertToShuf == Ext0 ? Index1 : Index0;
1467 int ExpensiveIndex = ConvertToShuf == Ext0 ? Index0 : Index1;
1470 CmpOpcode, VecTy, CmpInst::makeCmpResultType(VecTy), Pred, CostKind);
1471 SmallVector<int, 32> ShufMask(VecTy->getNumElements(), PoisonMaskElem);
1472 ShufMask[CheapIndex] = ExpensiveIndex;
1474 CmpTy, CostKind, ShufMask);
1475 NewCost += TTI.getArithmeticInstrCost(I.getOpcode(), CmpTy, CostKind);
1476 NewCost += TTI.getVectorInstrCost(*Ext0, CmpTy, CostKind, CheapIndex);
1477 NewCost += Ext0->hasOneUse() ? 0 : Ext0Cost;
1478 NewCost += Ext1->hasOneUse() ? 0 : Ext1Cost;
1479
1480 // Aggressively form vector ops if the cost is equal because the transform
1481 // may enable further optimization.
1482 // Codegen can reverse this transform (scalarize) if it was not profitable.
1483 if (OldCost < NewCost || !NewCost.isValid())
1484 return false;
1485
1486 // Create a vector constant from the 2 scalar constants.
1487 SmallVector<Constant *, 32> CmpC(VecTy->getNumElements(),
1488 PoisonValue::get(VecTy->getElementType()));
1489 CmpC[Index0] = C0;
1490 CmpC[Index1] = C1;
1491 Value *VCmp = Builder.CreateCmp(Pred, X, ConstantVector::get(CmpC));
1492 Value *Shuf = createShiftShuffle(VCmp, ExpensiveIndex, CheapIndex, Builder);
1493 Value *LHS = ConvertToShuf == Ext0 ? Shuf : VCmp;
1494 Value *RHS = ConvertToShuf == Ext0 ? VCmp : Shuf;
1495 Value *VecLogic = Builder.CreateBinOp(BI->getOpcode(), LHS, RHS);
1496 Value *NewExt = Builder.CreateExtractElement(VecLogic, CheapIndex);
1497 replaceValue(I, *NewExt);
1498 ++NumVecCmpBO;
1499 return true;
1500}
1501
1502/// Try to fold scalar selects that select between extracted elements and zero
1503/// into extracting from a vector select. This is rooted at the bitcast.
1504///
1505/// This pattern arises when a vector is bitcast to a smaller element type,
1506/// elements are extracted, and then conditionally selected with zero:
1507///
1508/// %bc = bitcast <4 x i32> %src to <16 x i8>
1509/// %e0 = extractelement <16 x i8> %bc, i32 0
1510/// %s0 = select i1 %cond, i8 %e0, i8 0
1511/// %e1 = extractelement <16 x i8> %bc, i32 1
1512/// %s1 = select i1 %cond, i8 %e1, i8 0
1513/// ...
1514///
1515/// Transforms to:
1516/// %sel = select i1 %cond, <4 x i32> %src, <4 x i32> zeroinitializer
1517/// %bc = bitcast <4 x i32> %sel to <16 x i8>
1518/// %e0 = extractelement <16 x i8> %bc, i32 0
1519/// %e1 = extractelement <16 x i8> %bc, i32 1
1520/// ...
1521///
1522/// This is profitable because vector select on wider types produces fewer
1523/// select/cndmask instructions than scalar selects on each element.
1524bool VectorCombine::foldSelectsFromBitcast(Instruction &I) {
1525 auto *BC = dyn_cast<BitCastInst>(&I);
1526 if (!BC)
1527 return false;
1528
1529 FixedVectorType *SrcVecTy = dyn_cast<FixedVectorType>(BC->getSrcTy());
1530 FixedVectorType *DstVecTy = dyn_cast<FixedVectorType>(BC->getDestTy());
1531 if (!SrcVecTy || !DstVecTy)
1532 return false;
1533
1534 // Source must be 32-bit or 64-bit elements, destination must be smaller
1535 // integer elements. Zero in all these types is all-bits-zero.
1536 Type *SrcEltTy = SrcVecTy->getElementType();
1537 Type *DstEltTy = DstVecTy->getElementType();
1538 unsigned SrcEltBits = SrcEltTy->getPrimitiveSizeInBits();
1539 unsigned DstEltBits = DstEltTy->getPrimitiveSizeInBits();
1540
1541 if (SrcEltBits != 32 && SrcEltBits != 64)
1542 return false;
1543
1544 if (!DstEltTy->isIntegerTy() || DstEltBits >= SrcEltBits)
1545 return false;
1546
1547 // Check profitability using TTI before collecting users.
1548 Type *CondTy = CmpInst::makeCmpResultType(DstEltTy);
1549 Type *VecCondTy = CmpInst::makeCmpResultType(SrcVecTy);
1550
1551 InstructionCost ScalarSelCost =
1552 TTI.getCmpSelInstrCost(Instruction::Select, DstEltTy, CondTy,
1554 InstructionCost VecSelCost =
1555 TTI.getCmpSelInstrCost(Instruction::Select, SrcVecTy, VecCondTy,
1557
1558 // We need at least this many selects for vectorization to be profitable.
1559 // VecSelCost < ScalarSelCost * NumSelects => NumSelects > VecSelCost /
1560 // ScalarSelCost
1561 if (!ScalarSelCost.isValid() || ScalarSelCost == 0)
1562 return false;
1563
1564 unsigned MinSelects = (VecSelCost.getValue() / ScalarSelCost.getValue()) + 1;
1565
1566 // Quick check: if bitcast doesn't have enough users, bail early.
1567 if (!BC->hasNUsesOrMore(MinSelects))
1568 return false;
1569
1570 // Collect all select users that match the pattern, grouped by condition.
1571 // Pattern: select i1 %cond, (extractelement %bc, idx), 0
1572 DenseMap<Value *, SmallVector<SelectInst *, 8>> CondToSelects;
1573
1574 for (User *U : BC->users()) {
1575 auto *Ext = dyn_cast<ExtractElementInst>(U);
1576 if (!Ext)
1577 continue;
1578
1579 for (User *ExtUser : Ext->users()) {
1580 Value *Cond;
1581 // Match: select i1 %cond, %ext, 0
1582 if (match(ExtUser, m_Select(m_Value(Cond), m_Specific(Ext), m_Zero())) &&
1583 Cond->getType()->isIntegerTy(1))
1584 CondToSelects[Cond].push_back(cast<SelectInst>(ExtUser));
1585 }
1586 }
1587
1588 if (CondToSelects.empty())
1589 return false;
1590
1591 bool MadeChange = false;
1592 Value *SrcVec = BC->getOperand(0);
1593
1594 // Process each group of selects with the same condition.
1595 for (auto [Cond, Selects] : CondToSelects) {
1596 // Only profitable if vector select cost < total scalar select cost.
1597 if (Selects.size() < MinSelects) {
1598 LLVM_DEBUG(dbgs() << "VectorCombine: foldSelectsFromBitcast not "
1599 << "profitable (VecCost=" << VecSelCost
1600 << ", ScalarCost=" << ScalarSelCost
1601 << ", NumSelects=" << Selects.size() << ")\n");
1602 continue;
1603 }
1604
1605 // Create the vector select and bitcast once for this condition.
1606 auto InsertPt = std::next(BC->getIterator());
1607
1608 if (auto *CondInst = dyn_cast<Instruction>(Cond))
1609 if (DT.dominates(BC, CondInst))
1610 InsertPt = std::next(CondInst->getIterator());
1611
1612 Builder.SetInsertPoint(InsertPt);
1613 Value *VecSel =
1614 Builder.CreateSelect(Cond, SrcVec, Constant::getNullValue(SrcVecTy));
1615 Value *NewBC = Builder.CreateBitCast(VecSel, DstVecTy);
1616
1617 // Replace each scalar select with an extract from the new bitcast.
1618 for (SelectInst *Sel : Selects) {
1619 auto *Ext = cast<ExtractElementInst>(Sel->getTrueValue());
1620 Value *Idx = Ext->getIndexOperand();
1621
1622 Builder.SetInsertPoint(Sel);
1623 Value *NewExt = Builder.CreateExtractElement(NewBC, Idx);
1624 replaceValue(*Sel, *NewExt);
1625 MadeChange = true;
1626 }
1627
1628 LLVM_DEBUG(dbgs() << "VectorCombine: folded " << Selects.size()
1629 << " selects into vector select\n");
1630 }
1631
1632 return MadeChange;
1633}
1634
1637 const TargetTransformInfo &TTI,
1638 InstructionCost &CostBeforeReduction,
1639 InstructionCost &CostAfterReduction) {
1640 Instruction *Op0, *Op1;
1641 auto *RedOp = dyn_cast<Instruction>(II.getOperand(0));
1642 auto *VecRedTy = cast<VectorType>(II.getOperand(0)->getType());
1643 unsigned ReductionOpc =
1644 getArithmeticReductionInstruction(II.getIntrinsicID());
1645 if (RedOp && match(RedOp, m_ZExtOrSExt(m_Value()))) {
1646 bool IsUnsigned = isa<ZExtInst>(RedOp);
1647 auto *ExtType = cast<VectorType>(RedOp->getOperand(0)->getType());
1648
1649 CostBeforeReduction =
1650 TTI.getCastInstrCost(RedOp->getOpcode(), VecRedTy, ExtType,
1652 CostAfterReduction =
1653 TTI.getExtendedReductionCost(ReductionOpc, IsUnsigned, II.getType(),
1654 ExtType, FastMathFlags(), CostKind);
1655 return;
1656 }
1657 if (RedOp && II.getIntrinsicID() == Intrinsic::vector_reduce_add &&
1658 match(RedOp,
1660 match(Op0, m_ZExtOrSExt(m_Value())) &&
1661 Op0->getOpcode() == Op1->getOpcode() &&
1662 Op0->getOperand(0)->getType() == Op1->getOperand(0)->getType() &&
1663 (Op0->getOpcode() == RedOp->getOpcode() || Op0 == Op1)) {
1664 // Matched reduce.add(ext(mul(ext(A), ext(B)))
1665 bool IsUnsigned = isa<ZExtInst>(Op0);
1666 auto *ExtType = cast<VectorType>(Op0->getOperand(0)->getType());
1667 VectorType *MulType = VectorType::get(Op0->getType(), VecRedTy);
1668
1669 InstructionCost ExtCost =
1670 TTI.getCastInstrCost(Op0->getOpcode(), MulType, ExtType,
1672 InstructionCost MulCost =
1673 TTI.getArithmeticInstrCost(Instruction::Mul, MulType, CostKind);
1674 InstructionCost Ext2Cost =
1675 TTI.getCastInstrCost(RedOp->getOpcode(), VecRedTy, MulType,
1677
1678 CostBeforeReduction = ExtCost * 2 + MulCost + Ext2Cost;
1679 CostAfterReduction = TTI.getMulAccReductionCost(
1680 IsUnsigned, ReductionOpc, II.getType(), ExtType, CostKind);
1681 return;
1682 }
1683 CostAfterReduction = TTI.getArithmeticReductionCost(ReductionOpc, VecRedTy,
1684 std::nullopt, CostKind);
1685}
1686
1687bool VectorCombine::foldBinopOfReductions(Instruction &I) {
1688 Instruction::BinaryOps BinOpOpc = cast<BinaryOperator>(&I)->getOpcode();
1689 Intrinsic::ID ReductionIID = getReductionForBinop(BinOpOpc);
1690 if (BinOpOpc == Instruction::Sub)
1691 ReductionIID = Intrinsic::vector_reduce_add;
1692 if (ReductionIID == Intrinsic::not_intrinsic)
1693 return false;
1694 // FP reductions have a start-value operand that this fold doesn't handle.
1695 if (ReductionIID == Intrinsic::vector_reduce_fadd ||
1696 ReductionIID == Intrinsic::vector_reduce_fmul)
1697 return false;
1698
1699 auto checkIntrinsicAndGetItsArgument = [](Value *V,
1700 Intrinsic::ID IID) -> Value * {
1701 auto *II = dyn_cast<IntrinsicInst>(V);
1702 if (!II)
1703 return nullptr;
1704 if (II->getIntrinsicID() == IID && II->hasOneUse())
1705 return II->getArgOperand(0);
1706 return nullptr;
1707 };
1708
1709 Value *V0 = checkIntrinsicAndGetItsArgument(I.getOperand(0), ReductionIID);
1710 if (!V0)
1711 return false;
1712 Value *V1 = checkIntrinsicAndGetItsArgument(I.getOperand(1), ReductionIID);
1713 if (!V1)
1714 return false;
1715
1716 auto *VTy = cast<VectorType>(V0->getType());
1717 if (V1->getType() != VTy)
1718 return false;
1719 const auto &II0 = *cast<IntrinsicInst>(I.getOperand(0));
1720 const auto &II1 = *cast<IntrinsicInst>(I.getOperand(1));
1721 unsigned ReductionOpc =
1722 getArithmeticReductionInstruction(II0.getIntrinsicID());
1723
1724 InstructionCost OldCost = 0;
1725 InstructionCost NewCost = 0;
1726 InstructionCost CostOfRedOperand0 = 0;
1727 InstructionCost CostOfRed0 = 0;
1728 InstructionCost CostOfRedOperand1 = 0;
1729 InstructionCost CostOfRed1 = 0;
1730 analyzeCostOfVecReduction(II0, CostKind, TTI, CostOfRedOperand0, CostOfRed0);
1731 analyzeCostOfVecReduction(II1, CostKind, TTI, CostOfRedOperand1, CostOfRed1);
1732 OldCost = CostOfRed0 + CostOfRed1 + TTI.getInstructionCost(&I, CostKind);
1733 NewCost =
1734 CostOfRedOperand0 + CostOfRedOperand1 +
1735 TTI.getArithmeticInstrCost(BinOpOpc, VTy, CostKind) +
1736 TTI.getArithmeticReductionCost(ReductionOpc, VTy, std::nullopt, CostKind);
1737 if (NewCost >= OldCost || !NewCost.isValid())
1738 return false;
1739
1740 LLVM_DEBUG(dbgs() << "Found two mergeable reductions: " << I
1741 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
1742 << "\n");
1743 Value *VectorBO;
1744 if (BinOpOpc == Instruction::Or)
1745 VectorBO = Builder.CreateOr(V0, V1, "",
1746 cast<PossiblyDisjointInst>(I).isDisjoint());
1747 else
1748 VectorBO = Builder.CreateBinOp(BinOpOpc, V0, V1);
1749
1750 Value *Rdx = Builder.CreateIntrinsic(ReductionIID, {VTy}, {VectorBO});
1751 replaceValue(I, *Rdx);
1752 return true;
1753}
1754
1755// Check if memory is modified, freed, or synchronized between two instrs in
1756// the same BB.
1759 const MemoryLocation &Loc, AAResults &AA) {
1760 unsigned NumScanned = 0;
1761 if (std::any_of(Begin, End, [&](const Instruction &Instr) {
1762 return isModSet(AA.getModRefInfo(&Instr, Loc)) ||
1763 ++NumScanned > MaxInstrsToScan;
1764 }))
1765 return true;
1766
1767 // willNotFreeBetween expects instructions rather than iterators. An empty
1768 // range cannot free or synchronize, so avoid dereferencing its end.
1769 return Begin != End && !willNotFreeBetween(&*Begin, &*End);
1770}
1771
1772namespace {
1773/// Helper class to indicate whether a vector index can be safely scalarized and
1774/// if a freeze needs to be inserted.
1775class ScalarizationResult {
1776 enum class StatusTy { Unsafe, Safe, SafeWithFreeze };
1777
1778 StatusTy Status;
1779 Value *ToFreeze;
1780
1781 ScalarizationResult(StatusTy Status, Value *ToFreeze = nullptr)
1782 : Status(Status), ToFreeze(ToFreeze) {}
1783
1784public:
1785 ScalarizationResult(const ScalarizationResult &Other) = default;
1786 ~ScalarizationResult() {
1787 assert(!ToFreeze && "freeze() not called with ToFreeze being set");
1788 }
1789
1790 static ScalarizationResult unsafe() { return {StatusTy::Unsafe}; }
1791 static ScalarizationResult safe() { return {StatusTy::Safe}; }
1792 static ScalarizationResult safeWithFreeze(Value *ToFreeze) {
1793 return {StatusTy::SafeWithFreeze, ToFreeze};
1794 }
1795
1796 /// Returns true if the index can be scalarize without requiring a freeze.
1797 bool isSafe() const { return Status == StatusTy::Safe; }
1798 /// Returns true if the index cannot be scalarized.
1799 bool isUnsafe() const { return Status == StatusTy::Unsafe; }
1800 /// Returns true if the index can be scalarize, but requires inserting a
1801 /// freeze.
1802 bool isSafeWithFreeze() const { return Status == StatusTy::SafeWithFreeze; }
1803
1804 /// Reset the state of Unsafe and clear ToFreze if set.
1805 void discard() {
1806 ToFreeze = nullptr;
1807 Status = StatusTy::Unsafe;
1808 }
1809
1810 /// Freeze the ToFreeze and update the use in \p User to use it.
1811 void freeze(IRBuilderBase &Builder, Instruction &UserI) {
1812 assert(isSafeWithFreeze() &&
1813 "should only be used when freezing is required");
1814 assert(is_contained(ToFreeze->users(), &UserI) &&
1815 "UserI must be a user of ToFreeze");
1816 IRBuilder<>::InsertPointGuard Guard(Builder);
1817 Builder.SetInsertPoint(cast<Instruction>(&UserI));
1818 Value *Frozen =
1819 Builder.CreateFreeze(ToFreeze, ToFreeze->getName() + ".frozen");
1820 for (Use &U : make_early_inc_range((UserI.operands())))
1821 if (U.get() == ToFreeze)
1822 U.set(Frozen);
1823
1824 ToFreeze = nullptr;
1825 }
1826};
1827} // namespace
1828
1829/// Check if it is legal to scalarize a memory access to \p VecTy at index \p
1830/// Idx. \p Idx must access a valid vector element.
1831static ScalarizationResult canScalarizeAccess(VectorType *VecTy, Value *Idx,
1832 const SimplifyQuery &SQ) {
1833 // We do checks for both fixed vector types and scalable vector types.
1834 // This is the number of elements of fixed vector types,
1835 // or the minimum number of elements of scalable vector types.
1836 uint64_t NumElements = VecTy->getElementCount().getKnownMinValue();
1837 unsigned IntWidth = Idx->getType()->getScalarSizeInBits();
1838
1839 if (auto *C = dyn_cast<ConstantInt>(Idx)) {
1840 if (C->getValue().ult(NumElements))
1841 return ScalarizationResult::safe();
1842 return ScalarizationResult::unsafe();
1843 }
1844
1845 // Always unsafe if the index type can't handle all inbound values.
1846 if (!llvm::isUIntN(IntWidth, NumElements))
1847 return ScalarizationResult::unsafe();
1848
1849 APInt Zero(IntWidth, 0);
1850 APInt MaxElts(IntWidth, NumElements);
1851 ConstantRange ValidIndices(Zero, MaxElts);
1852 ConstantRange IdxRange(IntWidth, true);
1853
1854 if (isGuaranteedNotToBePoison(Idx, SQ.AC, SQ.CtxI, SQ.DT)) {
1855 if (ValidIndices.contains(
1856 computeConstantRange(Idx, /*ForSigned=*/false, SQ)))
1857 return ScalarizationResult::safe();
1858 return ScalarizationResult::unsafe();
1859 }
1860
1861 // If the index may be poison, check if we can insert a freeze before the
1862 // range of the index is restricted.
1863 Value *IdxBase;
1864 ConstantInt *CI;
1865 if (match(Idx, m_And(m_Value(IdxBase), m_ConstantInt(CI)))) {
1866 IdxRange = IdxRange.binaryAnd(CI->getValue());
1867 } else if (match(Idx, m_URem(m_Value(IdxBase), m_ConstantInt(CI)))) {
1868 IdxRange = IdxRange.urem(CI->getValue());
1869 }
1870
1871 if (ValidIndices.contains(IdxRange))
1872 return ScalarizationResult::safeWithFreeze(IdxBase);
1873 return ScalarizationResult::unsafe();
1874}
1875
1876/// Return the GEP index type if the unsigned vector index \p Idx can be
1877/// represented by an inbounds GEP. A null result means that the maximum byte
1878/// offset cannot be represented by the pointer's signed GEP index type.
1879///
1880/// unsigned lane range
1881/// |
1882/// v
1883/// MaxByteOffset = MaxLane * element store size
1884/// |
1885/// +-- unavailable or outside signed GEP range --> reject
1886/// |
1887/// v
1888/// valid range --> use the pointer's GEP index type
1890 Type *PtrTy,
1891 const DataLayout &DL) {
1892 auto *GEPIndexTy = cast<IntegerType>(DL.getIndexType(PtrTy));
1893 unsigned GEPBits = GEPIndexTy->getBitWidth();
1894 uint64_t NumElements = VecTy->getElementCount().getKnownMinValue();
1895
1896 uint64_t MaxLane = NumElements - 1;
1897 if (auto *C = dyn_cast<ConstantInt>(Idx)) {
1898 if (C->getValue().uge(NumElements))
1899 return nullptr;
1900 MaxLane = C->getZExtValue();
1901 }
1902
1903 Type *ElemTy = VecTy->getElementType();
1904 if (!DL.typeSizeEqualsStoreSize(ElemTy))
1905 return nullptr;
1906
1907 TypeSize ElemStride = DL.getTypeStoreSize(ElemTy);
1908 if (ElemStride.isScalable())
1909 return nullptr;
1910
1911 // Compare both values in a common width:
1912 //
1913 // MaxLane (uint64_t) * ElemStride (uint64_t) signed_max(GEPBits)
1914 // | |
1915 // v v
1916 // ByteOffset (up to 128 bits) sext to WideBits
1917 // \ /
1918 // +------------ ugt ------------+
1919 // |
1920 // greater -> reject
1921 //
1922 // WideBits = max(GEPBits, 128) prevents the multiplication from wrapping
1923 // and preserves the GEP limit during the comparison.
1924 unsigned WideBits = std::max(GEPBits, 128u);
1925 APInt MaxLaneValue(WideBits, MaxLane);
1926 APInt ByteOffset = MaxLaneValue;
1927 ByteOffset *= APInt(WideBits, ElemStride.getFixedValue());
1928 APInt MaxGEPOffset = APInt::getSignedMaxValue(GEPBits).sext(WideBits);
1929 // Reject offsets outside the GEP's positive signed range. Compare as
1930 // unsigned because the full 128-bit product may set its sign bit.
1931 if (ByteOffset.ugt(MaxGEPOffset))
1932 return nullptr;
1933
1934 return GEPIndexTy;
1935}
1936
1937/// Materialize an index for a scalarized GEP after profitability is known.
1938/// Vector element indices are unsigned, but GEP sign-extends narrow integer
1939/// indices. Widen a narrow index explicitly so its unsigned value is retained.
1941 IRBuilderBase &Builder) {
1942 unsigned SrcBits = Idx->getType()->getIntegerBitWidth();
1943 unsigned DstBits = GEPIndexTy->getBitWidth();
1944 if (SrcBits >= DstBits)
1945 return Idx;
1946
1947 return Builder.CreateZExt(Idx, GEPIndexTy, Idx->getName() + ".gepidx");
1948}
1949
1950/// The memory operation on a vector of \p ScalarType had alignment of
1951/// \p VectorAlignment. Compute the maximal, but conservatively correct,
1952/// alignment that will be valid for the memory operation on a single scalar
1953/// element of the same type with index \p Idx.
1955 Type *ScalarType, Value *Idx,
1956 const DataLayout &DL) {
1957 if (auto *C = dyn_cast<ConstantInt>(Idx))
1958 return commonAlignment(VectorAlignment,
1959 C->getZExtValue() * DL.getTypeStoreSize(ScalarType));
1960 return commonAlignment(VectorAlignment, DL.getTypeStoreSize(ScalarType));
1961}
1962
1963/// Fold a vector store fed by a single-use insertelement chain into scalar
1964/// stores.
1965///
1966/// Before:
1967///
1968/// %p --> vector load --> insert %x, lane 1 --> insert %y, lane 3
1969/// |
1970/// v
1971/// vector store to %p
1972///
1973/// Vector lanes: [ 0 ] [ 1 ] [ 2 ] [ 3 ]
1974/// Stored value: [ old | x | old | y ] (one vector store)
1975///
1976/// After:
1977///
1978/// +--> GEP(%p, lane 1) --> store %x
1979/// %p -------------+
1980/// +--> GEP(%p, lane 3) --> store %y
1981///
1982/// Vector lanes: [ 0 ] [ 1 ] [ 2 ] [ 3 ]
1983/// Scalar stores: x y
1984/// store@1 store@3
1985///
1986/// Step 1. Gate:
1987/// target supports vector-element GEP addressing
1988///
1989/// Step 2. Trace:
1990/// vector store <-- insertelement <-- ... <-- insertelement <-- load
1991///
1992/// Steps 3-5. Validate:
1993/// reject unprofitable full overwrites; require simple accesses, a
1994/// common address/block, no memory write in between, and scalarizable
1995/// indices.
1996bool VectorCombine::foldInsertElementsToStores(Instruction &I) {
1997 // Step 1: The target must support addressing a vector element with a GEP.
1999 return false;
2000
2001 auto *SI = cast<StoreInst>(&I);
2002 if (!SI->isSimple() || !isa<VectorType>(SI->getValueOperand()->getType()))
2003 return false;
2004
2005 // Step 2: Collect a single-use insertelement chain, starting at the vector
2006 // store and walking back to the candidate load.
2007 Value *Source = SI->getValueOperand();
2008 SmallVector<std::pair<Value *, Value *>, 4> InsertElements;
2009 Value *Base = Source;
2010 while (auto *Insert = dyn_cast<InsertElementInst>(Base)) {
2011 if (!Insert->hasOneUse())
2012 break;
2013 Value *InsertVal = Insert->getOperand(1);
2014 Value *Idx = Insert->getOperand(2);
2015 InsertElements.push_back({InsertVal, Idx});
2016 Base = Insert->getOperand(0);
2017 }
2018
2019 if (InsertElements.empty())
2020 return false;
2021
2022 // The backwards walk collected the inserts in reverse program order. Restore
2023 // it now so later scalar stores preserve writes to duplicate/equal indices.
2024 std::reverse(InsertElements.begin(), InsertElements.end());
2025 auto *Load = dyn_cast<LoadInst>(Base);
2026 if (!Load)
2027 return false;
2028 auto *VecTy = cast<VectorType>(SI->getValueOperand()->getType());
2029
2030 // Step 3: Avoid replacing a complete overwrite with scalar stores when every
2031 // lane receives the same value; keeping the vector operation is preferable.
2032 if (auto *FVT = dyn_cast<FixedVectorType>(VecTy)) {
2033 if (InsertElements.size() == FVT->getNumElements()) {
2034 Value *FirstVal = InsertElements.front().first;
2035 if (all_of(InsertElements,
2036 [FirstVal](const auto &Elt) { return Elt.first == FirstVal; }))
2037 return false;
2038 }
2039 }
2040 Value *SrcAddr = Load->getPointerOperand()->stripPointerCasts();
2041 // Step 4: Establish the load/store update is legal: both accesses are simple,
2042 // have the same base address and block, have scalar elements whose type size
2043 // equals their store size, and no intervening operation modifies the updated
2044 // memory.
2045 if (!Load->isSimple() || Load->getParent() != SI->getParent() ||
2046 !DL->typeSizeEqualsStoreSize(Load->getType()->getScalarType()) ||
2047 SrcAddr != SI->getPointerOperand()->stripPointerCasts())
2048 return false;
2049
2050 if (isMemModifiedBetween(Load->getIterator(), SI->getIterator(),
2051 MemoryLocation::get(SI), AA))
2052 return false;
2053
2054 // Step 5: Validate every index before changing IR. A safe-with-freeze result
2055 // is recorded by ScalarizationResult, so discard it until profitability is
2056 // known; otherwise a rejected candidate could leave a freeze behind.
2057 for (auto [InsertVal, Idx] : InsertElements) {
2058 auto ScalarizableIdx =
2059 canScalarizeAccess(VecTy, Idx, SQ.getWithInstruction(&I));
2060 if (ScalarizableIdx.isUnsafe())
2061 return false;
2062
2063 auto GEPIndex =
2064 getScalarizedGEPIndexInfo(VecTy, Idx, SI->getPointerOperandType(), *DL);
2065 if (!GEPIndex) {
2066 ScalarizableIdx.discard();
2067 return false;
2068 }
2069
2070 // We are only checking legality here. Do not mutate IR before the
2071 // profitability check, but also do not leave a pending ToFreeze behind.
2072 ScalarizableIdx.discard();
2073 }
2074
2076 Instruction::Store, SI->getValueOperand()->getType(), SI->getAlign(),
2077 SI->getPointerAddressSpace(), CostKind);
2078
2079 if (Load->hasOneUse())
2080 OldCost += TTI.getMemoryOpCost(Instruction::Load, Load->getType(),
2081 Load->getAlign(),
2082 Load->getPointerAddressSpace(), CostKind);
2083
2084 for (auto [InsertVal, Idx] : InsertElements) {
2085 int Index = -1;
2086 if (auto *CIdx = dyn_cast<ConstantInt>(Idx))
2087 Index = CIdx->getZExtValue();
2088
2089 OldCost += TTI.getVectorInstrCost(Instruction::InsertElement, VecTy,
2090 CostKind, Index);
2091 }
2092
2093 InstructionCost NewCost = 0;
2094 // This transform replaces insertelement operations on a single vector with
2095 // GEPs and scalar stores, so assume constant-index GEP offsets stay within
2096 // addressing-mode ranges that getGEPCost considers TCC_Free. Cost only GEPs
2097 // with dynamic indices.
2098 for (auto [InsertVal, Idx] : InsertElements) {
2099 if (isa<ConstantInt>(Idx))
2100 continue;
2101 const Value *GEPIndices[] = {ConstantInt::get(Idx->getType(), 0), Idx};
2102 NewCost += TTI.getGEPCost(VecTy, SI->getPointerOperand(), GEPIndices,
2103 CostKind, InsertVal->getType());
2104 }
2105
2106 for (auto [InsertVal, Idx] : InsertElements) {
2107 Align ScalarOpAlignment = computeAlignmentAfterScalarization(
2108 std::max(SI->getAlign(), Load->getAlign()), InsertVal->getType(), Idx,
2109 *DL);
2110
2111 NewCost += TTI.getMemoryOpCost(Instruction::Store, InsertVal->getType(),
2112 ScalarOpAlignment,
2113 SI->getPointerAddressSpace(), CostKind);
2114 }
2115
2116 LLVM_DEBUG(dbgs() << "Found an insert-elements vector store scalarization "
2117 "candidate: "
2118 << I << "\n"
2119 << " NumInserts: " << InsertElements.size() << "\n"
2120 << " OldCost: " << OldCost << " vs NewCost: " << NewCost
2121 << "\n");
2122
2123 if (OldCost <= NewCost)
2124 return false;
2125
2126 for (auto [InsertVal, Idx] : InsertElements) {
2127 auto ScalarizableIdx =
2128 canScalarizeAccess(VecTy, Idx, SQ.getWithInstruction(&I));
2129 assert(!ScalarizableIdx.isUnsafe() && "already checked above");
2130
2131 if (ScalarizableIdx.isSafeWithFreeze())
2132 ScalarizableIdx.freeze(Builder, *cast<Instruction>(Idx));
2133 }
2134
2135 Worklist.push(Load);
2136 StoreInst *LastStore = nullptr;
2137 for (auto [InsertVal, Idx] : InsertElements) {
2138 auto ScalarizableIdx =
2139 canScalarizeAccess(VecTy, Idx, SQ.getWithInstruction(&I));
2140 if (ScalarizableIdx.isUnsafe())
2141 return false;
2142
2143 IntegerType *GEPIndexTy =
2144 getScalarizedGEPIndexInfo(VecTy, Idx, SI->getPointerOperandType(), *DL);
2145
2146 Value *GEPIdx = materializeScalarizedGEPIndex(Idx, GEPIndexTy, Builder);
2147 Value *GEP = Builder.CreateInBoundsGEP(
2148 SI->getValueOperand()->getType(), SI->getPointerOperand(),
2149 {ConstantInt::get(GEPIdx->getType(), 0), GEPIdx});
2150
2151 LastStore = Builder.CreateStore(InsertVal, GEP);
2152 LastStore->copyMetadata(*SI);
2153
2154 // The new GEP may change the pointer operand, so !invariant.group cannot
2155 // be transferred to the scalar store.
2156 LastStore->setMetadata(LLVMContext::MD_invariant_group, nullptr);
2157 Align ScalarOpAlignment = computeAlignmentAfterScalarization(
2158 std::max(SI->getAlign(), Load->getAlign()), InsertVal->getType(), Idx,
2159 *DL);
2160 LastStore->setAlignment(ScalarOpAlignment);
2161 }
2162
2163 replaceValue(I, *LastStore);
2165 return true;
2166}
2167
2168/// Try to scalarize vector loads feeding extractelement or bitcast
2169/// instructions.
2170bool VectorCombine::scalarizeLoad(Instruction &I) {
2171 Value *Ptr;
2172 if (!match(&I, m_Load(m_Value(Ptr))))
2173 return false;
2174
2175 auto *LI = cast<LoadInst>(&I);
2176 auto *VecTy = cast<VectorType>(LI->getType());
2177
2178 // The isSimple() check could be isUnordered(), but for now we cowardly
2179 // refuse to handle even unordered atomics.
2180 if (!LI->isSimple() || !DL->typeSizeEqualsStoreSize(VecTy->getScalarType()))
2181 return false;
2182
2183 bool AllExtracts = true;
2184 bool AllBitcasts = true;
2185 Instruction *LastCheckedInst = LI;
2186 unsigned NumInstChecked = 0;
2187
2188 // Check what type of users we have (must either all be extracts or
2189 // bitcasts) and ensure no memory modifications between the load and
2190 // its users.
2191 for (User *U : LI->users()) {
2192 auto *UI = dyn_cast<Instruction>(U);
2193 if (!UI || UI->getParent() != LI->getParent())
2194 return false;
2195
2196 // If any user is waiting to be erased, then bail out as this will
2197 // distort the cost calculation and possibly lead to infinite loops.
2198 if (UI->use_empty())
2199 return false;
2200
2201 if (!isa<ExtractElementInst>(UI))
2202 AllExtracts = false;
2203 if (!isa<BitCastInst>(UI))
2204 AllBitcasts = false;
2205
2206 // Check if any instruction between the load and the user may modify memory.
2207 if (LastCheckedInst->comesBefore(UI)) {
2208 for (Instruction &I :
2209 make_range(std::next(LI->getIterator()), UI->getIterator())) {
2210 // Bail out if we reached the check limit or the instruction may write
2211 // to memory.
2212 if (NumInstChecked == MaxInstrsToScan || I.mayWriteToMemory())
2213 return false;
2214 NumInstChecked++;
2215 }
2216 LastCheckedInst = UI;
2217 }
2218 }
2219
2220 if (AllExtracts)
2221 return scalarizeLoadExtract(LI, VecTy, Ptr);
2222 if (AllBitcasts)
2223 return scalarizeLoadBitcast(LI, VecTy, Ptr);
2224 return false;
2225}
2226
2227/// Try to scalarize vector loads feeding extractelement instructions.
2228bool VectorCombine::scalarizeLoadExtract(LoadInst *LI, VectorType *VecTy,
2229 Value *Ptr) {
2231 return false;
2232
2233 DenseMap<ExtractElementInst *, ScalarizationResult> NeedFreeze;
2234 DenseMap<ExtractElementInst *, IntegerType *> GEPIndexInfos;
2235 llvm::scope_exit FailureGuard([&]() {
2236 // If the transform is aborted, discard the ScalarizationResults.
2237 for (auto &Pair : NeedFreeze)
2238 Pair.second.discard();
2239 });
2240
2241 InstructionCost OriginalCost =
2242 TTI.getMemoryOpCost(Instruction::Load, VecTy, LI->getAlign(),
2244 InstructionCost ScalarizedCost = 0;
2245
2246 for (User *U : LI->users()) {
2247 auto *UI = cast<ExtractElementInst>(U);
2248
2249 auto ScalarIdx = canScalarizeAccess(VecTy, UI->getIndexOperand(),
2250 SQ.getWithInstruction(LI));
2251 if (ScalarIdx.isUnsafe())
2252 return false;
2253
2254 IntegerType *GEPIndex = getScalarizedGEPIndexInfo(
2255 VecTy, UI->getIndexOperand(), LI->getPointerOperandType(), *DL);
2256 if (!GEPIndex) {
2257 ScalarIdx.discard();
2258 return false;
2259 }
2260
2261 GEPIndexInfos.try_emplace(UI, GEPIndex);
2262
2263 if (ScalarIdx.isSafeWithFreeze()) {
2264 NeedFreeze.try_emplace(UI, ScalarIdx);
2265 ScalarIdx.discard();
2266 }
2267
2268 auto *Index = dyn_cast<ConstantInt>(UI->getIndexOperand());
2269 OriginalCost +=
2270 TTI.getVectorInstrCost(Instruction::ExtractElement, VecTy, CostKind,
2271 Index ? Index->getZExtValue() : -1);
2272 ScalarizedCost +=
2273 TTI.getMemoryOpCost(Instruction::Load, VecTy->getElementType(),
2275 ScalarizedCost += TTI.getAddressComputationCost(LI->getPointerOperandType(),
2276 nullptr, nullptr, CostKind);
2277 if (!Index && UI->getIndexOperand()->getType()->getIntegerBitWidth() <
2278 GEPIndex->getBitWidth())
2279 ScalarizedCost += TTI.getCastInstrCost(
2280 Instruction::ZExt, GEPIndex, UI->getIndexOperand()->getType(),
2282 }
2283
2284 LLVM_DEBUG(dbgs() << "Found all extractions of a vector load: " << *LI
2285 << "\n LoadExtractCost: " << OriginalCost
2286 << " vs ScalarizedCost: " << ScalarizedCost << "\n");
2287
2288 if (ScalarizedCost > OriginalCost)
2289 return false;
2290 if (ScalarizedCost == OriginalCost && !LI->hasOneUse())
2291 return false;
2292
2293 // Ensure we add the load back to the worklist BEFORE its users so they can
2294 // erased in the correct order.
2295 Worklist.push(LI);
2296
2297 Type *ElemType = VecTy->getElementType();
2298
2299 // Replace extracts with narrow scalar loads.
2300 for (User *U : LI->users()) {
2301 auto *EI = cast<ExtractElementInst>(U);
2302 Value *Idx = EI->getIndexOperand();
2303
2304 // Insert 'freeze' for poison indexes.
2305 if (auto It = NeedFreeze.find(EI); It != NeedFreeze.end())
2306 It->second.freeze(Builder, *cast<Instruction>(Idx));
2307
2308 Builder.SetInsertPoint(EI);
2309 auto It = GEPIndexInfos.find(EI);
2310 assert(It != GEPIndexInfos.end() &&
2311 "Missing scalarized GEP index information");
2312 Value *GEPIdx = materializeScalarizedGEPIndex(Idx, It->second, Builder);
2313 Value *GEP = Builder.CreateInBoundsGEP(
2314 VecTy, Ptr, {ConstantInt::get(GEPIdx->getType(), 0), GEPIdx});
2315 auto *NewLoad = cast<LoadInst>(
2316 Builder.CreateLoad(ElemType, GEP, EI->getName() + ".scalar"));
2317
2318 Align ScalarOpAlignment =
2319 computeAlignmentAfterScalarization(LI->getAlign(), ElemType, Idx, *DL);
2320 NewLoad->setAlignment(ScalarOpAlignment);
2321
2322 if (auto *ConstIdx = dyn_cast<ConstantInt>(Idx)) {
2323 size_t Offset = ConstIdx->getZExtValue() * DL->getTypeStoreSize(ElemType);
2324 AAMDNodes OldAAMD = LI->getAAMetadata();
2325 NewLoad->setAAMetadata(OldAAMD.adjustForAccess(Offset, ElemType, *DL));
2326 }
2327
2328 replaceValue(*EI, *NewLoad, false);
2329 }
2330
2331 FailureGuard.release();
2332 return true;
2333}
2334
2335/// Try to scalarize vector loads feeding bitcast instructions.
2336bool VectorCombine::scalarizeLoadBitcast(LoadInst *LI, VectorType *VecTy,
2337 Value *Ptr) {
2338 InstructionCost OriginalCost =
2339 TTI.getMemoryOpCost(Instruction::Load, VecTy, LI->getAlign(),
2341
2342 if (!isa<FixedVectorType>(VecTy))
2343 return false;
2344
2345 Type *TargetScalarType = nullptr;
2346 unsigned VecBitWidth = DL->getTypeSizeInBits(VecTy);
2347
2348 for (User *U : LI->users()) {
2349 auto *BC = cast<BitCastInst>(U);
2350
2351 Type *DestTy = BC->getDestTy();
2352 if (!DestTy->isIntegerTy() && !DestTy->isFloatingPointTy())
2353 return false;
2354
2355 unsigned DestBitWidth = DL->getTypeSizeInBits(DestTy);
2356 if (DestBitWidth != VecBitWidth)
2357 return false;
2358
2359 // All bitcasts must target the same scalar type.
2360 if (!TargetScalarType)
2361 TargetScalarType = DestTy;
2362 else if (TargetScalarType != DestTy)
2363 return false;
2364
2365 OriginalCost +=
2366 TTI.getCastInstrCost(Instruction::BitCast, TargetScalarType, VecTy,
2368 }
2369
2370 if (!TargetScalarType)
2371 return false;
2372
2373 assert(!LI->user_empty() && "Unexpected load without bitcast users");
2374 InstructionCost ScalarizedCost =
2375 TTI.getMemoryOpCost(Instruction::Load, TargetScalarType, LI->getAlign(),
2377
2378 LLVM_DEBUG(dbgs() << "Found vector load feeding only bitcasts: " << *LI
2379 << "\n OriginalCost: " << OriginalCost
2380 << " vs ScalarizedCost: " << ScalarizedCost << "\n");
2381
2382 if (ScalarizedCost >= OriginalCost)
2383 return false;
2384
2385 // Ensure we add the load back to the worklist BEFORE its users so they can
2386 // erased in the correct order.
2387 Worklist.push(LI);
2388
2389 Builder.SetInsertPoint(LI);
2390 auto *ScalarLoad =
2391 Builder.CreateLoad(TargetScalarType, Ptr, LI->getName() + ".scalar");
2392 ScalarLoad->setAlignment(LI->getAlign());
2393 ScalarLoad->copyMetadata(*LI);
2394
2395 // Replace all bitcast users with the scalar load.
2396 for (User *U : LI->users()) {
2397 auto *BC = cast<BitCastInst>(U);
2398 replaceValue(*BC, *ScalarLoad, false);
2399 }
2400
2401 return true;
2402}
2403
2404bool VectorCombine::scalarizeExtExtract(Instruction &I) {
2406 return false;
2407 auto *Ext = dyn_cast<ZExtInst>(&I);
2408 if (!Ext)
2409 return false;
2410
2411 // Try to convert a vector zext feeding only extracts to a set of scalar
2412 // (Src << ExtIdx *Size) & (Size -1)
2413 // if profitable .
2414 auto *SrcTy = dyn_cast<FixedVectorType>(Ext->getOperand(0)->getType());
2415 if (!SrcTy)
2416 return false;
2417 auto *DstTy = cast<FixedVectorType>(Ext->getType());
2418
2419 Type *ScalarDstTy = DstTy->getElementType();
2420 if (DL->getTypeSizeInBits(SrcTy) != DL->getTypeSizeInBits(ScalarDstTy))
2421 return false;
2422
2423 InstructionCost VectorCost =
2424 TTI.getCastInstrCost(Instruction::ZExt, DstTy, SrcTy,
2426 unsigned ExtCnt = 0;
2427 bool ExtLane0 = false;
2428 for (User *U : Ext->users()) {
2429 uint64_t Idx;
2430 if (!match(U, m_ExtractElt(m_Value(), m_ConstantInt(Idx))))
2431 return false;
2432 // An out-of-bounds extractelement produces poison; bail out rather
2433 // than computing a shift amount that overflows the packed type.
2434 if (Idx >= SrcTy->getNumElements())
2435 return false;
2436 if (cast<Instruction>(U)->use_empty())
2437 continue;
2438 ExtCnt += 1;
2439 ExtLane0 |= !Idx;
2440 VectorCost += TTI.getVectorInstrCost(Instruction::ExtractElement, DstTy,
2441 CostKind, Idx, U);
2442 }
2443
2444 InstructionCost ScalarCost =
2445 ExtCnt * TTI.getArithmeticInstrCost(
2446 Instruction::And, ScalarDstTy, CostKind,
2449 (ExtCnt - ExtLane0) *
2451 Instruction::LShr, ScalarDstTy, CostKind,
2454 if (ScalarCost > VectorCost)
2455 return false;
2456
2457 Value *ScalarV = Ext->getOperand(0);
2458 if (!isGuaranteedNotToBePoison(ScalarV, SQ.AC, dyn_cast<Instruction>(ScalarV),
2459 SQ.DT)) {
2460 // Check wether all lanes are extracted, all extracts trigger UB
2461 // on poison, and the last extract (and hence all previous ones)
2462 // are guaranteed to execute if Ext executes. If so, we do not
2463 // need to insert a freeze.
2464 SmallDenseSet<ConstantInt *, 8> ExtractedLanes;
2465 bool AllExtractsTriggerUB = true;
2466 ExtractElementInst *LastExtract = nullptr;
2467 BasicBlock *ExtBB = Ext->getParent();
2468 for (User *U : Ext->users()) {
2469 auto *Extract = cast<ExtractElementInst>(U);
2470 if (Extract->getParent() != ExtBB || !programUndefinedIfPoison(Extract)) {
2471 AllExtractsTriggerUB = false;
2472 break;
2473 }
2474 ExtractedLanes.insert(cast<ConstantInt>(Extract->getIndexOperand()));
2475 if (!LastExtract || LastExtract->comesBefore(Extract))
2476 LastExtract = Extract;
2477 }
2478 if (ExtractedLanes.size() != DstTy->getNumElements() ||
2479 !AllExtractsTriggerUB ||
2481 LastExtract->getIterator()))
2482 ScalarV = Builder.CreateFreeze(ScalarV);
2483 }
2484 ScalarV = Builder.CreateBitCast(
2485 ScalarV,
2486 IntegerType::get(SrcTy->getContext(), DL->getTypeSizeInBits(SrcTy)));
2487 uint64_t SrcEltSizeInBits = DL->getTypeSizeInBits(SrcTy->getElementType());
2488 uint64_t TotalBits = DL->getTypeSizeInBits(SrcTy);
2489 APInt EltBitMask = APInt::getLowBitsSet(TotalBits, SrcEltSizeInBits);
2490 Type *PackedTy = IntegerType::get(SrcTy->getContext(), TotalBits);
2491 Value *Mask = ConstantInt::get(PackedTy, EltBitMask);
2492 for (User *U : Ext->users()) {
2493 auto *Extract = cast<ExtractElementInst>(U);
2494 uint64_t Idx =
2495 cast<ConstantInt>(Extract->getIndexOperand())->getZExtValue();
2496 uint64_t ShiftAmt =
2497 DL->isBigEndian()
2498 ? (TotalBits - SrcEltSizeInBits - Idx * SrcEltSizeInBits)
2499 : (Idx * SrcEltSizeInBits);
2500 Value *LShr = Builder.CreateLShr(ScalarV, ShiftAmt);
2501 Value *And = Builder.CreateAnd(LShr, Mask);
2502 U->replaceAllUsesWith(And);
2503 }
2504 return true;
2505}
2506
2507/// Try to fold "(or (zext (bitcast X)), (shl (zext (bitcast Y)), C))"
2508/// to "(bitcast (concat X, Y))"
2509/// where X/Y are bitcasted from i1 mask vectors.
2510bool VectorCombine::foldConcatOfBoolMasks(Instruction &I) {
2511 Type *Ty = I.getType();
2512 if (!Ty->isIntegerTy())
2513 return false;
2514
2515 // TODO: Add big endian test coverage
2516 if (DL->isBigEndian())
2517 return false;
2518
2519 // Restrict to disjoint cases so the mask vectors aren't overlapping.
2520 Instruction *X, *Y;
2522 return false;
2523
2524 // Allow both sources to contain shl, to handle more generic pattern:
2525 // "(or (shl (zext (bitcast X)), C1), (shl (zext (bitcast Y)), C2))"
2526 Value *SrcX;
2527 uint64_t ShAmtX = 0;
2528 if (!match(X, m_OneUse(m_ZExt(m_OneUse(m_BitCast(m_Value(SrcX)))))) &&
2529 !match(X, m_OneUse(
2531 m_ConstantInt(ShAmtX)))))
2532 return false;
2533
2534 Value *SrcY;
2535 uint64_t ShAmtY = 0;
2536 if (!match(Y, m_OneUse(m_ZExt(m_OneUse(m_BitCast(m_Value(SrcY)))))) &&
2537 !match(Y, m_OneUse(
2539 m_ConstantInt(ShAmtY)))))
2540 return false;
2541
2542 // Canonicalize larger shift to the RHS.
2543 if (ShAmtX > ShAmtY) {
2544 std::swap(X, Y);
2545 std::swap(SrcX, SrcY);
2546 std::swap(ShAmtX, ShAmtY);
2547 }
2548
2549 // Ensure both sources are matching vXi1 bool mask types, and that the shift
2550 // difference is the mask width so they can be easily concatenated together.
2551 uint64_t ShAmtDiff = ShAmtY - ShAmtX;
2552 unsigned NumSHL = (ShAmtX > 0) + (ShAmtY > 0);
2553 unsigned BitWidth = Ty->getPrimitiveSizeInBits();
2554 auto *MaskTy = dyn_cast<FixedVectorType>(SrcX->getType());
2555 if (!MaskTy || SrcX->getType() != SrcY->getType() ||
2556 !MaskTy->getElementType()->isIntegerTy(1) ||
2557 MaskTy->getNumElements() != ShAmtDiff ||
2558 MaskTy->getNumElements() > (BitWidth / 2))
2559 return false;
2560
2561 auto *ConcatTy = FixedVectorType::getDoubleElementsVectorType(MaskTy);
2562 auto *ConcatIntTy =
2563 Type::getIntNTy(Ty->getContext(), ConcatTy->getNumElements());
2564 auto *MaskIntTy = Type::getIntNTy(Ty->getContext(), ShAmtDiff);
2565
2566 SmallVector<int, 32> ConcatMask(ConcatTy->getNumElements());
2567 std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
2568
2569 // TODO: Is it worth supporting multi use cases?
2570 InstructionCost OldCost = 0;
2571 OldCost += TTI.getArithmeticInstrCost(Instruction::Or, Ty, CostKind);
2572 OldCost +=
2573 NumSHL * TTI.getArithmeticInstrCost(Instruction::Shl, Ty, CostKind);
2574 OldCost += 2 * TTI.getCastInstrCost(Instruction::ZExt, Ty, MaskIntTy,
2576 OldCost += 2 * TTI.getCastInstrCost(Instruction::BitCast, MaskIntTy, MaskTy,
2578
2579 InstructionCost NewCost = 0;
2581 MaskTy, CostKind, ConcatMask);
2582 NewCost += TTI.getCastInstrCost(Instruction::BitCast, ConcatIntTy, ConcatTy,
2584 if (Ty != ConcatIntTy)
2585 NewCost += TTI.getCastInstrCost(Instruction::ZExt, Ty, ConcatIntTy,
2587 if (ShAmtX > 0)
2588 NewCost += TTI.getArithmeticInstrCost(Instruction::Shl, Ty, CostKind);
2589
2590 LLVM_DEBUG(dbgs() << "Found a concatenation of bitcasted bool masks: " << I
2591 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
2592 << "\n");
2593
2594 if (NewCost > OldCost)
2595 return false;
2596
2597 // Build bool mask concatenation, bitcast back to scalar integer, and perform
2598 // any residual zero-extension or shifting.
2599 Value *Concat = Builder.CreateShuffleVector(SrcX, SrcY, ConcatMask);
2600 Worklist.pushValue(Concat);
2601
2602 Value *Result = Builder.CreateBitCast(Concat, ConcatIntTy);
2603
2604 if (Ty != ConcatIntTy) {
2605 Worklist.pushValue(Result);
2606 Result = Builder.CreateZExt(Result, Ty);
2607 }
2608
2609 if (ShAmtX > 0) {
2610 Worklist.pushValue(Result);
2611 Result = Builder.CreateShl(Result, ShAmtX);
2612 }
2613
2614 replaceValue(I, *Result);
2615 return true;
2616}
2617
2618/// Try to convert "shuffle (binop (shuffle, shuffle)), undef"
2619/// --> "binop (shuffle), (shuffle)".
2620bool VectorCombine::foldPermuteOfBinops(Instruction &I) {
2621 BinaryOperator *BinOp;
2622 ArrayRef<int> OuterMask;
2623 if (!match(&I, m_Shuffle(m_BinOp(BinOp), m_Undef(), m_Mask(OuterMask))))
2624 return false;
2625
2626 // Don't introduce poison into div/rem.
2627 if (BinOp->isIntDivRem() && llvm::is_contained(OuterMask, PoisonMaskElem))
2628 return false;
2629
2630 Value *Op00, *Op01, *Op10, *Op11;
2631 ArrayRef<int> Mask0, Mask1;
2632 bool Match0 = match(BinOp->getOperand(0),
2633 m_Shuffle(m_Value(Op00), m_Value(Op01), m_Mask(Mask0)));
2634 bool Match1 = match(BinOp->getOperand(1),
2635 m_Shuffle(m_Value(Op10), m_Value(Op11), m_Mask(Mask1)));
2636 if (!Match0 && !Match1)
2637 return false;
2638
2639 Op00 = Match0 ? Op00 : BinOp->getOperand(0);
2640 Op01 = Match0 ? Op01 : BinOp->getOperand(0);
2641 Op10 = Match1 ? Op10 : BinOp->getOperand(1);
2642 Op11 = Match1 ? Op11 : BinOp->getOperand(1);
2643
2644 Instruction::BinaryOps Opcode = BinOp->getOpcode();
2645 auto *ShuffleDstTy = dyn_cast<FixedVectorType>(I.getType());
2646 auto *BinOpTy = dyn_cast<FixedVectorType>(BinOp->getType());
2647 auto *Op0Ty = dyn_cast<FixedVectorType>(Op00->getType());
2648 auto *Op1Ty = dyn_cast<FixedVectorType>(Op10->getType());
2649 if (!ShuffleDstTy || !BinOpTy || !Op0Ty || !Op1Ty)
2650 return false;
2651
2652 unsigned NumSrcElts = BinOpTy->getNumElements();
2653
2654 // Don't accept shuffles that reference the second operand in
2655 // div/rem or if its an undef arg.
2656 if ((BinOp->isIntDivRem() || !isa<PoisonValue>(I.getOperand(1))) &&
2657 any_of(OuterMask, [NumSrcElts](int M) { return M >= (int)NumSrcElts; }))
2658 return false;
2659
2660 // Merge outer / inner (or identity if no match) shuffles.
2661 SmallVector<int> NewMask0, NewMask1;
2662 for (int M : OuterMask) {
2663 if (M < 0 || M >= (int)NumSrcElts) {
2664 NewMask0.push_back(PoisonMaskElem);
2665 NewMask1.push_back(PoisonMaskElem);
2666 } else {
2667 NewMask0.push_back(Match0 ? Mask0[M] : M);
2668 NewMask1.push_back(Match1 ? Mask1[M] : M);
2669 }
2670 }
2671
2672 unsigned NumOpElts = Op0Ty->getNumElements();
2673 bool IsIdentity0 = ShuffleDstTy == Op0Ty &&
2674 all_of(NewMask0, [NumOpElts](int M) { return M < (int)NumOpElts; }) &&
2675 ShuffleVectorInst::isIdentityMask(NewMask0, NumOpElts);
2676 bool IsIdentity1 = ShuffleDstTy == Op1Ty &&
2677 all_of(NewMask1, [NumOpElts](int M) { return M < (int)NumOpElts; }) &&
2678 ShuffleVectorInst::isIdentityMask(NewMask1, NumOpElts);
2679
2680 InstructionCost NewCost = 0;
2681 // Try to merge shuffles across the binop if the new shuffles are not costly.
2682 InstructionCost BinOpCost =
2683 TTI.getArithmeticInstrCost(Opcode, BinOpTy, CostKind);
2684 InstructionCost OldCost =
2686 ShuffleDstTy, BinOpTy, CostKind, OuterMask,
2687 0, nullptr, {BinOp}, &I);
2688 if (!BinOp->hasOneUse())
2689 NewCost += BinOpCost;
2690
2691 if (Match0) {
2693 TargetTransformInfo::SK_PermuteTwoSrc, BinOpTy, Op0Ty, CostKind, Mask0,
2694 0, nullptr, {Op00, Op01}, cast<Instruction>(BinOp->getOperand(0)));
2695 OldCost += Shuf0Cost;
2696 if (!BinOp->hasOneUse() || !BinOp->getOperand(0)->hasOneUse())
2697 NewCost += Shuf0Cost;
2698 }
2699 if (Match1) {
2701 TargetTransformInfo::SK_PermuteTwoSrc, BinOpTy, Op1Ty, CostKind, Mask1,
2702 0, nullptr, {Op10, Op11}, cast<Instruction>(BinOp->getOperand(1)));
2703 OldCost += Shuf1Cost;
2704 if (!BinOp->hasOneUse() || !BinOp->getOperand(1)->hasOneUse())
2705 NewCost += Shuf1Cost;
2706 }
2707
2708 NewCost += TTI.getArithmeticInstrCost(Opcode, ShuffleDstTy, CostKind);
2709
2710 if (!IsIdentity0)
2711 NewCost +=
2713 Op0Ty, CostKind, NewMask0, 0, nullptr, {Op00, Op01});
2714 if (!IsIdentity1)
2715 NewCost +=
2717 Op1Ty, CostKind, NewMask1, 0, nullptr, {Op10, Op11});
2718
2719 LLVM_DEBUG(dbgs() << "Found a shuffle feeding a shuffled binop: " << I
2720 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
2721 << "\n");
2722
2723 // If costs are equal, still fold as we reduce instruction count.
2724 if (NewCost > OldCost)
2725 return false;
2726
2727 Value *LHS =
2728 IsIdentity0 ? Op00 : Builder.CreateShuffleVector(Op00, Op01, NewMask0);
2729 Value *RHS =
2730 IsIdentity1 ? Op10 : Builder.CreateShuffleVector(Op10, Op11, NewMask1);
2731 Value *NewBO = Builder.CreateBinOp(Opcode, LHS, RHS);
2732
2733 // Intersect flags from the old binops.
2734 if (auto *NewInst = dyn_cast<Instruction>(NewBO))
2735 NewInst->copyIRFlags(BinOp);
2736
2737 Worklist.pushValue(LHS);
2738 Worklist.pushValue(RHS);
2739 replaceValue(I, *NewBO);
2740 return true;
2741}
2742
2743/// Try to convert "shuffle (binop), (binop)" into "binop (shuffle), (shuffle)".
2744/// Try to convert "shuffle (cmpop), (cmpop)" into "cmpop (shuffle), (shuffle)".
2745bool VectorCombine::foldShuffleOfBinops(Instruction &I) {
2746 ArrayRef<int> OldMask;
2747 Instruction *LHS, *RHS;
2749 m_Mask(OldMask))))
2750 return false;
2751
2752 // TODO: Add support for addlike etc.
2753 if (LHS->getOpcode() != RHS->getOpcode())
2754 return false;
2755
2756 Value *X, *Y, *Z, *W;
2757 bool IsCommutative = false;
2758 CmpPredicate PredLHS = CmpInst::BAD_ICMP_PREDICATE;
2759 CmpPredicate PredRHS = CmpInst::BAD_ICMP_PREDICATE;
2760 if (match(LHS, m_BinOp(m_Value(X), m_Value(Y))) &&
2761 match(RHS, m_BinOp(m_Value(Z), m_Value(W)))) {
2762 auto *BO = cast<BinaryOperator>(LHS);
2763 // Don't introduce poison into div/rem.
2764 if (llvm::is_contained(OldMask, PoisonMaskElem) && BO->isIntDivRem())
2765 return false;
2766 IsCommutative = BinaryOperator::isCommutative(BO->getOpcode());
2767 } else if (match(LHS, m_Cmp(PredLHS, m_Value(X), m_Value(Y))) &&
2768 match(RHS, m_Cmp(PredRHS, m_Value(Z), m_Value(W))) &&
2769 (CmpInst::Predicate)PredLHS == (CmpInst::Predicate)PredRHS) {
2770 IsCommutative = cast<CmpInst>(LHS)->isCommutative();
2771 } else
2772 return false;
2773
2774 auto *ShuffleDstTy = dyn_cast<FixedVectorType>(I.getType());
2775 auto *BinResTy = dyn_cast<FixedVectorType>(LHS->getType());
2776 auto *BinOpTy = dyn_cast<FixedVectorType>(X->getType());
2777 if (!ShuffleDstTy || !BinResTy || !BinOpTy || X->getType() != Z->getType())
2778 return false;
2779
2780 bool SameBinOp = LHS == RHS;
2781 unsigned NumSrcElts = BinOpTy->getNumElements();
2782
2783 // If we have something like "add X, Y" and "add Z, X", swap ops to match.
2784 if (IsCommutative && X != Z && Y != W && (X == W || Y == Z))
2785 std::swap(X, Y);
2786
2787 auto ConvertToUnary = [NumSrcElts](int &M) {
2788 if (M >= (int)NumSrcElts)
2789 M -= NumSrcElts;
2790 };
2791
2792 SmallVector<int> NewMask0(OldMask);
2794 TTI::OperandValueInfo Op0Info = TTI.commonOperandInfo(X, Z);
2795 if (X == Z) {
2796 llvm::for_each(NewMask0, ConvertToUnary);
2798 Z = PoisonValue::get(BinOpTy);
2799 }
2800
2801 SmallVector<int> NewMask1(OldMask);
2803 TTI::OperandValueInfo Op1Info = TTI.commonOperandInfo(Y, W);
2804 if (Y == W) {
2805 llvm::for_each(NewMask1, ConvertToUnary);
2807 W = PoisonValue::get(BinOpTy);
2808 }
2809
2810 // Try to replace a binop with a shuffle if the shuffle is not costly.
2811 // When SameBinOp, only count the binop cost once.
2814
2815 InstructionCost OldCost = LHSCost;
2816 if (!SameBinOp) {
2817 OldCost += RHSCost;
2818 }
2820 ShuffleDstTy, BinResTy, CostKind, OldMask, 0,
2821 nullptr, {LHS, RHS}, &I);
2822
2823 // Handle shuffle(binop(shuffle(x),y),binop(z,shuffle(w))) style patterns
2824 // where one use shuffles have gotten split across the binop/cmp. These
2825 // often allow a major reduction in total cost that wouldn't happen as
2826 // individual folds.
2827 auto MergeInner = [&](Value *&Op, int Offset, MutableArrayRef<int> Mask,
2828 TTI::TargetCostKind CostKind) -> bool {
2829 Value *InnerOp;
2830 ArrayRef<int> InnerMask;
2831 if (match(Op, m_OneUse(m_Shuffle(m_Value(InnerOp), m_Undef(),
2832 m_Mask(InnerMask)))) &&
2833 InnerOp->getType() == Op->getType() &&
2834 all_of(InnerMask,
2835 [NumSrcElts](int M) { return M < (int)NumSrcElts; })) {
2836 for (int &M : Mask)
2837 if (Offset <= M && M < (int)(Offset + NumSrcElts)) {
2838 M = InnerMask[M - Offset];
2839 M = 0 <= M ? M + Offset : M;
2840 }
2842 Op = InnerOp;
2843 return true;
2844 }
2845 return false;
2846 };
2847 bool ReducedInstCount = false;
2848 ReducedInstCount |= MergeInner(X, 0, NewMask0, CostKind);
2849 ReducedInstCount |= MergeInner(Y, 0, NewMask1, CostKind);
2850 ReducedInstCount |= MergeInner(Z, NumSrcElts, NewMask0, CostKind);
2851 ReducedInstCount |= MergeInner(W, NumSrcElts, NewMask1, CostKind);
2852 bool SingleSrcBinOp = (X == Y) && (Z == W) && (NewMask0 == NewMask1);
2853 // SingleSrcBinOp only reduces instruction count if we also eliminate the
2854 // original binop(s). If binops have multiple uses, they won't be eliminated.
2855 ReducedInstCount |= SingleSrcBinOp && LHS->hasOneUser() && RHS->hasOneUser();
2856
2857 // For concat shuffles of i1 vectors where both binops are one-use, the
2858 // transform keeps the same instruction count but canonicalises to a single
2859 // wider binop, enabling downstream folds (e.g. NOT(XOR(concat(a,b),
2860 // concat(c,d))) -> XNOR(concat(a,b),concat(c,d)) on AVX-512 mask regs).
2861 // Restrict to BinaryOperator (not CmpInst) since narrow comparisons may
2862 // be cheaper than wide ones on some targets (e.g. AVX-512 vpcmpeq).
2863 ReducedInstCount |= cast<ShuffleVectorInst>(&I)->isConcat() &&
2864 I.getType()->getScalarType()->isIntegerTy(1) &&
2866 RHS->hasOneUser();
2867
2868 auto *ShuffleCmpTy =
2869 FixedVectorType::get(BinOpTy->getElementType(), ShuffleDstTy);
2871 SK0, ShuffleCmpTy, BinOpTy, CostKind, NewMask0, 0, nullptr, {X, Z});
2872 if (!SingleSrcBinOp)
2873 NewCost += TTI.getShuffleCost(SK1, ShuffleCmpTy, BinOpTy, CostKind,
2874 NewMask1, 0, nullptr, {Y, W});
2875
2876 if (PredLHS == CmpInst::BAD_ICMP_PREDICATE) {
2877 NewCost += TTI.getArithmeticInstrCost(LHS->getOpcode(), ShuffleDstTy,
2878 CostKind, Op0Info, Op1Info);
2879 } else {
2880 NewCost +=
2881 TTI.getCmpSelInstrCost(LHS->getOpcode(), ShuffleCmpTy, ShuffleDstTy,
2882 PredLHS, CostKind, Op0Info, Op1Info);
2883 }
2884 // If LHS/RHS have other uses, we need to account for the cost of keeping
2885 // the original instructions. When SameBinOp, only add the cost once.
2886 if (!LHS->hasOneUser())
2887 NewCost += LHSCost;
2888 if (!SameBinOp && !RHS->hasOneUser())
2889 NewCost += RHSCost;
2890
2891 LLVM_DEBUG(dbgs() << "Found a shuffle feeding two binops: " << I
2892 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
2893 << "\n");
2894
2895 // If either shuffle will constant fold away, then fold for the same cost as
2896 // we will reduce the instruction count.
2897 ReducedInstCount |= (isa<Constant>(X) && isa<Constant>(Z)) ||
2898 (isa<Constant>(Y) && isa<Constant>(W));
2899 if (ReducedInstCount ? (NewCost > OldCost) : (NewCost >= OldCost))
2900 return false;
2901
2902 Value *Shuf0 = Builder.CreateShuffleVector(X, Z, NewMask0);
2903 Value *Shuf1 =
2904 SingleSrcBinOp ? Shuf0 : Builder.CreateShuffleVector(Y, W, NewMask1);
2905 Value *NewBO = PredLHS == CmpInst::BAD_ICMP_PREDICATE
2906 ? Builder.CreateBinOp(
2907 cast<BinaryOperator>(LHS)->getOpcode(), Shuf0, Shuf1)
2908 : Builder.CreateCmp(PredLHS, Shuf0, Shuf1);
2909
2910 // Intersect flags from the old binops.
2911 if (auto *NewInst = dyn_cast<Instruction>(NewBO)) {
2912 NewInst->copyIRFlags(LHS);
2913 NewInst->andIRFlags(RHS);
2914 }
2915
2916 Worklist.pushValue(Shuf0);
2917 Worklist.pushValue(Shuf1);
2918 replaceValue(I, *NewBO);
2919 return true;
2920}
2921
2922/// Try to convert,
2923/// (shuffle(select(c1,t1,f1)), (select(c2,t2,f2)), m) into
2924/// (select (shuffle c1,c2,m), (shuffle t1,t2,m), (shuffle f1,f2,m))
2925bool VectorCombine::foldShuffleOfSelects(Instruction &I) {
2926 ArrayRef<int> Mask;
2927 Value *C1, *T1, *F1, *C2, *T2, *F2;
2928 if (!match(&I, m_Shuffle(m_Select(m_Value(C1), m_Value(T1), m_Value(F1)),
2929 m_Select(m_Value(C2), m_Value(T2), m_Value(F2)),
2930 m_Mask(Mask))))
2931 return false;
2932
2933 auto *Sel1 = cast<Instruction>(I.getOperand(0));
2934 auto *Sel2 = cast<Instruction>(I.getOperand(1));
2935
2936 auto *C1VecTy = dyn_cast<FixedVectorType>(C1->getType());
2937 auto *C2VecTy = dyn_cast<FixedVectorType>(C2->getType());
2938 if (!C1VecTy || !C2VecTy || C1VecTy != C2VecTy)
2939 return false;
2940
2941 auto *SI0FOp = dyn_cast<FPMathOperator>(I.getOperand(0));
2942 auto *SI1FOp = dyn_cast<FPMathOperator>(I.getOperand(1));
2943 // SelectInsts must have the same FMF.
2944 if (((SI0FOp == nullptr) != (SI1FOp == nullptr)) ||
2945 ((SI0FOp != nullptr) &&
2946 (SI0FOp->getFastMathFlags() != SI1FOp->getFastMathFlags())))
2947 return false;
2948
2949 auto *SrcVecTy = cast<FixedVectorType>(T1->getType());
2950 auto *DstVecTy = cast<FixedVectorType>(I.getType());
2952 auto SelOp = Instruction::Select;
2953
2955 SelOp, SrcVecTy, C1VecTy, CmpInst::BAD_ICMP_PREDICATE, CostKind);
2957 SelOp, SrcVecTy, C2VecTy, CmpInst::BAD_ICMP_PREDICATE, CostKind);
2958
2959 InstructionCost OldCost =
2960 CostSel1 + CostSel2 +
2961 TTI.getShuffleCost(SK, DstVecTy, SrcVecTy, CostKind, Mask, 0, nullptr,
2962 {I.getOperand(0), I.getOperand(1)}, &I);
2963
2965 SK, FixedVectorType::get(C1VecTy->getScalarType(), Mask.size()), C1VecTy,
2966 CostKind, Mask, 0, nullptr, {C1, C2});
2967 NewCost += TTI.getShuffleCost(SK, DstVecTy, SrcVecTy, CostKind, Mask, 0,
2968 nullptr, {T1, T2});
2969 NewCost += TTI.getShuffleCost(SK, DstVecTy, SrcVecTy, CostKind, Mask, 0,
2970 nullptr, {F1, F2});
2971 auto *C1C2ShuffledVecTy = FixedVectorType::get(
2972 Type::getInt1Ty(I.getContext()), DstVecTy->getNumElements());
2973 NewCost += TTI.getCmpSelInstrCost(SelOp, DstVecTy, C1C2ShuffledVecTy,
2975
2976 if (!Sel1->hasOneUse())
2977 NewCost += CostSel1;
2978 if (!Sel2->hasOneUse())
2979 NewCost += CostSel2;
2980
2981 LLVM_DEBUG(dbgs() << "Found a shuffle feeding two selects: " << I
2982 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
2983 << "\n");
2984 if (NewCost > OldCost)
2985 return false;
2986
2987 Value *ShuffleCmp = Builder.CreateShuffleVector(C1, C2, Mask);
2988 Value *ShuffleTrue = Builder.CreateShuffleVector(T1, T2, Mask);
2989 Value *ShuffleFalse = Builder.CreateShuffleVector(F1, F2, Mask);
2990 Value *NewSel;
2991 // We presuppose that the SelectInsts have the same FMF.
2992 if (SI0FOp)
2993 NewSel = Builder.CreateSelectFMF(ShuffleCmp, ShuffleTrue, ShuffleFalse,
2994 SI0FOp->getFastMathFlags());
2995 else
2996 NewSel = Builder.CreateSelect(ShuffleCmp, ShuffleTrue, ShuffleFalse);
2997
2998 Worklist.pushValue(ShuffleCmp);
2999 Worklist.pushValue(ShuffleTrue);
3000 Worklist.pushValue(ShuffleFalse);
3001 replaceValue(I, *NewSel);
3002 return true;
3003}
3004
3005/// Try to convert "shuffle (castop), (castop)" with a shared castop operand
3006/// into "castop (shuffle)".
3007bool VectorCombine::foldShuffleOfCastops(Instruction &I) {
3008 Value *V0, *V1;
3009 ArrayRef<int> OldMask;
3010 if (!match(&I, m_Shuffle(m_Value(V0), m_Value(V1), m_Mask(OldMask))))
3011 return false;
3012
3013 // Check whether this is a binary shuffle.
3014 bool IsBinaryShuffle = !isa<UndefValue>(V1);
3015
3016 auto *C0 = dyn_cast<CastInst>(V0);
3017 auto *C1 = dyn_cast<CastInst>(V1);
3018 if (!C0 || (IsBinaryShuffle && !C1))
3019 return false;
3020
3021 Instruction::CastOps Opcode = C0->getOpcode();
3022
3023 // If this is allowed, foldShuffleOfCastops can get stuck in a loop
3024 // with foldBitcastOfShuffle. Reject in favor of foldBitcastOfShuffle.
3025 if (!IsBinaryShuffle && Opcode == Instruction::BitCast)
3026 return false;
3027
3028 if (IsBinaryShuffle) {
3029 if (C0->getSrcTy() != C1->getSrcTy())
3030 return false;
3031 // Handle shuffle(zext_nneg(x), sext(y)) -> sext(shuffle(x,y)) folds.
3032 if (Opcode != C1->getOpcode()) {
3033 if (match(C0, m_SExtLike(m_Value())) && match(C1, m_SExtLike(m_Value())))
3034 Opcode = Instruction::SExt;
3035 else
3036 return false;
3037 }
3038 }
3039
3040 auto *ShuffleDstTy = dyn_cast<FixedVectorType>(I.getType());
3041 auto *CastDstTy = dyn_cast<FixedVectorType>(C0->getDestTy());
3042 auto *CastSrcTy = dyn_cast<FixedVectorType>(C0->getSrcTy());
3043 if (!ShuffleDstTy || !CastDstTy || !CastSrcTy)
3044 return false;
3045
3046 unsigned NumSrcElts = CastSrcTy->getNumElements();
3047 unsigned NumDstElts = CastDstTy->getNumElements();
3048 assert((NumDstElts == NumSrcElts || Opcode == Instruction::BitCast) &&
3049 "Only bitcasts expected to alter src/dst element counts");
3050
3051 // Check for bitcasting of unscalable vector types.
3052 // e.g. <32 x i40> -> <40 x i32>
3053 if (NumDstElts != NumSrcElts && (NumSrcElts % NumDstElts) != 0 &&
3054 (NumDstElts % NumSrcElts) != 0)
3055 return false;
3056
3057 SmallVector<int, 16> NewMask;
3058 if (NumSrcElts >= NumDstElts) {
3059 // The bitcast is from wide to narrow/equal elements. The shuffle mask can
3060 // always be expanded to the equivalent form choosing narrower elements.
3061 assert(NumSrcElts % NumDstElts == 0 && "Unexpected shuffle mask");
3062 unsigned ScaleFactor = NumSrcElts / NumDstElts;
3063 narrowShuffleMaskElts(ScaleFactor, OldMask, NewMask);
3064 } else {
3065 // The bitcast is from narrow elements to wide elements. The shuffle mask
3066 // must choose consecutive elements to allow casting first.
3067 assert(NumDstElts % NumSrcElts == 0 && "Unexpected shuffle mask");
3068 unsigned ScaleFactor = NumDstElts / NumSrcElts;
3069 if (!widenShuffleMaskElts(ScaleFactor, OldMask, NewMask))
3070 return false;
3071 }
3072
3073 auto *NewShuffleDstTy =
3074 FixedVectorType::get(CastSrcTy->getScalarType(), NewMask.size());
3075
3076 // Try to replace a castop with a shuffle if the shuffle is not costly.
3077 InstructionCost CostC0 =
3078 TTI.getCastInstrCost(C0->getOpcode(), CastDstTy, CastSrcTy,
3080
3082 if (IsBinaryShuffle)
3084 else
3086
3087 InstructionCost OldCost = CostC0;
3088 OldCost += TTI.getShuffleCost(ShuffleKind, ShuffleDstTy, CastDstTy, CostKind,
3089 OldMask, 0, nullptr, {}, &I);
3090
3091 InstructionCost NewCost = TTI.getShuffleCost(ShuffleKind, NewShuffleDstTy,
3092 CastSrcTy, CostKind, NewMask);
3093 NewCost += TTI.getCastInstrCost(Opcode, ShuffleDstTy, NewShuffleDstTy,
3095 if (!C0->hasOneUse())
3096 NewCost += CostC0;
3097 if (IsBinaryShuffle) {
3098 InstructionCost CostC1 =
3099 TTI.getCastInstrCost(C1->getOpcode(), CastDstTy, CastSrcTy,
3101 OldCost += CostC1;
3102 if (!C1->hasOneUse())
3103 NewCost += CostC1;
3104 }
3105
3106 LLVM_DEBUG(dbgs() << "Found a shuffle feeding two casts: " << I
3107 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
3108 << "\n");
3109 if (NewCost > OldCost)
3110 return false;
3111
3112 Value *Shuf;
3113 if (IsBinaryShuffle)
3114 Shuf = Builder.CreateShuffleVector(C0->getOperand(0), C1->getOperand(0),
3115 NewMask);
3116 else
3117 Shuf = Builder.CreateShuffleVector(C0->getOperand(0), NewMask);
3118
3119 Value *Cast = Builder.CreateCast(Opcode, Shuf, ShuffleDstTy);
3120
3121 // Intersect flags from the old casts.
3122 if (auto *NewInst = dyn_cast<Instruction>(Cast)) {
3123 NewInst->copyIRFlags(C0);
3124 if (IsBinaryShuffle)
3125 NewInst->andIRFlags(C1);
3126 }
3127
3128 Worklist.pushValue(Shuf);
3129 replaceValue(I, *Cast);
3130 return true;
3131}
3132
3133/// Try to convert any of:
3134/// "shuffle (shuffle x, y), (shuffle y, x)"
3135/// "shuffle (shuffle x, undef), (shuffle y, undef)"
3136/// "shuffle (shuffle x, undef), y"
3137/// "shuffle x, (shuffle y, undef)"
3138/// into "shuffle x, y".
3139bool VectorCombine::foldShuffleOfShuffles(Instruction &I) {
3140 ArrayRef<int> OuterMask;
3141 Value *OuterV0, *OuterV1;
3142 if (!match(&I,
3143 m_Shuffle(m_Value(OuterV0), m_Value(OuterV1), m_Mask(OuterMask))))
3144 return false;
3145
3146 ArrayRef<int> InnerMask0, InnerMask1;
3147 Value *X0, *X1, *Y0, *Y1;
3148 bool Match0 =
3149 match(OuterV0, m_Shuffle(m_Value(X0), m_Value(Y0), m_Mask(InnerMask0)));
3150 bool Match1 =
3151 match(OuterV1, m_Shuffle(m_Value(X1), m_Value(Y1), m_Mask(InnerMask1)));
3152 if (!Match0 && !Match1)
3153 return false;
3154
3155 // If the outer shuffle is a permute, then create a fake inner all-poison
3156 // shuffle. This is easier than accounting for length-changing shuffles below.
3157 SmallVector<int, 16> PoisonMask1;
3158 if (!Match1 && isa<PoisonValue>(OuterV1)) {
3159 X1 = X0;
3160 Y1 = Y0;
3161 PoisonMask1.append(InnerMask0.size(), PoisonMaskElem);
3162 InnerMask1 = PoisonMask1;
3163 Match1 = true; // fake match
3164 }
3165
3166 X0 = Match0 ? X0 : OuterV0;
3167 Y0 = Match0 ? Y0 : OuterV0;
3168 X1 = Match1 ? X1 : OuterV1;
3169 Y1 = Match1 ? Y1 : OuterV1;
3170 auto *ShuffleDstTy = dyn_cast<FixedVectorType>(I.getType());
3171 auto *ShuffleSrcTy = dyn_cast<FixedVectorType>(X0->getType());
3172 auto *ShuffleImmTy = dyn_cast<FixedVectorType>(OuterV0->getType());
3173 if (!ShuffleDstTy || !ShuffleSrcTy || !ShuffleImmTy ||
3174 X0->getType() != X1->getType())
3175 return false;
3176
3177 unsigned NumSrcElts = ShuffleSrcTy->getNumElements();
3178 unsigned NumImmElts = ShuffleImmTy->getNumElements();
3179
3180 // Attempt to merge shuffles, matching upto 2 source operands.
3181 // Replace index to a poison arg with PoisonMaskElem.
3182 // Bail if either inner masks reference an undef arg.
3183 SmallVector<int, 16> NewMask(OuterMask);
3184 Value *NewX = nullptr, *NewY = nullptr;
3185 for (int &M : NewMask) {
3186 Value *Src = nullptr;
3187 if (0 <= M && M < (int)NumImmElts) {
3188 Src = OuterV0;
3189 if (Match0) {
3190 M = InnerMask0[M];
3191 Src = M >= (int)NumSrcElts ? Y0 : X0;
3192 M = M >= (int)NumSrcElts ? (M - NumSrcElts) : M;
3193 }
3194 } else if (M >= (int)NumImmElts) {
3195 Src = OuterV1;
3196 M -= NumImmElts;
3197 if (Match1) {
3198 M = InnerMask1[M];
3199 Src = M >= (int)NumSrcElts ? Y1 : X1;
3200 M = M >= (int)NumSrcElts ? (M - NumSrcElts) : M;
3201 }
3202 }
3203 if (Src && M != PoisonMaskElem) {
3204 assert(0 <= M && M < (int)NumSrcElts && "Unexpected shuffle mask index");
3205 if (isa<UndefValue>(Src)) {
3206 // We've referenced an undef element - if its poison, update the shuffle
3207 // mask, else bail.
3208 if (!isa<PoisonValue>(Src))
3209 return false;
3210 M = PoisonMaskElem;
3211 continue;
3212 }
3213 if (!NewX || NewX == Src) {
3214 NewX = Src;
3215 continue;
3216 }
3217 if (!NewY || NewY == Src) {
3218 M += NumSrcElts;
3219 NewY = Src;
3220 continue;
3221 }
3222 return false;
3223 }
3224 }
3225
3226 if (!NewX) {
3227 replaceValue(I, *PoisonValue::get(ShuffleDstTy));
3228 return true;
3229 }
3230
3231 if (!NewY)
3232 NewY = PoisonValue::get(ShuffleSrcTy);
3233
3234 // Have we folded to an Identity shuffle?
3235 if (ShuffleVectorInst::isIdentityMask(NewMask, NumSrcElts)) {
3236 replaceValue(I, *NewX);
3237 return true;
3238 }
3239
3240 // Try to merge the shuffles if the new shuffle is not costly.
3241 InstructionCost InnerCost0 = 0;
3242 if (Match0)
3243 InnerCost0 = TTI.getInstructionCost(cast<User>(OuterV0), CostKind);
3244
3245 InstructionCost InnerCost1 = 0;
3246 if (Match1)
3247 InnerCost1 = TTI.getInstructionCost(cast<User>(OuterV1), CostKind);
3248
3250
3251 InstructionCost OldCost = InnerCost0 + InnerCost1 + OuterCost;
3252
3253 bool IsUnary = all_of(NewMask, [&](int M) { return M < (int)NumSrcElts; });
3257 InstructionCost NewCost =
3258 TTI.getShuffleCost(SK, ShuffleDstTy, ShuffleSrcTy, CostKind, NewMask, 0,
3259 nullptr, {NewX, NewY});
3260 if (!OuterV0->hasOneUse())
3261 NewCost += InnerCost0;
3262 if (!OuterV1->hasOneUse())
3263 NewCost += InnerCost1;
3264
3265 LLVM_DEBUG(dbgs() << "Found a shuffle feeding two shuffles: " << I
3266 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
3267 << "\n");
3268 if (NewCost > OldCost)
3269 return false;
3270
3271 Value *Shuf = Builder.CreateShuffleVector(NewX, NewY, NewMask);
3272 replaceValue(I, *Shuf);
3273 return true;
3274}
3275
3276/// Try to convert a chain of length-preserving shuffles that are fed by
3277/// length-changing shuffles from the same source, e.g. a chain of length 3:
3278///
3279/// "shuffle (shuffle (shuffle x, (shuffle y, undef)),
3280/// (shuffle y, undef)),
3281// (shuffle y, undef)"
3282///
3283/// into a single shuffle fed by a length-changing shuffle:
3284///
3285/// "shuffle x, (shuffle y, undef)"
3286///
3287/// Such chains arise e.g. from folding extract/insert sequences.
3288bool VectorCombine::foldShufflesOfLengthChangingShuffles(Instruction &I) {
3289 FixedVectorType *TrunkType = dyn_cast<FixedVectorType>(I.getType());
3290 if (!TrunkType)
3291 return false;
3292
3293 unsigned ChainLength = 0;
3294 SmallVector<int> Mask;
3295 SmallVector<int> YMask;
3296 InstructionCost OldCost = 0;
3297 InstructionCost NewCost = 0;
3298 Value *Trunk = &I;
3299 unsigned NumTrunkElts = TrunkType->getNumElements();
3300 Value *Y = nullptr;
3301
3302 for (;;) {
3303 // Match the current trunk against (commutations of) the pattern
3304 // "shuffle trunk', (shuffle y, undef)"
3305 ArrayRef<int> OuterMask;
3306 Value *OuterV0, *OuterV1;
3307 if (ChainLength != 0 && !Trunk->hasOneUse())
3308 break;
3309 if (!match(Trunk, m_Shuffle(m_Value(OuterV0), m_Value(OuterV1),
3310 m_Mask(OuterMask))))
3311 break;
3312 if (OuterV0->getType() != TrunkType) {
3313 // This shuffle is not length-preserving, so it cannot be part of the
3314 // chain.
3315 break;
3316 }
3317
3318 ArrayRef<int> InnerMask0, InnerMask1;
3319 Value *A0, *A1, *B0, *B1;
3320 bool Match0 =
3321 match(OuterV0, m_Shuffle(m_Value(A0), m_Value(B0), m_Mask(InnerMask0)));
3322 bool Match1 =
3323 match(OuterV1, m_Shuffle(m_Value(A1), m_Value(B1), m_Mask(InnerMask1)));
3324 bool Match0Leaf = Match0 && A0->getType() != I.getType();
3325 bool Match1Leaf = Match1 && A1->getType() != I.getType();
3326 if (Match0Leaf == Match1Leaf) {
3327 // Only handle the case of exactly one leaf in each step. The "two leaves"
3328 // case is handled by foldShuffleOfShuffles.
3329 break;
3330 }
3331
3332 SmallVector<int> CommutedOuterMask;
3333 if (Match0Leaf) {
3334 std::swap(OuterV0, OuterV1);
3335 std::swap(InnerMask0, InnerMask1);
3336 std::swap(A0, A1);
3337 std::swap(B0, B1);
3338 llvm::append_range(CommutedOuterMask, OuterMask);
3339 for (int &M : CommutedOuterMask) {
3340 if (M == PoisonMaskElem)
3341 continue;
3342 if (M < (int)NumTrunkElts)
3343 M += NumTrunkElts;
3344 else
3345 M -= NumTrunkElts;
3346 }
3347 OuterMask = CommutedOuterMask;
3348 }
3349 if (!OuterV1->hasOneUse())
3350 break;
3351
3352 if (!isa<UndefValue>(A1)) {
3353 if (!Y)
3354 Y = A1;
3355 else if (Y != A1)
3356 break;
3357 }
3358 if (!isa<UndefValue>(B1)) {
3359 if (!Y)
3360 Y = B1;
3361 else if (Y != B1)
3362 break;
3363 }
3364
3365 auto *YType = cast<FixedVectorType>(A1->getType());
3366 int NumLeafElts = YType->getNumElements();
3367 SmallVector<int> LocalYMask(InnerMask1);
3368 for (int &M : LocalYMask) {
3369 if (M >= NumLeafElts)
3370 M -= NumLeafElts;
3371 }
3372
3373 InstructionCost LocalOldCost =
3376
3377 // Handle the initial (start of chain) case.
3378 if (!ChainLength) {
3379 Mask.assign(OuterMask);
3380 YMask.assign(LocalYMask);
3381 OldCost = NewCost = LocalOldCost;
3382 Trunk = OuterV0;
3383 ChainLength++;
3384 continue;
3385 }
3386
3387 // For the non-root case, first attempt to combine masks.
3388 SmallVector<int> NewYMask(YMask);
3389 bool Valid = true;
3390 for (auto [CombinedM, LeafM] : llvm::zip(NewYMask, LocalYMask)) {
3391 if (LeafM == -1 || CombinedM == LeafM)
3392 continue;
3393 if (CombinedM == -1) {
3394 CombinedM = LeafM;
3395 } else {
3396 Valid = false;
3397 break;
3398 }
3399 }
3400 if (!Valid)
3401 break;
3402
3403 SmallVector<int> NewMask;
3404 NewMask.reserve(NumTrunkElts);
3405 for (int M : Mask) {
3406 if (M < 0 || M >= static_cast<int>(NumTrunkElts))
3407 NewMask.push_back(M);
3408 else
3409 NewMask.push_back(OuterMask[M]);
3410 }
3411
3412 // Break the chain if adding this new step complicates the shuffles such
3413 // that it would increase the new cost by more than the old cost of this
3414 // step.
3415 InstructionCost LocalNewCost =
3417 YType, CostKind, NewYMask) +
3419 TrunkType, CostKind, NewMask);
3420
3421 if (LocalNewCost >= NewCost && LocalOldCost < LocalNewCost - NewCost)
3422 break;
3423
3424 LLVM_DEBUG({
3425 if (ChainLength == 1) {
3426 dbgs() << "Found chain of shuffles fed by length-changing shuffles: "
3427 << I << '\n';
3428 }
3429 dbgs() << " next chain link: " << *Trunk << '\n'
3430 << " old cost: " << (OldCost + LocalOldCost)
3431 << " new cost: " << LocalNewCost << '\n';
3432 });
3433
3434 Mask = NewMask;
3435 YMask = NewYMask;
3436 OldCost += LocalOldCost;
3437 NewCost = LocalNewCost;
3438 Trunk = OuterV0;
3439 ChainLength++;
3440 }
3441 if (ChainLength <= 1)
3442 return false;
3443
3444 // Bail out if all leaves were poison.
3445 if (!Y)
3446 return false;
3447
3448 if (llvm::all_of(Mask, [&](int M) {
3449 return M < 0 || M >= static_cast<int>(NumTrunkElts);
3450 })) {
3451 // Produce a canonical simplified form if all elements are sourced from Y.
3452 for (int &M : Mask) {
3453 if (M >= static_cast<int>(NumTrunkElts))
3454 M = YMask[M - NumTrunkElts];
3455 }
3456 Value *Root =
3457 Builder.CreateShuffleVector(Y, PoisonValue::get(Y->getType()), Mask);
3458 replaceValue(I, *Root);
3459 return true;
3460 }
3461
3462 Value *Leaf =
3463 Builder.CreateShuffleVector(Y, PoisonValue::get(Y->getType()), YMask);
3464 Value *Root = Builder.CreateShuffleVector(Trunk, Leaf, Mask);
3465 replaceValue(I, *Root);
3466 return true;
3467}
3468
3469/// Try to convert
3470/// "shuffle (intrinsic), (intrinsic)" into "intrinsic (shuffle), (shuffle)".
3471bool VectorCombine::foldShuffleOfIntrinsics(Instruction &I) {
3472 Value *V0, *V1;
3473 ArrayRef<int> OldMask;
3474 if (!match(&I, m_Shuffle(m_Value(V0), m_Value(V1), m_Mask(OldMask))))
3475 return false;
3476
3477 auto *II0 = dyn_cast<IntrinsicInst>(V0);
3478 auto *II1 = dyn_cast<IntrinsicInst>(V1);
3479 if (!II0 || !II1)
3480 return false;
3481
3482 Intrinsic::ID IID = II0->getIntrinsicID();
3483 if (IID != II1->getIntrinsicID())
3484 return false;
3485 InstructionCost CostII0 =
3486 TTI.getIntrinsicInstrCost(IntrinsicCostAttributes(IID, *II0), CostKind);
3487 InstructionCost CostII1 =
3488 TTI.getIntrinsicInstrCost(IntrinsicCostAttributes(IID, *II1), CostKind);
3489
3490 auto *ShuffleDstTy = dyn_cast<FixedVectorType>(I.getType());
3491 auto *II0Ty = dyn_cast<FixedVectorType>(II0->getType());
3492 if (!ShuffleDstTy || !II0Ty)
3493 return false;
3494
3495 if (!isTriviallyVectorizable(IID))
3496 return false;
3497
3498 for (unsigned Idx = 0, E = II0->arg_size(); Idx != E; ++Idx) {
3499 Value *Arg0 = II0->getArgOperand(Idx);
3500 Value *Arg1 = II1->getArgOperand(Idx);
3501 if (isVectorIntrinsicWithScalarOpAtArg(IID, Idx, &TTI)) {
3502 // Scalar operands must be identical.
3503 if (Arg0 != Arg1)
3504 return false;
3505 } else if (Arg0->getType() != Arg1->getType()) {
3506 // The corresponding vector operands are shuffled together, so they must
3507 // share the same type. For intrinsics overloaded on their operand type
3508 // (e.g. llvm.fptosi.sat), two calls can produce the same result type
3509 // from different operand types; shuffling those would be invalid.
3510 return false;
3511 }
3512 }
3513
3514 InstructionCost OldCost =
3515 CostII0 + CostII1 +
3517 II0Ty, CostKind, OldMask, 0, nullptr, {II0, II1}, &I);
3518
3519 SmallVector<Type *> NewArgsTy;
3520 InstructionCost NewCost = 0;
3521 SmallDenseSet<std::pair<Value *, Value *>> SeenOperandPairs;
3522 for (unsigned Idx = 0, E = II0->arg_size(); Idx != E; ++Idx) {
3523 if (isVectorIntrinsicWithScalarOpAtArg(IID, Idx, &TTI)) {
3524 NewArgsTy.push_back(II0->getArgOperand(Idx)->getType());
3525 } else {
3526 auto *VecTy = cast<FixedVectorType>(II0->getArgOperand(Idx)->getType());
3527 auto *ArgTy = FixedVectorType::get(VecTy->getElementType(),
3528 ShuffleDstTy->getNumElements());
3529 NewArgsTy.push_back(ArgTy);
3530 std::pair<Value *, Value *> OperandPair =
3531 std::make_pair(II0->getArgOperand(Idx), II1->getArgOperand(Idx));
3532 if (!SeenOperandPairs.insert(OperandPair).second) {
3533 // We've already computed the cost for this operand pair.
3534 continue;
3535 }
3536 NewCost += TTI.getShuffleCost(
3538 OldMask, 0, nullptr,
3539 {II0->getArgOperand(Idx), II1->getArgOperand(Idx)});
3540 }
3541 }
3542 IntrinsicCostAttributes NewAttr(IID, ShuffleDstTy, NewArgsTy);
3543
3544 NewCost += TTI.getIntrinsicInstrCost(NewAttr, CostKind);
3545 if (!II0->hasOneUse())
3546 NewCost += CostII0;
3547 if (II1 != II0 && !II1->hasOneUse())
3548 NewCost += CostII1;
3549
3550 LLVM_DEBUG(dbgs() << "Found a shuffle feeding two intrinsics: " << I
3551 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
3552 << "\n");
3553
3554 if (NewCost > OldCost)
3555 return false;
3556
3557 SmallVector<Value *> NewArgs;
3558 SmallDenseMap<std::pair<Value *, Value *>, Value *> ShuffleCache;
3559 for (unsigned Idx = 0, E = II0->arg_size(); Idx != E; ++Idx) {
3560 if (isVectorIntrinsicWithScalarOpAtArg(IID, Idx, &TTI)) {
3561 NewArgs.push_back(II0->getArgOperand(Idx));
3562 } else {
3563 std::pair<Value *, Value *> OperandPair =
3564 std::make_pair(II0->getArgOperand(Idx), II1->getArgOperand(Idx));
3565 auto It = ShuffleCache.find(OperandPair);
3566 if (It != ShuffleCache.end()) {
3567 // Reuse previously created shuffle for this operand pair.
3568 NewArgs.push_back(It->second);
3569 continue;
3570 }
3571 Value *Shuf = Builder.CreateShuffleVector(
3572 II0->getArgOperand(Idx), II1->getArgOperand(Idx), OldMask);
3573 ShuffleCache[OperandPair] = Shuf;
3574 NewArgs.push_back(Shuf);
3575 Worklist.pushValue(Shuf);
3576 }
3577 }
3578 Value *NewIntrinsic = Builder.CreateIntrinsic(ShuffleDstTy, IID, NewArgs);
3579
3580 // Intersect flags from the old intrinsics.
3581 if (auto *NewInst = dyn_cast<Instruction>(NewIntrinsic)) {
3582 NewInst->copyIRFlags(II0);
3583 NewInst->andIRFlags(II1);
3584 }
3585
3586 replaceValue(I, *NewIntrinsic);
3587 return true;
3588}
3589
3590/// Try to convert
3591/// "shuffle (intrinsic), (poison/undef)" into "intrinsic (shuffle)".
3592bool VectorCombine::foldPermuteOfIntrinsic(Instruction &I) {
3593 Value *V0;
3594 ArrayRef<int> Mask;
3595 if (!match(&I, m_Shuffle(m_Value(V0), m_Undef(), m_Mask(Mask))))
3596 return false;
3597
3598 auto *II0 = dyn_cast<IntrinsicInst>(V0);
3599 if (!II0)
3600 return false;
3601
3602 auto *ShuffleDstTy = dyn_cast<FixedVectorType>(I.getType());
3603 auto *IntrinsicSrcTy = dyn_cast<FixedVectorType>(II0->getType());
3604 if (!ShuffleDstTy || !IntrinsicSrcTy)
3605 return false;
3606
3607 // Validate it's a pure permute, mask should only reference the first vector
3608 unsigned NumSrcElts = IntrinsicSrcTy->getNumElements();
3609 if (any_of(Mask, [NumSrcElts](int M) { return M >= (int)NumSrcElts; }))
3610 return false;
3611
3612 Intrinsic::ID IID = II0->getIntrinsicID();
3613 if (!isTriviallyVectorizable(IID))
3614 return false;
3615
3616 // Cost analysis
3618 TTI.getIntrinsicInstrCost(IntrinsicCostAttributes(IID, *II0), CostKind);
3619 InstructionCost OldCost =
3622 IntrinsicSrcTy, CostKind, Mask, 0, nullptr, {V0}, &I);
3623
3624 SmallVector<Type *> NewArgsTy;
3625 InstructionCost NewCost = 0;
3626 for (unsigned I = 0, E = II0->arg_size(); I != E; ++I) {
3628 NewArgsTy.push_back(II0->getArgOperand(I)->getType());
3629 } else {
3630 auto *VecTy = cast<FixedVectorType>(II0->getArgOperand(I)->getType());
3631 auto *ArgTy = FixedVectorType::get(VecTy->getElementType(),
3632 ShuffleDstTy->getNumElements());
3633 NewArgsTy.push_back(ArgTy);
3635 ArgTy, VecTy, CostKind, Mask, 0, nullptr,
3636 {II0->getArgOperand(I)});
3637 }
3638 }
3639 IntrinsicCostAttributes NewAttr(IID, ShuffleDstTy, NewArgsTy);
3640 NewCost += TTI.getIntrinsicInstrCost(NewAttr, CostKind);
3641
3642 // If the intrinsic has multiple uses, we need to account for the cost of
3643 // keeping the original intrinsic around.
3644 if (!II0->hasOneUse())
3645 NewCost += IntrinsicCost;
3646
3647 LLVM_DEBUG(dbgs() << "Found a permute of intrinsic: " << I << "\n OldCost: "
3648 << OldCost << " vs NewCost: " << NewCost << "\n");
3649
3650 if (NewCost > OldCost)
3651 return false;
3652
3653 // Transform
3654 SmallVector<Value *> NewArgs;
3655 for (unsigned I = 0, E = II0->arg_size(); I != E; ++I) {
3657 NewArgs.push_back(II0->getArgOperand(I));
3658 } else {
3659 Value *Shuf = Builder.CreateShuffleVector(II0->getArgOperand(I), Mask);
3660 NewArgs.push_back(Shuf);
3661 Worklist.pushValue(Shuf);
3662 }
3663 }
3664
3665 Value *NewIntrinsic = Builder.CreateIntrinsic(ShuffleDstTy, IID, NewArgs);
3666
3667 if (auto *NewInst = dyn_cast<Instruction>(NewIntrinsic))
3668 NewInst->copyIRFlags(II0);
3669
3670 replaceValue(I, *NewIntrinsic);
3671 return true;
3672}
3673
3674using InstLane = std::pair<Value *, int>;
3675
3676static InstLane lookThroughShuffles(Value *V, int Lane) {
3677 while (auto *SV = dyn_cast<ShuffleVectorInst>(V)) {
3678 unsigned NumElts =
3679 cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
3680 int M = SV->getMaskValue(Lane);
3681 if (M < 0)
3682 return {nullptr, PoisonMaskElem};
3683 if (static_cast<unsigned>(M) < NumElts) {
3684 V = SV->getOperand(0);
3685 Lane = M;
3686 } else {
3687 V = SV->getOperand(1);
3688 Lane = M - NumElts;
3689 }
3690 }
3691 return InstLane{V, Lane};
3692}
3693
3697 for (InstLane IL : Item) {
3698 auto [U, Lane] = IL;
3699 InstLane OpLane =
3700 U ? lookThroughShuffles(cast<Instruction>(U)->getOperand(Op), Lane)
3701 : InstLane{nullptr, PoisonMaskElem};
3702 NItem.emplace_back(OpLane);
3703 }
3704 return NItem;
3705}
3706
3707/// Detect concat of multiple values into a vector
3709 const TargetTransformInfo &TTI) {
3710 auto *Ty = cast<FixedVectorType>(Item.front().first->getType());
3711 unsigned NumElts = Ty->getNumElements();
3712 if (Item.size() == NumElts || NumElts == 1 || Item.size() % NumElts != 0)
3713 return false;
3714
3715 // Check that the concat is free, usually meaning that the type will be split
3716 // during legalization.
3717 SmallVector<int, 16> ConcatMask(NumElts * 2);
3718 std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
3719 if (TTI.getShuffleCost(TTI::SK_PermuteTwoSrc,
3720 FixedVectorType::get(Ty->getScalarType(), NumElts * 2),
3721 Ty, CostKind, ConcatMask) != 0)
3722 return false;
3723
3724 unsigned NumSlices = Item.size() / NumElts;
3725 // Currently we generate a tree of shuffles for the concats, which limits us
3726 // to a power2.
3727 if (!isPowerOf2_32(NumSlices))
3728 return false;
3729 for (unsigned Slice = 0; Slice < NumSlices; ++Slice) {
3730 Value *SliceV = Item[Slice * NumElts].first;
3731 if (!SliceV || SliceV->getType() != Ty)
3732 return false;
3733 for (unsigned Elt = 0; Elt < NumElts; ++Elt) {
3734 auto [V, Lane] = Item[Slice * NumElts + Elt];
3735 if (Lane != static_cast<int>(Elt) || SliceV != V)
3736 return false;
3737 }
3738 }
3739 return true;
3740}
3741
3742static Value *
3744 const DenseSet<std::pair<Value *, Use *>> &IdentityLeafs,
3745 const DenseSet<std::pair<Value *, Use *>> &SplatLeafs,
3746 const DenseSet<std::pair<Value *, Use *>> &ConcatLeafs,
3747 IRBuilderBase &Builder, InstructionWorklist &WorkList,
3748 const TargetTransformInfo *TTI) {
3749 auto [FrontV, FrontLane] = Item.front();
3750
3751 if (IdentityLeafs.contains(std::make_pair(FrontV, From))) {
3752 return FrontV;
3753 }
3754 if (SplatLeafs.contains(std::make_pair(FrontV, From))) {
3755 SmallVector<int, 16> Mask(Item.size(), FrontLane);
3756 return Builder.CreateShuffleVector(FrontV, Mask);
3757 }
3758 if (ConcatLeafs.contains(std::make_pair(FrontV, From))) {
3759 unsigned NumElts =
3760 cast<FixedVectorType>(FrontV->getType())->getNumElements();
3761 SmallVector<Value *> Values(Item.size() / NumElts, nullptr);
3762 for (unsigned S = 0; S < Values.size(); ++S)
3763 Values[S] = Item[S * NumElts].first;
3764
3765 while (Values.size() > 1) {
3766 NumElts *= 2;
3767 SmallVector<int, 16> Mask(NumElts, 0);
3768 std::iota(Mask.begin(), Mask.end(), 0);
3769 SmallVector<Value *> NewValues(Values.size() / 2, nullptr);
3770 for (unsigned S = 0; S < NewValues.size(); ++S)
3771 NewValues[S] =
3772 Builder.CreateShuffleVector(Values[S * 2], Values[S * 2 + 1], Mask);
3773 Values = NewValues;
3774 }
3775 return Values[0];
3776 }
3777
3778 auto *I = cast<Instruction>(FrontV);
3779
3780 // Handle vector bitcasts that change element count. We cannot use
3781 // generateInstLaneVectorFromOperand for these because the lane indices
3782 // don't map 1:1 through the bitcast.
3783 if (auto *BitCast = dyn_cast<BitCastInst>(I)) {
3784 auto *BCDstTy = dyn_cast<FixedVectorType>(BitCast->getDestTy());
3785 auto *BCSrcTy = dyn_cast<FixedVectorType>(BitCast->getSrcTy());
3786 if (BCDstTy && BCSrcTy &&
3787 BCDstTy->getElementCount() != BCSrcTy->getElementCount()) {
3788 unsigned DstElts = BCDstTy->getNumElements();
3789 unsigned SrcElts = BCSrcTy->getNumElements();
3790 SmallVector<InstLane> NewItem;
3791 if (DstElts > SrcElts) {
3792 // Widening: compress operand Item.
3793 unsigned R = DstElts / SrcElts;
3794 if (Item.size() % R != 0)
3795 return nullptr;
3796 for (unsigned Idx = 0, E = Item.size(); Idx < E; Idx += R) {
3797 auto [V, Lane] = Item[Idx];
3798 if (!V) {
3799 NewItem.push_back({nullptr, PoisonMaskElem});
3800 continue;
3801 }
3802 NewItem.push_back(
3803 lookThroughShuffles(cast<Operator>(V)->getOperand(0), Lane / R));
3804 }
3805 } else {
3806 // Narrowing: expand operand Item.
3807 unsigned R = SrcElts / DstElts;
3808 for (auto [V, Lane] : Item) {
3809 if (!V) {
3810 NewItem.append(R, {nullptr, PoisonMaskElem});
3811 continue;
3812 }
3813 Value *Op = cast<Operator>(V)->getOperand(0);
3814 for (unsigned J = 0; J < R; ++J)
3815 NewItem.push_back(lookThroughShuffles(Op, Lane * R + J));
3816 }
3817 }
3818 Value *Op = generateNewInstTree(NewItem, &BitCast->getOperandUse(0),
3819 IdentityLeafs, SplatLeafs, ConcatLeafs,
3820 Builder, WorkList, TTI);
3821 WorkList.pushValue(Op);
3822 return Builder.CreateBitCast(
3823 Op, FixedVectorType::get(BCDstTy->getScalarType(), Item.size()));
3824 }
3825 }
3826 auto *II = dyn_cast<IntrinsicInst>(I);
3827 unsigned NumOps = I->getNumOperands() - (II ? 1 : 0);
3829 for (unsigned Idx = 0; Idx < NumOps; Idx++) {
3830 if (II &&
3831 isVectorIntrinsicWithScalarOpAtArg(II->getIntrinsicID(), Idx, TTI)) {
3832 Ops[Idx] = II->getOperand(Idx);
3833 continue;
3834 }
3835 Ops[Idx] = generateNewInstTree(
3836 generateInstLaneVectorFromOperand(Item, Idx), &I->getOperandUse(Idx),
3837 IdentityLeafs, SplatLeafs, ConcatLeafs, Builder, WorkList, TTI);
3838 // Don't re-queue the operand of a bitcast we just regenerated. Doing so
3839 // lets foldBitcastShuffle sink the bitcast back into a shuffle(bitcast),
3840 // which foldShuffleToIdentity then re-matches as the same superfluous
3841 // identity - an infinite loop between the two folds.
3842 if (!isa<BitCastInst>(I))
3843 WorkList.pushValue(Ops[Idx]);
3844 }
3845
3846 SmallVector<Value *, 8> ValueList;
3847 for (const auto &Lane : Item)
3848 if (Lane.first)
3849 ValueList.push_back(Lane.first);
3850
3851 Type *DstTy =
3852 FixedVectorType::get(I->getType()->getScalarType(), Item.size());
3853 if (auto *BI = dyn_cast<BinaryOperator>(I)) {
3854 auto *Value = Builder.CreateBinOp((Instruction::BinaryOps)BI->getOpcode(),
3855 Ops[0], Ops[1]);
3856 propagateIRFlags(Value, ValueList);
3857 return Value;
3858 }
3859 if (auto *CI = dyn_cast<CmpInst>(I)) {
3860 auto *Value = Builder.CreateCmp(CI->getPredicate(), Ops[0], Ops[1]);
3861 propagateIRFlags(Value, ValueList);
3862 return Value;
3863 }
3864 if (auto *SI = dyn_cast<SelectInst>(I)) {
3865 auto *Value = Builder.CreateSelect(Ops[0], Ops[1], Ops[2], "", SI);
3866 propagateIRFlags(Value, ValueList);
3867 return Value;
3868 }
3869 if (auto *CI = dyn_cast<CastInst>(I)) {
3870 auto *Value = Builder.CreateCast(CI->getOpcode(), Ops[0], DstTy);
3871 propagateIRFlags(Value, ValueList);
3872 return Value;
3873 }
3874 if (II) {
3875 auto *Value = Builder.CreateIntrinsic(DstTy, II->getIntrinsicID(), Ops);
3876 propagateIRFlags(Value, ValueList);
3877 return Value;
3878 }
3879 assert(isa<UnaryInstruction>(I) && "Unexpected instruction type in Generate");
3880 auto *Value =
3881 Builder.CreateUnOp((Instruction::UnaryOps)I->getOpcode(), Ops[0]);
3882 propagateIRFlags(Value, ValueList);
3883 return Value;
3884}
3885
3886// Starting from a shuffle, look up through operands tracking the shuffled index
3887// of each lane. If we can simplify away the shuffles to identities then
3888// do so.
3889bool VectorCombine::foldShuffleToIdentity(Instruction &I) {
3890 auto *Ty = dyn_cast<FixedVectorType>(I.getType());
3891 if (!Ty || I.use_empty())
3892 return false;
3893
3894 SmallVector<InstLane> Start(Ty->getNumElements());
3895 for (unsigned M = 0, E = Ty->getNumElements(); M < E; ++M)
3896 Start[M] = lookThroughShuffles(&I, M);
3897
3899 Candidates.push_back(std::make_pair(Start, &*I.use_begin()));
3900 DenseSet<std::pair<Value *, Use *>> IdentityLeafs, SplatLeafs, ConcatLeafs;
3901 unsigned NumVisited = 0;
3902 bool TraversedElCountChangingBitcast = false;
3903
3904 while (!Candidates.empty()) {
3905 if (++NumVisited > MaxInstrsToScan)
3906 return false;
3907
3908 auto ItemFrom = Candidates.pop_back_val();
3909 auto Item = ItemFrom.first;
3910 auto From = ItemFrom.second;
3911 auto [FrontV, FrontLane] = Item.front();
3912
3913 // If we found an undef first lane then bail out to keep things simple.
3914 if (!FrontV)
3915 return false;
3916
3917 // Look for an identity value.
3918 if (FrontLane == 0 &&
3919 cast<FixedVectorType>(FrontV->getType())->getNumElements() ==
3920 Item.size() &&
3921 all_of(drop_begin(enumerate(Item)), [Item](const auto &E) {
3922 Value *FrontV = Item.front().first;
3923 return !E.value().first || (isEquivBitcast(E.value().first, FrontV) &&
3924 E.value().second == (int)E.index());
3925 })) {
3926 IdentityLeafs.insert(std::make_pair(FrontV, From));
3927 continue;
3928 }
3929 // Look for constants, for the moment only supporting constant splats.
3930 if (auto *C = dyn_cast<Constant>(FrontV);
3931 C && C->getSplatValue() &&
3932 all_of(drop_begin(Item), [Item](InstLane &IL) {
3933 Value *FrontV = Item.front().first;
3934 Value *V = IL.first;
3935 return !V || (isa<Constant>(V) &&
3936 cast<Constant>(V)->getSplatValue() ==
3937 cast<Constant>(FrontV)->getSplatValue());
3938 })) {
3939 SplatLeafs.insert(std::make_pair(FrontV, From));
3940 continue;
3941 }
3942 // Look for a splat value.
3943 if (all_of(drop_begin(Item), [Item](InstLane &IL) {
3944 auto [FrontV, FrontLane] = Item.front();
3945 auto [V, Lane] = IL;
3946 return !V || (V == FrontV && Lane == FrontLane);
3947 })) {
3948 SplatLeafs.insert(std::make_pair(FrontV, From));
3949 continue;
3950 }
3951
3952 // We need each element to be the same type of value, and check that each
3953 // element has a single use.
3954 auto CheckLaneIsEquivalentToFirst = [Item](InstLane IL) {
3955 Value *FrontV = Item.front().first;
3956 if (!IL.first)
3957 return true;
3958 Value *V = IL.first;
3959 if (auto *I = dyn_cast<Instruction>(V); I && !I->hasOneUser())
3960 return false;
3961 if (V->getValueID() != FrontV->getValueID())
3962 return false;
3963 if (auto *CI = dyn_cast<CmpInst>(V))
3964 if (CI->getPredicate() != cast<CmpInst>(FrontV)->getPredicate())
3965 return false;
3966 if (auto *CI = dyn_cast<CastInst>(V))
3967 if (CI->getSrcTy()->getScalarType() !=
3968 cast<CastInst>(FrontV)->getSrcTy()->getScalarType())
3969 return false;
3970 if (auto *SI = dyn_cast<SelectInst>(V))
3971 if (!isa<VectorType>(SI->getOperand(0)->getType()) ||
3972 SI->getOperand(0)->getType() !=
3973 cast<SelectInst>(FrontV)->getOperand(0)->getType())
3974 return false;
3975 if (isa<CallInst>(V) && !isa<IntrinsicInst>(V))
3976 return false;
3977 auto *II = dyn_cast<IntrinsicInst>(V);
3978 return !II || (isa<IntrinsicInst>(FrontV) &&
3979 II->getIntrinsicID() ==
3980 cast<IntrinsicInst>(FrontV)->getIntrinsicID() &&
3981 !II->hasOperandBundles());
3982 };
3983 if (all_of(drop_begin(Item), CheckLaneIsEquivalentToFirst)) {
3984 // Check the operator is one that we support.
3985 if (isa<BinaryOperator, CmpInst>(FrontV)) {
3986 // We exclude div/rem in case they hit UB from poison lanes.
3987 if (auto *BO = dyn_cast<BinaryOperator>(FrontV);
3988 BO && BO->isIntDivRem())
3989 return false;
3991 &cast<Instruction>(FrontV)->getOperandUse(0));
3993 &cast<Instruction>(FrontV)->getOperandUse(1));
3994 continue;
3995 } else if (isa<UnaryOperator, TruncInst, ZExtInst, SExtInst, FPToSIInst,
3996 FPToUIInst, SIToFPInst, UIToFPInst>(FrontV)) {
3998 &cast<Instruction>(FrontV)->getOperandUse(0));
3999 continue;
4000 } else if (auto *BitCast = dyn_cast<BitCastInst>(FrontV)) {
4001 auto *BCDstTy = dyn_cast<FixedVectorType>(BitCast->getDestTy());
4002 auto *BCSrcTy = dyn_cast<FixedVectorType>(BitCast->getSrcTy());
4003 if (BCDstTy && BCSrcTy) {
4004 ElementCount DstEC = BCDstTy->getElementCount();
4005 ElementCount SrcEC = BCSrcTy->getElementCount();
4006 if (DstEC == SrcEC) {
4007 // Same element count - simple pass-through.
4009 &BitCast->getOperandUse(0));
4010 continue;
4011 }
4012 unsigned DstElts = DstEC.getFixedValue();
4013 unsigned SrcElts = SrcEC.getFixedValue();
4014 if (DstElts > SrcElts && DstElts % SrcElts == 0) {
4015 // Widening bitcast (e.g. <2 x i32> -> <4 x i16>). Compress
4016 // consecutive groups of R destination lanes into one source
4017 // lane.
4018 unsigned R = DstElts / SrcElts;
4020 bool Valid = Item.size() % R == 0;
4021 for (unsigned Idx = 0, E = Item.size(); Valid && Idx < E;
4022 Idx += R) {
4023 auto [V0, L0] = Item[Idx];
4024 if (!V0) {
4025 if (any_of(ArrayRef(Item).slice(Idx + 1, R - 1),
4026 [](InstLane IL) { return IL.first != nullptr; })) {
4027 Valid = false;
4028 break;
4029 }
4030 NItem.push_back({nullptr, PoisonMaskElem});
4031 continue;
4032 }
4033 if (L0 % R != 0) {
4034 Valid = false;
4035 break;
4036 }
4037 for (unsigned J = 1; J < R; ++J) {
4038 auto [VJ, LJ] = Item[Idx + J];
4039 if (!VJ || VJ != V0 || LJ != L0 + (int)J) {
4040 Valid = false;
4041 break;
4042 }
4043 }
4044 if (!Valid)
4045 break;
4047 cast<Operator>(V0)->getOperand(0), L0 / R));
4048 }
4049 if (Valid) {
4050 TraversedElCountChangingBitcast = true;
4051 Candidates.emplace_back(NItem, &BitCast->getOperandUse(0));
4052 continue;
4053 }
4054 } else if (SrcElts > DstElts && SrcElts % DstElts == 0) {
4055 // Narrowing bitcast (e.g. <4 x i16> -> <2 x i32>). Expand
4056 // each destination lane into R source lanes.
4057 unsigned R = SrcElts / DstElts;
4059 for (auto [V, Lane] : Item) {
4060 if (!V) {
4061 NItem.append(R, {nullptr, PoisonMaskElem});
4062 continue;
4063 }
4064 Value *Op = cast<Operator>(V)->getOperand(0);
4065 for (unsigned J = 0; J < R; ++J)
4066 NItem.push_back(lookThroughShuffles(Op, Lane * R + J));
4067 }
4068 TraversedElCountChangingBitcast = true;
4069 Candidates.emplace_back(NItem, &BitCast->getOperandUse(0));
4070 continue;
4071 }
4072 }
4073 } else if (auto *Sel = dyn_cast<SelectInst>(FrontV)) {
4075 &Sel->getOperandUse(0));
4077 &Sel->getOperandUse(1));
4079 &Sel->getOperandUse(2));
4080 continue;
4081 } else if (auto *II = dyn_cast<IntrinsicInst>(FrontV);
4082 II && isTriviallyVectorizable(II->getIntrinsicID()) &&
4083 !II->hasOperandBundles()) {
4084 for (unsigned Op = 0, E = II->getNumOperands() - 1; Op < E; Op++) {
4085 if (isVectorIntrinsicWithScalarOpAtArg(II->getIntrinsicID(), Op,
4086 &TTI)) {
4087 if (!all_of(drop_begin(Item), [Item, Op](InstLane &IL) {
4088 Value *FrontV = Item.front().first;
4089 Value *V = IL.first;
4090 return !V || (cast<Instruction>(V)->getOperand(Op) ==
4091 cast<Instruction>(FrontV)->getOperand(Op));
4092 }))
4093 return false;
4094 continue;
4095 }
4096 Candidates.emplace_back(
4098 &cast<Instruction>(FrontV)->getOperandUse(Op));
4099 }
4100 continue;
4101 }
4102 }
4103
4104 if (isFreeConcat(Item, CostKind, TTI)) {
4105 ConcatLeafs.insert(std::make_pair(FrontV, From));
4106 continue;
4107 }
4108
4109 return false;
4110 }
4111
4112 if (NumVisited <= 1)
4113 return false;
4114
4115 // If the only non-leaf node traversed was a single bitcast that changes
4116 // element count, the fold would just commute the bitcast and shuffle.
4117 // foldBitcastShuffle does the reverse transform, causing an infinite loop.
4118 if (NumVisited == 2 && TraversedElCountChangingBitcast)
4119 return false;
4120
4121 LLVM_DEBUG(dbgs() << "Found a superfluous identity shuffle: " << I << "\n");
4122
4123 // If we got this far, we know the shuffles are superfluous and can be
4124 // removed. Scan through again and generate the new tree of instructions.
4125 Builder.SetInsertPoint(&I);
4126 Value *V =
4127 generateNewInstTree(Start, &*I.use_begin(), IdentityLeafs, SplatLeafs,
4128 ConcatLeafs, Builder, Worklist, &TTI);
4129 replaceValue(I, *V);
4130 return true;
4131}
4132
4133/// Given a commutative reduction, the order of the input lanes does not alter
4134/// the results. We can use this to remove certain shuffles feeding the
4135/// reduction, removing the need to shuffle at all.
4136bool VectorCombine::foldShuffleFromReductions(Instruction &I) {
4137 auto *II = dyn_cast<IntrinsicInst>(&I);
4138 if (!II)
4139 return false;
4140 switch (II->getIntrinsicID()) {
4141 case Intrinsic::vector_reduce_add:
4142 case Intrinsic::vector_reduce_mul:
4143 case Intrinsic::vector_reduce_and:
4144 case Intrinsic::vector_reduce_or:
4145 case Intrinsic::vector_reduce_xor:
4146 case Intrinsic::vector_reduce_smin:
4147 case Intrinsic::vector_reduce_smax:
4148 case Intrinsic::vector_reduce_umin:
4149 case Intrinsic::vector_reduce_umax:
4150 break;
4151 default:
4152 return false;
4153 }
4154
4155 // Find all the inputs when looking through operations that do not alter the
4156 // lane order (binops, for example). Currently we look for a single shuffle,
4157 // and can ignore splat values.
4158 std::queue<Value *> Worklist;
4159 SmallPtrSet<Value *, 4> Visited;
4160 ShuffleVectorInst *Shuffle = nullptr;
4161 if (auto *Op = dyn_cast<Instruction>(I.getOperand(0)))
4162 Worklist.push(Op);
4163
4164 while (!Worklist.empty()) {
4165 Value *CV = Worklist.front();
4166 Worklist.pop();
4167 if (Visited.contains(CV))
4168 continue;
4169
4170 // Splats don't change the order, so can be safely ignored.
4171 if (isSplatValue(CV))
4172 continue;
4173
4174 Visited.insert(CV);
4175
4176 if (auto *CI = dyn_cast<Instruction>(CV)) {
4177 if (CI->isBinaryOp()) {
4178 for (auto *Op : CI->operand_values())
4179 Worklist.push(Op);
4180 continue;
4181 } else if (auto *SV = dyn_cast<ShuffleVectorInst>(CI)) {
4182 if (Shuffle && Shuffle != SV)
4183 return false;
4184 Shuffle = SV;
4185 continue;
4186 }
4187 }
4188
4189 // Anything else is currently an unknown node.
4190 return false;
4191 }
4192
4193 if (!Shuffle)
4194 return false;
4195
4196 // Check all uses of the binary ops and shuffles are also included in the
4197 // lane-invariant operations (Visited should be the list of lanewise
4198 // instructions, including the shuffle that we found).
4199 for (auto *V : Visited)
4200 for (auto *U : V->users())
4201 if (!Visited.contains(U) && U != &I)
4202 return false;
4203
4204 FixedVectorType *VecType =
4205 dyn_cast<FixedVectorType>(II->getOperand(0)->getType());
4206 if (!VecType)
4207 return false;
4208 FixedVectorType *ShuffleInputType =
4210 if (!ShuffleInputType)
4211 return false;
4212 unsigned NumInputElts = ShuffleInputType->getNumElements();
4213
4214 // Find the mask from sorting the lanes into order. This is most likely to
4215 // become a identity or concat mask. Undef elements are pushed to the end.
4216 SmallVector<int> ConcatMask;
4217 Shuffle->getShuffleMask(ConcatMask);
4218 sort(ConcatMask, [](int X, int Y) { return (unsigned)X < (unsigned)Y; });
4219 bool UsesSecondVec =
4220 any_of(ConcatMask, [&](int M) { return M >= (int)NumInputElts; });
4221
4223 UsesSecondVec ? TTI::SK_PermuteTwoSrc : TTI::SK_PermuteSingleSrc, VecType,
4224 ShuffleInputType, CostKind, Shuffle->getShuffleMask());
4226 UsesSecondVec ? TTI::SK_PermuteTwoSrc : TTI::SK_PermuteSingleSrc, VecType,
4227 ShuffleInputType, CostKind, ConcatMask);
4228
4229 LLVM_DEBUG(dbgs() << "Found a reduction feeding from a shuffle: " << *Shuffle
4230 << "\n");
4231 LLVM_DEBUG(dbgs() << " OldCost: " << OldCost << " vs NewCost: " << NewCost
4232 << "\n");
4233 bool MadeChanges = false;
4234 if (NewCost < OldCost) {
4235 Builder.SetInsertPoint(Shuffle);
4236 Value *NewShuffle = Builder.CreateShuffleVector(
4237 Shuffle->getOperand(0), Shuffle->getOperand(1), ConcatMask);
4238 LLVM_DEBUG(dbgs() << "Created new shuffle: " << *NewShuffle << "\n");
4239 replaceValue(*Shuffle, *NewShuffle);
4240 return true;
4241 }
4242
4243 // See if we can re-use foldSelectShuffle, getting it to reduce the size of
4244 // the shuffle into a nicer order, as it can ignore the order of the shuffles.
4245 MadeChanges |= foldSelectShuffle(*Shuffle, true);
4246 return MadeChanges;
4247}
4248
4249/// Try to fold a chain of shuffles and ops feeding extractelement(..., 0)
4250/// into llvm.vector.reduce.*, by tracking which lanes contribute to the
4251/// extracted lane and reducing the widest vector whose lanes each contribute
4252/// once.
4253///
4254/// For example:
4255///
4256/// %lo = shufflevector <4 x i32> %a, poison, <2 x i32> <i32 0, i32 1>
4257/// %hi = shufflevector <4 x i32> %a, poison, <2 x i32> <i32 2, i32 3>
4258/// %s = add <2 x i32> %lo, %hi
4259/// %sh = shufflevector <2 x i32> %s, poison, <2 x i32> <i32 1, i32 poison>
4260/// %r = add <2 x i32> %s, %sh
4261/// %e = extractelement <2 x i32> %r, i64 0
4262///
4263/// transforms to:
4264///
4265/// %e = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %a)
4266bool VectorCombine::foldShuffleChainsToReduce(Instruction &I) {
4267 Value *VecOpEE;
4268 if (!match(&I, m_ExtractElt(m_Value(VecOpEE), m_Zero())))
4269 return false;
4270
4271 auto *FVT = dyn_cast<FixedVectorType>(VecOpEE->getType());
4272 if (!FVT)
4273 return false;
4274
4275 if (FVT->getNumElements() < 2)
4276 return false;
4277
4278 std::optional<Instruction::BinaryOps> CommonBinOp;
4279 std::optional<Intrinsic::ID> CommonCallOp;
4280
4281 if (auto *BO = dyn_cast<BinaryOperator>(VecOpEE)) {
4282 if (!getReductionForBinop(BO->getOpcode()))
4283 return false;
4284 CommonBinOp = BO->getOpcode();
4285 } else if (auto *MMI = dyn_cast<MinMaxIntrinsic>(VecOpEE)) {
4286 CommonCallOp = MMI->getIntrinsicID();
4287 } else {
4288 return false;
4289 }
4290
4291 // For floating-point reductions, track FMF intersection across all binops.
4292 FastMathFlags CommonFMF;
4293 bool IsFloatReduction = false;
4294
4295 // A chain node is one we walk through, either a matching-opcode binop/min-max
4296 // or a single-source shuffle. Anything else is a leaf source.
4297 auto IsChainNode = [&](Value *V) {
4298 if (auto *BO = dyn_cast<BinaryOperator>(V))
4299 return CommonBinOp && BO->getOpcode() == *CommonBinOp;
4300 if (auto *MMI = dyn_cast<MinMaxIntrinsic>(V))
4301 return CommonCallOp && MMI->getIntrinsicID() == *CommonCallOp;
4302 if (auto *SVI = dyn_cast<ShuffleVectorInst>(V))
4303 return isa<PoisonValue>(SVI->getOperand(1));
4304 return false;
4305 };
4306
4307 // Collect the chain, building Nodes in postorder. Bail if the chain is empty
4308 // or exceeds MaxChainNodes.
4309 constexpr unsigned MaxChainNodes = 32;
4310 SmallSetVector<Value *, 16> Nodes;
4311 SmallSetVector<Value *, 4> Sources;
4312 unsigned NumVisited = 0;
4313 auto AddSource = [&](Value *V) {
4314 if (!isa<FixedVectorType>(V->getType()))
4315 return false;
4316 Sources.insert(V);
4317 return true;
4318 };
4319 auto Walk = [&](Value *V, auto &&Walk) -> bool {
4320 if (Nodes.contains(V) || Sources.contains(V))
4321 return true;
4322 if (++NumVisited > MaxChainNodes)
4323 return false;
4324 if (!IsChainNode(V))
4325 return AddSource(V);
4326 // Chain shuffles always have poison as op1, so only op0 matters.
4327 auto *U = cast<Instruction>(V);
4328 unsigned NumOps = isa<ShuffleVectorInst>(U) ? 1 : 2;
4329 for (unsigned I = 0; I != NumOps; ++I)
4330 if (!Walk(U->getOperand(I), Walk))
4331 return false;
4332 if (isa<ShuffleVectorInst>(U) || Nodes.contains(U->getOperand(0)) ||
4333 Nodes.contains(U->getOperand(1))) {
4334 Nodes.insert(V);
4335 return true;
4336 }
4337 // Both operands are leaves so treat this binop as a source rather than
4338 // walking into it.
4339 return AddSource(V);
4340 };
4341 if (!Walk(VecOpEE, Walk) || Nodes.empty())
4342 return false;
4343
4344 bool IsIdempotent =
4345 CommonCallOp || (CommonBinOp && Instruction::isIdempotent(*CommonBinOp));
4346
4347 // For FP reductions, require reassoc on every binop and collect FMF.
4348 for (Value *V : Nodes) {
4349 auto *BinOp = dyn_cast<BinaryOperator>(V);
4350 if (!BinOp || !BinOp->getType()->isFPOrFPVectorTy())
4351 continue;
4352 if (!BinOp->hasAllowReassoc())
4353 return false;
4354 if (!IsFloatReduction) {
4355 CommonFMF = BinOp->getFastMathFlags();
4356 IsFloatReduction = true;
4357 } else {
4358 CommonFMF &= BinOp->getFastMathFlags();
4359 }
4360 }
4361
4362 // Top-down demanded elements. For each chain value, track which lanes feed
4363 // the extracted lane 0 and which feed it more than once. Reverse postorder
4364 // visits every use before its value. A binop forwards its demand to both
4365 // operands and a shuffle follows its mask back to the source lane.
4366 struct Demand {
4367 APInt Lanes;
4368 APInt Duplicates;
4369 };
4370 DenseMap<Value *, Demand> Demands;
4371 auto DemandOf = [&](Value *V) -> Demand & {
4372 unsigned N = cast<FixedVectorType>(V->getType())->getNumElements();
4373 Demand &D = Demands[V];
4374 if (D.Lanes.getBitWidth() != N)
4375 D.Lanes = D.Duplicates = APInt::getZero(N);
4376 return D;
4377 };
4378 DemandOf(VecOpEE).Lanes.setBit(0);
4379 for (Value *V : reverse(Nodes)) {
4380 Demand DV = Demands.lookup(V);
4381 if (DV.Lanes.isZero())
4382 continue;
4383 if (auto *SVI = dyn_cast<ShuffleVectorInst>(V)) {
4384 ArrayRef<int> Mask = SVI->getShuffleMask();
4385 Demand &DS = DemandOf(SVI->getOperand(0));
4386 for (unsigned I = 0, E = Mask.size(); I != E; ++I) {
4387 // Skip lanes that are undemanded or map to poison.
4388 if (!DV.Lanes[I] || Mask[I] < 0 ||
4389 (unsigned)Mask[I] >= DS.Lanes.getBitWidth())
4390 continue;
4391 if (DS.Lanes[Mask[I]] || DV.Duplicates[I])
4392 DS.Duplicates.setBit(Mask[I]);
4393 DS.Lanes.setBit(Mask[I]);
4394 }
4395 } else {
4396 auto *U = cast<User>(V);
4397 for (Value *Op : {U->getOperand(0), U->getOperand(1)}) {
4398 Demand &DOp = DemandOf(Op);
4399 // Lanes demanded through more than one path accumulate in Duplicates.
4400 DOp.Duplicates |= DV.Duplicates | (DOp.Lanes & DV.Lanes);
4401 DOp.Lanes |= DV.Lanes;
4402 }
4403 }
4404 }
4405
4406 // Reducing V replaces the entire chain, so every contribution to the result
4407 // must flow through V. Reject if anything above V reads outside the chain.
4408 auto CoversChain = [&](Value *V) {
4409 SmallVector<Value *, 8> Worklist(1, VecOpEE);
4410 SmallPtrSet<Value *, 8> Seen;
4411 Seen.insert(VecOpEE);
4412 while (!Worklist.empty()) {
4413 auto *U = cast<Instruction>(Worklist.pop_back_val());
4414 unsigned NumOps = isa<ShuffleVectorInst>(U) ? 1 : 2;
4415 for (unsigned I = 0; I != NumOps; ++I) {
4416 Value *Op = U->getOperand(I);
4417 if (Op == V || !Seen.insert(Op).second)
4418 continue;
4419 if (!Nodes.contains(Op))
4420 return false;
4421 Worklist.push_back(Op);
4422 }
4423 }
4424 return true;
4425 };
4426
4427 // Reduce a single cleanly demanded source if there is one, otherwise the
4428 // deepest intermediate that covers the chain.
4429 struct ReductionCut {
4430 Value *Src;
4431 APInt Elts;
4432 };
4433 std::optional<ReductionCut> Cut;
4434 for (Value *S : Sources) {
4435 auto It = Demands.find(S);
4436 if (It == Demands.end() || It->second.Lanes.isZero())
4437 continue;
4438 if (!IsIdempotent && !It->second.Duplicates.isZero()) {
4439 Cut.reset();
4440 break;
4441 }
4442 if (!Cut) {
4443 Cut = ReductionCut{S, It->second.Lanes};
4444 continue;
4445 }
4446 if (!isEquivBitcast(Cut->Src, S)) {
4447 Cut.reset();
4448 break;
4449 }
4450 if (!IsIdempotent && !(Cut->Elts & It->second.Lanes).isZero()) {
4451 Cut.reset();
4452 break;
4453 }
4454 Cut->Elts |= It->second.Lanes;
4455 }
4456 if (!Cut) {
4457 for (Value *V : Nodes) {
4459 continue;
4460 auto It = Demands.find(V);
4461 if (It == Demands.end() || !It->second.Lanes.isAllOnes())
4462 continue;
4463 if (!IsIdempotent && !It->second.Duplicates.isZero())
4464 continue;
4465 if (!CoversChain(V))
4466 continue;
4467 Cut = ReductionCut{V, It->second.Lanes};
4468 break;
4469 }
4470 }
4471 // Reducing one lane is just an extract and can refold forever.
4472 if (!Cut || Cut->Elts.popcount() < 2)
4473 return false;
4474
4475 Intrinsic::ID ReducedOp =
4476 (CommonCallOp ? getMinMaxReductionIntrinsicID(*CommonCallOp)
4477 : getReductionForBinop(*CommonBinOp));
4478 if (!ReducedOp)
4479 return false;
4480
4481 InstructionCost OrigCost = 0;
4482 for (Value *V : Nodes)
4484
4485 auto *SrcVT = cast<FixedVectorType>(Cut->Src->getType());
4486 bool IsPartialReduction = !Cut->Elts.isAllOnes();
4487 FixedVectorType *ReduceVecTy =
4488 IsPartialReduction
4489 ? FixedVectorType::get(FVT->getElementType(), Cut->Elts.popcount())
4490 : SrcVT;
4491
4492 SmallVector<int> ExtractMask;
4493 InstructionCost NewCost = 0;
4494 if (IsPartialReduction) {
4495 for (unsigned I = 0, E = Cut->Elts.getBitWidth(); I != E; ++I)
4496 if (Cut->Elts[I])
4497 ExtractMask.push_back(I);
4498 unsigned SubIdx = 0, SubLen;
4499 auto SK = Cut->Elts.isShiftedMask(SubIdx, SubLen)
4502 NewCost += TTI.getShuffleCost(SK, ReduceVecTy, SrcVT, CostKind, ExtractMask,
4503 SubIdx, ReduceVecTy);
4504 }
4505
4506 IntrinsicCostAttributes ICA(
4507 ReducedOp, ReduceVecTy->getElementType(),
4508 IsFloatReduction
4509 ? SmallVector<Type *, 2>{ReduceVecTy->getElementType(), ReduceVecTy}
4510 : SmallVector<Type *, 2>{ReduceVecTy},
4511 IsFloatReduction ? CommonFMF : FastMathFlags());
4512 NewCost += TTI.getIntrinsicInstrCost(ICA, CostKind);
4513
4514 LLVM_DEBUG(dbgs() << "Found reduction shuffle chain: " << I << "\n OldCost : "
4515 << OrigCost << " vs NewCost: " << NewCost << "\n");
4516
4517 if (!OrigCost.isValid() || !NewCost.isValid())
4518 return false;
4519
4520 if (VecOpEE->hasOneUse() ? (NewCost > OrigCost) : (NewCost >= OrigCost))
4521 return false;
4522
4523 Value *ReduceInput = Cut->Src;
4524 if (IsPartialReduction)
4525 ReduceInput = Builder.CreateShuffleVector(Cut->Src, ExtractMask);
4526
4527 Value *ReducedResult;
4528 if (IsFloatReduction) {
4530 *CommonBinOp, ReduceVecTy->getElementType(), /*AllowRHSConstant=*/false,
4531 CommonFMF.noSignedZeros());
4532 ReducedResult = Builder.CreateIntrinsic(ReducedOp, {ReduceVecTy},
4533 {Identity, ReduceInput}, CommonFMF);
4534 } else {
4535 ReducedResult =
4536 Builder.CreateIntrinsic(ReducedOp, {ReduceVecTy}, {ReduceInput});
4537 }
4538 replaceValue(I, *ReducedResult);
4539
4540 return true;
4541}
4542
4543/// Determine if its more efficient to fold:
4544/// reduce(trunc(x)) -> trunc(reduce(x)).
4545/// reduce(sext(x)) -> sext(reduce(x)).
4546/// reduce(zext(x)) -> zext(reduce(x)).
4547bool VectorCombine::foldCastFromReductions(Instruction &I) {
4548 auto *II = dyn_cast<IntrinsicInst>(&I);
4549 if (!II)
4550 return false;
4551
4552 bool TruncOnly = false;
4553 Intrinsic::ID IID = II->getIntrinsicID();
4554 switch (IID) {
4555 case Intrinsic::vector_reduce_add:
4556 case Intrinsic::vector_reduce_mul:
4557 TruncOnly = true;
4558 break;
4559 case Intrinsic::vector_reduce_and:
4560 case Intrinsic::vector_reduce_or:
4561 case Intrinsic::vector_reduce_xor:
4562 break;
4563 default:
4564 return false;
4565 }
4566
4567 unsigned ReductionOpc = getArithmeticReductionInstruction(IID);
4568 Value *ReductionSrc = I.getOperand(0);
4569
4570 Value *Src;
4571 if (!match(ReductionSrc, m_OneUse(m_Trunc(m_Value(Src)))) &&
4572 (TruncOnly || !match(ReductionSrc, m_OneUse(m_ZExtOrSExt(m_Value(Src))))))
4573 return false;
4574
4575 auto CastOpc =
4576 (Instruction::CastOps)cast<Instruction>(ReductionSrc)->getOpcode();
4577
4578 auto *SrcTy = cast<VectorType>(Src->getType());
4579 auto *ReductionSrcTy = cast<VectorType>(ReductionSrc->getType());
4580 Type *ResultTy = I.getType();
4581
4583 ReductionOpc, ReductionSrcTy, std::nullopt, CostKind);
4584 OldCost += TTI.getCastInstrCost(CastOpc, ReductionSrcTy, SrcTy,
4586 cast<CastInst>(ReductionSrc));
4587 InstructionCost NewCost =
4588 TTI.getArithmeticReductionCost(ReductionOpc, SrcTy, std::nullopt,
4589 CostKind) +
4590 TTI.getCastInstrCost(CastOpc, ResultTy, ReductionSrcTy->getScalarType(),
4592
4593 if (OldCost <= NewCost || !NewCost.isValid())
4594 return false;
4595
4596 Value *NewReduction = Builder.CreateIntrinsic(SrcTy->getScalarType(),
4597 II->getIntrinsicID(), {Src});
4598 Value *NewCast = Builder.CreateCast(CastOpc, NewReduction, ResultTy);
4599 replaceValue(I, *NewCast);
4600 return true;
4601}
4602
4603/// Fold:
4604/// icmp pred (reduce.{add,or,and,umax,umin}(signbit_extract(x))), C
4605/// into:
4606/// icmp sgt/slt (reduce.{or,umax,and,umin}(x)), -1/0
4607///
4608/// Sign-bit reductions produce values with known semantics:
4609/// - reduce.{or,umax}: 0 if no element is negative, 1 if any is
4610/// - reduce.{and,umin}: 1 if all elements are negative, 0 if any isn't
4611/// - reduce.add: count of negative elements (0 to NumElts)
4612///
4613/// Both lshr and ashr are supported:
4614/// - lshr produces 0 or 1, so reduce.add range is [0, N]
4615/// - ashr produces 0 or -1, so reduce.add range is [-N, 0]
4616///
4617/// The fold generalizes to multiple source vectors combined with the same
4618/// operation as the reduction. For example:
4619/// reduce.or(or(shr A, shr B)) conceptually extends the vector
4620/// For reduce.add, this changes the count to M*N where M is the number of
4621/// source vectors.
4622///
4623/// We transform to a direct sign check on the original vector using
4624/// reduce.{or,umax} or reduce.{and,umin}.
4625///
4626/// In spirit, it's similar to foldSignBitCheck in InstCombine.
4627bool VectorCombine::foldSignBitReductionCmp(Instruction &I) {
4628 CmpPredicate Pred;
4629 IntrinsicInst *ReduceOp;
4630 const APInt *CmpVal;
4631 if (!match(&I,
4632 m_ICmp(Pred, m_OneUse(m_AnyIntrinsic(ReduceOp)), m_APInt(CmpVal))))
4633 return false;
4634
4635 Intrinsic::ID OrigIID = ReduceOp->getIntrinsicID();
4636 switch (OrigIID) {
4637 case Intrinsic::vector_reduce_or:
4638 case Intrinsic::vector_reduce_umax:
4639 case Intrinsic::vector_reduce_and:
4640 case Intrinsic::vector_reduce_umin:
4641 case Intrinsic::vector_reduce_add:
4642 break;
4643 default:
4644 return false;
4645 }
4646
4647 Value *ReductionSrc = ReduceOp->getArgOperand(0);
4648 auto *VecTy = dyn_cast<FixedVectorType>(ReductionSrc->getType());
4649 if (!VecTy)
4650 return false;
4651
4652 unsigned BitWidth = VecTy->getScalarSizeInBits();
4653 if (BitWidth == 1)
4654 return false;
4655
4656 unsigned NumElts = VecTy->getNumElements();
4657
4658 // Determine the expected tree opcode for multi-vector patterns.
4659 // The tree opcode must match the reduction's underlying operation.
4660 //
4661 // TODO: for pairs of equivalent operators, we should match both,
4662 // not only the most common.
4663 Instruction::BinaryOps TreeOpcode;
4664 switch (OrigIID) {
4665 case Intrinsic::vector_reduce_or:
4666 case Intrinsic::vector_reduce_umax:
4667 TreeOpcode = Instruction::Or;
4668 break;
4669 case Intrinsic::vector_reduce_and:
4670 case Intrinsic::vector_reduce_umin:
4671 TreeOpcode = Instruction::And;
4672 break;
4673 case Intrinsic::vector_reduce_add:
4674 TreeOpcode = Instruction::Add;
4675 break;
4676 default:
4677 llvm_unreachable("Unexpected intrinsic");
4678 }
4679
4680 // Collect sign-bit extraction leaves from an associative tree of TreeOpcode.
4681 // The tree conceptually extends the vector being reduced.
4682 SmallVector<Value *, 8> Worklist;
4683 SmallVector<Value *, 8> Sources; // Original vectors (X in shr X, BW-1)
4684 Worklist.push_back(ReductionSrc);
4685 std::optional<bool> IsAShr;
4686 constexpr unsigned MaxSources = 8;
4687
4688 // Calculate old cost: all shifts + tree ops + reduction
4689 InstructionCost OldCost = TTI.getInstructionCost(ReduceOp, CostKind);
4690
4691 while (!Worklist.empty() && Worklist.size() <= MaxSources &&
4692 Sources.size() <= MaxSources) {
4693 Value *V = Worklist.pop_back_val();
4694
4695 // Try to match sign-bit extraction: shr X, (bitwidth-1)
4696 Value *X;
4697 if (match(V, m_OneUse(m_Shr(m_Value(X), m_SpecificInt(BitWidth - 1))))) {
4698 auto *Shr = cast<Instruction>(V);
4699
4700 // All shifts must be the same type (all lshr or all ashr)
4701 bool ThisIsAShr = Shr->getOpcode() == Instruction::AShr;
4702 if (!IsAShr)
4703 IsAShr = ThisIsAShr;
4704 else if (*IsAShr != ThisIsAShr)
4705 return false;
4706
4707 Sources.push_back(X);
4708
4709 // As part of the fold, we remove all of the shifts, so we need to keep
4710 // track of their costs.
4711 OldCost += TTI.getInstructionCost(Shr, CostKind);
4712
4713 continue;
4714 }
4715
4716 // Try to extend through a tree node of the expected opcode
4717 Value *A, *B;
4718 if (!match(V, m_OneUse(m_BinOp(TreeOpcode, m_Value(A), m_Value(B)))))
4719 return false;
4720
4721 // We are potentially replacing these operations as well, so we add them
4722 // to the costs.
4724
4725 Worklist.push_back(A);
4726 Worklist.push_back(B);
4727 }
4728
4729 // Must have at least one source and not exceed limit
4730 if (Sources.empty() || Sources.size() > MaxSources ||
4731 Worklist.size() > MaxSources || !IsAShr)
4732 return false;
4733
4734 unsigned NumSources = Sources.size();
4735
4736 // For reduce.add, the total count must fit as a signed integer.
4737 // Range is [0, M*N] for lshr or [-M*N, 0] for ashr.
4738 if (OrigIID == Intrinsic::vector_reduce_add &&
4739 !isIntN(BitWidth, NumSources * NumElts))
4740 return false;
4741
4742 // Compute the boundary value when all elements are negative:
4743 // - Per-element contribution: 1 for lshr, -1 for ashr
4744 // - For add: M*N (total elements across all sources); for others: just 1
4745 unsigned Count =
4746 (OrigIID == Intrinsic::vector_reduce_add) ? NumSources * NumElts : 1;
4747 APInt NegativeVal(CmpVal->getBitWidth(), Count);
4748 if (*IsAShr)
4749 NegativeVal.negate();
4750
4751 // Range is [min(0, AllNegVal), max(0, AllNegVal)]
4752 APInt Zero = APInt::getZero(CmpVal->getBitWidth());
4753 APInt RangeLow = APIntOps::smin(Zero, NegativeVal);
4754 APInt RangeHigh = APIntOps::smax(Zero, NegativeVal);
4755
4756 // Determine comparison semantics:
4757 // - IsEq: true for equality test, false for inequality
4758 // - TestsNegative: true if testing against AllNegVal, false for zero
4759 //
4760 // In addition to EQ/NE against 0 or AllNegVal, we support inequalities
4761 // that fold to boundary tests given the narrow value range:
4762 // < RangeHigh -> != RangeHigh
4763 // > RangeHigh-1 -> == RangeHigh
4764 // > RangeLow -> != RangeLow
4765 // < RangeLow+1 -> == RangeLow
4766 //
4767 // For inequalities, we work with signed predicates only. Unsigned predicates
4768 // are canonicalized to signed when the range is non-negative (where they are
4769 // equivalent). When the range includes negative values, unsigned predicates
4770 // would have different semantics due to wrap-around, so we reject them.
4771 if (!ICmpInst::isEquality(Pred) && !ICmpInst::isSigned(Pred)) {
4772 if (RangeLow.isNegative())
4773 return false;
4774 Pred = ICmpInst::getSignedPredicate(Pred);
4775 }
4776
4777 bool IsEq;
4778 bool TestsNegative;
4779 if (ICmpInst::isEquality(Pred)) {
4780 if (CmpVal->isZero()) {
4781 TestsNegative = false;
4782 } else if (*CmpVal == NegativeVal) {
4783 TestsNegative = true;
4784 } else {
4785 return false;
4786 }
4787 IsEq = Pred == ICmpInst::ICMP_EQ;
4788 } else if (Pred == ICmpInst::ICMP_SLT && *CmpVal == RangeHigh) {
4789 IsEq = false;
4790 TestsNegative = (RangeHigh == NegativeVal);
4791 } else if (Pred == ICmpInst::ICMP_SGT && *CmpVal == RangeHigh - 1) {
4792 IsEq = true;
4793 TestsNegative = (RangeHigh == NegativeVal);
4794 } else if (Pred == ICmpInst::ICMP_SGT && *CmpVal == RangeLow) {
4795 IsEq = false;
4796 TestsNegative = (RangeLow == NegativeVal);
4797 } else if (Pred == ICmpInst::ICMP_SLT && *CmpVal == RangeLow + 1) {
4798 IsEq = true;
4799 TestsNegative = (RangeLow == NegativeVal);
4800 } else {
4801 return false;
4802 }
4803
4804 // For this fold we support four types of checks:
4805 //
4806 // 1. All lanes are negative - AllNeg
4807 // 2. All lanes are non-negative - AllNonNeg
4808 // 3. At least one negative lane - AnyNeg
4809 // 4. At least one non-negative lane - AnyNonNeg
4810 //
4811 // For each case, we can generate the following code:
4812 //
4813 // 1. AllNeg - reduce.and/umin(X) < 0
4814 // 2. AllNonNeg - reduce.or/umax(X) > -1
4815 // 3. AnyNeg - reduce.or/umax(X) < 0
4816 // 4. AnyNonNeg - reduce.and/umin(X) > -1
4817 //
4818 // The table below shows the aggregation of all supported cases
4819 // using these four cases.
4820 //
4821 // Reduction | == 0 | != 0 | == MAX | != MAX
4822 // ------------+-----------+-----------+-----------+-----------
4823 // or/umax | AllNonNeg | AnyNeg | AnyNeg | AllNonNeg
4824 // and/umin | AnyNonNeg | AllNeg | AllNeg | AnyNonNeg
4825 // add | AllNonNeg | AnyNeg | AllNeg | AnyNonNeg
4826 //
4827 // NOTE: MAX = 1 for or/and/umax/umin, and the vector size N for add
4828 //
4829 // For easier codegen and check inversion, we use the following encoding:
4830 //
4831 // 1. Bit-3 === requires or/umax (1) or and/umin (0) check
4832 // 2. Bit-2 === checks < 0 (1) or > -1 (0)
4833 // 3. Bit-1 === universal (1) or existential (0) check
4834 //
4835 // AnyNeg = 0b110: uses or/umax, checks negative, any-check
4836 // AllNonNeg = 0b101: uses or/umax, checks non-neg, all-check
4837 // AnyNonNeg = 0b000: uses and/umin, checks non-neg, any-check
4838 // AllNeg = 0b011: uses and/umin, checks negative, all-check
4839 //
4840 // XOR with 0b011 inverts the check (swaps all/any and neg/non-neg).
4841 //
4842 enum CheckKind : unsigned {
4843 AnyNonNeg = 0b000,
4844 AllNeg = 0b011,
4845 AllNonNeg = 0b101,
4846 AnyNeg = 0b110,
4847 };
4848 // Return true if we fold this check into or/umax and false for and/umin
4849 auto RequiresOr = [](CheckKind C) -> bool { return C & 0b100; };
4850 // Return true if we should check if result is negative and false otherwise
4851 auto IsNegativeCheck = [](CheckKind C) -> bool { return C & 0b010; };
4852 // Logically invert the check
4853 auto Invert = [](CheckKind C) { return CheckKind(C ^ 0b011); };
4854
4855 CheckKind Base;
4856 switch (OrigIID) {
4857 case Intrinsic::vector_reduce_or:
4858 case Intrinsic::vector_reduce_umax:
4859 Base = TestsNegative ? AnyNeg : AllNonNeg;
4860 break;
4861 case Intrinsic::vector_reduce_and:
4862 case Intrinsic::vector_reduce_umin:
4863 Base = TestsNegative ? AllNeg : AnyNonNeg;
4864 break;
4865 case Intrinsic::vector_reduce_add:
4866 Base = TestsNegative ? AllNeg : AllNonNeg;
4867 break;
4868 default:
4869 llvm_unreachable("Unexpected intrinsic");
4870 }
4871
4872 CheckKind Check = IsEq ? Base : Invert(Base);
4873
4874 auto PickCheaper = [&](Intrinsic::ID Arith, Intrinsic::ID MinMax) {
4875 InstructionCost ArithCost =
4877 VecTy, std::nullopt, CostKind);
4878 InstructionCost MinMaxCost =
4880 FastMathFlags(), CostKind);
4881 return ArithCost <= MinMaxCost ? std::make_pair(Arith, ArithCost)
4882 : std::make_pair(MinMax, MinMaxCost);
4883 };
4884
4885 // Choose output reduction based on encoding's MSB
4886 auto [NewIID, NewCost] = RequiresOr(Check)
4887 ? PickCheaper(Intrinsic::vector_reduce_or,
4888 Intrinsic::vector_reduce_umax)
4889 : PickCheaper(Intrinsic::vector_reduce_and,
4890 Intrinsic::vector_reduce_umin);
4891
4892 // Add cost of combining multiple sources with or/and
4893 if (NumSources > 1) {
4894 unsigned CombineOpc =
4895 RequiresOr(Check) ? Instruction::Or : Instruction::And;
4896 NewCost += TTI.getArithmeticInstrCost(CombineOpc, VecTy, CostKind) *
4897 (NumSources - 1);
4898 }
4899
4900 LLVM_DEBUG(dbgs() << "Found sign-bit reduction cmp: " << I << "\n OldCost: "
4901 << OldCost << " vs NewCost: " << NewCost << "\n");
4902
4903 if (NewCost > OldCost)
4904 return false;
4905
4906 // Generate the combined input and reduction
4907 Builder.SetInsertPoint(&I);
4908 Type *ScalarTy = VecTy->getScalarType();
4909
4910 Value *Input;
4911 if (NumSources == 1) {
4912 Input = Sources[0];
4913 } else {
4914 // Combine sources with or/and based on check type
4915 Input = RequiresOr(Check) ? Builder.CreateOr(Sources)
4916 : Builder.CreateAnd(Sources);
4917 }
4918
4919 Value *NewReduce = Builder.CreateIntrinsic(ScalarTy, NewIID, {Input});
4920 Value *NewCmp = IsNegativeCheck(Check) ? Builder.CreateIsNeg(NewReduce)
4921 : Builder.CreateIsNotNeg(NewReduce);
4922 replaceValue(I, *NewCmp);
4923 return true;
4924}
4925
4926/// Fold a zero test of reduce.or or reduce.umax into a boolean reduction.
4927///
4928/// Vectorization may produce IR that compares the result of a scalar reduction
4929/// with zero. Depending on the target, lowering a reduction and a scalar
4930/// comparison separately can cost more than reducing lane-wise comparison
4931/// results. This fold creates the latter form only when it is not costlier.
4932///
4933/// Before:
4934/// %r = call iT @llvm.vector.reduce.or.vNiT(<N x iT> %x)
4935/// %cmp = icmp ne iT %r, 0
4936///
4937/// After:
4938/// %lane.cmp = icmp ne <N x iT> %x, zeroinitializer
4939/// %cmp = call i1 @llvm.vector.reduce.or.vNi1(<N x i1> %lane.cmp)
4940///
4941/// `reduce.or` and `reduce.umax` are non-zero when at least one lane is
4942/// non-zero. Therefore, `icmp ne` uses the existential `reduce.or` test.
4943/// Conversely, `icmp eq` must check that every lane is zero, so it uses the
4944/// universal `reduce.and` test.
4945///
4946/// Before:
4947/// %r = call iT @llvm.vector.reduce.umax.vNiT(<N x iT> %x)
4948/// %cmp = icmp eq iT %r, 0
4949///
4950/// After:
4951/// %lane.cmp = icmp eq <N x iT> %x, zeroinitializer
4952/// %cmp = call i1 @llvm.vector.reduce.and.vNi1(<N x i1> %lane.cmp)
4953bool VectorCombine::foldReductionZeroTest(Instruction &I) {
4954 CmpPredicate Pred;
4955 Value *Op;
4956
4957 if (!match(&I, m_c_ICmp(Pred, m_Value(Op), m_Zero())) ||
4958 !ICmpInst::isEquality(Pred))
4959 return false;
4960
4961 auto *II = dyn_cast<IntrinsicInst>(Op);
4962 if (!II || !II->hasOneUse())
4963 return false;
4964
4965 auto ReduceID = II->getIntrinsicID();
4966 if (ReduceID != Intrinsic::vector_reduce_or &&
4967 ReduceID != Intrinsic::vector_reduce_umax)
4968 return false;
4969
4970 Value *Vec = II->getArgOperand(0);
4971 auto *VecTy = dyn_cast<FixedVectorType>(Vec->getType());
4972 if (!VecTy || !VecTy->getElementType()->isIntegerTy())
4973 return false;
4974
4975 // Map the scalar zero test to an any-lane or all-lane boolean reduction.
4976 Intrinsic::ID NewIID = (Pred == ICmpInst::ICMP_NE)
4977 ? Intrinsic::vector_reduce_or
4978 : Intrinsic::vector_reduce_and;
4979
4980 // This is not an unconditional canonicalization: compare the cost of the
4981 // original scalar reduction and compare with the vector compare and i1
4982 // reduction replacement for both reduce.or and reduce.umax.
4985
4986 auto *CmpTy = cast<VectorType>(CmpInst::makeCmpResultType(VecTy));
4987 InstructionCost NewCost =
4988 TTI.getCmpSelInstrCost(Instruction::ICmp, VecTy, CmpTy, Pred, CostKind);
4990 getArithmeticReductionInstruction(NewIID), CmpTy, std::nullopt, CostKind);
4991
4992 LLVM_DEBUG(dbgs() << "Found a reduction zero test: " << I << "\n OldCost: "
4993 << OldCost << " vs NewCost: " << NewCost << "\n");
4994
4995 if (!OldCost.isValid() || !NewCost.isValid() || NewCost > OldCost)
4996 return false;
4997
4998 Builder.SetInsertPoint(&I);
4999 Value *NewCmp = Builder.CreateICmp(Pred, Vec, Constant::getNullValue(VecTy));
5000 Value *NewReduce = Builder.CreateIntrinsic(NewIID, {CmpTy}, {NewCmp});
5001 replaceValue(I, *NewReduce);
5002 return true;
5003}
5004
5005/// vector.reduce.OP f(X_i) == 0 -> vector.reduce.OP X_i == 0
5006///
5007/// We can prove it for cases when:
5008///
5009/// 1. OP X_i == 0 <=> \forall i \in [1, N] X_i == 0
5010/// 1'. OP X_i == 0 <=> \exists j \in [1, N] X_j == 0
5011/// 2. f(x) == 0 <=> x == 0
5012///
5013/// From 1 and 2 (or 1' and 2), we can infer that
5014///
5015/// OP f(X_i) == 0 <=> OP X_i == 0.
5016///
5017/// (1)
5018/// OP f(X_i) == 0 <=> \forall i \in [1, N] f(X_i) == 0
5019/// (2)
5020/// <=> \forall i \in [1, N] X_i == 0
5021/// (1)
5022/// <=> OP(X_i) == 0
5023///
5024/// For some of the OP's and f's, we need to have domain constraints on X
5025/// to ensure properties 1 (or 1') and 2.
5026bool VectorCombine::foldICmpEqZeroVectorReduce(Instruction &I) {
5027 CmpPredicate Pred;
5028 Value *Op;
5029 if (!match(&I, m_ICmp(Pred, m_Value(Op), m_Zero())) ||
5030 !ICmpInst::isEquality(Pred))
5031 return false;
5032
5033 auto *II = dyn_cast<IntrinsicInst>(Op);
5034 if (!II)
5035 return false;
5036
5037 switch (II->getIntrinsicID()) {
5038 case Intrinsic::vector_reduce_add:
5039 case Intrinsic::vector_reduce_or:
5040 case Intrinsic::vector_reduce_umin:
5041 case Intrinsic::vector_reduce_umax:
5042 case Intrinsic::vector_reduce_smin:
5043 case Intrinsic::vector_reduce_smax:
5044 break;
5045 default:
5046 return false;
5047 }
5048
5049 Value *InnerOp = II->getArgOperand(0);
5050
5051 // TODO: fixed vector type might be too restrictive
5052 if (!II->hasOneUse() || !isa<FixedVectorType>(InnerOp->getType()))
5053 return false;
5054
5055 Value *X = nullptr;
5056
5057 // Check for zero-preserving operations where f(x) = 0 <=> x = 0
5058 //
5059 // 1. f(x) = shl nuw x, y for arbitrary y
5060 // 2. f(x) = mul nuw x, c for defined c != 0
5061 // 3. f(x) = zext x
5062 // 4. f(x) = sext x
5063 // 5. f(x) = neg x
5064 //
5065 if (!(match(InnerOp, m_NUWShl(m_Value(X), m_Value())) || // Case 1
5066 match(InnerOp, m_NUWMul(m_Value(X), m_NonZeroInt())) || // Case 2
5067 match(InnerOp, m_ZExt(m_Value(X))) || // Case 3
5068 match(InnerOp, m_SExt(m_Value(X))) || // Case 4
5069 match(InnerOp, m_Neg(m_Value(X))) // Case 5
5070 ))
5071 return false;
5072
5073 SimplifyQuery S = SQ.getWithInstruction(&I);
5074 auto *XTy = cast<FixedVectorType>(X->getType());
5075
5076 // Check for domain constraints for all supported reductions.
5077 //
5078 // a. OR X_i - has property 1 for every X
5079 // b. UMAX X_i - has property 1 for every X
5080 // c. UMIN X_i - has property 1' for every X
5081 // d. SMAX X_i - has property 1 for X >= 0
5082 // e. SMIN X_i - has property 1' for X >= 0
5083 // f. ADD X_i - has property 1 for X >= 0 && ADD X_i doesn't sign wrap
5084 //
5085 // In order for the proof to work, we need 1 (or 1') to be true for both
5086 // OP f(X_i) and OP X_i and that's why below we check constraints twice.
5087 //
5088 // NOTE: ADD X_i holds property 1 for a mirror case as well, i.e. when
5089 // X <= 0 && ADD X_i doesn't sign wrap. However, due to the nature
5090 // of known bits, we can't reasonably hold knowledge of "either 0
5091 // or negative".
5092 switch (II->getIntrinsicID()) {
5093 case Intrinsic::vector_reduce_add: {
5094 // We need to check that both X_i and f(X_i) have enough leading
5095 // zeros to not overflow.
5096 KnownBits KnownX = computeKnownBits(X, S);
5097 KnownBits KnownFX = computeKnownBits(InnerOp, S);
5098 unsigned NumElems = XTy->getNumElements();
5099 // Adding N elements loses at most ceil(log2(N)) leading bits.
5100 unsigned LostBits = Log2_32_Ceil(NumElems);
5101 unsigned LeadingZerosX = KnownX.countMinLeadingZeros();
5102 unsigned LeadingZerosFX = KnownFX.countMinLeadingZeros();
5103 // Need at least one leading zero left after summation to ensure no overflow
5104 if (LeadingZerosX <= LostBits || LeadingZerosFX <= LostBits)
5105 return false;
5106
5107 // We are not checking whether X or f(X) are positive explicitly because
5108 // we implicitly checked for it when we checked if both cases have enough
5109 // leading zeros to not wrap addition.
5110 break;
5111 }
5112 case Intrinsic::vector_reduce_smin:
5113 case Intrinsic::vector_reduce_smax:
5114 // Check whether X >= 0 and f(X) >= 0
5115 if (!isKnownNonNegative(InnerOp, S) || !isKnownNonNegative(X, S))
5116 return false;
5117
5118 break;
5119 default:
5120 break;
5121 };
5122
5123 LLVM_DEBUG(dbgs() << "Found a reduction to 0 comparison with removable op: "
5124 << *II << "\n");
5125
5126 // For zext/sext, check if the transform is profitable using cost model.
5127 // For other operations (shl, mul, neg), we're removing an instruction
5128 // while keeping the same reduction type, so it's always profitable.
5129 if (isa<ZExtInst>(InnerOp) || isa<SExtInst>(InnerOp)) {
5130 auto *FXTy = cast<FixedVectorType>(InnerOp->getType());
5131 Intrinsic::ID IID = II->getIntrinsicID();
5132
5134 cast<CastInst>(InnerOp)->getOpcode(), FXTy, XTy,
5136
5137 InstructionCost OldReduceCost, NewReduceCost;
5138 switch (IID) {
5139 case Intrinsic::vector_reduce_add:
5140 case Intrinsic::vector_reduce_or:
5141 OldReduceCost = TTI.getArithmeticReductionCost(
5142 getArithmeticReductionInstruction(IID), FXTy, std::nullopt, CostKind);
5143 NewReduceCost = TTI.getArithmeticReductionCost(
5144 getArithmeticReductionInstruction(IID), XTy, std::nullopt, CostKind);
5145 break;
5146 case Intrinsic::vector_reduce_umin:
5147 case Intrinsic::vector_reduce_umax:
5148 case Intrinsic::vector_reduce_smin:
5149 case Intrinsic::vector_reduce_smax:
5150 OldReduceCost = TTI.getMinMaxReductionCost(
5151 getMinMaxReductionIntrinsicOp(IID), FXTy, FastMathFlags(), CostKind);
5152 NewReduceCost = TTI.getMinMaxReductionCost(
5153 getMinMaxReductionIntrinsicOp(IID), XTy, FastMathFlags(), CostKind);
5154 break;
5155 default:
5156 llvm_unreachable("Unexpected reduction");
5157 }
5158
5159 InstructionCost OldCost = OldReduceCost + ExtCost;
5160 InstructionCost NewCost =
5161 NewReduceCost + (InnerOp->hasOneUse() ? 0 : ExtCost);
5162
5163 LLVM_DEBUG(dbgs() << "Found a removable extension before reduction: "
5164 << *InnerOp << "\n OldCost: " << OldCost
5165 << " vs NewCost: " << NewCost << "\n");
5166
5167 // We consider transformation to still be potentially beneficial even
5168 // when the costs are the same because we might remove a use from f(X)
5169 // and unlock other optimizations. Equal costs would just mean that we
5170 // didn't make it worse in the worst case.
5171 if (NewCost > OldCost)
5172 return false;
5173 }
5174
5175 // Since we support zext and sext as f, we might change the scalar type
5176 // of the intrinsic.
5177 Type *Ty = XTy->getScalarType();
5178 Value *NewReduce = Builder.CreateIntrinsic(Ty, II->getIntrinsicID(), {X});
5179 Value *NewCmp =
5180 Builder.CreateICmp(Pred, NewReduce, ConstantInt::getNullValue(Ty));
5181 replaceValue(I, *NewCmp);
5182 return true;
5183}
5184
5185/// Fold comparisons of reduce.or/reduce.and with reduce.umax/reduce.umin
5186/// based on cost, preserving the comparison semantics.
5187///
5188/// We use two fundamental properties for each pair:
5189///
5190/// 1. or(X) == 0 <=> umax(X) == 0
5191/// 2. or(X) == 1 <=> umax(X) == 1
5192/// 3. sign(or(X)) == sign(umax(X))
5193///
5194/// 1. and(X) == -1 <=> umin(X) == -1
5195/// 2. and(X) == -2 <=> umin(X) == -2
5196/// 3. sign(and(X)) == sign(umin(X))
5197///
5198/// From these we can infer the following transformations:
5199/// a. or(X) ==/!= 0 <-> umax(X) ==/!= 0
5200/// b. or(X) s< 0 <-> umax(X) s< 0
5201/// c. or(X) s> -1 <-> umax(X) s> -1
5202/// d. or(X) s< 1 <-> umax(X) s< 1
5203/// e. or(X) ==/!= 1 <-> umax(X) ==/!= 1
5204/// f. or(X) s< 2 <-> umax(X) s< 2
5205/// g. and(X) ==/!= -1 <-> umin(X) ==/!= -1
5206/// h. and(X) s< 0 <-> umin(X) s< 0
5207/// i. and(X) s> -1 <-> umin(X) s> -1
5208/// j. and(X) s> -2 <-> umin(X) s> -2
5209/// k. and(X) ==/!= -2 <-> umin(X) ==/!= -2
5210/// l. and(X) s> -3 <-> umin(X) s> -3
5211///
5212bool VectorCombine::foldEquivalentReductionCmp(Instruction &I) {
5213 CmpPredicate Pred;
5214 Value *ReduceOp;
5215 const APInt *CmpVal;
5216 if (!match(&I, m_ICmp(Pred, m_Value(ReduceOp), m_APInt(CmpVal))))
5217 return false;
5218
5219 auto *II = dyn_cast<IntrinsicInst>(ReduceOp);
5220 if (!II || !II->hasOneUse())
5221 return false;
5222
5223 const auto IsValidOrUmaxCmp = [&]() {
5224 // or === umax for i1
5225 if (CmpVal->getBitWidth() == 1)
5226 return true;
5227
5228 // Cases a and e
5229 bool IsEquality =
5230 (CmpVal->isZero() || CmpVal->isOne()) && ICmpInst::isEquality(Pred);
5231 // Case c
5232 bool IsPositive = CmpVal->isAllOnes() && Pred == ICmpInst::ICMP_SGT;
5233 // Cases b, d, and f
5234 bool IsNegative = (CmpVal->isZero() || CmpVal->isOne() || *CmpVal == 2) &&
5235 Pred == ICmpInst::ICMP_SLT;
5236 return IsEquality || IsPositive || IsNegative;
5237 };
5238
5239 const auto IsValidAndUminCmp = [&]() {
5240 // and === umin for i1
5241 if (CmpVal->getBitWidth() == 1)
5242 return true;
5243
5244 const auto LeadingOnes = CmpVal->countl_one();
5245
5246 // Cases g and k
5247 bool IsEquality =
5248 (CmpVal->isAllOnes() || LeadingOnes + 1 == CmpVal->getBitWidth()) &&
5250 // Case h
5251 bool IsNegative = CmpVal->isZero() && Pred == ICmpInst::ICMP_SLT;
5252 // Cases i, j, and l
5253 bool IsPositive =
5254 // if the number has at least N - 2 leading ones
5255 // and the two LSBs are:
5256 // - 1 x 1 -> -1
5257 // - 1 x 0 -> -2
5258 // - 0 x 1 -> -3
5259 LeadingOnes + 2 >= CmpVal->getBitWidth() &&
5260 ((*CmpVal)[0] || (*CmpVal)[1]) && Pred == ICmpInst::ICMP_SGT;
5261 return IsEquality || IsNegative || IsPositive;
5262 };
5263
5264 Intrinsic::ID OriginalIID = II->getIntrinsicID();
5265 Intrinsic::ID AlternativeIID;
5266
5267 // Check if this is a valid comparison pattern and determine the alternate
5268 // reduction intrinsic.
5269 switch (OriginalIID) {
5270 case Intrinsic::vector_reduce_or:
5271 if (!IsValidOrUmaxCmp())
5272 return false;
5273 AlternativeIID = Intrinsic::vector_reduce_umax;
5274 break;
5275 case Intrinsic::vector_reduce_umax:
5276 if (!IsValidOrUmaxCmp())
5277 return false;
5278 AlternativeIID = Intrinsic::vector_reduce_or;
5279 break;
5280 case Intrinsic::vector_reduce_and:
5281 if (!IsValidAndUminCmp())
5282 return false;
5283 AlternativeIID = Intrinsic::vector_reduce_umin;
5284 break;
5285 case Intrinsic::vector_reduce_umin:
5286 if (!IsValidAndUminCmp())
5287 return false;
5288 AlternativeIID = Intrinsic::vector_reduce_and;
5289 break;
5290 default:
5291 return false;
5292 }
5293
5294 Value *X = II->getArgOperand(0);
5295 auto *VecTy = dyn_cast<FixedVectorType>(X->getType());
5296 if (!VecTy)
5297 return false;
5298
5299 const auto GetReductionCost = [&](Intrinsic::ID IID) -> InstructionCost {
5300 unsigned ReductionOpc = getArithmeticReductionInstruction(IID);
5301 if (ReductionOpc != Instruction::ICmp)
5302 return TTI.getArithmeticReductionCost(ReductionOpc, VecTy, std::nullopt,
5303 CostKind);
5305 FastMathFlags(), CostKind);
5306 };
5307
5308 InstructionCost OrigCost = GetReductionCost(OriginalIID);
5309 InstructionCost AltCost = GetReductionCost(AlternativeIID);
5310
5311 LLVM_DEBUG(dbgs() << "Found equivalent reduction cmp: " << I
5312 << "\n OrigCost: " << OrigCost
5313 << " vs AltCost: " << AltCost << "\n");
5314
5315 if (AltCost >= OrigCost)
5316 return false;
5317
5318 Builder.SetInsertPoint(&I);
5319 Type *ScalarTy = VecTy->getScalarType();
5320 Value *NewReduce = Builder.CreateIntrinsic(ScalarTy, AlternativeIID, {X});
5321 Value *NewCmp =
5322 Builder.CreateICmp(Pred, NewReduce, ConstantInt::get(ScalarTy, *CmpVal));
5323
5324 replaceValue(I, *NewCmp);
5325 return true;
5326}
5327
5328/// Used by foldReduceAddCmpZero to check if we can prove that a value is
5329/// non-positive.
5330/// KnownBits cannot see sext <? x i1> as non-positive: each top bit equals a
5331/// single unknown input bit, which a per-bit lattice cannot track. The fold's
5332/// target shape is popcount-style sums of <N x i1> valid/invalid masks (e.g.
5333/// ray-intersection hits) tested for any-hit.
5334/// Previous attempts to approximate the known bits of such expressions were
5335/// using a fully recursive value tracking approach to infer a constant range
5336/// but ultimately turned to be too expensive in compile time.
5337static bool isKnownNonPositive(const Value *V, const SimplifyQuery &SQ,
5338 unsigned Depth = 0) {
5339 constexpr unsigned MaxLocalDepth = 2;
5340 if (Depth > MaxLocalDepth)
5341 return false;
5342
5343 auto NumSignBits = [&](const Value *X) {
5344 return ComputeNumSignBits(X, SQ.DL, SQ.AC, SQ.CtxI, SQ.DT);
5345 };
5346 if (NumSignBits(V) == V->getType()->getScalarSizeInBits())
5347 return true;
5348
5349 Value *A, *B;
5350 if (match(V, m_Add(m_Value(A), m_Value(B))))
5351 return NumSignBits(A) >= 2 && NumSignBits(B) >= 2 &&
5352 isKnownNonPositive(A, SQ, Depth + 1) &&
5353 isKnownNonPositive(B, SQ, Depth + 1);
5354
5355 return computeKnownBits(V, SQ).isNonPositive();
5356}
5357
5358/// Fold (icmp pred (reduce.add X), 0) to (icmp pred' (reduce.or X), 0) when X
5359/// has lanes known to all be non-negative or all non-positive, so that
5360/// sum == 0 iff every lane is 0. Falls back to reduce.umax if reduce.or is
5361/// more expensive on the target.
5362bool VectorCombine::foldReduceAddCmpZero(Instruction &I) {
5363 CmpPredicate Pred;
5364 Value *Vec;
5365 if (!match(&I, m_ICmp(Pred,
5367 m_Value(Vec))),
5368 m_Zero())))
5369 return false;
5370
5371 auto *VecTy = dyn_cast<FixedVectorType>(Vec->getType());
5372 if (!VecTy || VecTy->getNumElements() < 2)
5373 return false;
5374
5375 SimplifyQuery Q = SQ.getWithInstruction(&I);
5376 bool IsNonNegative = isKnownNonNegative(Vec, Q);
5377 bool IsNonPositive = !IsNonNegative && isKnownNonPositive(Vec, Q);
5378 if (!IsNonNegative && !IsNonPositive)
5379 return false;
5380
5381 // Summing NumElts lanes can consume up to log2(NumElts) sign bits. Require
5382 // strictly more headroom than that so the sum cannot wrap to zero.
5383 unsigned NumElts = VecTy->getNumElements();
5384 unsigned NumSignBits = ComputeNumSignBits(Vec, *DL, SQ.AC, &I, &DT);
5385 if (Log2_32(NumElts) >= NumSignBits)
5386 return false;
5387
5388 ICmpInst::Predicate NewPred;
5389 switch (Pred) {
5390 case ICmpInst::ICMP_EQ:
5391 case ICmpInst::ICMP_ULE:
5392 case ICmpInst::ICMP_SLE:
5393 case ICmpInst::ICMP_SGE:
5394 NewPred = ICmpInst::ICMP_EQ;
5395 break;
5396 case ICmpInst::ICMP_NE:
5397 case ICmpInst::ICMP_UGT:
5398 case ICmpInst::ICMP_SGT:
5399 case ICmpInst::ICMP_SLT:
5400 NewPred = ICmpInst::ICMP_NE;
5401 break;
5402 default:
5403 return false;
5404 }
5405
5406 // SGT and SLE on a non-positive tree, and SLT and SGE on a non-negative
5407 // tree, are tautologies (always true or always false). Leave those to
5408 // InstCombine rather than mapping them here. Remaining signed inequalities
5409 // also need one extra sign bit so the sum cannot flip sign.
5410 if (!IsNonNegative &&
5411 (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE))
5412 return false;
5413 if (!IsNonPositive &&
5414 (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE))
5415 return false;
5416 if ((Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE ||
5417 Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE) &&
5418 Log2_32(NumElts) >= NumSignBits - 1)
5419 return false;
5420
5422 Instruction::Add, VecTy, std::nullopt, CostKind);
5424 Instruction::Or, VecTy, std::nullopt, CostKind);
5426 Intrinsic::umax, VecTy, FastMathFlags(), CostKind);
5427 if (!OrCost.isValid() && !UmaxCost.isValid())
5428 return false;
5429 bool UseOr = OrCost.isValid() && (!UmaxCost.isValid() || OrCost <= UmaxCost);
5430 InstructionCost AltCost = UseOr ? OrCost : UmaxCost;
5431 if (AltCost > OrigCost)
5432 return false;
5433
5434 Builder.SetInsertPoint(&I);
5435 Value *NewReduce = UseOr ? Builder.CreateOrReduce(Vec)
5436 : Builder.CreateIntrinsic(
5437 Intrinsic::vector_reduce_umax, {VecTy}, {Vec});
5438 Worklist.pushValue(NewReduce);
5439 Value *NewCmp = Builder.CreateICmp(
5440 NewPred, NewReduce, ConstantInt::getNullValue(VecTy->getScalarType()));
5441 replaceValue(I, *NewCmp);
5442 return true;
5443}
5444
5445/// Returns true if this ShuffleVectorInst eventually feeds into a
5446/// vector reduction intrinsic (e.g., vector_reduce_add) by only following
5447/// chains of shuffles and binary operators (in any combination/order).
5448/// The search does not go deeper than the given Depth.
5450 constexpr unsigned MaxVisited = 32;
5453 bool FoundReduction = false;
5454
5455 WorkList.push_back(SVI);
5456 while (!WorkList.empty()) {
5457 Instruction *I = WorkList.pop_back_val();
5458 for (User *U : I->users()) {
5459 auto *UI = cast<Instruction>(U);
5460 if (!UI || !Visited.insert(UI).second)
5461 continue;
5462 if (Visited.size() > MaxVisited)
5463 return false;
5464 if (auto *II = dyn_cast<IntrinsicInst>(UI)) {
5465 // More than one reduction reached
5466 if (FoundReduction)
5467 return false;
5468 switch (II->getIntrinsicID()) {
5469 case Intrinsic::vector_reduce_add:
5470 case Intrinsic::vector_reduce_mul:
5471 case Intrinsic::vector_reduce_and:
5472 case Intrinsic::vector_reduce_or:
5473 case Intrinsic::vector_reduce_xor:
5474 case Intrinsic::vector_reduce_smin:
5475 case Intrinsic::vector_reduce_smax:
5476 case Intrinsic::vector_reduce_umin:
5477 case Intrinsic::vector_reduce_umax:
5478 FoundReduction = true;
5479 continue;
5480 default:
5481 return false;
5482 }
5483 }
5484
5486 return false;
5487
5488 WorkList.emplace_back(UI);
5489 }
5490 }
5491 return FoundReduction;
5492}
5493
5494/// This method looks for groups of shuffles acting on binops, of the form:
5495/// %x = shuffle ...
5496/// %y = shuffle ...
5497/// %a = binop %x, %y
5498/// %b = binop %x, %y
5499/// shuffle %a, %b, selectmask
5500/// We may, especially if the shuffle is wider than legal, be able to convert
5501/// the shuffle to a form where only parts of a and b need to be computed. On
5502/// architectures with no obvious "select" shuffle, this can reduce the total
5503/// number of operations if the target reports them as cheaper.
5504bool VectorCombine::foldSelectShuffle(Instruction &I, bool FromReduction) {
5505 auto *SVI = cast<ShuffleVectorInst>(&I);
5506 auto *VT = cast<FixedVectorType>(I.getType());
5507 auto *Op0 = dyn_cast<Instruction>(SVI->getOperand(0));
5508 auto *Op1 = dyn_cast<Instruction>(SVI->getOperand(1));
5509 if (!Op0 || !Op1 || Op0 == Op1 || !Op0->isBinaryOp() || !Op1->isBinaryOp() ||
5510 VT != Op0->getType())
5511 return false;
5512
5513 auto *SVI0A = dyn_cast<Instruction>(Op0->getOperand(0));
5514 auto *SVI0B = dyn_cast<Instruction>(Op0->getOperand(1));
5515 auto *SVI1A = dyn_cast<Instruction>(Op1->getOperand(0));
5516 auto *SVI1B = dyn_cast<Instruction>(Op1->getOperand(1));
5517 SmallPtrSet<Instruction *, 4> InputShuffles({SVI0A, SVI0B, SVI1A, SVI1B});
5518 auto checkSVNonOpUses = [&](Instruction *I) {
5519 if (!I || I->getOperand(0)->getType() != VT)
5520 return true;
5521 return any_of(I->users(), [&](User *U) {
5522 return U != Op0 && U != Op1 &&
5523 !(isa<ShuffleVectorInst>(U) &&
5524 (InputShuffles.contains(cast<Instruction>(U)) ||
5525 isInstructionTriviallyDead(cast<Instruction>(U))));
5526 });
5527 };
5528 if (checkSVNonOpUses(SVI0A) || checkSVNonOpUses(SVI0B) ||
5529 checkSVNonOpUses(SVI1A) || checkSVNonOpUses(SVI1B))
5530 return false;
5531
5532 // Collect all the uses that are shuffles that we can transform together. We
5533 // may not have a single shuffle, but a group that can all be transformed
5534 // together profitably.
5536 auto collectShuffles = [&](Instruction *I) {
5537 for (auto *U : I->users()) {
5539 if (!SV || SV->getType() != VT)
5540 return false;
5541 if ((SV->getOperand(0) != Op0 && SV->getOperand(0) != Op1) ||
5542 (SV->getOperand(1) != Op0 && SV->getOperand(1) != Op1))
5543 return false;
5544 if (!llvm::is_contained(Shuffles, SV))
5545 Shuffles.push_back(SV);
5546 }
5547 return true;
5548 };
5549 if (!collectShuffles(Op0) || !collectShuffles(Op1))
5550 return false;
5551 // From a reduction, we need to be processing a single shuffle, otherwise the
5552 // other uses will not be lane-invariant.
5553 if (FromReduction && Shuffles.size() > 1)
5554 return false;
5555
5556 // Add any shuffle uses for the shuffles we have found, to include them in our
5557 // cost calculations.
5558 if (!FromReduction) {
5559 for (size_t Idx = 0, E = Shuffles.size(); Idx != E; ++Idx) {
5560 for (auto *U : Shuffles[Idx]->users()) {
5561 ShuffleVectorInst *SSV = dyn_cast<ShuffleVectorInst>(U);
5562 if (SSV && isa<UndefValue>(SSV->getOperand(1)) && SSV->getType() == VT)
5563 Shuffles.push_back(SSV);
5564 }
5565 }
5566 }
5567
5568 // For each of the output shuffles, we try to sort all the first vector
5569 // elements to the beginning, followed by the second array elements at the
5570 // end. If the binops are legalized to smaller vectors, this may reduce total
5571 // number of binops. We compute the ReconstructMask mask needed to convert
5572 // back to the original lane order.
5574 SmallVector<SmallVector<int>> OrigReconstructMasks;
5575 int MaxV1Elt = 0, MaxV2Elt = 0;
5576 unsigned NumElts = VT->getNumElements();
5577 for (ShuffleVectorInst *SVN : Shuffles) {
5578 SmallVector<int> Mask;
5579 SVN->getShuffleMask(Mask);
5580
5581 // Check the operands are the same as the original, or reversed (in which
5582 // case we need to commute the mask).
5583 Value *SVOp0 = SVN->getOperand(0);
5584 Value *SVOp1 = SVN->getOperand(1);
5585 if (isa<UndefValue>(SVOp1)) {
5586 auto *SSV = cast<ShuffleVectorInst>(SVOp0);
5587 SVOp0 = SSV->getOperand(0);
5588 SVOp1 = SSV->getOperand(1);
5589 for (int &Elem : Mask) {
5590 if (Elem >= static_cast<int>(SSV->getShuffleMask().size()))
5591 return false;
5592 Elem = Elem < 0 ? Elem : SSV->getMaskValue(Elem);
5593 }
5594 }
5595 if (SVOp0 == Op1 && SVOp1 == Op0) {
5596 std::swap(SVOp0, SVOp1);
5598 }
5599 if (SVOp0 != Op0 || SVOp1 != Op1)
5600 return false;
5601
5602 // Calculate the reconstruction mask for this shuffle, as the mask needed to
5603 // take the packed values from Op0/Op1 and reconstructing to the original
5604 // order.
5605 SmallVector<int> ReconstructMask;
5606 for (unsigned I = 0; I < Mask.size(); I++) {
5607 if (Mask[I] < 0) {
5608 ReconstructMask.push_back(-1);
5609 } else if (Mask[I] < static_cast<int>(NumElts)) {
5610 MaxV1Elt = std::max(MaxV1Elt, Mask[I]);
5611 auto It = find_if(V1, [&](const std::pair<int, int> &A) {
5612 return Mask[I] == A.first;
5613 });
5614 if (It != V1.end())
5615 ReconstructMask.push_back(It - V1.begin());
5616 else {
5617 ReconstructMask.push_back(V1.size());
5618 V1.emplace_back(Mask[I], V1.size());
5619 }
5620 } else {
5621 MaxV2Elt = std::max<int>(MaxV2Elt, Mask[I] - NumElts);
5622 auto It = find_if(V2, [&](const std::pair<int, int> &A) {
5623 return Mask[I] - static_cast<int>(NumElts) == A.first;
5624 });
5625 if (It != V2.end())
5626 ReconstructMask.push_back(NumElts + It - V2.begin());
5627 else {
5628 ReconstructMask.push_back(NumElts + V2.size());
5629 V2.emplace_back(Mask[I] - NumElts, NumElts + V2.size());
5630 }
5631 }
5632 }
5633
5634 // For reductions, we know that the lane ordering out doesn't alter the
5635 // result. In-order can help simplify the shuffle away.
5636 if (FromReduction)
5637 sort(ReconstructMask);
5638 OrigReconstructMasks.push_back(std::move(ReconstructMask));
5639 }
5640
5641 // If the Maximum element used from V1 and V2 are not larger than the new
5642 // vectors, the vectors are already packes and performing the optimization
5643 // again will likely not help any further. This also prevents us from getting
5644 // stuck in a cycle in case the costs do not also rule it out.
5645 if (V1.empty() || V2.empty() ||
5646 (MaxV1Elt == static_cast<int>(V1.size()) - 1 &&
5647 MaxV2Elt == static_cast<int>(V2.size()) - 1))
5648 return false;
5649
5650 // GetBaseMaskValue takes one of the inputs, which may either be a shuffle, a
5651 // shuffle of another shuffle, or not a shuffle (that is treated like a
5652 // identity shuffle).
5653 auto GetBaseMaskValue = [&](Instruction *I, int M) {
5655 if (!SV)
5656 return M;
5657 if (isa<UndefValue>(SV->getOperand(1)))
5658 if (auto *SSV = dyn_cast<ShuffleVectorInst>(SV->getOperand(0)))
5659 if (InputShuffles.contains(SSV))
5660 return SSV->getMaskValue(SV->getMaskValue(M));
5661 return SV->getMaskValue(M);
5662 };
5663
5664 // Attempt to sort the inputs my ascending mask values to make simpler input
5665 // shuffles and push complex shuffles down to the uses. We sort on the first
5666 // of the two input shuffle orders, to try and get at least one input into a
5667 // nice order.
5668 auto SortBase = [&](Instruction *A, std::pair<int, int> X,
5669 std::pair<int, int> Y) {
5670 int MXA = GetBaseMaskValue(A, X.first);
5671 int MYA = GetBaseMaskValue(A, Y.first);
5672 return MXA < MYA;
5673 };
5674 stable_sort(V1, [&](std::pair<int, int> A, std::pair<int, int> B) {
5675 return SortBase(SVI0A, A, B);
5676 });
5677 stable_sort(V2, [&](std::pair<int, int> A, std::pair<int, int> B) {
5678 return SortBase(SVI1A, A, B);
5679 });
5680 // Calculate our ReconstructMasks from the OrigReconstructMasks and the
5681 // modified order of the input shuffles.
5682 SmallVector<SmallVector<int>> ReconstructMasks;
5683 for (const auto &Mask : OrigReconstructMasks) {
5684 SmallVector<int> ReconstructMask;
5685 for (int M : Mask) {
5686 auto FindIndex = [](const SmallVector<std::pair<int, int>> &V, int M) {
5687 auto It = find_if(V, [M](auto A) { return A.second == M; });
5688 assert(It != V.end() && "Expected all entries in Mask");
5689 return std::distance(V.begin(), It);
5690 };
5691 if (M < 0)
5692 ReconstructMask.push_back(-1);
5693 else if (M < static_cast<int>(NumElts)) {
5694 ReconstructMask.push_back(FindIndex(V1, M));
5695 } else {
5696 ReconstructMask.push_back(NumElts + FindIndex(V2, M));
5697 }
5698 }
5699 ReconstructMasks.push_back(std::move(ReconstructMask));
5700 }
5701
5702 // Calculate the masks needed for the new input shuffles, which get padded
5703 // with undef
5704 SmallVector<int> V1A, V1B, V2A, V2B;
5705 for (unsigned I = 0; I < V1.size(); I++) {
5706 V1A.push_back(GetBaseMaskValue(SVI0A, V1[I].first));
5707 V1B.push_back(GetBaseMaskValue(SVI0B, V1[I].first));
5708 }
5709 for (unsigned I = 0; I < V2.size(); I++) {
5710 V2A.push_back(GetBaseMaskValue(SVI1A, V2[I].first));
5711 V2B.push_back(GetBaseMaskValue(SVI1B, V2[I].first));
5712 }
5713 while (V1A.size() < NumElts) {
5716 }
5717 while (V2A.size() < NumElts) {
5720 }
5721
5722 auto AddShuffleCost = [&](InstructionCost C, Instruction *I) {
5724 if (!SV)
5725 return C;
5726 return C + TTI.getShuffleCost(isa<UndefValue>(SV->getOperand(1))
5729 VT, VT, CostKind, SV->getShuffleMask());
5730 };
5731 auto AddShuffleMaskCost = [&](InstructionCost C, ArrayRef<int> Mask) {
5732 return C +
5734 };
5735
5736 unsigned ElementSize = VT->getElementType()->getPrimitiveSizeInBits();
5737 unsigned MaxVectorSize =
5739 unsigned MaxElementsInVector = MaxVectorSize / ElementSize;
5740 if (MaxElementsInVector == 0)
5741 return false;
5742 // When there are multiple shufflevector operations on the same input,
5743 // especially when the vector length is larger than the register size,
5744 // identical shuffle patterns may occur across different groups of elements.
5745 // To avoid overestimating the cost by counting these repeated shuffles more
5746 // than once, we only account for unique shuffle patterns. This adjustment
5747 // prevents inflated costs in the cost model for wide vectors split into
5748 // several register-sized groups.
5749 std::set<SmallVector<int, 4>> UniqueShuffles;
5750 auto AddShuffleMaskAdjustedCost = [&](InstructionCost C, ArrayRef<int> Mask) {
5751 // Compute the cost for performing the shuffle over the full vector.
5752 auto ShuffleCost =
5754 unsigned NumFullVectors = Mask.size() / MaxElementsInVector;
5755 if (NumFullVectors < 2)
5756 return C + ShuffleCost;
5757 SmallVector<int, 4> SubShuffle(MaxElementsInVector);
5758 unsigned NumUniqueGroups = 0;
5759 unsigned NumGroups = Mask.size() / MaxElementsInVector;
5760 // For each group of MaxElementsInVector contiguous elements,
5761 // collect their shuffle pattern and insert into the set of unique patterns.
5762 for (unsigned I = 0; I < NumFullVectors; ++I) {
5763 for (unsigned J = 0; J < MaxElementsInVector; ++J)
5764 SubShuffle[J] = Mask[MaxElementsInVector * I + J];
5765 if (UniqueShuffles.insert(SubShuffle).second)
5766 NumUniqueGroups += 1;
5767 }
5768 return C + ShuffleCost * NumUniqueGroups / NumGroups;
5769 };
5770 auto AddShuffleAdjustedCost = [&](InstructionCost C, Instruction *I) {
5772 if (!SV)
5773 return C;
5774 SmallVector<int, 16> Mask;
5775 SV->getShuffleMask(Mask);
5776 return AddShuffleMaskAdjustedCost(C, Mask);
5777 };
5778 // Check that input consists of ShuffleVectors applied to the same input
5779 auto AllShufflesHaveSameOperands =
5780 [](SmallPtrSetImpl<Instruction *> &InputShuffles) {
5781 if (InputShuffles.size() < 2)
5782 return false;
5783 ShuffleVectorInst *FirstSV =
5784 dyn_cast<ShuffleVectorInst>(*InputShuffles.begin());
5785 if (!FirstSV)
5786 return false;
5787
5788 Value *In0 = FirstSV->getOperand(0), *In1 = FirstSV->getOperand(1);
5789 return std::all_of(
5790 std::next(InputShuffles.begin()), InputShuffles.end(),
5791 [&](Instruction *I) {
5792 ShuffleVectorInst *SV = dyn_cast<ShuffleVectorInst>(I);
5793 return SV && SV->getOperand(0) == In0 && SV->getOperand(1) == In1;
5794 });
5795 };
5796
5797 // Get the costs of the shuffles + binops before and after with the new
5798 // shuffle masks.
5799 InstructionCost CostBefore =
5800 TTI.getArithmeticInstrCost(Op0->getOpcode(), VT, CostKind) +
5801 TTI.getArithmeticInstrCost(Op1->getOpcode(), VT, CostKind);
5802 CostBefore += std::accumulate(Shuffles.begin(), Shuffles.end(),
5803 InstructionCost(0), AddShuffleCost);
5804 if (AllShufflesHaveSameOperands(InputShuffles)) {
5805 UniqueShuffles.clear();
5806 CostBefore += std::accumulate(InputShuffles.begin(), InputShuffles.end(),
5807 InstructionCost(0), AddShuffleAdjustedCost);
5808 } else {
5809 CostBefore += std::accumulate(InputShuffles.begin(), InputShuffles.end(),
5810 InstructionCost(0), AddShuffleCost);
5811 }
5812
5813 // The new binops will be unused for lanes past the used shuffle lengths.
5814 // These types attempt to get the correct cost for that from the target.
5815 FixedVectorType *Op0SmallVT =
5816 FixedVectorType::get(VT->getScalarType(), V1.size());
5817 FixedVectorType *Op1SmallVT =
5818 FixedVectorType::get(VT->getScalarType(), V2.size());
5819 InstructionCost CostAfter =
5820 TTI.getArithmeticInstrCost(Op0->getOpcode(), Op0SmallVT, CostKind) +
5821 TTI.getArithmeticInstrCost(Op1->getOpcode(), Op1SmallVT, CostKind);
5822 UniqueShuffles.clear();
5823 CostAfter += std::accumulate(ReconstructMasks.begin(), ReconstructMasks.end(),
5824 InstructionCost(0), AddShuffleMaskAdjustedCost);
5825 std::set<SmallVector<int>> OutputShuffleMasks({V1A, V1B, V2A, V2B});
5826 CostAfter +=
5827 std::accumulate(OutputShuffleMasks.begin(), OutputShuffleMasks.end(),
5828 InstructionCost(0), AddShuffleMaskCost);
5829
5830 LLVM_DEBUG(dbgs() << "Found a binop select shuffle pattern: " << I << "\n");
5831 LLVM_DEBUG(dbgs() << " CostBefore: " << CostBefore
5832 << " vs CostAfter: " << CostAfter << "\n");
5833 if (CostBefore < CostAfter ||
5834 (CostBefore == CostAfter && !feedsIntoVectorReduction(SVI)))
5835 return false;
5836
5837 // The cost model has passed, create the new instructions.
5838 auto GetShuffleOperand = [&](Instruction *I, unsigned Op) -> Value * {
5840 if (!SV)
5841 return I;
5842 if (isa<UndefValue>(SV->getOperand(1)))
5843 if (auto *SSV = dyn_cast<ShuffleVectorInst>(SV->getOperand(0)))
5844 if (InputShuffles.contains(SSV))
5845 return SSV->getOperand(Op);
5846 return SV->getOperand(Op);
5847 };
5848 Builder.SetInsertPoint(*SVI0A->getInsertionPointAfterDef());
5849 Value *NSV0A = Builder.CreateShuffleVector(GetShuffleOperand(SVI0A, 0),
5850 GetShuffleOperand(SVI0A, 1), V1A);
5851 Builder.SetInsertPoint(*SVI0B->getInsertionPointAfterDef());
5852 Value *NSV0B = Builder.CreateShuffleVector(GetShuffleOperand(SVI0B, 0),
5853 GetShuffleOperand(SVI0B, 1), V1B);
5854 Builder.SetInsertPoint(*SVI1A->getInsertionPointAfterDef());
5855 Value *NSV1A = Builder.CreateShuffleVector(GetShuffleOperand(SVI1A, 0),
5856 GetShuffleOperand(SVI1A, 1), V2A);
5857 Builder.SetInsertPoint(*SVI1B->getInsertionPointAfterDef());
5858 Value *NSV1B = Builder.CreateShuffleVector(GetShuffleOperand(SVI1B, 0),
5859 GetShuffleOperand(SVI1B, 1), V2B);
5860 Builder.SetInsertPoint(Op0);
5861 Value *NOp0 = Builder.CreateBinOp((Instruction::BinaryOps)Op0->getOpcode(),
5862 NSV0A, NSV0B);
5863 if (auto *I = dyn_cast<Instruction>(NOp0))
5864 I->copyIRFlags(Op0, true);
5865 Builder.SetInsertPoint(Op1);
5866 Value *NOp1 = Builder.CreateBinOp((Instruction::BinaryOps)Op1->getOpcode(),
5867 NSV1A, NSV1B);
5868 if (auto *I = dyn_cast<Instruction>(NOp1))
5869 I->copyIRFlags(Op1, true);
5870
5871 for (int S = 0, E = ReconstructMasks.size(); S != E; S++) {
5872 Builder.SetInsertPoint(Shuffles[S]);
5873 Value *NSV = Builder.CreateShuffleVector(NOp0, NOp1, ReconstructMasks[S]);
5874 replaceValue(*Shuffles[S], *NSV, false);
5875 }
5876
5877 Worklist.pushValue(NSV0A);
5878 Worklist.pushValue(NSV0B);
5879 Worklist.pushValue(NSV1A);
5880 Worklist.pushValue(NSV1B);
5881 return true;
5882}
5883
5884/// Check if instruction depends on ZExt and this ZExt can be moved after the
5885/// instruction. Move ZExt if it is profitable. For example:
5886/// logic(zext(x),y) -> zext(logic(x,trunc(y)))
5887/// lshr((zext(x),y) -> zext(lshr(x,trunc(y)))
5888/// Cost model calculations takes into account if zext(x) has other users and
5889/// whether it can be propagated through them too.
5890bool VectorCombine::shrinkType(Instruction &I) {
5891 Value *ZExted, *OtherOperand;
5892 if (!match(&I, m_c_BitwiseLogic(m_ZExt(m_Value(ZExted)),
5893 m_Value(OtherOperand))) &&
5894 !match(&I, m_LShr(m_ZExt(m_Value(ZExted)), m_Value(OtherOperand))))
5895 return false;
5896
5897 Value *ZExtOperand = I.getOperand(I.getOperand(0) == OtherOperand ? 1 : 0);
5898
5899 auto *BigTy = cast<FixedVectorType>(I.getType());
5900 auto *SmallTy = cast<FixedVectorType>(ZExted->getType());
5901 unsigned BW = SmallTy->getElementType()->getPrimitiveSizeInBits();
5902
5903 if (I.getOpcode() == Instruction::LShr) {
5904 // Check that the shift amount is less than the number of bits in the
5905 // smaller type. Otherwise, the smaller lshr will return a poison value.
5906 KnownBits ShAmtKB = computeKnownBits(I.getOperand(1), *DL);
5907 if (ShAmtKB.getMaxValue().uge(BW))
5908 return false;
5909 } else {
5910 // Check that the expression overall uses at most the same number of bits as
5911 // ZExted
5912 KnownBits KB = computeKnownBits(&I, *DL);
5913 if (KB.countMaxActiveBits() > BW)
5914 return false;
5915 }
5916
5917 // Calculate costs of leaving current IR as it is and moving ZExt operation
5918 // later, along with adding truncates if needed
5920 Instruction::ZExt, BigTy, SmallTy,
5921 TargetTransformInfo::CastContextHint::None, CostKind);
5922 InstructionCost CurrentCost = ZExtCost;
5923 InstructionCost ShrinkCost = 0;
5924
5925 // Calculate total cost and check that we can propagate through all ZExt users
5926 for (User *U : ZExtOperand->users()) {
5927 auto *UI = cast<Instruction>(U);
5928 if (UI == &I) {
5929 CurrentCost +=
5930 TTI.getArithmeticInstrCost(UI->getOpcode(), BigTy, CostKind);
5931 ShrinkCost +=
5932 TTI.getArithmeticInstrCost(UI->getOpcode(), SmallTy, CostKind);
5933 ShrinkCost += ZExtCost;
5934 continue;
5935 }
5936
5937 if (!Instruction::isBinaryOp(UI->getOpcode()))
5938 return false;
5939
5940 // Check if we can propagate ZExt through its other users
5941 KnownBits KB = computeKnownBits(UI, *DL);
5942 if (KB.countMaxActiveBits() > BW)
5943 return false;
5944
5945 CurrentCost += TTI.getArithmeticInstrCost(UI->getOpcode(), BigTy, CostKind);
5946 ShrinkCost +=
5947 TTI.getArithmeticInstrCost(UI->getOpcode(), SmallTy, CostKind);
5948 ShrinkCost += ZExtCost;
5949 }
5950
5951 // If the other instruction operand is not a constant, we'll need to
5952 // generate a truncate instruction. So we have to adjust cost
5953 if (!isa<Constant>(OtherOperand))
5954 ShrinkCost += TTI.getCastInstrCost(
5955 Instruction::Trunc, SmallTy, BigTy,
5956 TargetTransformInfo::CastContextHint::None, CostKind);
5957
5958 // If the cost of shrinking types and leaving the IR is the same, we'll lean
5959 // towards modifying the IR because shrinking opens opportunities for other
5960 // shrinking optimisations.
5961 if (ShrinkCost > CurrentCost)
5962 return false;
5963
5964 Builder.SetInsertPoint(&I);
5965 Value *Op0 = ZExted;
5966 Value *Op1 = Builder.CreateTrunc(OtherOperand, SmallTy);
5967 // Keep the order of operands the same
5968 if (I.getOperand(0) == OtherOperand)
5969 std::swap(Op0, Op1);
5970 Value *NewBinOp =
5971 Builder.CreateBinOp((Instruction::BinaryOps)I.getOpcode(), Op0, Op1);
5972 if (auto *NewBinOpI = dyn_cast<Instruction>(NewBinOp)) {
5973 NewBinOpI->copyIRFlags(&I);
5974 NewBinOpI->copyMetadata(I);
5975 }
5976 Value *NewZExtr = Builder.CreateZExt(NewBinOp, BigTy);
5977 replaceValue(I, *NewZExtr);
5978 return true;
5979}
5980
5981/// insert (DstVec, (extract SrcVec, ExtIdx), InsIdx) -->
5982/// shuffle (DstVec, SrcVec, Mask)
5983bool VectorCombine::foldInsExtVectorToShuffle(Instruction &I) {
5984 Value *DstVec, *SrcVec;
5985 uint64_t ExtIdx, InsIdx;
5986 if (!match(&I,
5987 m_InsertElt(m_Value(DstVec),
5988 m_ExtractElt(m_Value(SrcVec), m_ConstantInt(ExtIdx)),
5989 m_ConstantInt(InsIdx))))
5990 return false;
5991
5992 auto *DstVecTy = dyn_cast<FixedVectorType>(I.getType());
5993 auto *SrcVecTy = dyn_cast<FixedVectorType>(SrcVec->getType());
5994 // We can try combining vectors with different element sizes.
5995 if (!DstVecTy || !SrcVecTy ||
5996 SrcVecTy->getElementType() != DstVecTy->getElementType())
5997 return false;
5998
5999 unsigned NumDstElts = DstVecTy->getNumElements();
6000 unsigned NumSrcElts = SrcVecTy->getNumElements();
6001 if (InsIdx >= NumDstElts || ExtIdx >= NumSrcElts || NumDstElts == 1)
6002 return false;
6003
6004 // Insertion into poison is a cheaper single operand shuffle.
6006 SmallVector<int> Mask(NumDstElts, PoisonMaskElem);
6007
6008 bool NeedExpOrNarrow = NumSrcElts != NumDstElts;
6009 bool NeedDstSrcSwap = isa<PoisonValue>(DstVec) && !isa<UndefValue>(SrcVec);
6010 if (NeedDstSrcSwap) {
6012 Mask[InsIdx] = ExtIdx % NumDstElts;
6013 std::swap(DstVec, SrcVec);
6014 } else {
6016 std::iota(Mask.begin(), Mask.end(), 0);
6017 Mask[InsIdx] = (ExtIdx % NumDstElts) + NumDstElts;
6018 }
6019
6020 // Cost
6021 auto *Ins = cast<InsertElementInst>(&I);
6022 auto *Ext = cast<ExtractElementInst>(I.getOperand(1));
6023 InstructionCost InsCost =
6024 TTI.getVectorInstrCost(*Ins, DstVecTy, CostKind, InsIdx);
6025 InstructionCost ExtCost =
6026 TTI.getVectorInstrCost(*Ext, DstVecTy, CostKind, ExtIdx);
6027 InstructionCost OldCost = ExtCost + InsCost;
6028
6029 InstructionCost NewCost = 0;
6030 SmallVector<int> ExtToVecMask;
6031 if (!NeedExpOrNarrow) {
6032 // Ignore 'free' identity insertion shuffle.
6033 // TODO: getShuffleCost should return TCC_Free for Identity shuffles.
6034 if (!ShuffleVectorInst::isIdentityMask(Mask, NumSrcElts))
6035 NewCost += TTI.getShuffleCost(SK, DstVecTy, DstVecTy, CostKind, Mask, 0,
6036 nullptr, {DstVec, SrcVec});
6037 } else {
6038 // When creating a length-changing-vector, always try to keep the relevant
6039 // element in an equivalent position, so that bulk shuffles are more likely
6040 // to be useful.
6041 ExtToVecMask.assign(NumDstElts, PoisonMaskElem);
6042 ExtToVecMask[ExtIdx % NumDstElts] = ExtIdx;
6043 // Add cost for expanding or narrowing
6045 DstVecTy, SrcVecTy, CostKind, ExtToVecMask);
6046 NewCost += TTI.getShuffleCost(SK, DstVecTy, DstVecTy, CostKind, Mask);
6047 }
6048
6049 if (!Ext->hasOneUse())
6050 NewCost += ExtCost;
6051
6052 LLVM_DEBUG(dbgs() << "Found a insert/extract shuffle-like pair: " << I
6053 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
6054 << "\n");
6055
6056 if (OldCost < NewCost)
6057 return false;
6058
6059 if (NeedExpOrNarrow) {
6060 if (!NeedDstSrcSwap)
6061 SrcVec = Builder.CreateShuffleVector(SrcVec, ExtToVecMask);
6062 else
6063 DstVec = Builder.CreateShuffleVector(DstVec, ExtToVecMask);
6064 }
6065
6066 // Canonicalize undef param to RHS to help further folds.
6067 if (isa<UndefValue>(DstVec) && !isa<UndefValue>(SrcVec)) {
6068 ShuffleVectorInst::commuteShuffleMask(Mask, NumDstElts);
6069 std::swap(DstVec, SrcVec);
6070 }
6071
6072 Value *Shuf = Builder.CreateShuffleVector(DstVec, SrcVec, Mask);
6073 replaceValue(I, *Shuf);
6074
6075 return true;
6076}
6077
6078/// Try to replace a chain of insertelements of parts of the same scalar with a
6079/// bitcast and a shuffle (little endian):
6080/// insert (insert poison, (trunc (lshr X, 32)), 0), (trunc X), 1 -->
6081/// shuffle (bitcast X to <2 x i32>), poison, <1, 0>
6082bool VectorCombine::foldInsertScalarPartsToShuffle(Instruction &I) {
6083 auto *VecTy = dyn_cast<FixedVectorType>(I.getType());
6084 if (!VecTy)
6085 return false;
6086
6087 // Start from the last insertelement of the chain.
6088 if (I.hasOneUse() && isa<InsertElementInst>(I.user_back()))
6089 return false;
6090
6091 Type *EltTy = VecTy->getElementType();
6092 if ((!EltTy->isIntegerTy() && !EltTy->isIEEELikeFPTy()) ||
6093 !DL->typeSizeEqualsStoreSize(EltTy))
6094 return false;
6095 unsigned EltBits = EltTy->getPrimitiveSizeInBits();
6096 unsigned NumElts = VecTy->getNumElements();
6097
6098 Value *Src = nullptr;
6099 unsigned NumSrcElts = 0;
6100 SmallVector<int> Mask(NumElts, PoisonMaskElem);
6101 APInt DemandedElts = APInt::getZero(NumElts);
6102 InstructionCost OldCost = 0;
6103 Value *Vec = &I;
6104 while (auto *Ins = dyn_cast<InsertElementInst>(Vec)) {
6105 if (Ins != &I && !Ins->hasOneUse())
6106 return false;
6107 uint64_t Idx;
6108 if (!match(Ins->getOperand(2), m_ConstantInt(Idx)) || Idx >= NumElts)
6109 return false;
6110 Vec = Ins->getOperand(0);
6111 // A later insert to the same element overrides this one.
6112 if (DemandedElts[Idx])
6113 continue;
6114 DemandedElts.setBit(Idx);
6115
6116 // Match (bitcast (trunc (lshr X, ShAmt))), the bitcast and shift being
6117 // optional.
6118 Value *Elt = Ins->getOperand(1);
6119 Value *Trunc = Elt;
6120 match(Trunc, m_BitCast(m_Value(Trunc)));
6121 Value *X;
6122 if (!match(Trunc, m_Trunc(m_Value(X))) || !X->getType()->isIntegerTy() ||
6123 Trunc->getType()->getPrimitiveSizeInBits() != EltBits)
6124 return false;
6125 Value *Shift = nullptr;
6126 uint64_t ShAmt = 0;
6127 if (match(X, m_LShr(m_Value(), m_ConstantInt(ShAmt)))) {
6128 Shift = X;
6129 X = cast<Instruction>(Shift)->getOperand(0);
6130 }
6131
6132 if (!Src) {
6133 unsigned SrcBits = X->getType()->getIntegerBitWidth();
6134 if (SrcBits % EltBits)
6135 return false;
6136 Src = X;
6137 NumSrcElts = SrcBits / EltBits;
6138 } else if (X != Src) {
6139 return false;
6140 }
6141 uint64_t Part = ShAmt / EltBits;
6142 if (ShAmt % EltBits || Part >= NumSrcElts)
6143 return false;
6144 Mask[Idx] = DL->isBigEndian() ? NumSrcElts - 1 - Part : Part;
6145
6146 // The scalar ops die with the chain if it is their only user.
6147 for (Value *V : {Elt == Trunc ? nullptr : Elt, Trunc, Shift}) {
6148 if (!V)
6149 continue;
6150 if (!V->hasOneUse())
6151 break;
6153 }
6154 }
6155 // Elements that are not inserted become poison, so the base must be poison
6156 // unless every element is inserted.
6157 if (!Src || (!isa<PoisonValue>(Vec) && !DemandedElts.isAllOnes()))
6158 return false;
6159 // Inserting a single part is a scalar insert or a splat, whose canonical
6160 // insertelement (+ splat shuffle) form is better left alone.
6161 if (all_equal(
6162 make_filter_range(Mask, [](int M) { return M != PoisonMaskElem; })))
6163 return false;
6164
6165 OldCost += TTI.getScalarizationOverhead(VecTy, DemandedElts, /*Insert=*/true,
6166 /*Extract=*/false, CostKind);
6167
6168 auto *SrcVecTy = FixedVectorType::get(EltTy, NumSrcElts);
6169 InstructionCost NewCost =
6170 TTI.getCastInstrCost(Instruction::BitCast, SrcVecTy, Src->getType(),
6172 bool IsIdentity = NumSrcElts == NumElts &&
6173 ShuffleVectorInst::isIdentityMask(Mask, NumSrcElts);
6174 if (!IsIdentity)
6175 NewCost += TTI.getShuffleCost(TTI::SK_PermuteSingleSrc, VecTy, SrcVecTy,
6176 CostKind, Mask);
6177
6178 LLVM_DEBUG(dbgs() << "Found an insertelement chain of scalar parts: " << I
6179 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
6180 << "\n");
6181 if (!OldCost.isValid() || !NewCost.isValid() || NewCost >= OldCost)
6182 return false;
6183
6184 Value *Cast = Builder.CreateBitCast(Src, SrcVecTy);
6185 Value *Shuf = IsIdentity ? Cast : Builder.CreateShuffleVector(Cast, Mask);
6186 replaceValue(I, *Shuf);
6187 return true;
6188}
6189
6190/// Return the number of data operands of \p Inst.
6191static unsigned getNumDataOperands(const Instruction *Inst) {
6192 if (auto *CB = dyn_cast<CallBase>(Inst))
6193 return CB->arg_size(); // Exclude callee operand and bundles.
6194 return Inst->getNumOperands();
6195}
6196
6197/// Return true if \p Inst is an elementwise operation that can be rebuilt at a
6198/// wider element count.
6200 auto *ResultTy = dyn_cast<VectorType>(Inst->getType());
6201 if (!ResultTy || !isSafeToSpeculativelyExecute(Inst))
6202 return false;
6203
6204 if (auto *II = dyn_cast<IntrinsicInst>(Inst)) {
6205 if (II->hasOperandBundles() ||
6206 !isTriviallyVectorizable(II->getIntrinsicID()))
6207 return false;
6209 FreezeInst>(Inst)) {
6210 return false;
6211 }
6212
6213 // Reject operations that change the element-count.
6214 // E.g., bitcast <vscale x 4 x i16> %v to <vscale x 8 x i8>
6215 for (unsigned Op = 0, E = getNumDataOperands(Inst); Op != E; ++Op) {
6216 auto *OperandTy = dyn_cast<VectorType>(Inst->getOperand(Op)->getType());
6217 if (OperandTy &&
6218 OperandTy->getElementCount() != ResultTy->getElementCount())
6219 return false;
6220 }
6221
6222 return true;
6223}
6224
6225/// Return the common splat value of \p Values.
6227 auto GetSplatOrScalar = [](Value *V) {
6228 return isa<VectorType>(V->getType()) ? getSplatValue(V) : V;
6229 };
6230
6231 Value *CommonValue = GetSplatOrScalar(Values.front());
6232 if (!CommonValue)
6233 return nullptr;
6234 for (Value *V : Values.drop_front())
6235 if (GetSplatOrScalar(V) != CommonValue)
6236 return nullptr;
6237 return CommonValue;
6238}
6239
6240/// Return the common deinterleave intrinsic if \p Members are its extracts in
6241/// field order.
6243 IntrinsicInst *Deinterleave = nullptr;
6244 for (const auto &[Index, Member] : enumerate(Members)) {
6245 auto *Extract = dyn_cast<ExtractValueInst>(Member);
6246 if (!Extract || Extract->getNumIndices() != 1 ||
6247 *Extract->idx_begin() != Index)
6248 return nullptr;
6249
6250 auto *Current = dyn_cast<IntrinsicInst>(Extract->getAggregateOperand());
6251 if (!Current || (Deinterleave && Current != Deinterleave))
6252 return nullptr;
6253 Deinterleave = Current;
6254 }
6255 unsigned Factor = Members.size();
6256 if (Deinterleave->hasOperandBundles() ||
6257 getDeinterleaveIntrinsicFactor(Deinterleave->getIntrinsicID()) !=
6258 Factor ||
6259 !Deinterleave->hasNUndroppableUses(Factor))
6260 return nullptr;
6261 return Deinterleave;
6262}
6263
6264/// Return the operand at \p OperandIndex of each \p Members.
6266 unsigned OperandIndex) {
6268 for (Value *Member : Members)
6269 Operands.push_back(cast<Instruction>(Member)->getOperand(OperandIndex));
6270 return Operands;
6271}
6272
6273/// Check whether the tree of elementwise operations each feeding \p Members
6274/// can be rebuilt at the interleaved width.
6276 unsigned &NumScanned) {
6277 unsigned Factor = Members.size();
6278 if (getCommonDeinterleavedSource(Members))
6279 return true;
6280 if (NumScanned + Factor > MaxInstrsToScan)
6281 return false;
6282 NumScanned += Factor;
6283
6284 auto *FirstInst = dyn_cast<Instruction>(Members.front());
6285 if (!FirstInst || !isSupportedElementwise(FirstInst) ||
6286 !FirstInst->getSingleUndroppableUse())
6287 return false;
6288
6289 for (Value *Member : Members.drop_front()) {
6290 auto *Inst = dyn_cast<Instruction>(Member);
6291 if (!Inst || !Inst->getSingleUndroppableUse() ||
6292 !FirstInst->isSameOperationAs(Inst, Instruction::CompareCallTargets))
6293 return false;
6294 }
6295
6296 // Scalars operands should be equal among all members.
6297 // Vector operands should be a common splat value or can be widened.
6298 for (unsigned Op = 0, E = getNumDataOperands(FirstInst); Op != E; ++Op) {
6302 return false;
6303 }
6304 return true;
6305}
6306
6308 ArrayRef<Value *> NewOperands,
6309 VectorType *WideResultTy,
6311 if (isa<BinaryOperator, UnaryOperator>(NarrowInst))
6312 return Builder.CreateNAryOp(NarrowInst->getOpcode(), NewOperands);
6313 if (auto *Cast = dyn_cast<CastInst>(NarrowInst))
6314 return Builder.CreateCast(Cast->getOpcode(), NewOperands[0], WideResultTy);
6315 if (auto *Cmp = dyn_cast<CmpInst>(NarrowInst))
6316 return Builder.CreateCmp(Cmp->getPredicate(), NewOperands[0],
6317 NewOperands[1]);
6318 if (isa<SelectInst>(NarrowInst))
6319 return Builder.CreateSelect(
6320 NewOperands[0], NewOperands[1], NewOperands[2], /*Name=*/"",
6321 ProfcheckDisableMetadataFixes ? nullptr : NarrowInst);
6322 if (isa<FreezeInst>(NarrowInst))
6323 return Builder.CreateFreeze(NewOperands[0]);
6324 if (auto *II = dyn_cast<IntrinsicInst>(NarrowInst))
6325 return Builder.CreateIntrinsic(WideResultTy, II->getIntrinsicID(),
6326 NewOperands);
6327 llvm_unreachable("Unsupported instruction");
6328}
6329
6330static Value *
6333 if (auto *Deinterleave = getCommonDeinterleavedSource(Members)) {
6334 Value *Source = Deinterleave->getArgOperand(0);
6335 assert(cast<VectorType>(Source->getType())->getElementCount() == WideEC &&
6336 "deinterleave source must have the interleaved element count");
6337 return Source;
6338 }
6339
6340 auto *NarrowInst = cast<Instruction>(Members.front());
6341 unsigned NumOperands = getNumDataOperands(NarrowInst);
6342 SmallVector<Value *, 4> NewOperands;
6343 NewOperands.reserve(NumOperands);
6344 for (unsigned Op = 0; Op != NumOperands; ++Op) {
6346 Value *NewOperand = nullptr;
6347 if ((NewOperand = getCommonSplatValue(Operands))) {
6348 if (isa<VectorType>(Operands.front()->getType())) {
6349 Builder.SetCurrentDebugLocation(NarrowInst->getDebugLoc());
6350 NewOperand = Builder.CreateVectorSplat(WideEC, NewOperand);
6351 } else {
6352 assert(all_equal(Operands) && "expected all operands to be equal");
6353 }
6354 } else {
6355 NewOperand = widenDeinterleavedOperations(Operands, WideEC, Builder);
6356 }
6357 NewOperands.push_back(NewOperand);
6358 }
6359
6360 Builder.SetCurrentDebugLocation(NarrowInst->getDebugLoc());
6361 auto *WideResultTy =
6362 VectorType::get(NarrowInst->getType()->getScalarType(), WideEC);
6363 Value *NewValue =
6364 createWideInstruction(NarrowInst, NewOperands, WideResultTy, Builder);
6365 if (auto *NewInst = dyn_cast<Instruction>(NewValue)) {
6366 propagateIRFlags(NewInst, Members);
6367 propagateMetadata(NewInst, Members);
6368 }
6369 return NewValue;
6370}
6371
6372/// Fold away vector.deinterleave/interleave intrinsics with matching trees of
6373/// elementwise operations between them.
6374///
6375/// For example:
6376/// ```
6377/// %d = call { <2 x i16>, <2 x i16> } @deinterleave2.v4i16(<4 x i16> %v)
6378/// %f0 = extractvalue { <2 x i16>, <2 x i16> } %d, 0
6379/// %f1 = extractvalue { <2 x i16>, <2 x i16> } %d, 1
6380///
6381/// %u0 = add <2 x i16> %f0, splat (i16 3)
6382/// %u1 = add <2 x i16> %f1, splat (i16 3)
6383///
6384/// %r = call <4 x i16> @interleave2.v4i16(<2 x i16> %u0, <2 x i16> %u1)
6385/// ```
6386/// Folds to:
6387/// ```
6388/// %r = add <4 x i16> %v, splat (i16 3)
6389/// ```
6390/// And with two sources:
6391/// ```
6392/// %da = call { <2 x i16>, <2 x i16> } @deinterleave2.v4i16(<4 x i16> %a)
6393/// %a0 = extractvalue { <2 x i16>, <2 x i16> } %da, 0
6394/// %a1 = extractvalue { <2 x i16>, <2 x i16> } %da, 1
6395/// %db = call { <2 x i16>, <2 x i16> } @deinterleave2.v4i16(<4 x i16> %b)
6396/// %b0 = extractvalue { <2 x i16>, <2 x i16> } %db, 0
6397/// %b1 = extractvalue { <2 x i16>, <2 x i16> } %db, 1
6398///
6399/// %m0 = mul <2 x i16> %a0, %b0
6400/// %m1 = mul <2 x i16> %a1, %b1
6401///
6402/// %r = call <4 x i16> @interleave2.v4i16(<2 x i16> %m0, <2 x i16> %m1)
6403/// ```
6404/// Folds to:
6405/// ```
6406/// %r = mul <4 x i16> %a, %b
6407/// ```
6408bool VectorCombine::foldInterleaveOfDeinterleaveChains(Instruction &I) {
6409 auto *Interleave = dyn_cast<IntrinsicInst>(&I);
6410 if (!Interleave)
6411 return false;
6412
6413 unsigned Factor = getInterleaveIntrinsicFactor(Interleave->getIntrinsicID());
6414 if (!Factor || Interleave->hasOperandBundles())
6415 return false;
6416
6417 SmallVector<Value *, 8> RootMembers(Interleave->args());
6418 unsigned NumScanned = 0;
6419 if (!canWidenDeinterleavedOperations(RootMembers, NumScanned))
6420 return false;
6421
6422 ElementCount WideEC = cast<VectorType>(I.getType())->getElementCount();
6423 Builder.SetInsertPoint(Interleave);
6424 Value *WideValue = widenDeinterleavedOperations(RootMembers, WideEC, Builder);
6425 assert(WideValue->getType() == Interleave->getType());
6426 replaceValue(*Interleave, *WideValue);
6427 return true;
6428}
6429
6430/// If we're interleaving 2 constant splats, for instance `<vscale x 8 x i32>
6431/// <splat of 666>` and `<vscale x 8 x i32> <splat of 777>`, we can create a
6432/// larger splat `<vscale x 8 x i64> <splat of ((777 << 32) | 666)>` first
6433/// before casting it back into `<vscale x 16 x i32>`.
6434bool VectorCombine::foldInterleaveIntrinsics(Instruction &I) {
6435 if (foldInterleaveOfDeinterleaveChains(I))
6436 return true;
6437
6438 const APInt *SplatVal0, *SplatVal1;
6440 m_APInt(SplatVal0), m_APInt(SplatVal1))))
6441 return false;
6442
6443 LLVM_DEBUG(dbgs() << "VC: Folding interleave2 with two splats: " << I
6444 << "\n");
6445
6446 auto *VTy =
6447 cast<VectorType>(cast<IntrinsicInst>(I).getArgOperand(0)->getType());
6448 auto *ExtVTy = VectorType::getExtendedElementVectorType(VTy);
6449 unsigned Width = VTy->getElementType()->getIntegerBitWidth();
6450
6451 // Just in case the cost of interleave2 intrinsic and bitcast are both
6452 // invalid, in which case we want to bail out, we use <= rather
6453 // than < here. Even they both have valid and equal costs, it's probably
6454 // not a good idea to emit a high-cost constant splat.
6456 TTI.getCastInstrCost(Instruction::BitCast, I.getType(), ExtVTy,
6458 LLVM_DEBUG(dbgs() << "VC: The cost to cast from " << *ExtVTy << " to "
6459 << *I.getType() << " is too high.\n");
6460 return false;
6461 }
6462
6463 APInt NewSplatVal = SplatVal1->zext(Width * 2);
6464 NewSplatVal <<= Width;
6465 NewSplatVal |= SplatVal0->zext(Width * 2);
6466 auto *NewSplat = ConstantVector::getSplat(
6467 ExtVTy->getElementCount(), ConstantInt::get(F.getContext(), NewSplatVal));
6468
6469 IRBuilder<> Builder(&I);
6470 replaceValue(I, *Builder.CreateBitCast(NewSplat, I.getType()));
6471 return true;
6472}
6473
6474/// Given this sequence:
6475/// ```
6476/// %d = llvm.vector.deinterleave2 <vscale x 16 x i32> %v
6477/// %f0 = extractvalue { <vscale x 8 x i32>, <vscale x 8 x i32> } %d, 0
6478/// %f1 = extractvalue { <vscale x 8 x i32>, <vscale x 8 x i32> } %d, 1
6479///
6480/// %low0 = and <vscale x 8 x i32> %f0, splat (i32 65535)
6481/// %low1 = shl <vscale x 8 x i32> %f1, splat (i32 16)
6482/// %merge0 = or disjoint <vscale x 8 x i32> %low0, %low1
6483///
6484/// %high0 = and <vscale x 8 x i32> %f1, splat (i32 -65536)
6485/// %high1 = lshr <vscale x 8 x i32> %f0, splat (i32 16)
6486/// %merge1 = or disjoint <vscale x 8 x i32> %high0, %high1
6487/// ```
6488/// It is actually just de-interleaving a 16-bit vector with double the
6489/// vector length. More generally speaking, it's de-interleaving on a vector
6490/// with half the element width as the original vector.
6491///
6492/// Therefore, we can turn it into:
6493/// ```
6494/// %narrow.v = bitcast <vscale x 16 x i32> %v to <vscale x 32 x i16>
6495/// %d = llvm.vector.deinterleave2 <vscale x 32 x i16> %narrow.v
6496/// %f0 = extractvalue { <vscale x 16 x i16>, <vscale x 16 x i16> } %d, 0
6497/// %f1 = extractvalue { <vscale x 16 x i16>, <vscale x 16 x i16> } %d, 1
6498///
6499/// %merge0 = bitcast <vscale x 16 x i16> %f0 to <vscale x 8 x i32>
6500/// %merge1 = bitcast <vscale x 16 x i16> %f1 to <vscale x 8 x i32>
6501/// ```
6502bool VectorCombine::foldDeinterleaveIntrinsics(Instruction &I) {
6503 // This pattern involves bitcast that is not compatible with big endian.
6504 if (DL->isBigEndian())
6505 return false;
6506
6507 using namespace PatternMatch;
6508 Value *DeinterleavedVal;
6509 if (!match(&I, m_Deinterleave2(m_Value(DeinterleavedVal))))
6510 return false;
6511
6512 VectorType *VecTy = cast<VectorType>(DeinterleavedVal->getType());
6513 IntegerType *ElementTy = dyn_cast<IntegerType>(VecTy->getElementType());
6514 if (!ElementTy)
6515 return false;
6516 unsigned ElementWidth = ElementTy->getBitWidth();
6517 if (ElementWidth < 2 || !isPowerOf2_32(ElementWidth))
6518 return false;
6519 unsigned HalfElementWidth = ElementWidth / 2;
6520
6521 if (!I.hasNUses(2))
6522 return false;
6523 std::array<ExtractValueInst *, 2> OrigFields{};
6524 for (User *Usr : I.users()) {
6525 auto *E = dyn_cast<ExtractValueInst>(Usr);
6526 // The deinterleave result can only be used by extractions.
6527 if (!E || E->getNumIndices() != 1)
6528 return false;
6529 unsigned Idx = *E->idx_begin();
6530 // A single field cannot be extracted more than once.
6531 if (Idx >= 2 || OrigFields[Idx] || !E->hasNUses(2))
6532 return false;
6533 OrigFields[Idx] = E;
6534 }
6535
6536 // Find the merge instruction (i.e. OR) first.
6537 SmallVector<Instruction *, 2> MergeInsts;
6538 for (auto *FieldUsr : OrigFields[0]->users()) {
6539 if (!FieldUsr->hasOneUse() || !isa<Instruction>(FieldUsr->user_back()))
6540 return false;
6541 MergeInsts.push_back(cast<Instruction>(FieldUsr->user_back()));
6542 }
6543 assert(MergeInsts.size() == 2);
6544
6545 // Pattern match bottom-up from the merge instructions.
6546 auto MatchMerge = [&](void) -> bool {
6547 APInt LoMask = APInt::getLowBitsSet(ElementWidth, HalfElementWidth);
6548 APInt HiMask = APInt::getHighBitsSet(ElementWidth, HalfElementWidth);
6549 return match(MergeInsts[0],
6550 m_c_Or(m_And(m_Specific(OrigFields[0]), m_SpecificInt(LoMask)),
6551 m_Shl(m_Specific(OrigFields[1]),
6552 m_SpecificInt(HalfElementWidth)))) &&
6553 match(MergeInsts[1],
6554 m_c_Or(m_And(m_Specific(OrigFields[1]), m_SpecificInt(HiMask)),
6555 m_LShr(m_Specific(OrigFields[0]),
6556 m_SpecificInt(HalfElementWidth))));
6557 };
6558 if (!MatchMerge()) {
6559 std::swap(MergeInsts[0], MergeInsts[1]);
6560 if (!MatchMerge())
6561 return false;
6562 }
6563
6564 // Profitability check.
6565 InstructionCost OldCost =
6566 TTI.getInstructionCost(MergeInsts[0], CostKind) +
6567 TTI.getInstructionCost(cast<Instruction>(MergeInsts[0]->getOperand(0)),
6568 CostKind) +
6569 TTI.getInstructionCost(cast<Instruction>(MergeInsts[0]->getOperand(1)),
6570 CostKind);
6571 // There are two fields (assuming SHL has the same cost as LSHR).
6572 OldCost *= 2;
6573
6574 auto *NewFieldTy = VecTy->getWithNewBitWidth(HalfElementWidth);
6575 auto *NewVecTy =
6576 VectorType::getDoubleElementsVectorType(cast<VectorType>(NewFieldTy));
6577 InstructionCost NewCost =
6578 TTI.getCastInstrCost(Instruction::BitCast, VecTy, NewVecTy,
6580 TTI.getCastInstrCost(Instruction::BitCast, NewFieldTy,
6581 MergeInsts[0]->getType(), TTI::CastContextHint::None,
6582 CostKind) *
6583 2;
6584 if (OldCost <= NewCost || !NewCost.isValid()) {
6585 LLVM_DEBUG(
6586 dbgs() << "VC: New deinterleave2 sequence cost (" << NewCost << ")"
6587 << " is higher than that of the old one (" << OldCost << ")\n");
6588 return false;
6589 }
6590
6591 // Do the replacement.
6592 IRBuilder<> Builder(&I);
6593 Value *NewVecCast = Builder.CreateBitCast(DeinterleavedVal, NewVecTy);
6594 Value *NewDeinterleave = Builder.CreateIntrinsic(
6595 Intrinsic::vector_deinterleave2, {NewVecTy}, {NewVecCast});
6596 Worklist.pushValue(NewVecCast);
6597 Worklist.pushValue(NewDeinterleave);
6598 for (auto [Idx, MergeInst] : enumerate(MergeInsts)) {
6599 Value *NewField = Builder.CreateExtractValue(NewDeinterleave, Idx);
6600 Worklist.pushValue(NewField);
6601 NewField = Builder.CreateBitCast(NewField, MergeInst->getType());
6602 replaceValue(*MergeInst, *NewField);
6603 }
6604
6605 return true;
6606}
6607
6608bool VectorCombine::foldBitcastOfVPLoad(Instruction &I) {
6609 const DataLayout &DL = I.getDataLayout();
6610 auto *Cast = dyn_cast<CastInst>(&I);
6611 if (!Cast || !Cast->isNoopCast(DL) || !isa<VectorType>(Cast->getDestTy()))
6612 return false;
6613
6614 // Fold away bit casts of the loaded value by loading the desired type,
6615 // if the mask is all-ones.
6616 Value *EVL;
6617 auto *II = dyn_cast<VPIntrinsic>(I.getOperand(0));
6619 m_Value(), m_AllOnes(), m_Value(EVL)))))
6620 return false;
6621
6622 VectorType *OrigVecTy = cast<VectorType>(II->getType());
6623 Align OrigAlign =
6624 DL.getValueOrABITypeAlignment(II->getPointerAlignment(), OrigVecTy);
6625 ElementCount OrigVecCnt = OrigVecTy->getElementCount();
6626 VectorType *NewVecTy = cast<VectorType>(Cast->getDestTy());
6627 ElementCount NewVecCnt = NewVecTy->getElementCount();
6628
6629 // Right now we only support cases where the NewVec is longer, because for
6630 // cases where it's shorter, we have to be sure that EVL can be exactly
6631 // divided, otherwise it might yield incorrect results or even page faults
6632 // (if we round-up during the division).
6633 if (!(OrigVecCnt.isScalable() == NewVecCnt.isScalable() &&
6634 NewVecCnt.hasKnownScalarFactor(OrigVecCnt)))
6635 return false;
6636
6637 InstructionCost OldCost =
6638 TTI.getMemIntrinsicInstrCost({Intrinsic::vp_load, OrigVecTy,
6639 II->getMemoryPointerParam(), false,
6640 OrigAlign},
6641 CostKind) +
6642 TTI.getCastInstrCost(Instruction::BitCast, Cast->getType(), OrigVecTy,
6645 {Intrinsic::vp_load, NewVecTy, II->getMemoryPointerParam(), false,
6646 OrigAlign},
6647 CostKind);
6648 LLVM_DEBUG(dbgs() << "foldBitcastOfVPLoad: OldCost=" << OldCost
6649 << " NewCost=" << NewCost << "\n");
6650 if (NewCost > OldCost || !NewCost.isValid())
6651 return false;
6652
6653 Builder.SetInsertPoint(II);
6654 unsigned Factor = NewVecCnt.getKnownScalarFactor(OrigVecCnt);
6655 Value *NewEVL = Builder.CreateNUWMul(EVL, Builder.getInt32(Factor));
6656 Value *NewMask = Builder.CreateVectorSplat(NewVecCnt, Builder.getTrue());
6657 CallInst *NewVP = Builder.CreateIntrinsicWithoutFolding(
6658 NewVecTy, Intrinsic::vp_load,
6659 {II->getMemoryPointerParam(), NewMask, NewEVL});
6660 // Preserve the original alignment.
6661 NewVP->addParamAttrs(
6662 0, AttrBuilder(II->getContext()).addAlignmentAttr(OrigAlign));
6663 replaceValue(*Cast, *NewVP);
6664 return true;
6665}
6666/// Fold the following cases into a single byte-level bit-reverse operation
6667/// and accepts bswap and bitreverse intrinsics:
6668/// bswap(bitreverse(x)) --> bitcast(bitreverse(bitcast(x)))
6669/// bitreverse(bswap(x)) <--> bitcast(bitreverse(bitcast(x)))
6670/// The direction of the fold is cost-model driven.
6671/// Also supports:
6672/// bitcast(bitreverse(bitcast(x))) --> bitreverse(fshl(x))
6673bool VectorCombine::foldBitOrderReverseAndSwap(Instruction &I) {
6674 Value *X;
6675
6677 Type *Ty = X->getType();
6678 Type *VecTy = I.getOperand(0)->getType();
6679 // Detect the case when bitreversing every octet in X individually. Then we
6680 // can use bswap to reorder the octets before doing a single bitreverse.
6681 bool CanUseBswap =
6682 Ty->isIntegerTy() && Ty == I.getType() && isa<FixedVectorType>(VecTy) &&
6683 cast<FixedVectorType>(VecTy)->getElementType()->isIntegerTy(8) &&
6684 Ty->getIntegerBitWidth() % 16 == 0;
6685 // Detect the case when bitreversing upper and lower half of X
6686 // individually. Then we can use fshl as a rotate operation, to swap the
6687 // halves before doing a single bitreverse.
6688 bool CanUseFshl =
6689 Ty->isIntegerTy() && Ty == I.getType() && isa<FixedVectorType>(VecTy) &&
6690 cast<FixedVectorType>(VecTy)->getElementType()->isIntegerTy() &&
6691 cast<FixedVectorType>(VecTy)->getNumElements() == 2;
6692 if (CanUseBswap || CanUseFshl) {
6693 auto *InnerCall = dyn_cast<Instruction>(I.getOperand(0));
6694 if (!InnerCall)
6695 return false;
6696 auto *InnerBitCast = dyn_cast<BitCastInst>(InnerCall->getOperand(0));
6697 if (!InnerBitCast)
6698 return false;
6699 Constant *HalfBW = ConstantInt::get(Ty, Ty->getIntegerBitWidth() / 2);
6700 InstructionCost OldCost = TTI.getInstructionCost(InnerBitCast, CostKind) +
6701 TTI.getInstructionCost(InnerCall, CostKind) +
6703 IntrinsicCostAttributes ICABSwap(Intrinsic::bswap, Ty, {Ty});
6704 IntrinsicCostAttributes ICABFshl(Intrinsic::fshl, Ty, {X, X, HalfBW},
6705 {Ty, Ty, Ty});
6706 IntrinsicCostAttributes ICABRev(Intrinsic::bitreverse, Ty, {Ty});
6707 InstructionCost NewCost =
6708 TTI.getIntrinsicInstrCost(CanUseBswap ? ICABSwap : ICABFshl,
6709 CostKind) +
6711 if (!InnerCall->hasOneUse())
6712 NewCost += TTI.getInstructionCost(InnerCall, CostKind) +
6713 TTI.getInstructionCost(InnerBitCast, CostKind);
6714 else if (!InnerBitCast->hasOneUse())
6715 NewCost += TTI.getInstructionCost(InnerBitCast, CostKind);
6716 LLVM_DEBUG(dbgs() << "Found bitreverse vector roundtrip: " << I
6717 << "\n OldCost: " << OldCost
6718 << " vs NewCost: " << NewCost << "\n");
6719 if (NewCost.isValid() && NewCost < OldCost) {
6720 Builder.SetInsertPoint(&I);
6721 Value *Swap =
6722 CanUseBswap
6723 ? Builder.CreateUnaryIntrinsic(Intrinsic::bswap, X)
6724 : Builder.CreateIntrinsic(Ty, Intrinsic::fshl, {X, X, HalfBW});
6725 Worklist.pushValue(Swap);
6726 Value *BRev = Builder.CreateUnaryIntrinsic(Intrinsic::bitreverse, Swap);
6727 replaceValue(I, *BRev);
6728 return true;
6729 }
6730 }
6731 }
6732
6733 if (!match(&I, m_BitReverse(m_BSwap(m_Value(X)))) &&
6735 return false;
6736 Type *Ty = I.getType();
6737 Type *I8Ty = Builder.getInt8Ty();
6738 TypeSize ElementSize = DL->getTypeStoreSize(Ty);
6739 ElementCount NewVecCnt = ElementCount::get(ElementSize.getKnownMinValue(),
6740 ElementSize.isScalable());
6741 Type *NewVecTy = VectorType::get(I8Ty, NewVecCnt);
6742 auto *II = cast<IntrinsicInst>(&I);
6743 auto *InnerII = cast<IntrinsicInst>(II->getArgOperand(0));
6744 // OldCost = cost of bitreverse/bswap + cost of bswap/bitreverse
6747 // NewCost = cost of bitcast to byte vector +
6748 // cost of bitreverse/bswap on byte vector +
6749 // cost of bitcast back to original type
6750 InstructionCost CastToVecCost = TTI.getCastInstrCost(
6751 Instruction::BitCast, NewVecTy, Ty, TTI::CastContextHint::None, CostKind);
6752 InstructionCost CastToOrigCost = TTI.getCastInstrCost(
6753 Instruction::BitCast, Ty, NewVecTy, TTI::CastContextHint::None, CostKind);
6754 IntrinsicCostAttributes ICANew(Intrinsic::bitreverse, NewVecTy, {NewVecTy});
6755 InstructionCost NewIntrinsicCost =
6757 InstructionCost NewCost = CastToVecCost + NewIntrinsicCost + CastToOrigCost;
6758 if (!InnerII->hasOneUse())
6759 NewCost += TTI.getInstructionCost(InnerII, CostKind);
6760 LLVM_DEBUG(dbgs() << "Found bitorder reverse and swap: " << I
6761 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
6762 << "\n");
6763 if (!NewCost.isValid() || NewCost >= OldCost)
6764 return false;
6765 // Perform transform: bitcast(arg, <N x i8>), bitreverse, bitcast back
6766 Builder.SetInsertPoint(II);
6767 Value *CastToVec = Builder.CreateBitCast(X, NewVecTy);
6768 Value *NewCall =
6769 Builder.CreateUnaryIntrinsic(Intrinsic::bitreverse, CastToVec);
6770 Value *CastToOrig = Builder.CreateBitCast(NewCall, Ty);
6771 replaceValue(I, *CastToOrig);
6772 return true;
6773}
6774
6775/// Given the maximum shuffle index and load vector type, compute the number of
6776/// elements for the shrunk load, rounding up to the next full vector register
6777/// boundary to avoid scalar remainders that legalize poorly.
6778static unsigned getAlignedNumElements(unsigned MaxIdx, FixedVectorType *LoadTy,
6779 const TargetTransformInfo &TTI,
6780 const DataLayout &DL) {
6781 unsigned RawNumElements = MaxIdx + 1u;
6782 Type *ElemTy = LoadTy->getElementType();
6783 // Skip alignment for illegal element types.
6784 if (!TTI.isTypeLegal(ElemTy))
6785 return RawNumElements;
6786
6787 TypeSize ElemSize = DL.getTypeSizeInBits(ElemTy);
6788 if (ElemSize.isScalable() || ElemSize.isZero())
6789 return RawNumElements;
6790
6793 if (RegSize.isScalable() || RegSize.isZero())
6794 return RawNumElements;
6795
6796 unsigned ElemsPerReg = RegSize.getFixedValue() / ElemSize.getFixedValue();
6797 // If the load already fits in a register, keep the exact size.
6798 // Otherwise round up to the next full register boundary.
6799 if (ElemsPerReg == 0 || RawNumElements <= ElemsPerReg)
6800 return RawNumElements;
6801
6802 return alignTo(RawNumElements, ElemsPerReg);
6803}
6804
6805// Attempt to shrink loads that are only used by shufflevector instructions.
6806bool VectorCombine::shrinkLoadForShuffles(Instruction &I) {
6807 auto *OldLoad = dyn_cast<LoadInst>(&I);
6808 if (!OldLoad || !OldLoad->isSimple())
6809 return false;
6810
6811 auto *OldLoadTy = dyn_cast<FixedVectorType>(OldLoad->getType());
6812 if (!OldLoadTy)
6813 return false;
6814
6815 unsigned const OldNumElements = OldLoadTy->getNumElements();
6816
6817 // Search all uses of load. If all uses are shufflevector instructions, and
6818 // the second operands are all poison values, find the minimum and maximum
6819 // indices of the vector elements referenced by all shuffle masks.
6820 // Otherwise return `std::nullopt`.
6821 using IndexRange = std::pair<int, int>;
6822 auto GetIndexRangeInShuffles = [&]() -> std::optional<IndexRange> {
6823 IndexRange OutputRange = IndexRange(OldNumElements, -1);
6824 for (llvm::Use &Use : I.uses()) {
6825 // Ensure all uses match the required pattern.
6826 User *Shuffle = Use.getUser();
6827 ArrayRef<int> Mask;
6828
6829 if (!match(Shuffle,
6830 m_Shuffle(m_Specific(OldLoad), m_Undef(), m_Mask(Mask))))
6831 return std::nullopt;
6832
6833 // Ignore shufflevector instructions that have no uses.
6834 if (Shuffle->use_empty())
6835 continue;
6836
6837 // Find the min and max indices used by the shufflevector instruction.
6838 for (int Index : Mask) {
6839 if (Index >= 0 && Index < static_cast<int>(OldNumElements)) {
6840 OutputRange.first = std::min(Index, OutputRange.first);
6841 OutputRange.second = std::max(Index, OutputRange.second);
6842 }
6843 }
6844 }
6845
6846 if (OutputRange.second < OutputRange.first)
6847 return std::nullopt;
6848
6849 return OutputRange;
6850 };
6851
6852 // Get the range of vector elements used by shufflevector instructions.
6853 if (std::optional<IndexRange> Indices = GetIndexRangeInShuffles()) {
6854 unsigned const NewNumElements =
6855 getAlignedNumElements(Indices->second, OldLoadTy, TTI, *DL);
6856
6857 // If the range of vector elements is smaller than the full load, attempt
6858 // to create a smaller load.
6859 if (NewNumElements < OldNumElements) {
6860 IRBuilder Builder(&I);
6861 Builder.SetCurrentDebugLocation(I.getDebugLoc());
6862
6863 // Calculate costs of old and new ops.
6864 Type *ElemTy = OldLoadTy->getElementType();
6865 FixedVectorType *NewLoadTy = FixedVectorType::get(ElemTy, NewNumElements);
6866 Value *PtrOp = OldLoad->getPointerOperand();
6867
6869 Instruction::Load, OldLoad->getType(), OldLoad->getAlign(),
6870 OldLoad->getPointerAddressSpace(), CostKind);
6871 InstructionCost NewCost =
6872 TTI.getMemoryOpCost(Instruction::Load, NewLoadTy, OldLoad->getAlign(),
6873 OldLoad->getPointerAddressSpace(), CostKind);
6874
6875 using UseEntry = std::pair<ShuffleVectorInst *, std::vector<int>>;
6877 unsigned const MaxIndex = NewNumElements * 2u;
6878
6879 for (llvm::Use &Use : I.uses()) {
6880 auto *Shuffle = cast<ShuffleVectorInst>(Use.getUser());
6881
6882 // Ignore shufflevector instructions that have no uses.
6883 if (Shuffle->use_empty())
6884 continue;
6885
6886 ArrayRef<int> OldMask = Shuffle->getShuffleMask();
6887
6888 // Create entry for new use.
6889 NewUses.push_back({Shuffle, OldMask});
6890
6891 // Validate mask indices.
6892 for (int Index : OldMask) {
6893 if (Index >= static_cast<int>(MaxIndex))
6894 return false;
6895 }
6896
6897 // Update costs.
6898 OldCost +=
6900 OldLoadTy, CostKind, OldMask);
6901 NewCost +=
6903 NewLoadTy, CostKind, OldMask);
6904 }
6905
6906 LLVM_DEBUG(
6907 dbgs() << "Found a load used only by shufflevector instructions: "
6908 << I << "\n OldCost: " << OldCost
6909 << " vs NewCost: " << NewCost << "\n");
6910
6911 if (OldCost < NewCost || !NewCost.isValid())
6912 return false;
6913
6914 // Create new load of smaller vector.
6915 auto *NewLoad = cast<LoadInst>(
6916 Builder.CreateAlignedLoad(NewLoadTy, PtrOp, OldLoad->getAlign()));
6917 NewLoad->copyMetadata(I);
6918
6919 // Replace all uses.
6920 for (UseEntry &Use : NewUses) {
6921 ShuffleVectorInst *Shuffle = Use.first;
6922 std::vector<int> &NewMask = Use.second;
6923
6924 Builder.SetInsertPoint(Shuffle);
6925 Builder.SetCurrentDebugLocation(Shuffle->getDebugLoc());
6926 Value *NewShuffle = Builder.CreateShuffleVector(
6927 NewLoad, PoisonValue::get(NewLoadTy), NewMask);
6928
6929 replaceValue(*Shuffle, *NewShuffle, false);
6930 }
6931
6932 return true;
6933 }
6934 }
6935 return false;
6936}
6937
6938// Attempt to narrow a phi of shufflevector instructions where the two incoming
6939// values have the same operands but different masks. If the two shuffle masks
6940// are offsets of one another we can use one branch to rotate the incoming
6941// vector and perform one larger shuffle after the phi.
6942bool VectorCombine::shrinkPhiOfShuffles(Instruction &I) {
6943 auto *Phi = dyn_cast<PHINode>(&I);
6944 if (!Phi || Phi->getNumIncomingValues() != 2u)
6945 return false;
6946
6947 Value *Op = nullptr;
6948 ArrayRef<int> Mask0;
6949 ArrayRef<int> Mask1;
6950
6951 if (!match(Phi->getOperand(0u),
6952 m_OneUse(m_Shuffle(m_Value(Op), m_Poison(), m_Mask(Mask0)))) ||
6953 !match(Phi->getOperand(1u),
6954 m_OneUse(m_Shuffle(m_Specific(Op), m_Poison(), m_Mask(Mask1)))))
6955 return false;
6956
6957 auto *Shuf = cast<ShuffleVectorInst>(Phi->getOperand(0u));
6958
6959 // Ensure result vectors are wider than the argument vector.
6960 auto *InputVT = cast<FixedVectorType>(Op->getType());
6961 auto *ResultVT = cast<FixedVectorType>(Shuf->getType());
6962 auto const InputNumElements = InputVT->getNumElements();
6963
6964 if (InputNumElements >= ResultVT->getNumElements())
6965 return false;
6966
6967 // Take the difference of the two shuffle masks at each index. Ignore poison
6968 // values at the same index in both masks.
6969 SmallVector<int, 16> NewMask;
6970 NewMask.reserve(Mask0.size());
6971
6972 for (auto [M0, M1] : zip(Mask0, Mask1)) {
6973 if (M0 >= 0 && M1 >= 0)
6974 NewMask.push_back(M0 - M1);
6975 else if (M0 == -1 && M1 == -1)
6976 continue;
6977 else
6978 return false;
6979 }
6980
6981 // Ensure all elements of the new mask are equal. If the difference between
6982 // the incoming mask elements is the same, the two must be constant offsets
6983 // of one another.
6984 if (NewMask.empty() || !all_equal(NewMask))
6985 return false;
6986
6987 // Create new mask using difference of the two incoming masks.
6988 int MaskOffset = NewMask[0u];
6989 unsigned Index = (InputNumElements + MaskOffset) % InputNumElements;
6990 NewMask.clear();
6991
6992 for (unsigned I = 0u; I < InputNumElements; ++I) {
6993 NewMask.push_back(Index);
6994 Index = (Index + 1u) % InputNumElements;
6995 }
6996
6997 // Calculate costs for worst cases and compare.
6998 auto const Kind = TTI::SK_PermuteSingleSrc;
6999 auto OldCost =
7000 std::max(TTI.getShuffleCost(Kind, ResultVT, InputVT, CostKind, Mask0),
7001 TTI.getShuffleCost(Kind, ResultVT, InputVT, CostKind, Mask1));
7002 auto NewCost = TTI.getShuffleCost(Kind, InputVT, InputVT, CostKind, NewMask) +
7003 TTI.getShuffleCost(Kind, ResultVT, InputVT, CostKind, Mask1);
7004
7005 LLVM_DEBUG(dbgs() << "Found a phi of mergeable shuffles: " << I
7006 << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
7007 << "\n");
7008
7009 if (NewCost > OldCost)
7010 return false;
7011
7012 // Create new shuffles and narrowed phi.
7013 auto Builder = IRBuilder(Shuf);
7014 Builder.SetCurrentDebugLocation(Shuf->getDebugLoc());
7015 auto *PoisonVal = PoisonValue::get(InputVT);
7016 auto *NewShuf0 = Builder.CreateShuffleVector(Op, PoisonVal, NewMask);
7017 Worklist.push(cast<Instruction>(NewShuf0));
7018
7019 Builder.SetInsertPoint(Phi);
7020 Builder.SetCurrentDebugLocation(Phi->getDebugLoc());
7021 auto *NewPhi = Builder.CreatePHI(NewShuf0->getType(), 2u);
7022 NewPhi->addIncoming(NewShuf0, Phi->getIncomingBlock(0u));
7023 NewPhi->addIncoming(Op, Phi->getIncomingBlock(1u));
7024
7025 Builder.SetInsertPoint(*NewPhi->getInsertionPointAfterDef());
7026 PoisonVal = PoisonValue::get(NewPhi->getType());
7027 auto *NewShuf1 = Builder.CreateShuffleVector(NewPhi, PoisonVal, Mask1);
7028
7029 replaceValue(*Phi, *NewShuf1);
7030 return true;
7031}
7032
7033/// This is the entry point for all transforms. Pass manager differences are
7034/// handled in the callers of this function.
7035bool VectorCombine::run() {
7037 return false;
7038
7039 // Don't attempt vectorization if the target does not support vectors.
7040 if (!TTI.getNumberOfRegisters(TTI.getRegisterClassForType(/*Vector*/ true)))
7041 return false;
7042
7043 LLVM_DEBUG(dbgs() << "\n\nVECTORCOMBINE on " << F.getName() << "\n");
7044
7045 auto FoldInst = [this](Instruction &I) {
7046 Builder.SetInsertPoint(&I);
7047 bool IsVectorType = isa<VectorType>(I.getType());
7048 bool IsFixedVectorType = isa<FixedVectorType>(I.getType());
7049 auto Opcode = I.getOpcode();
7050
7051 LLVM_DEBUG(dbgs() << "VC: Visiting: " << I << '\n');
7052
7053 // These folds should be beneficial regardless of when this pass is run
7054 // in the optimization pipeline.
7055 // The type checking is for run-time efficiency. We can avoid wasting time
7056 // dispatching to folding functions if there's no chance of matching.
7057 if (IsFixedVectorType) {
7058 switch (Opcode) {
7059 case Instruction::InsertElement:
7060 if (vectorizeLoadInsert(I))
7061 return true;
7062 break;
7063 case Instruction::ShuffleVector:
7064 if (widenSubvectorLoad(I))
7065 return true;
7066 break;
7067 default:
7068 break;
7069 }
7070 }
7071
7072 // This transform works with scalable and fixed vectors
7073 // TODO: Identify and allow other scalable transforms
7074 if (IsVectorType) {
7075 if (scalarizeOpOrCmp(I))
7076 return true;
7077 if (scalarizeLoad(I))
7078 return true;
7079 if (scalarizeExtExtract(I))
7080 return true;
7081 if (foldInterleaveIntrinsics(I))
7082 return true;
7083 if (foldBitcastOfVPLoad(I))
7084 return true;
7085 }
7086
7087 if (foldDeinterleaveIntrinsics(I))
7088 return true;
7089
7090 if (Opcode == Instruction::Store)
7091 if (foldInsertElementsToStores(I))
7092 return true;
7093
7094 // If this is an early pipeline invocation of this pass, we are done.
7095 if (TryEarlyFoldsOnly)
7096 return false;
7097
7098 if (Opcode == Instruction::Call)
7099 if (foldBitOrderReverseAndSwap(I))
7100 return true;
7101 if (Opcode == Instruction::BitCast)
7102 if (foldBitOrderReverseAndSwap(I))
7103 return true;
7104
7105 // Otherwise, try folds that improve codegen but may interfere with
7106 // early IR canonicalizations.
7107 // The type checking is for run-time efficiency. We can avoid wasting time
7108 // dispatching to folding functions if there's no chance of matching.
7109 if (IsFixedVectorType) {
7110 switch (Opcode) {
7111 case Instruction::InsertElement:
7112 if (foldInsExtFNeg(I))
7113 return true;
7114 if (foldInsExtBinop(I))
7115 return true;
7116 if (foldInsExtVectorToShuffle(I))
7117 return true;
7118 if (foldInsertScalarPartsToShuffle(I))
7119 return true;
7120 break;
7121 case Instruction::ShuffleVector:
7122 if (foldPermuteOfBinops(I))
7123 return true;
7124 if (foldShuffleOfBinops(I))
7125 return true;
7126 if (foldShuffleOfSelects(I))
7127 return true;
7128 if (foldShuffleOfCastops(I))
7129 return true;
7130 if (foldShuffleOfShuffles(I))
7131 return true;
7132 if (foldPermuteOfIntrinsic(I))
7133 return true;
7134 if (foldShufflesOfLengthChangingShuffles(I))
7135 return true;
7136 if (foldShuffleOfIntrinsics(I))
7137 return true;
7138 if (foldSelectShuffle(I))
7139 return true;
7140 if (foldShuffleToIdentity(I))
7141 return true;
7142 break;
7143 case Instruction::Load:
7144 if (shrinkLoadForShuffles(I))
7145 return true;
7146 break;
7147 case Instruction::BitCast:
7148 if (foldBitcastShuffle(I))
7149 return true;
7150 if (foldSelectsFromBitcast(I))
7151 return true;
7152 break;
7153 case Instruction::And:
7154 case Instruction::Or:
7155 case Instruction::Xor:
7156 if (foldBitOpOfCastops(I))
7157 return true;
7158 if (foldBitOpOfCastConstant(I))
7159 return true;
7160 break;
7161 case Instruction::PHI:
7162 if (shrinkPhiOfShuffles(I))
7163 return true;
7164 break;
7165 default:
7166 if (shrinkType(I))
7167 return true;
7168 break;
7169 }
7170 } else {
7171 switch (Opcode) {
7172 case Instruction::Call:
7173 if (foldShuffleFromReductions(I))
7174 return true;
7175 if (foldCastFromReductions(I))
7176 return true;
7177 break;
7178 case Instruction::ExtractElement:
7179 if (foldShuffleChainsToReduce(I))
7180 return true;
7181 break;
7182 case Instruction::ICmp:
7183 if (foldSignBitReductionCmp(I))
7184 return true;
7185 if (foldICmpEqZeroVectorReduce(I))
7186 return true;
7187 if (foldReductionZeroTest(I))
7188 return true;
7189 if (foldEquivalentReductionCmp(I))
7190 return true;
7191 if (foldReduceAddCmpZero(I))
7192 return true;
7193 [[fallthrough]];
7194 case Instruction::FCmp:
7195 if (foldExtractExtract(I))
7196 return true;
7197 break;
7198 case Instruction::Or:
7199 if (foldConcatOfBoolMasks(I))
7200 return true;
7201 [[fallthrough]];
7202 default:
7203 if (Instruction::isBinaryOp(Opcode)) {
7204 if (foldExtractExtract(I))
7205 return true;
7206 if (foldExtractedCmps(I))
7207 return true;
7208 if (foldBinopOfReductions(I))
7209 return true;
7210 }
7211 break;
7212 }
7213 }
7214 return false;
7215 };
7216
7217 bool MadeChange = false;
7218 for (BasicBlock &BB : F) {
7219 // Ignore unreachable basic blocks.
7220 if (!DT.isReachableFromEntry(&BB))
7221 continue;
7222 // Use early increment range so that we can erase instructions in loop.
7223 // make_early_inc_range is not applicable here, as the next iterator may
7224 // be invalidated by RecursivelyDeleteTriviallyDeadInstructions.
7225 // We manually maintain the next instruction and update it when it is about
7226 // to be deleted.
7227 Instruction *I = &BB.front();
7228 while (I) {
7229 NextInst = I->getNextNode();
7230 if (!I->isDebugOrPseudoInst())
7231 MadeChange |= FoldInst(*I);
7232 I = NextInst;
7233 }
7234 }
7235
7236 NextInst = nullptr;
7237
7238 while (!Worklist.isEmpty()) {
7239 Instruction *I = Worklist.removeOne();
7240 if (!I)
7241 continue;
7242
7245 continue;
7246 }
7247
7248 MadeChange |= FoldInst(*I);
7249 }
7250
7251 return MadeChange;
7252}
7253
7256 auto &AC = FAM.getResult<AssumptionAnalysis>(F);
7258 DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
7259 AAResults &AA = FAM.getResult<AAManager>(F);
7260 const DataLayout *DL = &F.getDataLayout();
7263 VectorCombine Combiner(F, TTI, DT, AA, AC, DL, CostKind, TryEarlyFoldsOnly);
7264 if (!Combiner.run())
7265 return PreservedAnalyses::all();
7268 return PA;
7269}
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< unsigned > MaxInstrsToScan("aggressive-instcombine-max-scan-instrs", cl::init(64), cl::Hidden, cl::desc("Max number of instructions to scan for aggressive instcombine."))
static const Function * getParent(const Value *V)
This is the interface for LLVM's primary stateless and local alias analysis.
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
static cl::opt< IntrinsicCostStrategy > IntrinsicCost("intrinsic-cost-strategy", cl::desc("Costing strategy for intrinsic instructions"), cl::init(IntrinsicCostStrategy::InstructionCost), cl::values(clEnumValN(IntrinsicCostStrategy::InstructionCost, "instruction-cost", "Use TargetTransformInfo::getInstructionCost"), clEnumValN(IntrinsicCostStrategy::IntrinsicCost, "intrinsic-cost", "Use TargetTransformInfo::getIntrinsicInstrCost"), clEnumValN(IntrinsicCostStrategy::TypeBasedIntrinsicCost, "type-based-intrinsic-cost", "Calculate the intrinsic cost based only on argument types")))
This file defines the DenseMap class.
#define Check(C,...)
This is the interface for a simple mod/ref and alias analysis over globals.
Hexagon Common GEP
iv users
Definition IVUsers.cpp:48
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU)
Definition LICM.cpp:1210
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T1
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
if(PassOpts->AAPipeline)
This file contains the declarations for profiling metadata utility functions.
const SmallVectorImpl< MachineOperand > & Cond
SI Fold Operands
This file contains some templates that are useful if you are working with the STL at all.
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
This file defines less commonly used SmallVector utilities.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
This pass exposes codegen information to IR-level passes.
static bool isEquivBitcast(Value *X, Value *Y)
Helper to peek through bitcasts to the same value.
static SmallVector< Value *, 8 > getInstrOperandsAtIdx(ArrayRef< Value * > Members, unsigned OperandIndex)
Return the operand at OperandIndex of each Members.
static bool isFreeConcat(ArrayRef< InstLane > Item, TTI::TargetCostKind CostKind, const TargetTransformInfo &TTI)
Detect concat of multiple values into a vector.
static void analyzeCostOfVecReduction(const IntrinsicInst &II, TTI::TargetCostKind CostKind, const TargetTransformInfo &TTI, InstructionCost &CostBeforeReduction, InstructionCost &CostAfterReduction)
static Value * widenDeinterleavedOperations(ArrayRef< Value * > Members, ElementCount WideEC, IRBuilder< InstSimplifyFolder > &Builder)
static Value * generateNewInstTree(ArrayRef< InstLane > Item, Use *From, const DenseSet< std::pair< Value *, Use * > > &IdentityLeafs, const DenseSet< std::pair< Value *, Use * > > &SplatLeafs, const DenseSet< std::pair< Value *, Use * > > &ConcatLeafs, IRBuilderBase &Builder, InstructionWorklist &WorkList, const TargetTransformInfo *TTI)
static SmallVector< InstLane > generateInstLaneVectorFromOperand(ArrayRef< InstLane > Item, int Op)
static Value * createShiftShuffle(Value *Vec, unsigned OldIndex, unsigned NewIndex, IRBuilderBase &Builder)
Create a shuffle that translates (shifts) 1 element from the input vector to a new element location.
std::pair< Value *, int > InstLane
static unsigned getNumDataOperands(const Instruction *Inst)
Return the number of data operands of Inst.
static bool isKnownNonPositive(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Used by foldReduceAddCmpZero to check if we can prove that a value is non-positive.
static bool isSupportedElementwise(Instruction *Inst)
Return true if Inst is an elementwise operation that can be rebuilt at a wider element count.
static Value * materializeScalarizedGEPIndex(Value *Idx, IntegerType *GEPIndexTy, IRBuilderBase &Builder)
Materialize an index for a scalarized GEP after profitability is known.
static Align computeAlignmentAfterScalarization(Align VectorAlignment, Type *ScalarType, Value *Idx, const DataLayout &DL)
The memory operation on a vector of ScalarType had alignment of VectorAlignment.
static bool feedsIntoVectorReduction(ShuffleVectorInst *SVI)
Returns true if this ShuffleVectorInst eventually feeds into a vector reduction intrinsic (e....
static cl::opt< bool > DisableVectorCombine("disable-vector-combine", cl::init(false), cl::Hidden, cl::desc("Disable all vector combine transforms"))
static bool canWidenLoad(LoadInst *Load, const TargetTransformInfo &TTI)
static const unsigned InvalidIndex
static Value * getCommonSplatValue(ArrayRef< Value * > Values)
Return the common splat value of Values.
static bool canWidenDeinterleavedOperations(ArrayRef< Value * > Members, unsigned &NumScanned)
Check whether the tree of elementwise operations each feeding Members can be rebuilt at the interleav...
static IntegerType * getScalarizedGEPIndexInfo(VectorType *VecTy, Value *Idx, Type *PtrTy, const DataLayout &DL)
Return the GEP index type if the unsigned vector index Idx can be represented by an inbounds GEP.
static Value * translateExtract(ExtractElementInst *ExtElt, unsigned NewIndex, IRBuilderBase &Builder)
Given an extract element instruction with constant index operand, shuffle the source vector (shift th...
static ScalarizationResult canScalarizeAccess(VectorType *VecTy, Value *Idx, const SimplifyQuery &SQ)
Check if it is legal to scalarize a memory access to VecTy at index Idx.
static cl::opt< unsigned > MaxInstrsToScan("vector-combine-max-scan-instrs", cl::init(30), cl::Hidden, cl::desc("Max number of instructions to scan for vector combining."))
static cl::opt< bool > DisableBinopExtractShuffle("disable-binop-extract-shuffle", cl::init(false), cl::Hidden, cl::desc("Disable binop extract to shuffle transforms"))
static unsigned getAlignedNumElements(unsigned MaxIdx, FixedVectorType *LoadTy, const TargetTransformInfo &TTI, const DataLayout &DL)
Given the maximum shuffle index and load vector type, compute the number of elements for the shrunk l...
static InstLane lookThroughShuffles(Value *V, int Lane)
static IntrinsicInst * getCommonDeinterleavedSource(ArrayRef< Value * > Members)
Return the common deinterleave intrinsic if Members are its extracts in field order.
static bool isMemModifiedBetween(BasicBlock::iterator Begin, BasicBlock::iterator End, const MemoryLocation &Loc, AAResults &AA)
static Value * createWideInstruction(Instruction *NarrowInst, ArrayRef< Value * > NewOperands, VectorType *WideResultTy, IRBuilder< InstSimplifyFolder > &Builder)
static constexpr int Concat[]
Value * RHS
Value * LHS
A manager for alias analyses.
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1057
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1560
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
Definition APInt.h:1350
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:367
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
Definition APInt.h:1186
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:376
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1508
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
Definition APInt.h:205
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:325
unsigned countl_one() const
Count the number of leading one bits.
Definition APInt.h:1635
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
Definition APInt.cpp:1030
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:302
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition APInt.h:292
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:196
bool isOne() const
Determine if this is a value of 1.
Definition APInt.h:385
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
Definition APInt.h:235
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
Definition APInt.h:1225
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
Definition ArrayRef.h:194
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
BinaryOps getOpcode() const
Definition InstrTypes.h:409
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
Value * getArgOperand(unsigned i) const
void addParamAttrs(unsigned ArgNo, const AttrBuilder &B)
Adds attributes to the indicated argument.
This is the base class for all instructions that perform data casts.
Definition InstrTypes.h:512
static LLVM_ABI CastInst * Create(Instruction::CastOps, Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Provides a way to construct any of the CastInst subclasses using an opcode instead of the subclass's ...
This class is the base class for the comparison instructions.
Definition InstrTypes.h:728
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
bool isFPPredicate() const
Definition InstrTypes.h:845
static LLVM_ABI std::optional< CmpPredicate > getMatching(CmpPredicate A, CmpPredicate B)
Compares two CmpPredicates taking samesign into account and returns the canonicalized CmpPredicate if...
Combiner implementation.
Definition Combiner.h:33
static LLVM_ABI Constant * getExtractElement(Constant *Vec, Constant *Idx, Type *OnlyIfReducedTy=nullptr)
static LLVM_ABI Constant * getBinOpIdentity(unsigned Opcode, Type *Ty, bool AllowRHSConstant=false, bool NSZ=false)
Return the identity constant for a binary opcode.
This is the shared class of boolean and integer constants.
Definition Constants.h:87
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 urem(const ConstantRange &Other) const
Return a new range representing the possible values resulting from an unsigned remainder operation of...
LLVM_ABI ConstantRange binaryAnd(const ConstantRange &Other) const
Return a new range representing the possible values resulting from a binary-and of a value in this ra...
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
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
bool empty() const
Definition DenseMap.h:717
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:767
iterator end()
Definition DenseMap.h:687
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:794
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:857
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
Analysis pass which computes a DominatorTree.
Definition Dominators.h:241
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
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.
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
Definition TypeSize.h:311
This instruction extracts a single (scalar) element from a VectorType value.
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
bool noSignedZeros() const
Definition FMF.h:67
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static FixedVectorType * getDoubleElementsVectorType(FixedVectorType *VTy)
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:843
This class represents a freeze function that returns random concrete value if an operand is either a ...
Predicate getSignedPredicate() const
For example, EQ->EQ, SLE->SLE, UGT->SGT, etc.
bool isEquality() const
Return true if this predicate is either EQ or NE.
Common base class shared among various IRBuilders.
Definition IRBuilder.h:111
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 * CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1474
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2678
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2666
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
Definition IRBuilder.h:1943
Value * CreateNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, bool IsNUW, bool IsNSW, const Twine &Name="")
Definition IRBuilder.h:1753
LLVM_ABI Value * CreateSelectFMF(Value *C, Value *True, Value *False, FMFSource FMFSource, const Twine &Name="", Instruction *MDFrom=nullptr)
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition IRBuilder.h:2725
ConstantInt * getTrue()
Get the constant value for i1 true.
Definition IRBuilder.h:454
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateFreeze(Value *V, const Twine &Name="")
Definition IRBuilder.h:2744
void SetCurrentDebugLocation(const DebugLoc &L)
Set location information used by debugging information.
Definition IRBuilder.h:238
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1537
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
Definition IRBuilder.h:2293
Value * CreateIsNotNeg(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg > -1.
Definition IRBuilder.h:2782
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
Definition IRBuilder.h:2028
Value * CreatePointerBitCastOrAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2318
Value * CreateFCmpFMF(CmpInst::Predicate P, Value *LHS, Value *RHS, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2519
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Definition IRBuilder.h:479
LLVM_ABI Value * CreateOrReduce(Value *Src)
Create a vector int OR reduction intrinsic of the source vector.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Definition IRBuilder.h:474
Value * CreateCmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2525
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Definition IRBuilder.h:2556
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
Definition IRBuilder.h:150
Value * CreateBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:1742
Value * CreateIsNeg(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg < 0.
Definition IRBuilder.h:2777
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2252
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition IRBuilder.h:1916
Value * CreateUnOpFMF(Instruction::UnaryOps Opc, Value *V, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:1869
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1516
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Definition IRBuilder.h:2130
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Definition IRBuilder.h:2700
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1575
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.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition IRBuilder.h:1934
Value * CreateExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, bool IsExact, const Twine &Name="")
Definition IRBuilder.h:1765
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Definition IRBuilder.h:2116
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Definition IRBuilder.h:574
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:1736
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition IRBuilder.h:199
Value * CreateFNegFMF(Value *V, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:1849
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2501
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1597
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Definition IRBuilder.h:521
LLVM_ABI Value * CreateUnaryIntrinsic(Intrinsic::ID ID, Value *Op, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 1 operand which is mangled on its type.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2918
InstSimplifyFolder - Use InstructionSimplify to fold operations to existing values.
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
InstructionWorklist - This is the worklist management logic for InstCombine and other simplification ...
void push(Instruction *I)
Push the instruction onto the worklist stack.
LLVM_ABI void setHasNoUnsignedWrap(bool b=true)
Set or clear the nuw flag on this instruction, which must be an operator which supports this flag.
LLVM_ABI void copyIRFlags(const Value *V, bool IncludeWrapFlags=true)
Convenience method to copy supported exact, fast-math, and (optionally) wrapping flags from V to this...
LLVM_ABI void setHasNoSignedWrap(bool b=true)
Set or clear the nsw flag on this instruction, which must be an operator which supports this flag.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.
bool isBinaryOp() const
LLVM_ABI void setNonNeg(bool b=true)
Set or clear the nneg flag on this instruction, which must be a zext instruction.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
@ CompareCallTargets
Check for equivalence by comparing call targets.
LLVM_ABI AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
bool isIdempotent() const
Return true if the instruction is idempotent:
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI bool hasAllowReassoc() const LLVM_READONLY
Determine whether the allow-reassociation flag is set.
bool isIntDivRem() const
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:338
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void setAlignment(Align Align)
Type * getPointerOperandType() const
Align getAlign() const
Return the alignment of the access that is being performed.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
const SDValue & getOperand(unsigned Num) const
This class represents the LLVM 'select' instruction.
bool contains(const_arg_type key) const
Check if the SetVector contains the given key.
Definition SetVector.h:258
bool empty() const
Determine if the SetVector is empty or not.
Definition SetVector.h:100
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
This instruction constructs a fixed permutation of two input vectors.
int getMaskValue(unsigned Elt) const
Return the shuffle mask value of this instruction for the given element index.
VectorType * getType() const
Overload to return most specific vector type.
static LLVM_ABI void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static void commuteShuffleMask(MutableArrayRef< int > Mask, unsigned InVecNumElts)
Change values in a shuffle permute mask assuming the two vector operands of length InVecNumElts have ...
size_type size() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void setAlignment(Align Align)
Analysis pass providing the TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
static LLVM_ABI CastContextHint getCastContextHint(const Instruction *I)
Calculates a CastContextHint from I.
LLVM_ABI InstructionCost getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef< const Value * > Operands, TargetCostKind CostKind, Type *AccessType=nullptr) const
Estimate the cost of a GEP operation when lowered.
LLVM_ABI TypeSize getRegisterBitWidth(RegisterKind K) const
LLVM_ABI InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, OperandValueInfo OpdInfo={OK_AnyValue, OP_None}, const Instruction *I=nullptr) const
static LLVM_ABI OperandValueInfo commonOperandInfo(const Value *X, const Value *Y)
Collect common data between two OperandValueInfo inputs.
LLVM_ABI bool allowVectorElementIndexingUsingGEP() const
Returns true if GEP should not be used to index into vectors for this target.
LLVM_ABI InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const
LLVM_ABI InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index=-1, const Value *Op0=nullptr, const Value *Op1=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const
LLVM_ABI InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, OperandValueInfo Op1Info={OK_AnyValue, OP_None}, OperandValueInfo Op2Info={OK_AnyValue, OP_None}, const Instruction *I=nullptr) const
LLVM_ABI InstructionCost getShuffleCost(ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask={}, int Index=0, VectorType *SubTp=nullptr, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const
LLVM_ABI InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const
LLVM_ABI unsigned getRegisterClassForType(bool Vector, Type *Ty=nullptr) const
LLVM_ABI InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const
Calculate the cost of vector reduction intrinsics.
TargetCostKind
The kind of cost model.
@ TCK_RecipThroughput
Reciprocal throughput.
@ TCK_CodeSize
Instruction code size.
LLVM_ABI InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
LLVM_ABI InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const
LLVM_ABI unsigned getMinVectorRegisterBitWidth() const
LLVM_ABI InstructionCost getAddressComputationCost(Type *PtrTy, ScalarEvolution *SE, const SCEV *Ptr, TTI::TargetCostKind CostKind) const
LLVM_ABI unsigned getNumberOfRegisters(unsigned ClassID) const
LLVM_ABI InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Opd1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Opd2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, const TargetLibraryInfo *TLibInfo=nullptr) const
This is an approximation of reciprocal throughput of a math/logic op.
LLVM_ABI InstructionCost getInstructionCost(const User *U, ArrayRef< const Value * > Operands, TargetCostKind CostKind) const
Estimate the cost of a given IR user when lowered.
LLVM_ABI InstructionCost getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const
Estimate the overhead of scalarizing an instruction.
ShuffleKind
The various kinds of shuffle patterns for vector queries.
@ SK_PermuteSingleSrc
Shuffle elements of single source vector with any shuffle mask.
@ SK_PermuteTwoSrc
Merge elements from two source vectors into one with any shuffle mask.
@ SK_ExtractSubvector
ExtractSubvector Index indicates start offset.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:277
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:363
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:187
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:130
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
Definition Type.h:222
bool isIEEELikeFPTy() const
Return true if this is a well-behaved IEEE-like type, which has a IEEE compatible layout,...
Definition Type.h:172
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
op_range operands()
Definition User.h:267
Value * getOperand(unsigned i) const
Definition User.h:207
unsigned getNumOperands() const
Definition User.h:229
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
const Value * stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, APInt &Offset) const
This is a wrapper around stripAndAccumulateConstantOffsets with the in-bounds requirement set to fals...
Definition Value.h:729
LLVM_ABI bool hasOneUser() const
Return true if there is exactly one user of this value.
Definition Value.cpp:163
bool hasOneUse() const
Return true if there is exactly one use of this value.
Definition Value.h:441
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
iterator_range< user_iterator > users()
Definition Value.h:428
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
Definition Value.cpp:1002
unsigned getValueID() const
Return an ID for the concrete type of this object.
Definition Value.h:545
LLVM_ABI bool hasNUses(unsigned N) const
Return true if this Value has exactly N uses.
Definition Value.cpp:147
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:712
bool use_empty() const
Definition Value.h:348
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
bool user_empty() const
Definition Value.h:391
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
size_type size() const
Definition DenseSet.h:84
constexpr bool hasKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns true if there exists a value X where RHS*X will result in a value whose quantity matches our ...
Definition TypeSize.h:265
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr ScalarTy getKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns a value X where RHS*X will result in a value whose quantity matches our own.
Definition TypeSize.h:273
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
constexpr bool isZero() const
Definition TypeSize.h:153
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition ilist_node.h:348
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
Definition Attributor.h:165
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
const APInt & smin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be signed.
Definition APInt.h:2274
const APInt & smax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be signed.
Definition APInt.h:2279
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
AllOnesConstantMatch m_AllOnes()
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
match_combine_and< Ty... > m_CombineAnd(const Ty &...Ps)
Combine pattern matchers matching all of Ps patterns.
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
auto m_BSwap(const Opnd0 &Op0)
auto m_Cmp()
Matches any compare instruction and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
auto m_BitReverse(const Opnd0 &Op0)
BinaryOp_match< LHS, RHS, Instruction::URem > m_URem(const LHS &L, const RHS &R)
auto m_Poison()
Match an arbitrary poison constant.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
DisjointOr_match< LHS, RHS > m_DisjointOr(const LHS &L, const RHS &R)
BinOpPred_match< LHS, RHS, is_right_shift_op > m_Shr(const LHS &L, const RHS &R)
Matches logical shift operations.
CmpClass_match< LHS, RHS, ICmpInst, true > m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
Matches an ICmp with a predicate over LHS and RHS in either order.
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
auto m_Constant()
Match an arbitrary Constant and ignore it.
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
cst_pred_ty< is_non_zero_int > m_NonZeroInt()
Match a non-zero integer or a vector with all non-zero elements.
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Shl, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWShl(const LHS &L, const RHS &R)
auto m_AnyIntrinsic()
Matches any intrinsic call and ignore it.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Mul, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWMul(const LHS &L, const RHS &R)
BinOpPred_match< LHS, RHS, is_bitwiselogic_op, true > m_c_BitwiseLogic(const LHS &L, const RHS &R)
Matches bitwise logic operations in either order.
CastOperator_match< OpTy, Instruction::BitCast > m_BitCast(const OpTy &Op)
Matches BitCast.
match_combine_or< CastInst_match< OpTy, SExtInst >, NNegZExt_match< OpTy > > m_SExtLike(const OpTy &Op)
Match either "sext" or "zext nneg".
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_Deinterleave2(const Opnd &Op)
BinaryOp_match< LHS, RHS, Instruction::LShr > m_LShr(const LHS &L, const RHS &R)
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
auto m_Undef()
Match an arbitrary undef constant.
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.
BinaryOp_match< LHS, RHS, Instruction::Or, true > m_c_Or(const LHS &L, const RHS &R)
Matches an Or with LHS and RHS in either order.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
@ Valid
The data is already valid.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
@ User
could "use" a pointer
NodeAddr< PhiNode * > Phi
Definition RDFGraph.h:390
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
Definition MathExtras.h:339
@ Offset
Definition DWP.cpp:577
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
Definition STLExtras.h:846
void stable_sort(R &&Range)
Definition STLExtras.h:2132
LLVM_ABI cl::opt< bool > ProfcheckDisableMetadataFixes
Definition LoopInfo.cpp:60
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1748
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
LLVM_ABI Intrinsic::ID getMinMaxReductionIntrinsicOp(Intrinsic::ID RdxID)
Returns the min/max intrinsic used when expanding a min/max reduction.
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
Definition Local.cpp:526
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI Value * simplifyUnOp(unsigned Opcode, Value *Op, const SimplifyQuery &Q)
Given operand for a UnaryOperator, fold the result or return null.
scope_exit(Callable) -> scope_exit< Callable >
@ Load
The value being inserted comes from a load (InsertElement only).
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI unsigned getArithmeticReductionInstruction(Intrinsic::ID RdxID)
Returns the arithmetic instruction opcode used when expanding a reduction.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition MathExtras.h:244
LLVM_ABI Value * simplifyCall(CallBase *Call, Value *Callee, ArrayRef< Value * > Args, const SimplifyQuery &Q)
Given a callsite, callee, and arguments, fold the result or return null.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
LLVM_ABI bool mustSuppressSpeculation(const LoadInst &LI)
Return true if speculation of the given load must be suppressed to avoid ordering or interfering with...
Definition Loads.cpp:452
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
LLVM_ABI Instruction * propagateMetadata(Instruction *I, ArrayRef< Value * > VL)
Specifically, let Kinds = [MD_tbaa, MD_alias_scope, MD_noalias, MD_fpmath, MD_nontemporal,...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return the number of times the sign bit of the register is replicated into the other bits.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
unsigned M1(unsigned Val)
Definition VE.h:377
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
Definition Local.cpp:406
LLVM_ABI bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
bool isModSet(const ModRefInfo MRI)
Definition ModRef.h:49
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
LLVM_ABI bool programUndefinedIfPoison(const Instruction *Inst)
LLVM_ABI unsigned getDeinterleaveIntrinsicFactor(Intrinsic::ID ID)
Returns the corresponding factor of llvm.vector.deinterleaveN intrinsics.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
LLVM_ABI unsigned getInterleaveIntrinsicFactor(Intrinsic::ID ID)
Returns the corresponding factor of llvm.vector.interleaveN intrinsics.
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition STLExtras.h:552
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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
LLVM_ABI void propagateIRFlags(Value *I, ArrayRef< Value * > VL, Value *OpValue=nullptr, bool IncludeWrapFlags=true)
Get the intersection (logical and) of all of the potential IR flags of each scalar operation (VL) tha...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
constexpr int PoisonMaskElem
@ Other
Any other memory.
Definition ModRef.h:68
TargetTransformInfo TTI
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ, bool IgnoreFree=false)
Return true if we know that executing a load from this value cannot trap.
Definition Loads.cpp:456
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
LLVM_ABI void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
LLVM_ABI Intrinsic::ID getReductionForBinop(Instruction::BinaryOps Opc)
Returns the reduction intrinsic id corresponding to the binary operation.
@ And
Bitwise or logical AND of integers.
LLVM_ABI bool isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID, unsigned ScalarOpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic has a scalar operand.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
Definition VE.h:376
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI bool willNotFreeBetween(const Instruction *Assume, const Instruction *CtxI, const DominatorTree *DT=nullptr)
Returns true, if no instruction between Assume and CtxI may free (including through synchronization).
constexpr unsigned BitWidth
LLVM_ABI bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
LLVM_ABI Constant * getLosslessInvCast(Constant *C, Type *InvCastTo, unsigned CastOp, const DataLayout &DL, PreservedCastFlags *Flags=nullptr)
Try to cast C to InvC losslessly, satisfying CastOp(InvC) equals C, or CastOp(InvC) is a refined valu...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:206
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
Definition STLExtras.h:2182
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI bool isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Returns true if V cannot be poison, but may be undef.
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:267
LLVM_ABI bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
LLVM_ABI bool isTriviallyVectorizable(Intrinsic::ID ID)
Identify if the intrinsic is trivially vectorizable.
LLVM_ABI Intrinsic::ID getMinMaxReductionIntrinsicID(Intrinsic::ID IID)
Returns the llvm.vector.reduce min/max intrinsic that corresponds to the intrinsic op.
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
LLVM_ABI AAMDNodes adjustForAccess(unsigned AccessSize)
Create a new AAMDNode for accessing AccessSize bytes of this AAMDNode.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
Definition KnownBits.h:310
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
Definition KnownBits.h:262
APInt getMaxValue() const
Return the maximal unsigned value possible given these KnownBits.
Definition KnownBits.h:146
const DataLayout & DL
const DominatorTree * DT
SimplifyQuery getWithInstruction(const Instruction *I) const
AssumptionCache * AC
const Instruction * CtxI