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"
19#include "llvm/IR/Constants.h"
20#include "llvm/IR/InstrTypes.h"
21#include "llvm/IR/Instruction.h"
24#include "llvm/IR/Intrinsics.h"
26#include "llvm/IR/Value.h"
29
30#include <algorithm>
31#include <array>
32#include <cassert>
33#include <utility>
34
35using namespace llvm;
36using namespace llvm::PatternMatch;
37
38namespace llvm::slpvectorizer {
39
40bool isValidForAlternation(unsigned Opcode) {
41 return !Instruction::isIntDivRem(Opcode);
42}
43
44std::pair<Constant *, unsigned>
45BinOpSameOpcodeHelper::isBinOpWithConstant(const Instruction *I) {
46 [[maybe_unused]] unsigned Opcode = I->getOpcode();
47 assert(binary_search(SupportedOp, Opcode) && "Unsupported opcode.");
48 (void)SupportedOp;
49 auto *BinOp = cast<BinaryOperator>(I);
50 auto GetConstant = [](Value *V) -> Constant * {
51 if (auto *CI = dyn_cast<ConstantInt>(V))
52 return CI;
53 return dyn_cast<ConstantFP>(V);
54 };
55 if (Constant *C = GetConstant(BinOp->getOperand(1)))
56 return {C, 1};
57 if (!isCommutative(I))
58 return {nullptr, 0};
59 if (Constant *C = GetConstant(BinOp->getOperand(0)))
60 return {C, 0};
61 return {nullptr, 0};
62}
63
64bool BinOpSameOpcodeHelper::InterchangeableInfo::trySet(
65 MaskType OpcodeInMaskForm, MaskType InterchangeableMask) {
66 if (Mask & InterchangeableMask) {
67 SeenBefore |= OpcodeInMaskForm;
68 Mask &= InterchangeableMask;
69 return true;
70 }
71 return false;
72}
73
74unsigned BinOpSameOpcodeHelper::InterchangeableInfo::getOpcode() const {
75 MaskType Candidate = Mask & SeenBefore;
76 if (Candidate & MainOpBIT)
77 return I->getOpcode();
78 if (Candidate & ShlBIT)
79 return Instruction::Shl;
80 if (Candidate & AShrBIT)
81 return Instruction::AShr;
82 if (Candidate & MulBIT)
83 return Instruction::Mul;
84 if (Candidate & AddBIT)
85 return Instruction::Add;
86 if (Candidate & SubBIT)
87 return Instruction::Sub;
88 if (Candidate & FAddBIT)
89 return Instruction::FAdd;
90 if (Candidate & FSubBIT)
91 return Instruction::FSub;
92 if (Candidate & AndBIT)
93 return Instruction::And;
94 if (Candidate & OrBIT)
95 return Instruction::Or;
96 if (Candidate & XorBIT)
97 return Instruction::Xor;
98 llvm_unreachable("Cannot find interchangeable instruction.");
99}
100
101bool BinOpSameOpcodeHelper::InterchangeableInfo::hasCandidateOpcode(
102 unsigned Opcode) const {
103 MaskType Candidate = Mask & SeenBefore;
104 switch (Opcode) {
105 case Instruction::Shl:
106 return Candidate & ShlBIT;
107 case Instruction::AShr:
108 return Candidate & AShrBIT;
109 case Instruction::Mul:
110 return Candidate & MulBIT;
111 case Instruction::Add:
112 return Candidate & AddBIT;
113 case Instruction::Sub:
114 return Candidate & SubBIT;
115 case Instruction::And:
116 return Candidate & AndBIT;
117 case Instruction::Or:
118 return Candidate & OrBIT;
119 case Instruction::Xor:
120 return Candidate & XorBIT;
121 case Instruction::FAdd:
122 return Candidate & FAddBIT;
123 case Instruction::FSub:
124 return Candidate & FSubBIT;
125 case Instruction::LShr:
126 case Instruction::FMul:
127 case Instruction::SDiv:
128 case Instruction::UDiv:
129 case Instruction::FDiv:
130 case Instruction::SRem:
131 case Instruction::URem:
132 case Instruction::FRem:
133 return false;
134 default:
135 break;
136 }
137 llvm_unreachable("Cannot find interchangeable instruction.");
138}
139
140SmallVector<Value *> BinOpSameOpcodeHelper::InterchangeableInfo::getOperand(
141 const Instruction *To) const {
142 unsigned ToOpcode = To->getOpcode();
143 unsigned FromOpcode = I->getOpcode();
144 if (FromOpcode == ToOpcode)
145 return SmallVector<Value *>(I->operands());
146 assert(binary_search(SupportedOp, ToOpcode) && "Unsupported opcode.");
147 auto [C, Pos] = isBinOpWithConstant(I);
148 Type *RHSType = I->getOperand(Pos)->getType();
149 Constant *RHS;
150 if (auto *CFP = dyn_cast<ConstantFP>(C)) {
151 // fsub(x, c) == fadd(x, -c) for every FP constant c, since IEEE 754
152 // defines subtraction as addition of the negated operand.
153 assert(is_contained({Instruction::FAdd, Instruction::FSub}, ToOpcode) &&
154 "Cannot convert the instruction.");
155 RHS = ConstantFP::get(RHSType, -CFP->getValueAPF());
156 } else {
157 auto *CI = cast<ConstantInt>(C);
158 const APInt &FromCIValue = CI->getValue();
159 unsigned FromCIValueBitWidth = FromCIValue.getBitWidth();
160 switch (FromOpcode) {
161 case Instruction::Shl:
162 if (ToOpcode == Instruction::Add && FromCIValue.isOne())
163 return {I->getOperand(0), I->getOperand(0)};
164 if (ToOpcode == Instruction::Mul) {
165 RHS = ConstantInt::get(RHSType,
166 APInt::getOneBitSet(FromCIValueBitWidth,
167 FromCIValue.getZExtValue()));
168 } else {
169 assert(FromCIValue.isZero() && "Cannot convert the instruction.");
170 RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
171 /*AllowRHSConstant=*/true);
172 }
173 break;
174 case Instruction::Mul:
175 assert(FromCIValue.isPowerOf2() && "Cannot convert the instruction.");
176 if (ToOpcode == Instruction::Shl) {
177 RHS = ConstantInt::get(
178 RHSType, APInt(FromCIValueBitWidth, FromCIValue.logBase2()));
179 } else {
180 assert(FromCIValue.isOne() && "Cannot convert the instruction.");
181 RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
182 /*AllowRHSConstant=*/true);
183 }
184 break;
185 case Instruction::Add:
186 case Instruction::Sub:
187 if (FromCIValue.isZero()) {
188 RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
189 /*AllowRHSConstant=*/true);
190 } else {
191 assert(is_contained({Instruction::Add, Instruction::Sub}, ToOpcode) &&
192 "Cannot convert the instruction.");
193 APInt NegatedVal = APInt(FromCIValue);
194 NegatedVal.negate();
195 RHS = ConstantInt::get(RHSType, NegatedVal);
196 }
197 break;
198 case Instruction::And:
199 assert(FromCIValue.isAllOnes() && "Cannot convert the instruction.");
200 RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
201 /*AllowRHSConstant=*/true);
202 break;
203 default:
204 assert(FromCIValue.isZero() && "Cannot convert the instruction.");
205 RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
206 /*AllowRHSConstant=*/true);
207 break;
208 }
209 }
210 Value *LHS = I->getOperand(1 - Pos);
211 // If the target opcode is non-commutative (e.g., shl, sub),
212 // force the variable to the left and the constant to the right.
213 if (Pos == 1 || !Instruction::isCommutative(ToOpcode))
214 return SmallVector<Value *>({LHS, RHS});
215
216 return SmallVector<Value *>({RHS, LHS});
217}
218
219bool BinOpSameOpcodeHelper::isValidForAlternation(const Instruction *I) const {
220 return slpvectorizer::isValidForAlternation(MainOp.I->getOpcode()) &&
222}
223
224bool BinOpSameOpcodeHelper::initializeAltOp(const Instruction *I) {
225 if (AltOp.I)
226 return true;
227 if (!isValidForAlternation(I))
228 return false;
229 AltOp.I = I;
230 return true;
231}
232
235 "BinOpSameOpcodeHelper only accepts BinaryOperator.");
236 unsigned Opcode = I->getOpcode();
237 MaskType OpcodeInMaskForm;
238 // Prefer Shl, AShr, Mul, Add, Sub, And, Or, Xor, FAdd and FSub over
239 // MainOp.
240 switch (Opcode) {
241 case Instruction::Shl:
242 OpcodeInMaskForm = ShlBIT;
243 break;
244 case Instruction::AShr:
245 OpcodeInMaskForm = AShrBIT;
246 break;
247 case Instruction::Mul:
248 OpcodeInMaskForm = MulBIT;
249 break;
250 case Instruction::Add:
251 OpcodeInMaskForm = AddBIT;
252 break;
253 case Instruction::Sub:
254 OpcodeInMaskForm = SubBIT;
255 break;
256 case Instruction::And:
257 OpcodeInMaskForm = AndBIT;
258 break;
259 case Instruction::Or:
260 OpcodeInMaskForm = OrBIT;
261 break;
262 case Instruction::Xor:
263 OpcodeInMaskForm = XorBIT;
264 break;
265 case Instruction::FAdd:
266 OpcodeInMaskForm = FAddBIT;
267 break;
268 case Instruction::FSub:
269 OpcodeInMaskForm = FSubBIT;
270 break;
271 default:
272 return MainOp.equal(Opcode) || (initializeAltOp(I) && AltOp.equal(Opcode));
273 }
274 MaskType InterchangeableMask = OpcodeInMaskForm;
275 auto [C, Pos] = isBinOpWithConstant(I);
276 if (auto *CI = dyn_cast_or_null<ConstantInt>(C)) {
277 constexpr MaskType CanBeAll =
278 XorBIT | OrBIT | AndBIT | SubBIT | AddBIT | MulBIT | AShrBIT | ShlBIT;
279 const APInt &CIValue = CI->getValue();
280 switch (Opcode) {
281 case Instruction::Shl:
282 if (CIValue.ult(CIValue.getBitWidth()))
283 InterchangeableMask = CIValue.isZero() ? CanBeAll : MulBIT | ShlBIT;
284 if (CIValue.isOne())
285 InterchangeableMask |= AddBIT;
286 break;
287 case Instruction::Mul:
288 if (CIValue.isOne()) {
289 InterchangeableMask = CanBeAll;
290 break;
291 }
292 if (CIValue.isPowerOf2())
293 InterchangeableMask = MulBIT | ShlBIT;
294 break;
295 case Instruction::Add:
296 case Instruction::Sub:
297 InterchangeableMask = CIValue.isZero() ? CanBeAll : SubBIT | AddBIT;
298 break;
299 case Instruction::And:
300 if (CIValue.isAllOnes())
301 InterchangeableMask = CanBeAll;
302 break;
303 case Instruction::Xor:
304 if (CIValue.isZero())
305 InterchangeableMask = XorBIT | OrBIT | SubBIT | AddBIT;
306 break;
307 default:
308 if (CIValue.isZero())
309 InterchangeableMask = CanBeAll;
310 break;
311 }
312 } else if (C && Pos == 1) {
313 // FAdd/FSub with a constant RHS: negating the constant always
314 // converts one into the other, so no value check is needed. A
315 // constant LHS (Pos == 0, e.g. "0.0 - x") is excluded: unlike a
316 // constant RHS, it cannot be moved to the other opcode without also
317 // swapping the variable operand, which would misalign it against
318 // lanes that keep their native opcode (their variable operand stays
319 // on the other side).
320 InterchangeableMask = FSubBIT | FAddBIT;
321 }
322 return MainOp.trySet(OpcodeInMaskForm, InterchangeableMask) ||
323 (initializeAltOp(I) &&
324 AltOp.trySet(OpcodeInMaskForm, InterchangeableMask));
325}
326
328 const Instruction *Op) {
329 if (I->getOpcode() != Op->getOpcode())
330 return false;
331 const auto *II = dyn_cast<IntrinsicInst>(I);
332 const auto *IOp = dyn_cast<IntrinsicInst>(Op);
333 if (II || IOp)
334 return II && IOp &&
335 isEquivalentIntrinsicID(II->getIntrinsicID(),
336 IOp->getIntrinsicID()) !=
338 return true;
339}
340
342 assert(MainOp && "MainOp cannot be nullptr.");
343 if (isSameOperation(I, MainOp))
344 return MainOp;
345 if (MainOp->getOpcode() == Instruction::Select &&
346 I->getOpcode() == Instruction::ZExt && !isAltShuffle())
347 return MainOp;
348 // Prefer AltOp instead of interchangeable instruction of MainOp.
349 assert(AltOp && "AltOp cannot be nullptr.");
350 if (isSameOperation(I, AltOp))
351 return AltOp;
352 // BinOpSameOpcodeHelper handles only BinaryOperators; a call cannot match.
353 if (!I->isBinaryOp() || !MainOp->isBinaryOp())
354 return nullptr;
356 if (!Converter.add(I) || !Converter.add(MainOp))
357 return nullptr;
358 if (isAltShuffle() && !Converter.hasCandidateOpcode(MainOp->getOpcode())) {
359 BinOpSameOpcodeHelper AltConverter(AltOp);
360 if (AltConverter.add(I) && AltConverter.add(AltOp) &&
361 AltConverter.hasCandidateOpcode(AltOp->getOpcode()))
362 return AltOp;
363 }
364 if (Converter.hasAltOp() && !isAltShuffle())
365 return nullptr;
366 return Converter.hasAltOp() ? AltOp : MainOp;
367}
368
370 constexpr std::array<unsigned, 8> MulDiv = {
371 Instruction::Mul, Instruction::FMul, Instruction::SDiv,
372 Instruction::UDiv, Instruction::FDiv, Instruction::SRem,
373 Instruction::URem, Instruction::FRem};
374 return is_contained(MulDiv, getOpcode()) &&
375 is_contained(MulDiv, getAltOpcode());
376}
377
379 constexpr std::array<unsigned, 4> AddSub = {
380 Instruction::Add, Instruction::Sub, Instruction::FAdd, Instruction::FSub};
381 return is_contained(AddSub, getOpcode()) &&
382 is_contained(AddSub, getAltOpcode());
383}
384
386 assert(valid() && "InstructionsState is invalid.");
387 if (!HasCopyables)
388 return false;
389 if (isAltShuffle() || getOpcode() == Instruction::GetElementPtr)
390 return false;
391 auto *I = dyn_cast<Instruction>(V);
392 if (!I)
393 return !isa<PoisonValue>(V);
394 if (I->getParent() != MainOp->getParent() &&
397 return true;
398 if (isSameOperation(I, MainOp))
399 return false;
400 // BinOpSameOpcodeHelper handles only BinaryOperators; a call is copyable.
401 if (!I->isBinaryOp() || !MainOp->isBinaryOp())
402 return true;
404 return !Converter.add(I) || !Converter.add(MainOp) || Converter.hasAltOp() ||
405 !Converter.hasCandidateOpcode(getOpcode());
406}
407
409 auto *I = dyn_cast<Instruction>(V);
410 return I &&
411 (I->getOpcode() == Instruction::FMul ||
412 I->getOpcode() == Instruction::FAdd) &&
413 I->hasOneUse() && none_of(I->operands(), [&](Value *Op) {
414 return is_contained(VL, Op);
415 });
416}
417
419 auto *I = dyn_cast<Instruction>(V);
420 return I && S.isCopyableElement(I) &&
421 (I->getOpcode() == Instruction::FMul ||
422 I->getOpcode() == Instruction::FAdd) &&
423 I->hasOneUse();
424}
425
427 bool HasFMulOrFAdd = false;
428 for (Value *V : VL) {
429 if (isa<PoisonValue>(V))
430 continue;
431 auto *I = dyn_cast<Instruction>(V);
433 continue;
434 if (!isAbsorbableFMulOrFAdd(VL, V))
435 return false;
436 HasFMulOrFAdd = true;
437 }
438 return HasFMulOrFAdd;
439}
440
442 assert(valid() && "InstructionsState is invalid.");
443 if (isCopyableElement(V))
444 return false;
445 auto *ExpandingOp = dyn_cast<Instruction>(V);
446 if (!ExpandingOp)
447 return false;
448 auto CheckForTransformedOpcode = [](const Instruction *RefOp,
449 const Instruction *ExpandingOp) {
450 switch (RefOp->getOpcode()) {
451 case Instruction::Add:
452 switch (ExpandingOp->getOpcode()) {
453 case Instruction::Shl:
454 return match(ExpandingOp, m_Shl(m_Value(), m_One()));
455 default:
456 break;
457 }
458 break;
459 default:
460 break;
461 }
462 return false;
463 };
464 // getMatchingMainOpOrAltOp() may legitimately return nullptr, e.g. for a
465 // split node, whose Scalars combine two unrelated operations (main/alt
466 // ops of the split state), so V is not required to match either of them.
467 Instruction *MainOp = getMatchingMainOpOrAltOp(ExpandingOp);
468 if (!MainOp)
469 return false;
470 return CheckForTransformedOpcode(MainOp, ExpandingOp);
471}
472
474 assert(isExpandedBinOp(I) && "Expected an expanded binop.");
475 switch (I->getOpcode()) {
476 case Instruction::Shl:
477 assert(match(I, m_Shl(m_Value(), m_One())) && "Expected shl x, 1 only.");
478 return Idx == 1;
479 default:
480 llvm_unreachable("Unexpected opcode for an expanded operand.");
481 }
482}
483
485 assert(valid() && "InstructionsState is invalid.");
486 auto *I = dyn_cast<Instruction>(V);
487 if (!HasCopyables)
490 // MainOp for copyables always schedulable to correctly identify
491 // non-schedulable copyables.
492 if (getMainOp() == V)
493 return false;
494 if (isCopyableElement(V)) {
495 auto IsNonSchedulableCopyableElement = [this](Value *V) {
496 auto *I = dyn_cast<Instruction>(V);
497 return !I || isa<PHINode>(I) || I->getParent() != MainOp->getParent() ||
499 // If the copyable instructions comes after MainOp
500 // (non-schedulable, but used in the block) - cannot vectorize
501 // it, will possibly generate use before def.
502 !MainOp->comesBefore(I));
503 };
504
505 return IsNonSchedulableCopyableElement(V);
506 }
509}
510
511/// Find an instruction with a specific opcode in VL.
512/// \param VL Array of values to search through. Must contain only Instructions
513/// and PoisonValues.
514/// \param Opcode The instruction opcode to search for
515/// \returns
516/// - The first instruction found with matching opcode
517/// - nullptr if no matching instruction is found
519 unsigned Opcode) {
520 for (Value *V : VL) {
521 if (isa<PoisonValue>(V))
522 continue;
523 assert(isa<Instruction>(V) && "Only accepts PoisonValue and Instruction.");
524 auto *Inst = cast<Instruction>(V);
525 if (Inst->getOpcode() == Opcode)
526 return Inst;
527 }
528 return nullptr;
529}
530
531/// Checks if the provided operands of 2 cmp instructions are compatible, i.e.
532/// compatible instructions or constants, or just some other regular values.
533static bool areCompatibleCmpOps(Value *BaseOp0, Value *BaseOp1, Value *Op0,
534 Value *Op1, const TargetLibraryInfo &TLI) {
535 return (isConstant(BaseOp0) && isConstant(Op0)) ||
536 (isConstant(BaseOp1) && isConstant(Op1)) ||
537 (!isa<Instruction>(BaseOp0) && !isa<Instruction>(Op0) &&
538 !isa<Instruction>(BaseOp1) && !isa<Instruction>(Op1)) ||
539 BaseOp0 == Op0 || BaseOp1 == Op1 ||
540 getSameOpcode({BaseOp0, Op0}, TLI) ||
541 getSameOpcode({BaseOp1, Op1}, TLI);
542}
543
544/// \returns true if a compare instruction \p CI has similar "look" and
545/// same predicate as \p BaseCI, "as is" or with its operands and predicate
546/// swapped, false otherwise.
547static bool isCmpSameOrSwapped(const CmpInst *BaseCI, const CmpInst *CI,
548 const TargetLibraryInfo &TLI) {
549 assert(BaseCI->getOperand(0)->getType() == CI->getOperand(0)->getType() &&
550 "Assessing comparisons of different types?");
551 CmpInst::Predicate BasePred = BaseCI->getPredicate();
552 CmpInst::Predicate Pred = CI->getPredicate();
554
555 Value *BaseOp0 = BaseCI->getOperand(0);
556 Value *BaseOp1 = BaseCI->getOperand(1);
557 Value *Op0 = CI->getOperand(0);
558 Value *Op1 = CI->getOperand(1);
559
560 return (BasePred == Pred &&
561 areCompatibleCmpOps(BaseOp0, BaseOp1, Op0, Op1, TLI)) ||
562 (BasePred == SwappedPred &&
563 areCompatibleCmpOps(BaseOp0, BaseOp1, Op1, Op0, TLI));
564}
565
567 const TargetLibraryInfo &TLI) {
568 // Make sure these are all Instructions.
571
572 auto *It = find_if(VL, IsaPred<Instruction>);
573 if (It == VL.end())
575
576 Instruction *MainOp = cast<Instruction>(*It);
577 unsigned InstCnt = std::count_if(It, VL.end(), IsaPred<Instruction>);
578 if ((VL.size() > 2 && !isa<PHINode>(MainOp) && InstCnt < VL.size() / 2) ||
579 (VL.size() == 2 && InstCnt < 2))
581
582 bool IsCastOp = isa<CastInst>(MainOp);
583 bool IsBinOp = isa<BinaryOperator>(MainOp);
584 bool IsCmpOp = isa<CmpInst>(MainOp);
585 CmpInst::Predicate BasePred = IsCmpOp ? cast<CmpInst>(MainOp)->getPredicate()
587 Instruction *AltOp = MainOp;
588 unsigned Opcode = MainOp->getOpcode();
589 unsigned AltOpcode = Opcode;
590
591 BinOpSameOpcodeHelper BinOpHelper(MainOp);
592 bool SwappedPredsCompatible = IsCmpOp && [&]() {
593 SetVector<unsigned> UniquePreds, UniqueNonSwappedPreds;
594 UniquePreds.insert(BasePred);
595 UniqueNonSwappedPreds.insert(BasePred);
596 for (Value *V : VL) {
597 auto *I = dyn_cast<CmpInst>(V);
598 if (!I)
599 return false;
600 CmpInst::Predicate CurrentPred = I->getPredicate();
601 CmpInst::Predicate SwappedCurrentPred =
602 CmpInst::getSwappedPredicate(CurrentPred);
603 UniqueNonSwappedPreds.insert(CurrentPred);
604 if (!UniquePreds.contains(CurrentPred) &&
605 !UniquePreds.contains(SwappedCurrentPred))
606 UniquePreds.insert(CurrentPred);
607 }
608 // Total number of predicates > 2, but if consider swapped predicates
609 // compatible only 2, consider swappable predicates as compatible opcodes,
610 // not alternate.
611 return UniqueNonSwappedPreds.size() > 2 && UniquePreds.size() == 2;
612 }();
613 // Check for one alternate opcode from another BinaryOperator.
614 // TODO - generalize to support all operators (types, calls etc.).
615 Intrinsic::ID BaseID = 0;
616 SmallVector<VFInfo, 4> BaseMappings;
617 if (auto *CallBase = dyn_cast<CallInst>(MainOp)) {
619 BaseMappings = VFDatabase(*CallBase).getMappings(*CallBase);
620 if (!isTriviallyVectorizable(BaseID) && BaseMappings.empty())
622 }
623 bool AnyPoison = InstCnt != VL.size();
624 // Check MainOp too to be sure that it matches the requirements for the
625 // instructions.
626 for (Value *V : iterator_range(It, VL.end())) {
627 auto *I = dyn_cast<Instruction>(V);
628 if (!I)
629 continue;
630
631 // Cannot combine poison and divisions.
632 // TODO: do some smart analysis of the CallInsts to exclude divide-like
633 // intrinsics/functions only.
634 if (AnyPoison && (I->isIntDivRem() || I->isFPDivRem() || isa<CallInst>(I)))
636 unsigned InstOpcode = I->getOpcode();
637 if (IsBinOp && isa<BinaryOperator>(I)) {
638 if (BinOpHelper.add(I))
639 continue;
640 } else if (IsCastOp && isa<CastInst>(I)) {
641 Value *Op0 = MainOp->getOperand(0);
642 Type *Ty0 = Op0->getType();
643 Value *Op1 = I->getOperand(0);
644 Type *Ty1 = Op1->getType();
645 if (Ty0 == Ty1) {
646 if (InstOpcode == Opcode || InstOpcode == AltOpcode)
647 continue;
648 if (Opcode == AltOpcode) {
650 isValidForAlternation(InstOpcode) &&
651 "Cast isn't safe for alternation, logic needs to be updated!");
652 AltOpcode = InstOpcode;
653 AltOp = I;
654 continue;
655 }
656 }
657 } else if (auto *Inst = dyn_cast<CmpInst>(I); Inst && IsCmpOp) {
658 auto *BaseInst = cast<CmpInst>(MainOp);
659 Type *Ty0 = BaseInst->getOperand(0)->getType();
660 Type *Ty1 = Inst->getOperand(0)->getType();
661 if (Ty0 == Ty1) {
662 assert(InstOpcode == Opcode && "Expected same CmpInst opcode.");
663 assert(InstOpcode == AltOpcode &&
664 "Alternate instructions are only supported by BinaryOperator "
665 "and CastInst.");
666 // Check for compatible operands. If the corresponding operands are not
667 // compatible - need to perform alternate vectorization.
668 CmpInst::Predicate CurrentPred = Inst->getPredicate();
669 CmpInst::Predicate SwappedCurrentPred =
670 CmpInst::getSwappedPredicate(CurrentPred);
671
672 if ((VL.size() == 2 || SwappedPredsCompatible) &&
673 (BasePred == CurrentPred || BasePred == SwappedCurrentPred))
674 continue;
675
676 if (isCmpSameOrSwapped(BaseInst, Inst, TLI))
677 continue;
678 auto *AltInst = cast<CmpInst>(AltOp);
679 if (MainOp != AltOp) {
680 if (isCmpSameOrSwapped(AltInst, Inst, TLI))
681 continue;
682 } else if (BasePred != CurrentPred) {
683 assert(
684 isValidForAlternation(InstOpcode) &&
685 "CmpInst isn't safe for alternation, logic needs to be updated!");
686 AltOp = I;
687 continue;
688 }
689 CmpInst::Predicate AltPred = AltInst->getPredicate();
690 if (BasePred == CurrentPred || BasePred == SwappedCurrentPred ||
691 AltPred == CurrentPred || AltPred == SwappedCurrentPred)
692 continue;
693 }
694 } else if (InstOpcode == Opcode) {
695 assert(InstOpcode == AltOpcode &&
696 "Alternate instructions are only supported by BinaryOperator and "
697 "CastInst.");
698 if (auto *Gep = dyn_cast<GetElementPtrInst>(I)) {
699 if (Gep->getNumOperands() != 2 ||
700 Gep->getOperand(0)->getType() != MainOp->getOperand(0)->getType())
702 } else if (auto *EI = dyn_cast<ExtractElementInst>(I)) {
705 } else if (auto *LI = dyn_cast<LoadInst>(I)) {
706 auto *BaseLI = cast<LoadInst>(MainOp);
707 if (!LI->isSimple() || !BaseLI->isSimple())
709 } else if (auto *Call = dyn_cast<CallInst>(I)) {
710 auto *CallBase = cast<CallInst>(MainOp);
712 Intrinsic::ID Equivalent = isEquivalentIntrinsicID(ID, BaseID);
713 if (Call->getCalledFunction() != CallBase->getCalledFunction() &&
714 isEquivalentIntrinsicID(Equivalent, Intrinsic::fmuladd) ==
717 if (Call->hasOperandBundles() &&
719 !std::equal(Call->op_begin() + Call->getBundleOperandsStartIndex(),
720 Call->op_begin() + Call->getBundleOperandsEndIndex(),
721 CallBase->op_begin() +
724 if (ID != BaseID && Equivalent == Intrinsic::not_intrinsic)
726 if (!ID) {
727 SmallVector<VFInfo, 4> Mappings =
728 VFDatabase(*Call).getMappings(*Call);
729 if (Mappings.size() != BaseMappings.size() ||
730 Mappings.front().ISA != BaseMappings.front().ISA ||
731 Mappings.front().ScalarName != BaseMappings.front().ScalarName ||
732 Mappings.front().VectorName != BaseMappings.front().VectorName ||
733 Mappings.front().Shape.VF != BaseMappings.front().Shape.VF ||
734 Mappings.front().Shape.Parameters !=
735 BaseMappings.front().Shape.Parameters)
737 }
738 }
739 continue;
740 }
742 }
743
744 if (IsBinOp) {
745 if (!BinOpHelper.hasDefinedMainOpcode() ||
746 !BinOpHelper.hasDefinedAltOpcode())
748 MainOp = findInstructionWithOpcode(VL, BinOpHelper.getMainOpcode());
749 assert(MainOp && "Cannot find MainOp with Opcode from BinOpHelper.");
750 AltOp = findInstructionWithOpcode(VL, BinOpHelper.getAltOpcode());
751 assert(AltOp && "Cannot find AltOp with Opcode from BinOpHelper.");
752 } else if (auto *CB = dyn_cast<CallInst>(MainOp);
753 CB &&
754 getVectorIntrinsicIDForCall(CB, &TLI) == Intrinsic::fmuladd) {
755 // fma and fmuladd share a single vector fma node; use the fma as the
756 // representative so the fused form is not weakened to fmuladd.
757 auto *It = find_if(VL, [&](Value *V) {
758 auto *CI = dyn_cast<CallInst>(V);
759 return CI && getVectorIntrinsicIDForCall(CI, &TLI) == Intrinsic::fma;
760 });
761 if (It != VL.end())
762 MainOp = AltOp = cast<Instruction>(*It);
763 }
764 assert((MainOp == AltOp || !allSameOpcode(VL)) &&
765 "Incorrect implementation of allSameOpcode.");
766 InstructionsState S(MainOp, AltOp);
767 assert(all_of(VL,
768 [&](Value *V) {
769 return isa<PoisonValue>(V) ||
771 }) &&
772 "Invalid InstructionsState.");
773 return S;
774}
775
776std::pair<Instruction *, SmallVector<Value *>>
778 Instruction *SelectedOp = S.getMatchingMainOpOrAltOp(I);
779 assert(SelectedOp && "Cannot convert the instruction.");
780 if (I->isBinaryOp()) {
782 return std::make_pair(SelectedOp, Converter.getOperand(SelectedOp));
783 }
784 // Use args() to skip the trailing callee operand in CallInst::operands().
785 if (auto *CI = dyn_cast<CallInst>(I))
786 return std::make_pair(SelectedOp, SmallVector<Value *>(CI->args()));
787 return std::make_pair(SelectedOp, SmallVector<Value *>(I->operands()));
788}
789
791 Instruction *AltOp, const TargetLibraryInfo &TLI) {
792 if (auto *MainCI = dyn_cast<CmpInst>(MainOp)) {
793 auto *AltCI = cast<CmpInst>(AltOp);
794 CmpInst::Predicate MainP = MainCI->getPredicate();
795 [[maybe_unused]] CmpInst::Predicate AltP = AltCI->getPredicate();
796 assert(MainP != AltP && "Expected different main/alternate predicates.");
797 auto *CI = cast<CmpInst>(I);
798 if (isCmpSameOrSwapped(MainCI, CI, TLI))
799 return false;
800 if (isCmpSameOrSwapped(AltCI, CI, TLI))
801 return true;
802 CmpInst::Predicate P = CI->getPredicate();
804
805 assert((MainP == P || AltP == P || MainP == SwappedP || AltP == SwappedP) &&
806 "CmpInst expected to match either main or alternate predicate or "
807 "their swap.");
808 return MainP != P && MainP != SwappedP;
809 }
810 return InstructionsState(MainOp, AltOp).getMatchingMainOpOrAltOp(I) == AltOp;
811}
812
814 const InstructionsState &S, const TargetLibraryInfo &TLI,
816 SmallVectorImpl<Value *> &ReassocScalars, SmallBitVector &SubLanes) {
817 assert(S.isAltShuffle() && "Expected an alternate node.");
818 const unsigned NumLanes = VL.size();
819 SmallVector<unsigned> LaneOpcodes =
820 map_to_vector(seq<unsigned>(NumLanes), [&](unsigned Lane) {
822 S.getMainOp(), S.getAltOp(), TLI)
823 ? S.getAltOpcode()
824 : S.getOpcode();
825 });
826 // A lane value peels only as a single-use chain link with the lane's own
827 // opcode, keeping every combine level on the same main/alt pattern.
828 auto GetChainLink = [&](unsigned Lane, Value *V) -> Instruction * {
829 auto *I = dyn_cast<Instruction>(V);
830 if (!I || !I->hasOneUse() || I->getOpcode() != LaneOpcodes[Lane] ||
832 return nullptr;
833 return I;
834 };
836 Columns.emplace_back(Op0.begin(), Op0.end());
837 Columns.emplace_back(Op1.begin(), Op1.end());
838 // The chain link of a commutative lane may sit in the second column;
839 // normalize so every lane's link leads.
840 for (unsigned Lane : seq<unsigned>(NumLanes)) {
841 if (GetChainLink(Lane, Columns[0][Lane]))
842 continue;
843 Instruction *Link = GetChainLink(Lane, Columns[1][Lane]);
844 if (!Link || !Link->isCommutative())
845 return {};
846 std::swap(Columns[0][Lane], Columns[1][Lane]);
847 }
848 // Peel the leading column while every lane stays a matching chain link.
849 while (all_of(seq<unsigned>(NumLanes), [&](unsigned Lane) {
850 return GetChainLink(Lane, Columns[0][Lane]) != nullptr;
851 })) {
852 SmallVector<Value *> NewColumn(NumLanes);
853 for (unsigned Lane : seq<unsigned>(NumLanes)) {
854 Instruction *Link = GetChainLink(Lane, Columns[0][Lane]);
855 ReassocScalars.push_back(Link);
856 // The chain of a commutative lane may continue in the second operand;
857 // keep the chain link as the running value.
858 unsigned RunningOp = Link->isCommutative() &&
859 !GetChainLink(Lane, Link->getOperand(0)) &&
860 GetChainLink(Lane, Link->getOperand(1))
861 ? 1
862 : 0;
863 NewColumn[Lane] = Link->getOperand(1 - RunningOp);
864 Columns[0][Lane] = Link->getOperand(RunningOp);
865 }
866 Columns.insert(std::next(Columns.begin()), std::move(NewColumn));
867 }
868 assert(!ReassocScalars.empty() &&
869 "Normalization guarantees at least one peeled level.");
870 SubLanes.resize(NumLanes);
871 for (unsigned Lane : seq<unsigned>(NumLanes))
872 if (LaneOpcodes[Lane] == Instruction::Sub ||
873 LaneOpcodes[Lane] == Instruction::FSub)
874 SubLanes.set(Lane);
875 return Columns;
876}
877} // namespace llvm::slpvectorizer
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
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
#define P(N)
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
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1561
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:368
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:377
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1509
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition APInt.h:1116
unsigned logBase2() const
Definition APInt.h:1782
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
Definition APInt.h:437
bool isOne() const
Determine if this is a value of 1.
Definition APInt.h:386
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
Definition APInt.h:236
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
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition InstrTypes.h:890
Predicate getPredicate() const
Return the predicate for this instruction.
Definition InstrTypes.h:828
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:43
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...
reference emplace_back(ArgTypes &&... Args)
iterator insert(iterator I, T &&Elt)
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
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:255
Helper class that determines VL can use the same opcode.
bool hasCandidateOpcode(unsigned Opcode) const
Checks if the list of potential opcodes includes Opcode.
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 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.
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.
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.
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)
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...
bool allSameOpcode(ArrayRef< Value * > VL)
Definition SLPUtils.cpp:254
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:161
bool isReassocChainLink(const Instruction *I)
Definition SLPUtils.cpp:54
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:152
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:62
bool doesNotNeedToBeScheduled(Value *V)
Checks if the specified value does not require scheduling.
Definition SLPUtils.cpp:382
bool isConstant(Value *V)
Definition SLPUtils.cpp:34
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:1739
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 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:2039
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
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:1753
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:1772
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:1947
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