LLVM 24.0.0git
SLPCompatibilityAnalysis.cpp
Go to the documentation of this file.
1//===- SLPCompatibilityAnalysis.cpp - SLP same-opcode helpers -------------===//
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
10#include "SLPUtils.h"
11
12#include "llvm/ADT/APInt.h"
13#include "llvm/ADT/ArrayRef.h"
14#include "llvm/ADT/STLExtras.h"
15#include "llvm/ADT/SetVector.h"
18#include "llvm/ADT/bit.h"
21#include "llvm/IR/Constants.h"
23#include "llvm/IR/InstrTypes.h"
24#include "llvm/IR/Instruction.h"
27#include "llvm/IR/Intrinsics.h"
29#include "llvm/IR/Value.h"
32
33#include <algorithm>
34#include <array>
35#include <cassert>
36#include <optional>
37#include <utility>
38
39using namespace llvm;
40using namespace llvm::PatternMatch;
41
42namespace llvm::slpvectorizer {
43
44bool isValidForAlternation(unsigned Opcode) {
45 return !Instruction::isIntDivRem(Opcode);
46}
47
48std::pair<Constant *, unsigned>
49BinOpSameOpcodeHelper::isBinOpWithConstant(const Instruction *I) {
50 [[maybe_unused]] unsigned Opcode = I->getOpcode();
51 assert(binary_search(SupportedOp, Opcode) && "Unsupported opcode.");
52 (void)SupportedOp;
53 auto *BinOp = cast<BinaryOperator>(I);
54 auto GetConstant = [](Value *V) -> Constant * {
55 if (auto *CI = dyn_cast<ConstantInt>(V))
56 return CI;
57 return dyn_cast<ConstantFP>(V);
58 };
59 if (Constant *C = GetConstant(BinOp->getOperand(1)))
60 return {C, 1};
61 if (!isCommutative(I))
62 return {nullptr, 0};
63 if (Constant *C = GetConstant(BinOp->getOperand(0)))
64 return {C, 0};
65 return {nullptr, 0};
66}
67
68bool BinOpSameOpcodeHelper::InterchangeableInfo::trySet(
69 MaskType OpcodeInMaskForm, MaskType InterchangeableMask) {
70 if (Mask & InterchangeableMask) {
71 SeenBefore |= OpcodeInMaskForm;
72 Mask &= InterchangeableMask;
73 return true;
74 }
75 return false;
76}
77
78unsigned BinOpSameOpcodeHelper::InterchangeableInfo::getOpcode() const {
79 MaskType Candidate = Mask & SeenBefore;
80 if (Candidate & MainOpBIT)
81 return I->getOpcode();
82 if (Candidate & ShlBIT)
83 return Instruction::Shl;
84 if (Candidate & AShrBIT)
85 return Instruction::AShr;
86 if (Candidate & MulBIT)
87 return Instruction::Mul;
88 if (Candidate & AddBIT)
89 return Instruction::Add;
90 if (Candidate & SubBIT)
91 return Instruction::Sub;
92 if (Candidate & FAddBIT)
93 return Instruction::FAdd;
94 if (Candidate & FSubBIT)
95 return Instruction::FSub;
96 if (Candidate & AndBIT)
97 return Instruction::And;
98 if (Candidate & OrBIT)
99 return Instruction::Or;
100 if (Candidate & XorBIT)
101 return Instruction::Xor;
102 llvm_unreachable("Cannot find interchangeable instruction.");
103}
104
105bool BinOpSameOpcodeHelper::InterchangeableInfo::hasCandidateOpcode(
106 unsigned Opcode) const {
107 MaskType Candidate = Mask & SeenBefore;
108 switch (Opcode) {
109 case Instruction::Shl:
110 return Candidate & ShlBIT;
111 case Instruction::AShr:
112 return Candidate & AShrBIT;
113 case Instruction::Mul:
114 return Candidate & MulBIT;
115 case Instruction::Add:
116 return Candidate & AddBIT;
117 case Instruction::Sub:
118 return Candidate & SubBIT;
119 case Instruction::And:
120 return Candidate & AndBIT;
121 case Instruction::Or:
122 return Candidate & OrBIT;
123 case Instruction::Xor:
124 return Candidate & XorBIT;
125 case Instruction::FAdd:
126 return Candidate & FAddBIT;
127 case Instruction::FSub:
128 return Candidate & FSubBIT;
129 case Instruction::LShr:
130 case Instruction::FMul:
131 case Instruction::SDiv:
132 case Instruction::UDiv:
133 case Instruction::FDiv:
134 case Instruction::SRem:
135 case Instruction::URem:
136 case Instruction::FRem:
137 return false;
138 default:
139 break;
140 }
141 llvm_unreachable("Cannot find interchangeable instruction.");
142}
143
144SmallVector<Value *> BinOpSameOpcodeHelper::InterchangeableInfo::getOperand(
145 const Instruction *To) const {
146 unsigned ToOpcode = To->getOpcode();
147 unsigned FromOpcode = I->getOpcode();
148 if (FromOpcode == ToOpcode)
149 return SmallVector<Value *>(I->operands());
150 assert(binary_search(SupportedOp, ToOpcode) && "Unsupported opcode.");
151 auto [C, Pos] = isBinOpWithConstant(I);
152 Type *RHSType = I->getOperand(Pos)->getType();
153 Constant *RHS;
154 if (auto *CFP = dyn_cast<ConstantFP>(C)) {
155 // fsub(x, c) == fadd(x, -c) for every FP constant c, since IEEE 754
156 // defines subtraction as addition of the negated operand.
157 assert(is_contained({Instruction::FAdd, Instruction::FSub}, ToOpcode) &&
158 "Cannot convert the instruction.");
159 RHS = ConstantFP::get(RHSType, -CFP->getValueAPF());
160 } else {
161 auto *CI = cast<ConstantInt>(C);
162 const APInt &FromCIValue = CI->getValue();
163 unsigned FromCIValueBitWidth = FromCIValue.getBitWidth();
164 switch (FromOpcode) {
165 case Instruction::Shl:
166 if (ToOpcode == Instruction::Add && FromCIValue.isOne())
167 return {I->getOperand(0), I->getOperand(0)};
168 if (ToOpcode == Instruction::Mul) {
169 RHS = ConstantInt::get(RHSType,
170 APInt::getOneBitSet(FromCIValueBitWidth,
171 FromCIValue.getZExtValue()));
172 } else {
173 assert(FromCIValue.isZero() && "Cannot convert the instruction.");
174 RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
175 /*AllowRHSConstant=*/true);
176 }
177 break;
178 case Instruction::Mul:
179 assert(FromCIValue.isPowerOf2() && "Cannot convert the instruction.");
180 if (ToOpcode == Instruction::Shl) {
181 RHS = ConstantInt::get(
182 RHSType, APInt(FromCIValueBitWidth, FromCIValue.logBase2()));
183 } else {
184 assert(FromCIValue.isOne() && "Cannot convert the instruction.");
185 RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
186 /*AllowRHSConstant=*/true);
187 }
188 break;
189 case Instruction::Add:
190 case Instruction::Sub:
191 if (FromCIValue.isZero()) {
192 RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
193 /*AllowRHSConstant=*/true);
194 } else {
195 assert(is_contained({Instruction::Add, Instruction::Sub}, ToOpcode) &&
196 "Cannot convert the instruction.");
197 APInt NegatedVal = APInt(FromCIValue);
198 NegatedVal.negate();
199 RHS = ConstantInt::get(RHSType, NegatedVal);
200 }
201 break;
202 case Instruction::And:
203 assert(FromCIValue.isAllOnes() && "Cannot convert the instruction.");
204 RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
205 /*AllowRHSConstant=*/true);
206 break;
207 default:
208 assert(FromCIValue.isZero() && "Cannot convert the instruction.");
209 RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
210 /*AllowRHSConstant=*/true);
211 break;
212 }
213 }
214 Value *LHS = I->getOperand(1 - Pos);
215 // If the target opcode is non-commutative (e.g., shl, sub),
216 // force the variable to the left and the constant to the right.
217 if (Pos == 1 || !Instruction::isCommutative(ToOpcode))
218 return SmallVector<Value *>({LHS, RHS});
219
220 return SmallVector<Value *>({RHS, LHS});
221}
222
223bool BinOpSameOpcodeHelper::isValidForAlternation(const Instruction *I) const {
224 return slpvectorizer::isValidForAlternation(MainOp.I->getOpcode()) &&
226}
227
228bool BinOpSameOpcodeHelper::initializeAltOp(const Instruction *I) {
229 if (AltOp.I)
230 return true;
231 if (!isValidForAlternation(I))
232 return false;
233 AltOp.I = I;
234 return true;
235}
236
239 "BinOpSameOpcodeHelper only accepts BinaryOperator.");
240 unsigned Opcode = I->getOpcode();
241 MaskType OpcodeInMaskForm;
242 // Prefer Shl, AShr, Mul, Add, Sub, And, Or, Xor, FAdd and FSub over
243 // MainOp.
244 switch (Opcode) {
245 case Instruction::Shl:
246 OpcodeInMaskForm = ShlBIT;
247 break;
248 case Instruction::AShr:
249 OpcodeInMaskForm = AShrBIT;
250 break;
251 case Instruction::Mul:
252 OpcodeInMaskForm = MulBIT;
253 break;
254 case Instruction::Add:
255 OpcodeInMaskForm = AddBIT;
256 break;
257 case Instruction::Sub:
258 OpcodeInMaskForm = SubBIT;
259 break;
260 case Instruction::And:
261 OpcodeInMaskForm = AndBIT;
262 break;
263 case Instruction::Or:
264 OpcodeInMaskForm = OrBIT;
265 break;
266 case Instruction::Xor:
267 OpcodeInMaskForm = XorBIT;
268 break;
269 case Instruction::FAdd:
270 OpcodeInMaskForm = FAddBIT;
271 break;
272 case Instruction::FSub:
273 OpcodeInMaskForm = FSubBIT;
274 break;
275 default:
276 return MainOp.equal(Opcode) || (initializeAltOp(I) && AltOp.equal(Opcode));
277 }
278 MaskType InterchangeableMask = OpcodeInMaskForm;
279 auto [C, Pos] = isBinOpWithConstant(I);
280 if (auto *CI = dyn_cast_if_present<ConstantInt>(C)) {
281 constexpr MaskType CanBeAll =
282 XorBIT | OrBIT | AndBIT | SubBIT | AddBIT | MulBIT | AShrBIT | ShlBIT;
283 const APInt &CIValue = CI->getValue();
284 switch (Opcode) {
285 case Instruction::Shl:
286 if (CIValue.ult(CIValue.getBitWidth()))
287 InterchangeableMask = CIValue.isZero() ? CanBeAll : MulBIT | ShlBIT;
288 if (CIValue.isOne())
289 InterchangeableMask |= AddBIT;
290 break;
291 case Instruction::Mul:
292 if (CIValue.isOne()) {
293 InterchangeableMask = CanBeAll;
294 break;
295 }
296 if (CIValue.isPowerOf2())
297 InterchangeableMask = MulBIT | ShlBIT;
298 break;
299 case Instruction::Add:
300 case Instruction::Sub:
301 InterchangeableMask = CIValue.isZero() ? CanBeAll : SubBIT | AddBIT;
302 break;
303 case Instruction::And:
304 if (CIValue.isAllOnes())
305 InterchangeableMask = CanBeAll;
306 break;
307 case Instruction::Xor:
308 if (CIValue.isZero())
309 InterchangeableMask = XorBIT | OrBIT | SubBIT | AddBIT;
310 break;
311 default:
312 if (CIValue.isZero())
313 InterchangeableMask = CanBeAll;
314 break;
315 }
316 } else if (C && Pos == 1) {
317 // FAdd/FSub with a constant RHS: negating the constant always
318 // converts one into the other, so no value check is needed. A
319 // constant LHS (Pos == 0, e.g. "0.0 - x") is excluded: unlike a
320 // constant RHS, it cannot be moved to the other opcode without also
321 // swapping the variable operand, which would misalign it against
322 // lanes that keep their native opcode (their variable operand stays
323 // on the other side).
324 InterchangeableMask = FSubBIT | FAddBIT;
325 }
326 return MainOp.trySet(OpcodeInMaskForm, InterchangeableMask) ||
327 (initializeAltOp(I) &&
328 AltOp.trySet(OpcodeInMaskForm, InterchangeableMask));
329}
330
331/// If the comparison (Pred, X, C) is a single-element or single-complement
332/// range check, returns its boundary family: false + K for the singleton
333/// {K} (eq forms), true + K for the complement of {K} (ne forms).
334static std::optional<std::pair<bool, APInt>>
336 const unsigned BW = C.getBitWidth();
337 const bool IsSigned = CmpInst::isSigned(Pred);
338 const APInt Min = IsSigned ? APInt::getSignedMinValue(BW) : APInt(BW, 0);
339 const APInt Max =
340 IsSigned ? APInt::getSignedMaxValue(BW) : APInt::getMaxValue(BW);
341 switch (Pred) {
342 case CmpInst::ICMP_EQ:
343 return std::make_pair(false, C);
344 case CmpInst::ICMP_NE:
345 return std::make_pair(true, C);
348 if (C == Min + 1)
349 return std::make_pair(false, Min);
350 if (C == Max)
351 return std::make_pair(true, C);
352 break;
355 if (C == Min)
356 return std::make_pair(false, C);
357 if (C == Max - 1)
358 return std::make_pair(true, Max);
359 break;
362 if (C == Min)
363 return std::make_pair(true, C);
364 if (C == Max - 1)
365 return std::make_pair(false, Max);
366 break;
369 if (C == Min + 1)
370 return std::make_pair(true, Min);
371 if (C == Max)
372 return std::make_pair(false, C);
373 break;
374 default:
375 break;
376 }
377 return std::nullopt;
378}
379
380CmpSamePredicateHelper::MaskType
381CmpSamePredicateHelper::getFormsMask(CmpInst::Predicate Pred, const APInt &C) {
382 MaskType M = getBit(Pred);
383 std::optional<std::pair<bool, APInt>> Family = getCmpBoundaryFamily(Pred, C);
384 if (!Family)
385 return M;
386 const auto &[IsComplement, K] = *Family;
387 // At each type boundary the two range checks covering exactly {K}; the
388 // complement family uses their inverses, covering everything but {K}.
389 const MaskType LoU = getBit(CmpInst::ICMP_ULT) | getBit(CmpInst::ICMP_ULE);
390 const MaskType HiU = getBit(CmpInst::ICMP_UGT) | getBit(CmpInst::ICMP_UGE);
391 const MaskType LoS = getBit(CmpInst::ICMP_SLT) | getBit(CmpInst::ICMP_SLE);
392 const MaskType HiS = getBit(CmpInst::ICMP_SGT) | getBit(CmpInst::ICMP_SGE);
393 if (K.isZero())
394 M |= IsComplement ? HiU : LoU;
395 if (K.isMaxValue())
396 M |= IsComplement ? LoU : HiU;
397 if (K.isMinSignedValue())
398 M |= IsComplement ? HiS : LoS;
399 if (K.isMaxSignedValue())
400 M |= IsComplement ? LoS : HiS;
401 return M | getBit(IsComplement ? CmpInst::ICMP_NE : CmpInst::ICMP_EQ);
402}
403
404APInt CmpSamePredicateHelper::getFamilyConstant(bool IsComplement,
405 const APInt &K,
408 return K;
409 // The complement form uses the singleton constant of the inverse
410 // predicate.
411 if (IsComplement)
413 switch (Pred) {
416 return K + 1;
419 return K - 1;
420 default:
421 return K;
422 }
423}
424
425/// Returns the predicate and the compared constant of the comparison lane
426/// \p I, treating trunc X to i1 as and X, 1 ne 0.
427static std::optional<std::pair<CmpInst::Predicate, APInt>>
429 if (auto *TI = dyn_cast<TruncInst>(I);
430 TI && TI->getType()->isIntOrIntVectorTy(1))
431 return std::make_pair(
433 APInt::getZero(TI->getSrcTy()->getScalarSizeInBits()));
434 const APInt *C;
435 if (auto *CI = dyn_cast<ICmpInst>(I);
436 CI && match(CI->getOperand(1), m_APInt(C)))
437 return std::make_pair(CI->getPredicate(), *C);
438 return std::nullopt;
439}
440
441CmpSamePredicateHelper::MaskType
442CmpSamePredicateHelper::getLaneMask(const Instruction *I) {
443 if (std::optional<std::pair<CmpInst::Predicate, APInt>> Cmp =
445 MaskType M = getFormsMask(Cmp->first, Cmp->second);
446 // trunc X to i1 is also and X, 1 eq 1.
447 return isa<TruncInst>(I) ? M | getBit(CmpInst::ICMP_EQ) : M;
448 }
449 if (auto *CI = dyn_cast<ICmpInst>(I))
450 return getBit(CI->getPredicate());
451 return 0;
452}
453
455 if (auto *CI = dyn_cast<ICmpInst>(I);
456 CI && !match(CI->getOperand(0), m_OneUse(m_And(m_Value(), m_Value()))))
457 return false;
458 std::optional<std::pair<CmpInst::Predicate, APInt>> Cmp =
460 if (!Cmp)
461 return false;
462 std::optional<std::pair<bool, APInt>> Family =
463 getCmpBoundaryFamily(Cmp->first, Cmp->second);
464 return Family && Family->second.isZero();
465}
466
468 if (auto *CI = dyn_cast<ICmpInst>(I))
469 SeenBefore |= getBit(CI->getPredicate());
470 Mask &= getLaneMask(I);
471 return Mask != 0;
472}
473
476 MaskType Candidate = Mask & SeenBefore;
477 if (!Candidate)
479 if (Candidate & getBit(Preferred->getPredicate()))
480 return Preferred->getPredicate();
481 return static_cast<CmpInst::Predicate>(CmpInst::ICMP_EQ +
482 countr_zero(Candidate));
483}
484
487 const ICmpInst *Preferred) {
489 if (!all_of(VL, [&](Value *V) {
490 auto *I = dyn_cast<Instruction>(V);
491 return isa<PoisonValue>(V) || (I && Helper.add(I));
492 }))
494 return Helper.getPredicate(Preferred);
495}
496
498 CmpInst::Predicate Pred) {
499 return CmpInst::isIntPredicate(Pred) && (getLaneMask(I) & getBit(Pred)) != 0;
500}
501
503 CmpInst::Predicate Pred) {
504 if (!canConvertTo(I, Pred))
505 return nullptr;
506 if (auto *CI = dyn_cast<ICmpInst>(I); CI && CI->getPredicate() == Pred)
507 return nullptr;
508 if (isa<TruncInst>(I) && Pred == CmpInst::ICMP_EQ)
509 return ConstantInt::get(I->getOperand(0)->getType(), 1);
510 auto [LanePred, C] = *getLaneConstantCmp(I);
511 std::optional<std::pair<bool, APInt>> Family =
512 getCmpBoundaryFamily(LanePred, C);
513 assert(Family && "Expected a boundary family for a convertible compare.");
514 const auto &[IsComplement, K] = *Family;
515 return ConstantInt::get(I->getOperand(0)->getType(),
516 getFamilyConstant(IsComplement, K, Pred));
517}
518
523
525 const Instruction *Op) {
526 if (I->getOpcode() != Op->getOpcode())
527 return false;
528 const auto *II = dyn_cast<IntrinsicInst>(I);
529 const auto *IOp = dyn_cast<IntrinsicInst>(Op);
530 if (II || IOp)
531 return II && IOp &&
532 isEquivalentIntrinsicID(II->getIntrinsicID(),
533 IOp->getIntrinsicID()) !=
535 return true;
536}
537
539 assert(MainOp && "MainOp cannot be nullptr.");
540 if (isSameOperation(I, MainOp))
541 return MainOp;
542 if (MainOp->getOpcode() == Instruction::Select &&
543 I->getOpcode() == Instruction::ZExt && !isAltShuffle())
544 return MainOp;
545 if (MainOp->getOpcode() == Instruction::ICmp &&
546 I->getOpcode() == Instruction::Trunc && !isAltShuffle())
547 return MainOp;
548 // Prefer AltOp instead of interchangeable instruction of MainOp.
549 assert(AltOp && "AltOp cannot be nullptr.");
550 if (isSameOperation(I, AltOp))
551 return AltOp;
552 // BinOpSameOpcodeHelper handles only BinaryOperators; a call cannot match.
553 if (!I->isBinaryOp() || !MainOp->isBinaryOp())
554 return nullptr;
556 if (!Converter.add(I) || !Converter.add(MainOp))
557 return nullptr;
558 if (isAltShuffle() && !Converter.hasCandidateOpcode(MainOp->getOpcode())) {
559 BinOpSameOpcodeHelper AltConverter(AltOp);
560 if (AltConverter.add(I) && AltConverter.add(AltOp) &&
561 AltConverter.hasCandidateOpcode(AltOp->getOpcode()))
562 return AltOp;
563 }
564 if (Converter.hasAltOp() && !isAltShuffle())
565 return nullptr;
566 return Converter.hasAltOp() ? AltOp : MainOp;
567}
568
570 constexpr std::array<unsigned, 8> MulDiv = {
571 Instruction::Mul, Instruction::FMul, Instruction::SDiv,
572 Instruction::UDiv, Instruction::FDiv, Instruction::SRem,
573 Instruction::URem, Instruction::FRem};
574 return is_contained(MulDiv, getOpcode()) &&
575 is_contained(MulDiv, getAltOpcode());
576}
577
579 constexpr std::array<unsigned, 4> AddSub = {
580 Instruction::Add, Instruction::Sub, Instruction::FAdd, Instruction::FSub};
581 return is_contained(AddSub, getOpcode()) &&
582 is_contained(AddSub, getAltOpcode());
583}
584
586 return isAddSubLikeOp() || getOpcode() == Instruction::FNeg;
587}
588
590 assert(valid() && "InstructionsState is invalid.");
591 if (!HasCopyables)
592 return false;
593 if (isAltShuffle())
594 return false;
595 auto *I = dyn_cast<Instruction>(V);
596 // Copyable lanes of a cast node are limited to constants representable as
597 // the cast of a source-type constant.
598 if (isa<CastInst>(MainOp)) {
599 if (I || isa<PoisonValue>(V))
600 return false;
601 if (isa<UndefValue>(V))
602 return true;
603 auto *C = dyn_cast<ConstantInt>(V);
604 return C && C->getValue().getActiveBits() <=
605 cast<CastInst>(MainOp)->getSrcTy()->getIntegerBitWidth();
606 }
607 if (!I)
608 return !isa<PoisonValue>(V);
609 // For a GEP main op only single-index GEPs with the same source element
610 // type can be matching lanes; GEPs with a different shape are copyable.
611 if (getOpcode() == Instruction::GetElementPtr)
612 if (auto *GEP = dyn_cast<GetElementPtrInst>(I);
613 GEP && (GEP->getNumOperands() != 2 ||
614 GEP->getSourceElementType() !=
615 cast<GetElementPtrInst>(MainOp)->getSourceElementType()))
616 return true;
617 if (I->getParent() != MainOp->getParent() &&
620 return true;
621 if (isSameOperation(I, MainOp))
622 return false;
623 // BinOpSameOpcodeHelper handles only BinaryOperators; a call is copyable.
624 if (!I->isBinaryOp() || !MainOp->isBinaryOp())
625 return true;
627 return !Converter.add(I) || !Converter.add(MainOp) || Converter.hasAltOp() ||
628 !Converter.hasCandidateOpcode(getOpcode());
629}
630
632 auto *I = dyn_cast<Instruction>(V);
633 return I &&
634 (I->getOpcode() == Instruction::FMul ||
635 I->getOpcode() == Instruction::FAdd) &&
636 I->hasOneUse() && none_of(I->operands(), [&](Value *Op) {
637 return is_contained(VL, Op);
638 });
639}
640
642 auto *I = dyn_cast<Instruction>(V);
643 return I && S.isCopyableElement(I) &&
644 (I->getOpcode() == Instruction::FMul ||
645 I->getOpcode() == Instruction::FAdd) &&
646 I->hasOneUse();
647}
648
650 bool HasFMulOrFAdd = false;
651 for (Value *V :
652 make_filter_range(VL, [](Value *V) { return !isa<PoisonValue>(V); })) {
653 auto *I = dyn_cast<Instruction>(V);
655 continue;
656 if (!isAbsorbableFMulOrFAdd(VL, V))
657 return false;
658 HasFMulOrFAdd = true;
659 }
660 return HasFMulOrFAdd;
661}
662
664 assert(valid() && "InstructionsState is invalid.");
665 if (isCopyableElement(V))
666 return false;
667 auto *ExpandingOp = dyn_cast<Instruction>(V);
668 if (!ExpandingOp)
669 return false;
670 auto CheckForTransformedOpcode = [](const Instruction *RefOp,
671 const Instruction *ExpandingOp) {
672 switch (RefOp->getOpcode()) {
673 case Instruction::Add:
674 switch (ExpandingOp->getOpcode()) {
675 case Instruction::Shl:
676 return match(ExpandingOp, m_Shl(m_Value(), m_One()));
677 default:
678 break;
679 }
680 break;
681 default:
682 break;
683 }
684 return false;
685 };
686 // getMatchingMainOpOrAltOp() may legitimately return nullptr, e.g. for a
687 // split node, whose Scalars combine two unrelated operations (main/alt
688 // ops of the split state), so V is not required to match either of them.
689 Instruction *MainOp = getMatchingMainOpOrAltOp(ExpandingOp);
690 if (!MainOp)
691 return false;
692 return CheckForTransformedOpcode(MainOp, ExpandingOp);
693}
694
696 assert(isExpandedBinOp(I) && "Expected an expanded binop.");
697 switch (I->getOpcode()) {
698 case Instruction::Shl:
699 assert(match(I, m_Shl(m_Value(), m_One())) && "Expected shl x, 1 only.");
700 return Idx == 1;
701 default:
702 llvm_unreachable("Unexpected opcode for an expanded operand.");
703 }
704}
705
707 assert(valid() && "InstructionsState is invalid.");
708 auto *I = dyn_cast<Instruction>(V);
709 if (!HasCopyables)
712 // MainOp for copyables always schedulable to correctly identify
713 // non-schedulable copyables.
714 if (getMainOp() == V)
715 return false;
716 if (isCopyableElement(V)) {
717 auto IsNonSchedulableCopyableElement = [this](Value *V) {
718 auto *I = dyn_cast<Instruction>(V);
719 return !I || isa<PHINode>(I) || I->getParent() != MainOp->getParent() ||
721 // If the copyable instructions comes after MainOp
722 // (non-schedulable, but used in the block) - cannot vectorize
723 // it, will possibly generate use before def.
724 !MainOp->comesBefore(I));
725 };
726
727 return IsNonSchedulableCopyableElement(V);
728 }
731}
732
733/// Find an instruction with a specific opcode in VL.
734/// \param VL Array of values to search through. Must contain only Instructions
735/// and PoisonValues.
736/// \param Opcode The instruction opcode to search for
737/// \returns
738/// - The first instruction found with matching opcode
739/// - nullptr if no matching instruction is found
741 unsigned Opcode) {
742 for (Value *V :
743 make_filter_range(VL, [](Value *V) { return !isa<PoisonValue>(V); })) {
744 assert(isa<Instruction>(V) && "Only accepts PoisonValue and Instruction.");
745 auto *Inst = cast<Instruction>(V);
746 if (Inst->getOpcode() == Opcode)
747 return Inst;
748 }
749 return nullptr;
750}
751
752/// Checks if the provided operands of 2 cmp instructions are compatible, i.e.
753/// compatible instructions or constants, or just some other regular values.
754static bool areCompatibleCmpOps(Value *BaseOp0, Value *BaseOp1, Value *Op0,
755 Value *Op1, const TargetLibraryInfo &TLI) {
756 return (isConstant(BaseOp0) && isConstant(Op0)) ||
757 (isConstant(BaseOp1) && isConstant(Op1)) ||
758 (!isa<Instruction>(BaseOp0) && !isa<Instruction>(Op0) &&
759 !isa<Instruction>(BaseOp1) && !isa<Instruction>(Op1)) ||
760 BaseOp0 == Op0 || BaseOp1 == Op1 ||
761 getSameOpcode({BaseOp0, Op0}, TLI) ||
762 getSameOpcode({BaseOp1, Op1}, TLI);
763}
764
765/// \returns true if a compare instruction \p CI has similar "look" and
766/// same predicate as \p BaseCI, "as is" or with its operands and predicate
767/// swapped, false otherwise.
768static bool isCmpSameOrSwapped(const CmpInst *BaseCI, const CmpInst *CI,
769 const TargetLibraryInfo &TLI) {
770 assert(BaseCI->getOperand(0)->getType() == CI->getOperand(0)->getType() &&
771 "Assessing comparisons of different types?");
772 CmpInst::Predicate BasePred = BaseCI->getPredicate();
773 CmpInst::Predicate Pred = CI->getPredicate();
775
776 Value *BaseOp0 = BaseCI->getOperand(0);
777 Value *BaseOp1 = BaseCI->getOperand(1);
778 Value *Op0 = CI->getOperand(0);
779 Value *Op1 = CI->getOperand(1);
780
781 return (BasePred == Pred &&
782 areCompatibleCmpOps(BaseOp0, BaseOp1, Op0, Op1, TLI)) ||
783 (BasePred == SwappedPred &&
784 areCompatibleCmpOps(BaseOp0, BaseOp1, Op1, Op0, TLI));
785}
786
788 const TargetLibraryInfo &TLI) {
789 // Make sure these are all Instructions.
792
793 auto *It = find_if(VL, IsaPred<Instruction>);
794 if (It == VL.end())
796
797 Instruction *MainOp = cast<Instruction>(*It);
798 unsigned InstCnt = std::count_if(It, VL.end(), IsaPred<Instruction>);
799 if ((VL.size() > 2 && !isa<PHINode>(MainOp) && InstCnt < VL.size() / 2) ||
800 (VL.size() == 2 && InstCnt < 2))
802
803 // Match trunc X to i1 lanes against the compares.
804 if (isa<TruncInst>(MainOp) && MainOp->getType()->isIntOrIntVectorTy(1))
805 if (auto *CmpIt = find_if(VL, IsaPred<ICmpInst>); CmpIt != VL.end())
806 MainOp = cast<Instruction>(*CmpIt);
807
808 bool IsCastOp = isa<CastInst>(MainOp);
809 bool IsBinOp = isa<BinaryOperator>(MainOp);
810 bool IsCmpOp = isa<CmpInst>(MainOp);
811 CmpInst::Predicate BasePred = IsCmpOp ? cast<CmpInst>(MainOp)->getPredicate()
813 Instruction *AltOp = MainOp;
814 unsigned Opcode = MainOp->getOpcode();
815 unsigned AltOpcode = Opcode;
816
817 BinOpSameOpcodeHelper BinOpHelper(MainOp);
818 bool SwappedPredsCompatible = IsCmpOp && [&]() {
819 SetVector<unsigned> UniquePreds, UniqueNonSwappedPreds;
820 UniquePreds.insert(BasePred);
821 UniqueNonSwappedPreds.insert(BasePred);
822 for (Value *V : VL) {
823 auto *I = dyn_cast<CmpInst>(V);
824 if (!I)
825 return false;
826 CmpInst::Predicate CurrentPred = I->getPredicate();
827 CmpInst::Predicate SwappedCurrentPred =
828 CmpInst::getSwappedPredicate(CurrentPred);
829 UniqueNonSwappedPreds.insert(CurrentPred);
830 if (!UniquePreds.contains(CurrentPred) &&
831 !UniquePreds.contains(SwappedCurrentPred))
832 UniquePreds.insert(CurrentPred);
833 }
834 // Total number of predicates > 2, but if consider swapped predicates
835 // compatible only 2, consider swappable predicates as compatible opcodes,
836 // not alternate.
837 return UniqueNonSwappedPreds.size() > 2 && UniquePreds.size() == 2;
838 }();
839 // Find the predicate the whole bundle can share, if any, treating
840 // boundary comparisons canonicalized to eq/ne as interchangeable.
842 if (IsCmpOp && isa<ICmpInst>(MainOp))
843 InterchangeablePred =
845 // Check for one alternate opcode from another BinaryOperator.
846 // TODO - generalize to support all operators (types, calls etc.).
847 Intrinsic::ID BaseID = 0;
848 SmallVector<VFInfo, 4> BaseMappings;
849 if (auto *CallBase = dyn_cast<CallInst>(MainOp)) {
851 BaseMappings = VFDatabase(*CallBase).getMappings(*CallBase);
852 if (!isTriviallyVectorizable(BaseID) && BaseMappings.empty())
854 }
855 bool AnyPoison = InstCnt != VL.size();
856 // Check MainOp too to be sure that it matches the requirements for the
857 // instructions.
858 for (Instruction *I :
860 // Cannot combine poison and divisions.
861 // TODO: do some smart analysis of the CallInsts to exclude divide-like
862 // intrinsics/functions only.
863 if (AnyPoison && (I->isIntDivRem() || I->isFPDivRem() || isa<CallInst>(I)))
865 unsigned InstOpcode = I->getOpcode();
866 if (IsBinOp && isa<BinaryOperator>(I)) {
867 if (BinOpHelper.add(I))
868 continue;
869 } else if (IsCastOp && isa<CastInst>(I)) {
870 Value *Op0 = MainOp->getOperand(0);
871 Type *Ty0 = Op0->getType();
872 Value *Op1 = I->getOperand(0);
873 Type *Ty1 = Op1->getType();
874 if (Ty0 == Ty1) {
875 if (InstOpcode == Opcode || InstOpcode == AltOpcode)
876 continue;
877 if (Opcode == AltOpcode) {
879 isValidForAlternation(InstOpcode) &&
880 "Cast isn't safe for alternation, logic needs to be updated!");
881 AltOpcode = InstOpcode;
882 AltOp = I;
883 continue;
884 }
885 }
886 } else if (auto *Inst = dyn_cast<CmpInst>(I); Inst && IsCmpOp) {
887 auto *BaseInst = cast<CmpInst>(MainOp);
888 Type *Ty0 = BaseInst->getOperand(0)->getType();
889 Type *Ty1 = Inst->getOperand(0)->getType();
890 if (Ty0 == Ty1) {
891 assert(InstOpcode == Opcode && "Expected same CmpInst opcode.");
892 assert(InstOpcode == AltOpcode &&
893 "Alternate instructions are only supported by BinaryOperator "
894 "and CastInst.");
895 // Check for compatible operands. If the corresponding operands are not
896 // compatible - need to perform alternate vectorization.
897 CmpInst::Predicate CurrentPred = Inst->getPredicate();
898 CmpInst::Predicate SwappedCurrentPred =
899 CmpInst::getSwappedPredicate(CurrentPred);
900
901 if ((VL.size() == 2 || SwappedPredsCompatible) &&
902 (BasePred == CurrentPred || BasePred == SwappedCurrentPred))
903 continue;
904
905 if (isCmpSameOrSwapped(BaseInst, Inst, TLI))
906 continue;
907 if (CmpSamePredicateHelper::canConvertTo(Inst, InterchangeablePred))
908 continue;
909 auto *AltInst = cast<CmpInst>(AltOp);
910 if (MainOp != AltOp) {
911 if (isCmpSameOrSwapped(AltInst, Inst, TLI))
912 continue;
913 } else if (BasePred != CurrentPred) {
914 assert(
915 isValidForAlternation(InstOpcode) &&
916 "CmpInst isn't safe for alternation, logic needs to be updated!");
917 AltOp = I;
918 continue;
919 }
920 CmpInst::Predicate AltPred = AltInst->getPredicate();
921 if (BasePred == CurrentPred || BasePred == SwappedCurrentPred ||
922 AltPred == CurrentPred || AltPred == SwappedCurrentPred)
923 continue;
924 }
925 } else if (auto *TI = dyn_cast<TruncInst>(I); TI && IsCmpOp) {
926 // trunc X to i1 is the bit test and X, 1 != 0 or and X, 1 == 1, so the
927 // whole list must be the bit tests of the same type sharing the
928 // predicate.
929 if (InterchangeablePred != CmpInst::BAD_ICMP_PREDICATE &&
930 TI->getSrcTy() == MainOp->getOperand(0)->getType() &&
931 all_of(VL, [](Value *V) {
932 auto *I = dyn_cast<Instruction>(V);
933 return isa<PoisonValue>(V) ||
935 }))
936 continue;
937 } else if (InstOpcode == Opcode) {
938 assert(InstOpcode == AltOpcode &&
939 "Alternate instructions are only supported by BinaryOperator and "
940 "CastInst.");
941 if (auto *Gep = dyn_cast<GetElementPtrInst>(I)) {
942 if (Gep->getNumOperands() != 2 ||
943 Gep->getOperand(0)->getType() != MainOp->getOperand(0)->getType())
945 } else if (auto *EI = dyn_cast<ExtractElementInst>(I)) {
948 } else if (auto *LI = dyn_cast<LoadInst>(I)) {
949 auto *BaseLI = cast<LoadInst>(MainOp);
950 if (!LI->isSimple() || !BaseLI->isSimple())
952 } else if (auto *Call = dyn_cast<CallInst>(I)) {
953 auto *CallBase = cast<CallInst>(MainOp);
955 Intrinsic::ID Equivalent = isEquivalentIntrinsicID(ID, BaseID);
956 if (Call->getCalledFunction() != CallBase->getCalledFunction() &&
957 isEquivalentIntrinsicID(Equivalent, Intrinsic::fmuladd) ==
960 if (Call->hasOperandBundles() &&
962 !std::equal(Call->op_begin() + Call->getBundleOperandsStartIndex(),
963 Call->op_begin() + Call->getBundleOperandsEndIndex(),
964 CallBase->op_begin() +
967 if (ID != BaseID && Equivalent == Intrinsic::not_intrinsic)
969 if (!ID) {
970 SmallVector<VFInfo, 4> Mappings =
971 VFDatabase(*Call).getMappings(*Call);
972 if (Mappings.size() != BaseMappings.size() ||
973 Mappings.front().ISA != BaseMappings.front().ISA ||
974 Mappings.front().ScalarName != BaseMappings.front().ScalarName ||
975 Mappings.front().VectorName != BaseMappings.front().VectorName ||
976 Mappings.front().Shape.VF != BaseMappings.front().Shape.VF ||
977 Mappings.front().Shape.Parameters !=
978 BaseMappings.front().Shape.Parameters)
980 }
981 }
982 continue;
983 }
985 }
986
987 if (IsBinOp) {
988 if (!BinOpHelper.hasDefinedMainOpcode() ||
989 !BinOpHelper.hasDefinedAltOpcode())
991 MainOp = findInstructionWithOpcode(VL, BinOpHelper.getMainOpcode());
992 assert(MainOp && "Cannot find MainOp with Opcode from BinOpHelper.");
993 AltOp = findInstructionWithOpcode(VL, BinOpHelper.getAltOpcode());
994 assert(AltOp && "Cannot find AltOp with Opcode from BinOpHelper.");
995 } else if (auto *CB = dyn_cast<CallInst>(MainOp);
996 CB &&
997 getVectorIntrinsicIDForCall(CB, &TLI) == Intrinsic::fmuladd) {
998 // fma and fmuladd share a single vector fma node; use the fma as the
999 // representative so the fused form is not weakened to fmuladd.
1000 auto *It = find_if(VL, [&](Value *V) {
1001 auto *CI = dyn_cast<CallInst>(V);
1002 return CI && getVectorIntrinsicIDForCall(CI, &TLI) == Intrinsic::fma;
1003 });
1004 if (It != VL.end())
1005 MainOp = AltOp = cast<Instruction>(*It);
1006 }
1007 if (IsCmpOp && InterchangeablePred != CmpInst::BAD_ICMP_PREDICATE &&
1008 InterchangeablePred != BasePred) {
1009 // Every lane is convertible to the shared predicate, so the alternate
1010 // operation is never set for such bundles.
1011 auto *SharedIt = find_if(VL, [&](Value *V) {
1012 auto *CI = dyn_cast<ICmpInst>(V);
1013 return CI && CI->getPredicate() == InterchangeablePred;
1014 });
1015 assert(SharedIt != VL.end() &&
1016 "Expected an instruction with the shared predicate.");
1017 MainOp = AltOp = cast<Instruction>(*SharedIt);
1018 }
1019 assert((MainOp == AltOp || !allSameOpcode(VL)) &&
1020 "Incorrect implementation of allSameOpcode.");
1021 InstructionsState S(MainOp, AltOp);
1022 assert(all_of(VL,
1023 [&](Value *V) {
1024 return isa<PoisonValue>(V) ||
1026 }) &&
1027 "Invalid InstructionsState.");
1028 return S;
1029}
1030
1031std::pair<Instruction *, SmallVector<Value *>>
1033 Instruction *SelectedOp = S.getMatchingMainOpOrAltOp(I);
1034 assert(SelectedOp && "Cannot convert the instruction.");
1035 if (I->isBinaryOp()) {
1037 return std::make_pair(SelectedOp, Converter.getOperand(SelectedOp));
1038 }
1039 // Use args() to skip the trailing callee operand in CallInst::operands().
1040 if (auto *CI = dyn_cast<CallInst>(I))
1041 return std::make_pair(SelectedOp, SmallVector<Value *>(CI->args()));
1042 // A comparison lane interchangeable with the main operation (e.g. x == 0
1043 // in an x <u C bundle) is emitted with the main predicate and the
1044 // adjusted constant.
1045 if (auto *MainCI = dyn_cast<ICmpInst>(SelectedOp);
1046 MainCI && !S.isAltShuffle())
1048 I, MainCI->getPredicate()))
1049 return std::make_pair(SelectedOp,
1050 SmallVector<Value *>{I->getOperand(0), C});
1051 return std::make_pair(SelectedOp, SmallVector<Value *>(I->operands()));
1052}
1053
1055 Instruction *AltOp, const TargetLibraryInfo &TLI) {
1056 if (auto *MainCI = dyn_cast<CmpInst>(MainOp)) {
1057 auto *AltCI = cast<CmpInst>(AltOp);
1058 CmpInst::Predicate MainP = MainCI->getPredicate();
1059 [[maybe_unused]] CmpInst::Predicate AltP = AltCI->getPredicate();
1060 assert(MainP != AltP && "Expected different main/alternate predicates.");
1061 auto *CI = cast<CmpInst>(I);
1062 if (isCmpSameOrSwapped(MainCI, CI, TLI))
1063 return false;
1064 if (isCmpSameOrSwapped(AltCI, CI, TLI))
1065 return true;
1066 CmpInst::Predicate P = CI->getPredicate();
1068
1069 assert((MainP == P || AltP == P || MainP == SwappedP || AltP == SwappedP) &&
1070 "CmpInst expected to match either main or alternate predicate or "
1071 "their swap.");
1072 return MainP != P && MainP != SwappedP;
1073 }
1074 return InstructionsState(MainOp, AltOp).getMatchingMainOpOrAltOp(I) == AltOp;
1075}
1076
1078 const InstructionsState &S, const TargetLibraryInfo &TLI,
1080 SmallVectorImpl<Value *> &ReassocScalars, SmallBitVector &SubLanes) {
1081 assert(S.isAltShuffle() && "Expected an alternate node.");
1082 const unsigned NumLanes = VL.size();
1083 SmallVector<unsigned> LaneOpcodes =
1084 map_to_vector(seq<unsigned>(NumLanes), [&](unsigned Lane) {
1086 S.getMainOp(), S.getAltOp(), TLI)
1087 ? S.getAltOpcode()
1088 : S.getOpcode();
1089 });
1090 // A lane value peels only as a single-use chain link with the lane's own
1091 // opcode, keeping every combine level on the same main/alt pattern.
1092 auto GetChainLink = [&](unsigned Lane, Value *V) -> Instruction * {
1093 auto *I = dyn_cast<Instruction>(V);
1094 if (!I || !I->hasOneUse() || I->getOpcode() != LaneOpcodes[Lane] ||
1096 return nullptr;
1097 return I;
1098 };
1100 Columns.emplace_back(Op0.begin(), Op0.end());
1101 Columns.emplace_back(Op1.begin(), Op1.end());
1102 // The chain link of a commutative lane may sit in the second column;
1103 // normalize so every lane's link leads.
1104 for (unsigned Lane : seq<unsigned>(NumLanes)) {
1105 if (GetChainLink(Lane, Columns[0][Lane]))
1106 continue;
1107 Instruction *Link = GetChainLink(Lane, Columns[1][Lane]);
1108 if (!Link || !Link->isCommutative())
1109 return {};
1110 std::swap(Columns[0][Lane], Columns[1][Lane]);
1111 }
1112 // Peel the leading column while every lane stays a matching chain link.
1113 while (all_of(seq<unsigned>(NumLanes), [&](unsigned Lane) {
1114 return GetChainLink(Lane, Columns[0][Lane]) != nullptr;
1115 })) {
1116 SmallVector<Value *> NewColumn(NumLanes);
1117 for (unsigned Lane : seq<unsigned>(NumLanes)) {
1118 Instruction *Link = GetChainLink(Lane, Columns[0][Lane]);
1119 ReassocScalars.push_back(Link);
1120 // The chain of a commutative lane may continue in the second operand;
1121 // keep the chain link as the running value.
1122 unsigned RunningOp = Link->isCommutative() &&
1123 !GetChainLink(Lane, Link->getOperand(0)) &&
1124 GetChainLink(Lane, Link->getOperand(1))
1125 ? 1
1126 : 0;
1127 NewColumn[Lane] = Link->getOperand(1 - RunningOp);
1128 Columns[0][Lane] = Link->getOperand(RunningOp);
1129 }
1130 Columns.insert(std::next(Columns.begin()), std::move(NewColumn));
1131 }
1132 assert(!ReassocScalars.empty() &&
1133 "Normalization guarantees at least one peeled level.");
1134 SubLanes.resize(NumLanes);
1135 for (unsigned Lane : seq<unsigned>(NumLanes))
1136 if (LaneOpcodes[Lane] == Instruction::Sub ||
1137 LaneOpcodes[Lane] == Instruction::FSub)
1138 SubLanes.set(Lane);
1139 return Columns;
1140}
1141
1142std::pair<Instruction *, Instruction *>
1144 Instruction *MainOp = nullptr;
1145 Instruction *AltOp = nullptr;
1146 for (Value *V :
1147 make_filter_range(VL, [](Value *V) { return !isa<PoisonValue>(V); })) {
1148 auto *I = dyn_cast<Instruction>(V);
1149 if (!I)
1150 return {};
1151 if (!MainOp) {
1152 MainOp = I;
1153 continue;
1154 }
1155 if (MainOp->getOpcode() == I->getOpcode()) {
1156 if (I->getParent() != MainOp->getParent())
1157 return {};
1158 continue;
1159 }
1160 if (!AltOp) {
1161 AltOp = I;
1162 continue;
1163 }
1164 if (AltOp->getOpcode() == I->getOpcode()) {
1165 if (I->getParent() != AltOp->getParent())
1166 return {};
1167 continue;
1168 }
1169 return {};
1170 }
1171 if (!AltOp)
1172 return {};
1173 assert(MainOp && AltOp && MainOp->getOpcode() != AltOp->getOpcode() &&
1174 "Expected different main and alt instructions.");
1175 return std::make_pair(MainOp, AltOp);
1176}
1177
1179 const TargetLibraryInfo &TLI,
1181 SmallVectorImpl<Value *> &Calls) {
1182 assert(S && S.getOpcode() == Instruction::ExtractValue &&
1183 "Expected extractvalue instruction state.");
1185 return false;
1186 auto *VL0 = cast<ExtractValueInst>(S.getMainOp());
1187 ArrayRef<unsigned> VL0Indices = VL0->getIndices();
1189 for (Value *V : VL) {
1190 if (V == VL0) {
1191 Aggregates.push_back(VL0->getAggregateOperand());
1192 continue;
1193 }
1194 auto *IV = cast<ExtractValueInst>(V);
1195 if (IV->getIndices() != VL0Indices ||
1196 isa<ScalableVectorType>(IV->getType()))
1197 return false;
1198 Value *Agg = IV->getAggregateOperand();
1199 Aggregates.push_back(Agg);
1200 }
1201 const InstructionsState AggState = getSameOpcode(Aggregates, TLI);
1202 if (AggState && AggState.getOpcode() == Instruction::Call &&
1203 !AggState.isAltShuffle() &&
1204 isa<StructType>(AggState.getMainOp()->getType()) &&
1206 // The struct-returning call may have non-bundle users too. The external
1207 // extraction code rebuilds scalars by extractvalue + extractelement,
1208 // which only works when every user of the call is an ExtractValueInst.
1209 // Bail out if any aggregate has a different kind of user.
1210 for (Value *Agg : Aggregates) {
1211 if (!all_of(Agg->users(), IsaPred<ExtractValueInst>))
1212 return false;
1213 }
1214 Indices.assign(VL0Indices.begin(), VL0Indices.end());
1215 Calls.swap(Aggregates);
1216 return true;
1217 }
1218 return false;
1219}
1220
1221} // namespace llvm::slpvectorizer
const TargetLowering & TLI
SDValue Pred
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Early If Converter
Hexagon Common GEP
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
#define P(N)
Scalar Replacement Of Aggregates
Definition SROA.cpp:6697
This file contains some templates that are useful if you are working with the STL at all.
This file implements a set that has insertion order iteration characteristics.
This file defines less commonly used SmallVector utilities.
This file defines the SmallVector class.
Value * RHS
Value * LHS
This file implements the C++20 <bit> header.
static const uint32_t IV[8]
Definition blake3_impl.h:83
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1560
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
Definition APInt.h:202
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:367
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
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition APInt.h:1115
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
Definition APInt.h:205
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
Definition APInt.h:215
unsigned logBase2() const
Definition APInt.h:1781
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
Definition APInt.h:436
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
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator end() const
Definition ArrayRef.h:130
size_t size() const
Get the array size.
Definition ArrayRef.h:141
iterator begin() const
Definition ArrayRef.h:129
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
unsigned getBundleOperandsStartIndex() const
Return the index of the first bundle operand in the Use array.
bool hasOperandBundles() const
Return true if this User has any operand bundles.
This class is the base class for the comparison instructions.
Definition InstrTypes.h:728
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ ICMP_SLT
signed less than
Definition InstrTypes.h:769
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:770
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:764
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:767
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ ICMP_NE
not equal
Definition InstrTypes.h:762
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:768
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
bool isSigned() const
Definition InstrTypes.h:993
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition InstrTypes.h:890
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition InstrTypes.h:852
Predicate getPredicate() const
Return the predicate for this instruction.
Definition InstrTypes.h:828
bool isIntPredicate() const
Definition InstrTypes.h:846
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 an important base class in LLVM.
Definition Constant.h:44
This instruction compares its operands according to the predicate given to the constructor.
LLVM_ABI bool isCommutative() const LLVM_READONLY
Return true if the instruction is commutative:
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
bool isIntDivRem() const
static bool isFMulAddIntrinsic(Instruction *I)
Returns true if the instruction is a call to the llvm.fmuladd intrinsic.
A vector that has set insertion semantics.
Definition SetVector.h:57
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
bool contains(const_arg_type key) const
Check if the SetVector contains the given key.
Definition SetVector.h:258
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
SmallBitVector & set()
void resize(unsigned N, bool t=false)
Grow or shrink the bitvector.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
iterator insert(iterator I, T &&Elt)
void swap(SmallVectorImpl &RHS)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
Definition Type.h:258
op_iterator op_begin()
Definition User.h:259
Value * getOperand(unsigned i) const
Definition User.h:207
The Vector Function Database.
Definition VectorUtils.h:35
static SmallVector< VFInfo, 8 > getMappings(const CallInst &CI)
Retrieve all the VFInfo instances associated to the CallInst CI.
Definition VectorUtils.h:76
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 ParentTy * getParent() const
Definition ilist_node.h:34
Helper class that determines VL can use the same opcode.
bool hasCandidateOpcode(unsigned Opcode) const
Checks if the list of potential opcodes includes Opcode.
Helper class that determines whether a list of integer comparisons can share a single predicate.
static CmpInst::Predicate getSharedPredicate(ArrayRef< Value * > VL, const ICmpInst *Preferred)
Returns the predicate the whole list can share, or BAD_ICMP_PREDICATE when it cannot share a natively...
static Constant * getAdjustedConstant(const Instruction *I, CmpInst::Predicate Pred)
Returns the adjusted constant operand expressing the comparison lane I with the predicate Pred,...
CmpInst::Predicate getPredicate(const ICmpInst *Preferred) const
Returns the shared predicate, preferring the predicate of Preferred when the whole list can use it,...
static bool isBitTest(const Instruction *I)
Checks if the comparison lane I is the bit test of the single use and A, B != 0 or and A,...
bool add(const Instruction *I)
Intersects the convertible predicate set of the comparison lane I (an icmp or a trunc to i1) with the...
static bool canConvertTo(const Instruction *I, CmpInst::Predicate Pred)
Checks if the comparison lane I can be expressed with the predicate Pred by adjusting its constant op...
Main data required for vectorization of instructions.
Instruction * getMatchingMainOpOrAltOp(Instruction *I) const
Checks if the instruction matches either the main or alternate opcode.
static bool isSameOperation(const Instruction *I, const Instruction *Op)
Checks if I is the same operation as Op, distinguishing calls by intrinsic ID (all calls share the Ca...
bool valid() const
Checks if the current state is valid, i.e. has non-null MainOp.
bool isExpandedBinOp(Value *V) const
Checks if the value V is a transformed instruction, compatible either with main or alternate ops.
bool isAddSubLikeOp() const
Checks if main/alt instructions are add/sub/fadd/fsub operations.
bool isExpandedOperand(Instruction *I, unsigned Idx) const
Checks if the operand at index Idx of instruction I is an expanded operand.
bool isCopyableElement(Value *V) const
Checks if the value is a copyable element.
bool isAltShuffle() const
Some of the instructions in the list have alternate opcodes.
bool isNonSchedulable(Value *V) const
Checks if the value is non-schedulable.
bool isAddSubOrFNegLikeOp() const
Checks for an add/sub-like operation or an fneg, which models a flattened fadd reduction chain link: ...
bool isMulDivLikeOp() const
Checks if main/alt instructions are mul/div/rem/fmul/fdiv/frem operations.
unsigned getOpcode() const
The main/alternate opcodes for the list of instructions.
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
bool match(Val *V, const Pattern &P)
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
auto m_Value()
Match an arbitrary value and ignore it.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
A private "module" namespace for types and utilities used by this pass.
static std::optional< std::pair< bool, APInt > > getCmpBoundaryFamily(CmpInst::Predicate Pred, const APInt &C)
If the comparison (Pred, X, C) is a single-element or single-complement range check,...
SmallVector< SmallVector< Value * > > scanAltAssociativeOperands(const InstructionsState &S, const TargetLibraryInfo &TLI, ArrayRef< Value * > VL, ArrayRef< Value * > Op0, ArrayRef< Value * > Op1, SmallVectorImpl< Value * > &ReassocScalars, SmallBitVector &SubLanes)
Peel the per-lane associative chains of an alternate node into operand columns.
std::pair< Instruction *, SmallVector< Value * > > convertTo(Instruction *I, const InstructionsState &S)
std::pair< Instruction *, Instruction * > getMainAltOpsNoStateVL(ArrayRef< Value * > VL)
Returns main/alternate instructions for the given VL.
bool isAlternateInstruction(Instruction *I, Instruction *MainOp, Instruction *AltOp, const TargetLibraryInfo &TLI)
Checks if the specified instruction I is an alternate operation for the given MainOp and AltOp instru...
static std::optional< std::pair< CmpInst::Predicate, APInt > > getLaneConstantCmp(const Instruction *I)
Returns the predicate and the compared constant of the comparison lane I, treating trunc X to i1 as a...
bool allSameOpcode(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:289
bool isValidForAlternation(unsigned Opcode)
static bool areCompatibleCmpOps(Value *BaseOp0, Value *BaseOp1, Value *Op0, Value *Op1, const TargetLibraryInfo &TLI)
Checks if the provided operands of 2 cmp instructions are compatible, i.e.
static Instruction * findInstructionWithOpcode(ArrayRef< Value * > VL, unsigned Opcode)
Find an instruction with a specific opcode in VL.
bool hasOnlyAbsorbableCopyableFMulOrFAdds(ArrayRef< Value * > VL)
Checks if every copyable in VL is an absorbable fmul/fadd: the binops die instead of being computed a...
bool isCommutative(const Instruction *I, const Value *ValWithUses, bool IsCopyable)
Definition SLPUtils.cpp:195
bool checkEVsForVecCalls(ArrayRef< Value * > VL, const InstructionsState &S, const TargetLibraryInfo &TLI, SmallVectorImpl< unsigned > &Indices, SmallVectorImpl< Value * > &Calls)
Detects an extractvalue bundle that can be widened by vectorizing the underlying struct-returning cal...
bool allSameBlock(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:144
bool isReassocChainLink(const Instruction *I)
Definition SLPUtils.cpp:89
Intrinsic::ID isEquivalentIntrinsicID(Intrinsic::ID LHS, Intrinsic::ID RHS)
Checks if LHS and RHS are the same intrinsic, or one is llvm.fma and the other is llvm....
Definition SLPUtils.cpp:186
bool isFMAOrFMulAdd(const Instruction *I)
Checks if I is a call to llvm.fma or llvm.fmuladd.
InstructionsState getSameOpcode(ArrayRef< Value * > VL, const TargetLibraryInfo &TLI)
bool isAbsorbableCopyableFMulOrFAdd(const InstructionsState &S, Value *V)
Checks if V is a copyable single-use fmul/fadd, absorbable as fmuladd(a, b, -0.0) or fmuladd(1....
bool isVectorLikeInstWithConstOps(Value *V)
Checks if V is one of vector-like instructions, i.e.
Definition SLPUtils.cpp:97
bool doesNotNeedToBeScheduled(Value *V)
Checks if the specified value does not require scheduling.
Definition SLPUtils.cpp:511
bool isConstant(Value *V)
Definition SLPUtils.cpp:47
bool isAbsorbableFMulOrFAdd(ArrayRef< Value * > VL, Value *V)
Checks if V is a single-use fmul/fadd with operands outside VL.
static bool isCmpSameOrSwapped(const CmpInst *BaseCI, const CmpInst *CI, const TargetLibraryInfo &TLI)
This is an optimization pass for GlobalISel generic memory operations.
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 getVectorIntrinsicIDForCall(const CallInst *CI, const TargetLibraryInfo *TLI)
Returns intrinsic ID for call.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto map_to_vector(ContainerTy &&C, FuncTy &&F)
Map a range to a SmallVector with element types deduced from the mapping.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
auto binary_search(R &&Range, T &&Value)
Provide wrappers to std::binary_search which take ranges instead of having to pass begin/end explicit...
Definition STLExtras.h:2055
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
auto make_isa_range(RangeT &&Range)
Return a range over Range containing only elements for which isa<T> holds, casting each of them to T.
Definition STLExtras.h:567
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1769
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
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
DWARFExpression::Operation Op
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 auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
LLVM_ABI bool isTriviallyVectorizable(Intrinsic::ID ID)
Identify if the intrinsic is trivially vectorizable.
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
Definition Casting.h:866
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880