LLVM 24.0.0git
LoopIdiomVectorize.cpp
Go to the documentation of this file.
1//===-------- LoopIdiomVectorize.cpp - Loop idiom vectorization -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This pass implements a pass that recognizes certain loop idioms and
10// transforms them into more optimized versions of the same loop. In cases
11// where this happens, it can be a significant performance win.
12//
13// We currently support two loops:
14//
15// 1. A loop that finds the first mismatched byte in an array and returns the
16// index, i.e. something like:
17//
18// while (++i != n) {
19// if (a[i] != b[i])
20// break;
21// }
22//
23// In this example we can actually vectorize the loop despite the early exit,
24// although the loop vectorizer does not support it. It requires some extra
25// checks to deal with the possibility of faulting loads when crossing page
26// boundaries. However, even with these checks it is still profitable to do the
27// transformation.
28//
29// TODO List:
30//
31// * Add support for the inverse case where we scan for a matching element.
32// * Permit 64-bit induction variable types.
33// * Recognize loops that increment the IV *after* comparing bytes.
34// * Allow 32-bit sign-extends of the IV used by the GEP.
35//
36// 2. A loop that finds the first matching character in an array among a set of
37// possible matches, e.g.:
38//
39// for (; first != last; ++first)
40// for (s_it = s_first; s_it != s_last; ++s_it)
41// if (*first == *s_it)
42// return first;
43// return last;
44//
45// This corresponds to std::find_first_of (for arrays of bytes) from the C++
46// standard library. This function can be implemented efficiently for targets
47// that support @llvm.experimental.vector.match. For example, on AArch64 targets
48// that implement SVE2, this lower to a MATCH instruction, which enables us to
49// perform up to 16x16=256 comparisons in one go. This can lead to very
50// significant speedups.
51//
52// TODO:
53//
54// * Add support for `find_first_not_of' loops (i.e. with not-equal comparison).
55// * Make VF a configurable parameter (right now we assume 128-bit vectors).
56// * Potentially adjust the cost model to let the transformation kick-in even if
57// @llvm.experimental.vector.match doesn't have direct support in hardware.
58//
59//===----------------------------------------------------------------------===//
60//
61// NOTE: This Pass matches really specific loop patterns because it's only
62// supposed to be a temporary solution until our LoopVectorizer is powerful
63// enough to vectorize them automatically.
64//
65//===----------------------------------------------------------------------===//
66
68#include "VectorizeOptions.h"
73#include "llvm/IR/Dominators.h"
74#include "llvm/IR/IRBuilder.h"
75#include "llvm/IR/Intrinsics.h"
76#include "llvm/IR/MDBuilder.h"
80
81using namespace llvm;
82using namespace PatternMatch;
83
84#define DEBUG_TYPE "loop-idiom-vectorize"
85
86namespace {
87class LoopIdiomVectorize {
88 const VectorizeOptions &Opts;
89 LoopIdiomVectorizeStyle VectorizeStyle;
90 unsigned ByteCompareVF;
91 Loop *CurLoop = nullptr;
92 DominatorTree *DT;
93 LoopInfo *LI;
95 const DataLayout *DL;
96
97 /// Interface to emit optimization remarks.
99
100 // Blocks that will be used for inserting vectorized code.
101 BasicBlock *EndBlock = nullptr;
102 BasicBlock *VectorLoopPreheaderBlock = nullptr;
103 BasicBlock *VectorLoopStartBlock = nullptr;
104 BasicBlock *VectorLoopMismatchBlock = nullptr;
105 BasicBlock *VectorLoopIncBlock = nullptr;
106
107public:
108 LoopIdiomVectorize(const VectorizeOptions &Opts, LoopIdiomVectorizeStyle S,
109 unsigned VF, DominatorTree *DT, LoopInfo *LI,
110 const TargetTransformInfo *TTI, const DataLayout *DL,
112 : Opts(Opts), VectorizeStyle(S), ByteCompareVF(VF), DT(DT), LI(LI),
113 TTI(TTI), DL(DL), ORE(ORE) {}
114
115 bool run(Loop *L);
116
117private:
118 /// \name Countable Loop Idiom Handling
119 /// @{
120
121 bool runOnLoopBlock(BasicBlock *BB, const SCEV *BECount,
123
124 bool recognizeByteCompare();
125
126 Value *expandFindMismatch(IRBuilder<> &Builder, DomTreeUpdater &DTU,
128 Instruction *Index, Value *Start, Value *MaxLen);
129
130 Value *createMaskedFindMismatch(IRBuilder<> &Builder, DomTreeUpdater &DTU,
131 GetElementPtrInst *GEPA,
132 GetElementPtrInst *GEPB, Value *ExtStart,
133 Value *ExtEnd);
134 Value *createPredicatedFindMismatch(IRBuilder<> &Builder, DomTreeUpdater &DTU,
135 GetElementPtrInst *GEPA,
136 GetElementPtrInst *GEPB, Value *ExtStart,
137 Value *ExtEnd);
138
139 void transformByteCompare(GetElementPtrInst *GEPA, GetElementPtrInst *GEPB,
140 PHINode *IndPhi, Value *MaxLen, Instruction *Index,
141 Value *Start, bool IncIdx, BasicBlock *FoundBB,
142 BasicBlock *EndBB);
143
144 bool recognizeFindFirstByte();
145
146 Value *expandFindFirstByte(IRBuilder<> &Builder, DomTreeUpdater &DTU,
147 unsigned VF, Type *CharTy, Value *IndPhi,
148 BasicBlock *ExitSucc, BasicBlock *ExitFail,
149 Value *SearchStart, Value *SearchEnd,
150 Value *NeedleStart, Value *NeedleEnd);
151
152 void transformFindFirstByte(PHINode *IndPhi, unsigned VF, Type *CharTy,
153 BasicBlock *ExitSucc, BasicBlock *ExitFail,
154 Value *SearchStart, Value *SearchEnd,
155 Value *NeedleStart, Value *NeedleEnd);
156 /// @}
157};
158} // anonymous namespace
159
162 LPMUpdater &) {
163 const VectorizeOptions &Opts = getVectorizeOptions(L);
164 if (Opts.disable_loop_idiom_vectorize_all)
165 return PreservedAnalyses::all();
166
167 const auto *DL = &L.getHeader()->getDataLayout();
168
169 LoopIdiomVectorizeStyle VecStyle =
170 Opts.loop_idiom_vectorize_style.value_or(VectorizeStyle);
171 unsigned BCVF = Opts.loop_idiom_vectorize_bytecmp_vf.value_or(ByteCompareVF);
172
173 Function &F = *L.getHeader()->getParent();
174 auto &FAMP = AM.getResult<FunctionAnalysisManagerLoopProxy>(L, AR);
175 auto *ORE = FAMP.getCachedResult<OptimizationRemarkEmitterAnalysis>(F);
176
177 std::optional<OptimizationRemarkEmitter> ORELocal;
178 if (!ORE) {
179 ORELocal.emplace(&F);
180 ORE = &*ORELocal;
181 }
182
183 LoopIdiomVectorize LIV(Opts, VecStyle, BCVF, &AR.DT, &AR.LI, &AR.TTI, DL,
184 *ORE);
185 if (!LIV.run(&L))
186 return PreservedAnalyses::all();
187
189}
190
191//===----------------------------------------------------------------------===//
192//
193// Implementation of LoopIdiomVectorize
194//
195//===----------------------------------------------------------------------===//
196
197bool LoopIdiomVectorize::run(Loop *L) {
198 CurLoop = L;
199
200 Function &F = *L->getHeader()->getParent();
201 if (Opts.disable_loop_idiom_vectorize_all || F.hasOptSize())
202 return false;
203
204 // Bail if vectorization is disabled on loop.
205 LoopVectorizeHints Hints(Opts, L, /*InterleaveOnlyWhenForced=*/true, ORE);
206 if (!Hints.allowVectorization(&F, L, /*VectorizeOnlyWhenForced=*/false)) {
207 LLVM_DEBUG(dbgs() << DEBUG_TYPE << " is disabled on " << L->getName()
208 << " due to vectorization hints\n");
209 return false;
210 }
211
212 if (F.hasFnAttribute(Attribute::NoImplicitFloat)) {
213 LLVM_DEBUG(dbgs() << DEBUG_TYPE << " is disabled on " << F.getName()
214 << " due to its NoImplicitFloat attribute");
215 return false;
216 }
217
218 // If the loop could not be converted to canonical form, it must have an
219 // indirectbr in it, just give up.
220 if (!L->getLoopPreheader())
221 return false;
222
223 LLVM_DEBUG(dbgs() << DEBUG_TYPE " Scanning: F[" << F.getName() << "] Loop %"
224 << CurLoop->getHeader()->getName() << "\n");
225
226 if (recognizeByteCompare())
227 return true;
228
229 if (recognizeFindFirstByte())
230 return true;
231
232 return false;
233}
234
235static void fixSuccessorPhis(Loop *L, Value *ScalarRes, Value *VectorRes,
236 BasicBlock *SuccBB, BasicBlock *IncBB) {
237 for (PHINode &PN : SuccBB->phis()) {
238 // Look through the incoming values to find ScalarRes, meaning this is a
239 // PHI collecting the results of the transformation.
240 bool ResPhi = false;
241 for (Value *Op : PN.incoming_values())
242 if (Op == ScalarRes) {
243 ResPhi = true;
244 break;
245 }
246
247 // Any PHI that depended upon the result of the transformation needs a new
248 // incoming value from IncBB.
249 if (ResPhi)
250 PN.addIncoming(VectorRes, IncBB);
251 else {
252 // There should be no other outside uses of other values in the
253 // original loop. Any incoming values should either:
254 // 1. Be for blocks outside the loop, which aren't interesting. Or ..
255 // 2. These are from blocks in the loop with values defined outside
256 // the loop. We should a similar incoming value from CmpBB.
257 for (BasicBlock *BB : PN.blocks())
258 if (L->contains(BB)) {
259 PN.addIncoming(PN.getIncomingValueForBlock(BB), IncBB);
260 break;
261 }
262 }
263 }
264}
265
266bool LoopIdiomVectorize::recognizeByteCompare() {
267 // Currently the transformation only works on scalable vector types, although
268 // there is no fundamental reason why it cannot be made to work for fixed
269 // width too.
270
271 // We also need to know the minimum page size for the target in order to
272 // generate runtime memory checks to ensure the vector version won't fault.
273 if (!TTI->supportsScalableVectors() || !TTI->getMinPageSize().has_value() ||
274 Opts.disable_loop_idiom_vectorize_bytecmp)
275 return false;
276
277 BasicBlock *Header = CurLoop->getHeader();
278
279 // In LoopIdiomVectorize::run we have already checked that the loop
280 // has a preheader so we can assume it's in a canonical form.
281 if (CurLoop->getNumBackEdges() != 1 || CurLoop->getNumBlocks() != 2)
282 return false;
283
284 PHINode *PN = dyn_cast<PHINode>(&Header->front());
285 if (!PN || PN->getNumIncomingValues() != 2)
286 return false;
287
288 auto LoopBlocks = CurLoop->getBlocks();
289 // The first block in the loop should contain only 4 instructions, e.g.
290 //
291 // while.cond:
292 // %res.phi = phi i32 [ %start, %ph ], [ %inc, %while.body ]
293 // %inc = add i32 %res.phi, 1
294 // %cmp.not = icmp eq i32 %inc, %n
295 // br i1 %cmp.not, label %while.end, label %while.body
296 //
297 if (LoopBlocks[0]->size() > 4)
298 return false;
299
300 // The second block should contain 7 instructions, e.g.
301 //
302 // while.body:
303 // %idx = zext i32 %inc to i64
304 // %idx.a = getelementptr inbounds i8, ptr %a, i64 %idx
305 // %load.a = load i8, ptr %idx.a
306 // %idx.b = getelementptr inbounds i8, ptr %b, i64 %idx
307 // %load.b = load i8, ptr %idx.b
308 // %cmp.not.ld = icmp eq i8 %load.a, %load.b
309 // br i1 %cmp.not.ld, label %while.cond, label %while.end
310 //
311 if (LoopBlocks[1]->size() > 7)
312 return false;
313
314 // The incoming value to the PHI node from the loop should be an add of 1.
315 Value *StartIdx = nullptr;
316 Instruction *Index = nullptr;
317 if (!CurLoop->contains(PN->getIncomingBlock(0))) {
318 StartIdx = PN->getIncomingValue(0);
320 } else {
321 StartIdx = PN->getIncomingValue(1);
323 }
324
325 // Limit to 32-bit types for now
326 if (!Index || !Index->getType()->isIntegerTy(32) ||
327 !match(Index, m_c_Add(m_Specific(PN), m_One())))
328 return false;
329
330 // If we match the pattern, PN and Index will be replaced with the result of
331 // the cttz.elts intrinsic. If any other instructions are used outside of
332 // the loop, we cannot replace it.
333 for (BasicBlock *BB : LoopBlocks)
334 for (Instruction &I : *BB)
335 if (&I != PN && &I != Index)
336 for (User *U : I.users())
337 if (!CurLoop->contains(cast<Instruction>(U)))
338 return false;
339
340 // Match the branch instruction for the header
341 Value *MaxLen;
342 BasicBlock *EndBB, *WhileBB;
343 if (!match(Header->getTerminator(),
345 m_Value(MaxLen)),
346 m_BasicBlock(EndBB), m_BasicBlock(WhileBB))) ||
347 !CurLoop->contains(WhileBB))
348 return false;
349
350 // WhileBB should contain the pattern of load & compare instructions. Match
351 // the pattern and find the GEP instructions used by the loads.
352 BasicBlock *FoundBB;
353 BasicBlock *TrueBB;
354 Value *LoadA, *LoadB;
355 if (!match(WhileBB->getTerminator(),
357 m_Value(LoadB)),
358 m_BasicBlock(TrueBB), m_BasicBlock(FoundBB))) ||
359 !CurLoop->contains(TrueBB))
360 return false;
361
362 Value *A, *B;
363 if (!match(LoadA, m_Load(m_Value(A))) || !match(LoadB, m_Load(m_Value(B))))
364 return false;
365
366 LoadInst *LoadAI = cast<LoadInst>(LoadA);
367 LoadInst *LoadBI = cast<LoadInst>(LoadB);
368 if (!LoadAI->isSimple() || !LoadBI->isSimple())
369 return false;
370
373
374 if (!GEPA || !GEPB)
375 return false;
376
377 Value *PtrA = GEPA->getPointerOperand();
378 Value *PtrB = GEPB->getPointerOperand();
379
380 // Check we are loading i8 values from two loop invariant pointers
381 if (!CurLoop->isLoopInvariant(PtrA) || !CurLoop->isLoopInvariant(PtrB) ||
382 !GEPA->getResultElementType()->isIntegerTy(8) ||
383 !GEPB->getResultElementType()->isIntegerTy(8) ||
384 !LoadAI->getType()->isIntegerTy(8) ||
385 !LoadBI->getType()->isIntegerTy(8) || PtrA == PtrB)
386 return false;
387
388 // Check that the index to the GEPs is the index we found earlier
389 if (GEPA->getNumIndices() > 1 || GEPB->getNumIndices() > 1)
390 return false;
391
392 Value *IdxA = GEPA->getOperand(GEPA->getNumIndices());
393 Value *IdxB = GEPB->getOperand(GEPB->getNumIndices());
394 if (IdxA != IdxB || !match(IdxA, m_ZExt(m_Specific(Index))))
395 return false;
396
397 // We only ever expect the pre-incremented index value to be used inside the
398 // loop.
399 if (!PN->hasOneUse())
400 return false;
401
402 // Ensure that when the Found and End blocks are identical the PHIs have the
403 // supported format. We don't currently allow cases like this:
404 // while.cond:
405 // ...
406 // br i1 %cmp.not, label %while.end, label %while.body
407 //
408 // while.body:
409 // ...
410 // br i1 %cmp.not2, label %while.cond, label %while.end
411 //
412 // while.end:
413 // %final_ptr = phi ptr [ %c, %while.body ], [ %d, %while.cond ]
414 //
415 // Where the incoming values for %final_ptr are unique and from each of the
416 // loop blocks, but not actually defined in the loop. This requires extra
417 // work setting up the byte.compare block, i.e. by introducing a select to
418 // choose the correct value.
419 // TODO: We could add support for this in future.
420 if (FoundBB == EndBB) {
421 for (PHINode &EndPN : EndBB->phis()) {
422 Value *WhileCondVal = EndPN.getIncomingValueForBlock(Header);
423 Value *WhileBodyVal = EndPN.getIncomingValueForBlock(WhileBB);
424
425 // The value of the index when leaving the while.cond block is always the
426 // same as the end value (MaxLen) so we permit either. The value when
427 // leaving the while.body block should only be the index. Otherwise for
428 // any other values we only allow ones that are same for both blocks.
429 if (WhileCondVal != WhileBodyVal &&
430 ((WhileCondVal != Index && WhileCondVal != MaxLen) ||
431 (WhileBodyVal != Index)))
432 return false;
433 }
434 }
435
436 LLVM_DEBUG(dbgs() << "FOUND IDIOM IN LOOP: \n"
437 << *(EndBB->getParent()) << "\n\n");
438
439 // The index is incremented before the GEP/Load pair so we need to
440 // add 1 to the start value.
441 transformByteCompare(GEPA, GEPB, PN, MaxLen, Index, StartIdx, /*IncIdx=*/true,
442 FoundBB, EndBB);
443 return true;
444}
445
446Value *LoopIdiomVectorize::createMaskedFindMismatch(
447 IRBuilder<> &Builder, DomTreeUpdater &DTU, GetElementPtrInst *GEPA,
448 GetElementPtrInst *GEPB, Value *ExtStart, Value *ExtEnd) {
449 Type *I64Type = Builder.getInt64Ty();
450 Type *ResType = Builder.getInt32Ty();
451 Type *LoadType = Builder.getInt8Ty();
452 Value *PtrA = GEPA->getPointerOperand();
453 Value *PtrB = GEPB->getPointerOperand();
454
455 ScalableVectorType *PredVTy =
456 ScalableVectorType::get(Builder.getInt1Ty(), ByteCompareVF);
457
458 Value *InitialPred = Builder.CreateIntrinsic(
459 Intrinsic::get_active_lane_mask, {PredVTy, I64Type}, {ExtStart, ExtEnd});
460
461 Value *VecLen = Builder.CreateVScale(I64Type);
462 VecLen =
463 Builder.CreateMul(VecLen, ConstantInt::get(I64Type, ByteCompareVF), "",
464 /*HasNUW=*/true, /*HasNSW=*/true);
465
466 Value *PFalse = Builder.CreateVectorSplat(PredVTy->getElementCount(),
467 Builder.getInt1(false));
468
469 Builder.CreateBr(VectorLoopStartBlock);
470
471 DTU.applyUpdates({{DominatorTree::Insert, VectorLoopPreheaderBlock,
472 VectorLoopStartBlock}});
473
474 // Set up the first vector loop block by creating the PHIs, doing the vector
475 // loads and comparing the vectors.
476 Builder.SetInsertPoint(VectorLoopStartBlock);
477 PHINode *LoopPred = Builder.CreatePHI(PredVTy, 2, "mismatch_vec_loop_pred");
478 LoopPred->addIncoming(InitialPred, VectorLoopPreheaderBlock);
479 PHINode *VectorIndexPhi = Builder.CreatePHI(I64Type, 2, "mismatch_vec_index");
480 VectorIndexPhi->addIncoming(ExtStart, VectorLoopPreheaderBlock);
481 Type *VectorLoadType =
482 ScalableVectorType::get(Builder.getInt8Ty(), ByteCompareVF);
483 Value *Passthru = ConstantInt::getNullValue(VectorLoadType);
484
485 Value *VectorLhsGep =
486 Builder.CreateGEP(LoadType, PtrA, VectorIndexPhi, "", GEPA->isInBounds());
487 Value *VectorLhsLoad = Builder.CreateMaskedLoad(VectorLoadType, VectorLhsGep,
488 Align(1), LoopPred, Passthru);
489
490 Value *VectorRhsGep =
491 Builder.CreateGEP(LoadType, PtrB, VectorIndexPhi, "", GEPB->isInBounds());
492 Value *VectorRhsLoad = Builder.CreateMaskedLoad(VectorLoadType, VectorRhsGep,
493 Align(1), LoopPred, Passthru);
494
495 Value *VectorMatchCmp = Builder.CreateICmpNE(VectorLhsLoad, VectorRhsLoad);
496 VectorMatchCmp = Builder.CreateSelect(LoopPred, VectorMatchCmp, PFalse);
497 Value *VectorMatchHasActiveLanes = Builder.CreateOrReduce(VectorMatchCmp);
498 Builder.CreateCondBr(VectorMatchHasActiveLanes, VectorLoopMismatchBlock,
499 VectorLoopIncBlock);
500
501 DTU.applyUpdates(
502 {{DominatorTree::Insert, VectorLoopStartBlock, VectorLoopMismatchBlock},
503 {DominatorTree::Insert, VectorLoopStartBlock, VectorLoopIncBlock}});
504
505 // Increment the index counter and calculate the predicate for the next
506 // iteration of the loop. We branch back to the start of the loop if there
507 // is at least one active lane.
508 Builder.SetInsertPoint(VectorLoopIncBlock);
509 Value *NewVectorIndexPhi =
510 Builder.CreateAdd(VectorIndexPhi, VecLen, "",
511 /*HasNUW=*/true, /*HasNSW=*/true);
512 VectorIndexPhi->addIncoming(NewVectorIndexPhi, VectorLoopIncBlock);
513 Value *NewPred =
514 Builder.CreateIntrinsic(Intrinsic::get_active_lane_mask,
515 {PredVTy, I64Type}, {NewVectorIndexPhi, ExtEnd});
516 LoopPred->addIncoming(NewPred, VectorLoopIncBlock);
517
518 Value *PredHasActiveLanes =
519 Builder.CreateExtractElement(NewPred, uint64_t(0));
520 Builder.CreateCondBr(PredHasActiveLanes, VectorLoopStartBlock, EndBlock);
521
522 DTU.applyUpdates(
523 {{DominatorTree::Insert, VectorLoopIncBlock, VectorLoopStartBlock},
524 {DominatorTree::Insert, VectorLoopIncBlock, EndBlock}});
525
526 // If we found a mismatch then we need to calculate which lane in the vector
527 // had a mismatch and add that on to the current loop index.
528 Builder.SetInsertPoint(VectorLoopMismatchBlock);
529 PHINode *FoundPred = Builder.CreatePHI(PredVTy, 1, "mismatch_vec_found_pred");
530 FoundPred->addIncoming(VectorMatchCmp, VectorLoopStartBlock);
531 PHINode *LastLoopPred =
532 Builder.CreatePHI(PredVTy, 1, "mismatch_vec_last_loop_pred");
533 LastLoopPred->addIncoming(LoopPred, VectorLoopStartBlock);
534 PHINode *VectorFoundIndex =
535 Builder.CreatePHI(I64Type, 1, "mismatch_vec_found_index");
536 VectorFoundIndex->addIncoming(VectorIndexPhi, VectorLoopStartBlock);
537
538 Value *PredMatchCmp = Builder.CreateAnd(LastLoopPred, FoundPred);
539 Value *Ctz = Builder.CreateCountTrailingZeroElems(ResType, PredMatchCmp);
540 Ctz = Builder.CreateZExt(Ctz, I64Type);
541 Value *VectorLoopRes64 = Builder.CreateAdd(VectorFoundIndex, Ctz, "",
542 /*HasNUW=*/true, /*HasNSW=*/true);
543 return Builder.CreateTrunc(VectorLoopRes64, ResType);
544}
545
546Value *LoopIdiomVectorize::createPredicatedFindMismatch(
547 IRBuilder<> &Builder, DomTreeUpdater &DTU, GetElementPtrInst *GEPA,
548 GetElementPtrInst *GEPB, Value *ExtStart, Value *ExtEnd) {
549 Type *I64Type = Builder.getInt64Ty();
550 Type *I32Type = Builder.getInt32Ty();
551 Type *ResType = I32Type;
552 Type *LoadType = Builder.getInt8Ty();
553 Value *PtrA = GEPA->getPointerOperand();
554 Value *PtrB = GEPB->getPointerOperand();
555
556 auto *JumpToVectorLoop = UncondBrInst::Create(VectorLoopStartBlock);
557 Builder.Insert(JumpToVectorLoop);
558
559 DTU.applyUpdates({{DominatorTree::Insert, VectorLoopPreheaderBlock,
560 VectorLoopStartBlock}});
561
562 // Set up the first Vector loop block by creating the PHIs, doing the vector
563 // loads and comparing the vectors.
564 Builder.SetInsertPoint(VectorLoopStartBlock);
565 auto *VectorIndexPhi = Builder.CreatePHI(I64Type, 2, "mismatch_vector_index");
566 VectorIndexPhi->addIncoming(ExtStart, VectorLoopPreheaderBlock);
567
568 // Calculate AVL by subtracting the vector loop index from the trip count
569 Value *AVL = Builder.CreateSub(ExtEnd, VectorIndexPhi, "avl", /*HasNUW=*/true,
570 /*HasNSW=*/true);
571
572 auto *VectorLoadType = ScalableVectorType::get(LoadType, ByteCompareVF);
573 auto *VF = ConstantInt::get(I32Type, ByteCompareVF);
574
575 Value *VL = Builder.CreateIntrinsic(Intrinsic::experimental_get_vector_length,
576 {I64Type}, {AVL, VF, Builder.getTrue()});
577 Value *GepOffset = VectorIndexPhi;
578
579 Value *VectorLhsGep =
580 Builder.CreateGEP(LoadType, PtrA, GepOffset, "", GEPA->isInBounds());
581 VectorType *TrueMaskTy =
582 VectorType::get(Builder.getInt1Ty(), VectorLoadType->getElementCount());
583 Value *AllTrueMask = Constant::getAllOnesValue(TrueMaskTy);
584 Value *VectorLhsLoad = Builder.CreateIntrinsic(
585 Intrinsic::vp_load, {VectorLoadType, VectorLhsGep->getType()},
586 {VectorLhsGep, AllTrueMask, VL}, nullptr, "lhs.load");
587
588 Value *VectorRhsGep =
589 Builder.CreateGEP(LoadType, PtrB, GepOffset, "", GEPB->isInBounds());
590 Value *VectorRhsLoad = Builder.CreateIntrinsic(
591 Intrinsic::vp_load, {VectorLoadType, VectorLhsGep->getType()},
592 {VectorRhsGep, AllTrueMask, VL}, nullptr, "rhs.load");
593
594 Value *VectorMatchCmp =
595 Builder.CreateICmpNE(VectorLhsLoad, VectorRhsLoad, "mismatch.cmp");
596 Value *CTZ = Builder.CreateIntrinsic(
597 Intrinsic::vp_cttz_elts, {ResType, VectorMatchCmp->getType()},
598 {VectorMatchCmp, /*ZeroIsPoison=*/Builder.getInt1(false), AllTrueMask,
599 VL});
600 Value *MismatchFound = Builder.CreateICmpNE(CTZ, VL);
601 auto *VectorEarlyExit = CondBrInst::Create(
602 MismatchFound, VectorLoopMismatchBlock, VectorLoopIncBlock);
603 Builder.Insert(VectorEarlyExit);
604
605 DTU.applyUpdates(
606 {{DominatorTree::Insert, VectorLoopStartBlock, VectorLoopMismatchBlock},
607 {DominatorTree::Insert, VectorLoopStartBlock, VectorLoopIncBlock}});
608
609 // Increment the index counter and calculate the predicate for the next
610 // iteration of the loop. We branch back to the start of the loop if there
611 // is at least one active lane.
612 Builder.SetInsertPoint(VectorLoopIncBlock);
613 Value *VL64 = Builder.CreateZExt(VL, I64Type);
614 Value *NewVectorIndexPhi =
615 Builder.CreateAdd(VectorIndexPhi, VL64, "",
616 /*HasNUW=*/true, /*HasNSW=*/true);
617 VectorIndexPhi->addIncoming(NewVectorIndexPhi, VectorLoopIncBlock);
618 Value *ExitCond = Builder.CreateICmpNE(NewVectorIndexPhi, ExtEnd);
619 auto *VectorLoopBranchBack =
620 CondBrInst::Create(ExitCond, VectorLoopStartBlock, EndBlock);
621 Builder.Insert(VectorLoopBranchBack);
622
623 DTU.applyUpdates(
624 {{DominatorTree::Insert, VectorLoopIncBlock, VectorLoopStartBlock},
625 {DominatorTree::Insert, VectorLoopIncBlock, EndBlock}});
626
627 // If we found a mismatch then we need to calculate which lane in the vector
628 // had a mismatch and add that on to the current loop index.
629 Builder.SetInsertPoint(VectorLoopMismatchBlock);
630
631 // Add LCSSA phis for CTZ and VectorIndexPhi.
632 auto *CTZLCSSAPhi = Builder.CreatePHI(CTZ->getType(), 1, "ctz");
633 CTZLCSSAPhi->addIncoming(CTZ, VectorLoopStartBlock);
634 auto *VectorIndexLCSSAPhi =
635 Builder.CreatePHI(VectorIndexPhi->getType(), 1, "mismatch_vector_index");
636 VectorIndexLCSSAPhi->addIncoming(VectorIndexPhi, VectorLoopStartBlock);
637
638 Value *CTZI64 = Builder.CreateZExt(CTZLCSSAPhi, I64Type);
639 Value *VectorLoopRes64 = Builder.CreateAdd(VectorIndexLCSSAPhi, CTZI64, "",
640 /*HasNUW=*/true, /*HasNSW=*/true);
641 return Builder.CreateTrunc(VectorLoopRes64, ResType);
642}
643
644Value *LoopIdiomVectorize::expandFindMismatch(
645 IRBuilder<> &Builder, DomTreeUpdater &DTU, GetElementPtrInst *GEPA,
646 GetElementPtrInst *GEPB, Instruction *Index, Value *Start, Value *MaxLen) {
647 Value *PtrA = GEPA->getPointerOperand();
648 Value *PtrB = GEPB->getPointerOperand();
649
650 // Get the arguments and types for the intrinsic.
651 BasicBlock *Preheader = CurLoop->getLoopPreheader();
652 Instruction *PHBranch = Preheader->getTerminator();
653 LLVMContext &Ctx = PHBranch->getContext();
654 Type *LoadType = Type::getInt8Ty(Ctx);
655 Type *ResType = Builder.getInt32Ty();
656
657 // Split block in the original loop preheader.
658 EndBlock = SplitBlock(Preheader, PHBranch, DT, LI, nullptr, "mismatch_end");
659
660 // Create the blocks that we're going to need:
661 // 1. A block for checking the zero-extended length exceeds 0
662 // 2. A block to check that the start and end addresses of a given array
663 // lie on the same page.
664 // 3. The vector loop preheader.
665 // 4. The first vector loop block.
666 // 5. The vector loop increment block.
667 // 6. A block we can jump to from the vector loop when a mismatch is found.
668 // 7. The first block of the scalar loop itself, containing PHIs , loads
669 // and cmp.
670 // 8. A scalar loop increment block to increment the PHIs and go back
671 // around the loop.
672
673 BasicBlock *MinItCheckBlock = BasicBlock::Create(
674 Ctx, "mismatch_min_it_check", EndBlock->getParent(), EndBlock);
675
676 // Update the terminator added by SplitBlock to branch to the first block
677 Preheader->getTerminator()->setSuccessor(0, MinItCheckBlock);
678
679 BasicBlock *MemCheckBlock = BasicBlock::Create(
680 Ctx, "mismatch_mem_check", EndBlock->getParent(), EndBlock);
681
682 VectorLoopPreheaderBlock = BasicBlock::Create(
683 Ctx, "mismatch_vec_loop_preheader", EndBlock->getParent(), EndBlock);
684
685 VectorLoopStartBlock = BasicBlock::Create(Ctx, "mismatch_vec_loop",
686 EndBlock->getParent(), EndBlock);
687
688 VectorLoopIncBlock = BasicBlock::Create(Ctx, "mismatch_vec_loop_inc",
689 EndBlock->getParent(), EndBlock);
690
691 VectorLoopMismatchBlock = BasicBlock::Create(Ctx, "mismatch_vec_loop_found",
692 EndBlock->getParent(), EndBlock);
693
694 BasicBlock *LoopPreHeaderBlock = BasicBlock::Create(
695 Ctx, "mismatch_loop_pre", EndBlock->getParent(), EndBlock);
696
697 BasicBlock *LoopStartBlock =
698 BasicBlock::Create(Ctx, "mismatch_loop", EndBlock->getParent(), EndBlock);
699
700 BasicBlock *LoopIncBlock = BasicBlock::Create(
701 Ctx, "mismatch_loop_inc", EndBlock->getParent(), EndBlock);
702
703 DTU.applyUpdates({{DominatorTree::Insert, Preheader, MinItCheckBlock},
704 {DominatorTree::Delete, Preheader, EndBlock}});
705
706 // Update LoopInfo with the new vector & scalar loops.
707 auto VectorLoop = LI->AllocateLoop();
708 auto ScalarLoop = LI->AllocateLoop();
709
710 if (CurLoop->getParentLoop()) {
711 CurLoop->getParentLoop()->addBasicBlockToLoop(MinItCheckBlock, *LI);
712 CurLoop->getParentLoop()->addBasicBlockToLoop(MemCheckBlock, *LI);
713 CurLoop->getParentLoop()->addBasicBlockToLoop(VectorLoopPreheaderBlock,
714 *LI);
715 CurLoop->getParentLoop()->addChildLoop(VectorLoop);
716 CurLoop->getParentLoop()->addBasicBlockToLoop(VectorLoopMismatchBlock, *LI);
717 CurLoop->getParentLoop()->addBasicBlockToLoop(LoopPreHeaderBlock, *LI);
718 CurLoop->getParentLoop()->addChildLoop(ScalarLoop);
719 } else {
720 LI->addTopLevelLoop(VectorLoop);
721 LI->addTopLevelLoop(ScalarLoop);
722 }
723
724 // Add the new basic blocks to their associated loops.
725 VectorLoop->addBasicBlockToLoop(VectorLoopStartBlock, *LI);
726 VectorLoop->addBasicBlockToLoop(VectorLoopIncBlock, *LI);
727
728 ScalarLoop->addBasicBlockToLoop(LoopStartBlock, *LI);
729 ScalarLoop->addBasicBlockToLoop(LoopIncBlock, *LI);
730
731 // Set up some types and constants that we intend to reuse.
732 Type *I64Type = Builder.getInt64Ty();
733
734 // Check the zero-extended iteration count > 0
735 Builder.SetInsertPoint(MinItCheckBlock);
736 Value *ExtStart = Builder.CreateZExt(Start, I64Type);
737 Value *ExtEnd = Builder.CreateZExt(MaxLen, I64Type);
738 // This check doesn't really cost us very much.
739
740 Value *LimitCheck = Builder.CreateICmpULE(Start, MaxLen);
741 CondBrInst *MinItCheckBr =
742 CondBrInst::Create(LimitCheck, MemCheckBlock, LoopPreHeaderBlock);
743 MinItCheckBr->setMetadata(
744 LLVMContext::MD_prof,
745 MDBuilder(MinItCheckBr->getContext()).createBranchWeights(99, 1));
746 Builder.Insert(MinItCheckBr);
747
748 DTU.applyUpdates(
749 {{DominatorTree::Insert, MinItCheckBlock, MemCheckBlock},
750 {DominatorTree::Insert, MinItCheckBlock, LoopPreHeaderBlock}});
751
752 // For each of the arrays, check the start/end addresses are on the same
753 // page.
754 Builder.SetInsertPoint(MemCheckBlock);
755
756 // The early exit in the original loop means that when performing vector
757 // loads we are potentially reading ahead of the early exit. So we could
758 // fault if crossing a page boundary. Therefore, we create runtime memory
759 // checks based on the minimum page size as follows:
760 // 1. Calculate the addresses of the first memory accesses in the loop,
761 // i.e. LhsStart and RhsStart.
762 // 2. Get the last accessed addresses in the loop, i.e. LhsEnd and RhsEnd.
763 // 3. Determine which pages correspond to all the memory accesses, i.e
764 // LhsStartPage, LhsEndPage, RhsStartPage, RhsEndPage.
765 // 4. If LhsStartPage == LhsEndPage and RhsStartPage == RhsEndPage, then
766 // we know we won't cross any page boundaries in the loop so we can
767 // enter the vector loop! Otherwise we fall back on the scalar loop.
768 Value *LhsStartGEP = Builder.CreateGEP(LoadType, PtrA, ExtStart);
769 Value *RhsStartGEP = Builder.CreateGEP(LoadType, PtrB, ExtStart);
770 Value *RhsStart = Builder.CreatePtrToInt(RhsStartGEP, I64Type);
771 Value *LhsStart = Builder.CreatePtrToInt(LhsStartGEP, I64Type);
772 Value *LhsEndGEP = Builder.CreateGEP(LoadType, PtrA, ExtEnd);
773 Value *RhsEndGEP = Builder.CreateGEP(LoadType, PtrB, ExtEnd);
774 Value *LhsEnd = Builder.CreatePtrToInt(LhsEndGEP, I64Type);
775 Value *RhsEnd = Builder.CreatePtrToInt(RhsEndGEP, I64Type);
776
777 const uint64_t MinPageSize = TTI->getMinPageSize().value();
778 const uint64_t AddrShiftAmt = llvm::Log2_64(MinPageSize);
779 Value *LhsStartPage = Builder.CreateLShr(LhsStart, AddrShiftAmt);
780 Value *LhsEndPage = Builder.CreateLShr(LhsEnd, AddrShiftAmt);
781 Value *RhsStartPage = Builder.CreateLShr(RhsStart, AddrShiftAmt);
782 Value *RhsEndPage = Builder.CreateLShr(RhsEnd, AddrShiftAmt);
783 Value *LhsPageCmp = Builder.CreateICmpNE(LhsStartPage, LhsEndPage);
784 Value *RhsPageCmp = Builder.CreateICmpNE(RhsStartPage, RhsEndPage);
785
786 Value *CombinedPageCmp = Builder.CreateOr(LhsPageCmp, RhsPageCmp);
787 CondBrInst *CombinedPageCmpCmpBr = CondBrInst::Create(
788 CombinedPageCmp, LoopPreHeaderBlock, VectorLoopPreheaderBlock);
789 CombinedPageCmpCmpBr->setMetadata(
790 LLVMContext::MD_prof, MDBuilder(CombinedPageCmpCmpBr->getContext())
791 .createBranchWeights(10, 90));
792 Builder.Insert(CombinedPageCmpCmpBr);
793
794 DTU.applyUpdates(
795 {{DominatorTree::Insert, MemCheckBlock, LoopPreHeaderBlock},
796 {DominatorTree::Insert, MemCheckBlock, VectorLoopPreheaderBlock}});
797
798 // Set up the vector loop preheader, i.e. calculate initial loop predicate,
799 // zero-extend MaxLen to 64-bits, determine the number of vector elements
800 // processed in each iteration, etc.
801 Builder.SetInsertPoint(VectorLoopPreheaderBlock);
802
803 // At this point we know two things must be true:
804 // 1. Start <= End
805 // 2. ExtMaxLen <= MinPageSize due to the page checks.
806 // Therefore, we know that we can use a 64-bit induction variable that
807 // starts from 0 -> ExtMaxLen and it will not overflow.
808 Value *VectorLoopRes = nullptr;
809 switch (VectorizeStyle) {
811 VectorLoopRes =
812 createMaskedFindMismatch(Builder, DTU, GEPA, GEPB, ExtStart, ExtEnd);
813 break;
815 VectorLoopRes = createPredicatedFindMismatch(Builder, DTU, GEPA, GEPB,
816 ExtStart, ExtEnd);
817 break;
818 }
819
820 Builder.CreateBr(EndBlock);
821
822 DTU.applyUpdates(
823 {{DominatorTree::Insert, VectorLoopMismatchBlock, EndBlock}});
824
825 // Generate code for scalar loop.
826 Builder.SetInsertPoint(LoopPreHeaderBlock);
827 Builder.CreateBr(LoopStartBlock);
828
829 DTU.applyUpdates(
830 {{DominatorTree::Insert, LoopPreHeaderBlock, LoopStartBlock}});
831
832 Builder.SetInsertPoint(LoopStartBlock);
833 PHINode *IndexPhi = Builder.CreatePHI(ResType, 2, "mismatch_index");
834 IndexPhi->addIncoming(Start, LoopPreHeaderBlock);
835
836 // Otherwise compare the values
837 // Load bytes from each array and compare them.
838 Value *GepOffset = Builder.CreateZExt(IndexPhi, I64Type);
839
840 Value *LhsGep =
841 Builder.CreateGEP(LoadType, PtrA, GepOffset, "", GEPA->isInBounds());
842 Value *LhsLoad = Builder.CreateLoad(LoadType, LhsGep);
843
844 Value *RhsGep =
845 Builder.CreateGEP(LoadType, PtrB, GepOffset, "", GEPB->isInBounds());
846 Value *RhsLoad = Builder.CreateLoad(LoadType, RhsGep);
847
848 Value *MatchCmp = Builder.CreateICmpEQ(LhsLoad, RhsLoad);
849 // If we have a mismatch then exit the loop ...
850 Builder.CreateCondBr(MatchCmp, LoopIncBlock, EndBlock);
851
852 DTU.applyUpdates({{DominatorTree::Insert, LoopStartBlock, LoopIncBlock},
853 {DominatorTree::Insert, LoopStartBlock, EndBlock}});
854
855 // Have we reached the maximum permitted length for the loop?
856 Builder.SetInsertPoint(LoopIncBlock);
857 Value *PhiInc = Builder.CreateAdd(IndexPhi, ConstantInt::get(ResType, 1), "",
858 /*HasNUW=*/Index->hasNoUnsignedWrap(),
859 /*HasNSW=*/Index->hasNoSignedWrap());
860 IndexPhi->addIncoming(PhiInc, LoopIncBlock);
861 Value *IVCmp = Builder.CreateICmpEQ(PhiInc, MaxLen);
862 Builder.CreateCondBr(IVCmp, EndBlock, LoopStartBlock);
863
864 DTU.applyUpdates({{DominatorTree::Insert, LoopIncBlock, EndBlock},
865 {DominatorTree::Insert, LoopIncBlock, LoopStartBlock}});
866
867 // In the end block we need to insert a PHI node to deal with three cases:
868 // 1. We didn't find a mismatch in the scalar loop, so we return MaxLen.
869 // 2. We exitted the scalar loop early due to a mismatch and need to return
870 // the index that we found.
871 // 3. We didn't find a mismatch in the vector loop, so we return MaxLen.
872 // 4. We exitted the vector loop early due to a mismatch and need to return
873 // the index that we found.
874 Builder.SetInsertPoint(EndBlock->getFirstInsertionPt());
875 PHINode *ResPhi = Builder.CreatePHI(ResType, 4, "mismatch_result");
876 ResPhi->addIncoming(MaxLen, LoopIncBlock);
877 ResPhi->addIncoming(IndexPhi, LoopStartBlock);
878 ResPhi->addIncoming(MaxLen, VectorLoopIncBlock);
879 ResPhi->addIncoming(VectorLoopRes, VectorLoopMismatchBlock);
880
881 Value *FinalRes = Builder.CreateTrunc(ResPhi, ResType);
882
883 if (Opts.loop_idiom_vectorize_verify) {
884 ScalarLoop->verifyLoop();
885 VectorLoop->verifyLoop();
886 if (!VectorLoop->isRecursivelyLCSSAForm(*DT, *LI))
887 report_fatal_error("Loops must remain in LCSSA form!");
888 if (!ScalarLoop->isRecursivelyLCSSAForm(*DT, *LI))
889 report_fatal_error("Loops must remain in LCSSA form!");
890 }
891
892 return FinalRes;
893}
894
895void LoopIdiomVectorize::transformByteCompare(GetElementPtrInst *GEPA,
896 GetElementPtrInst *GEPB,
897 PHINode *IndPhi, Value *MaxLen,
898 Instruction *Index, Value *Start,
899 bool IncIdx, BasicBlock *FoundBB,
900 BasicBlock *EndBB) {
901
902 // Insert the byte compare code at the end of the preheader block
903 BasicBlock *Preheader = CurLoop->getLoopPreheader();
904 BasicBlock *Header = CurLoop->getHeader();
905 UncondBrInst *PHBranch = cast<UncondBrInst>(Preheader->getTerminator());
906 IRBuilder<> Builder(PHBranch);
907 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
908 Builder.SetCurrentDebugLocation(PHBranch->getDebugLoc());
909
910 // Increment the pointer if this was done before the loads in the loop.
911 if (IncIdx)
912 Start = Builder.CreateAdd(Start, ConstantInt::get(Start->getType(), 1));
913
914 Value *ByteCmpRes =
915 expandFindMismatch(Builder, DTU, GEPA, GEPB, Index, Start, MaxLen);
916
917 // Replaces uses of index & induction Phi with intrinsic (we already
918 // checked that the the first instruction of Header is the Phi above).
919 assert(IndPhi->hasOneUse() && "Index phi node has more than one use!");
920 Index->replaceAllUsesWith(ByteCmpRes);
921
922 // If no mismatch was found, we can jump to the end block. Create a
923 // new basic block for the compare instruction.
924 auto *CmpBB = BasicBlock::Create(Preheader->getContext(), "byte.compare",
925 Preheader->getParent());
926 CmpBB->moveBefore(EndBB);
927
928 // Replace the branch in the preheader with an always-true conditional branch.
929 // This ensures there is still a reference to the original loop.
930 Builder.CreateCondBr(Builder.getTrue(), CmpBB, Header);
931 PHBranch->eraseFromParent();
932
933 BasicBlock *MismatchEnd = cast<Instruction>(ByteCmpRes)->getParent();
934 DTU.applyUpdates({{DominatorTree::Insert, MismatchEnd, CmpBB}});
935
936 // Create the branch to either the end or found block depending on the value
937 // returned by the intrinsic.
938 Builder.SetInsertPoint(CmpBB);
939 if (FoundBB != EndBB) {
940 Value *FoundCmp = Builder.CreateICmpEQ(ByteCmpRes, MaxLen);
941 Builder.CreateCondBr(FoundCmp, EndBB, FoundBB);
942 DTU.applyUpdates({{DominatorTree::Insert, CmpBB, FoundBB},
943 {DominatorTree::Insert, CmpBB, EndBB}});
944
945 } else {
946 Builder.CreateBr(FoundBB);
947 DTU.applyUpdates({{DominatorTree::Insert, CmpBB, FoundBB}});
948 }
949
950 // Ensure all Phis in the successors of CmpBB have an incoming value from it.
951 fixSuccessorPhis(CurLoop, ByteCmpRes, ByteCmpRes, EndBB, CmpBB);
952 if (EndBB != FoundBB)
953 fixSuccessorPhis(CurLoop, ByteCmpRes, ByteCmpRes, FoundBB, CmpBB);
954
955 // The new CmpBB block isn't part of the loop, but will need to be added to
956 // the outer loop if there is one.
957 if (!CurLoop->isOutermost())
958 CurLoop->getParentLoop()->addBasicBlockToLoop(CmpBB, *LI);
959
960 if (Opts.loop_idiom_vectorize_verify && CurLoop->getParentLoop()) {
961 CurLoop->getParentLoop()->verifyLoop();
962 if (!CurLoop->getParentLoop()->isRecursivelyLCSSAForm(*DT, *LI))
963 report_fatal_error("Loops must remain in LCSSA form!");
964 }
965}
966
967bool LoopIdiomVectorize::recognizeFindFirstByte() {
968 // Currently the transformation only works on scalable vector types, although
969 // there is no fundamental reason why it cannot be made to work for fixed
970 // vectors. We also need to know the target's minimum page size in order to
971 // generate runtime memory checks to ensure the vector version won't fault.
972 if (!TTI->supportsScalableVectors() || !TTI->getMinPageSize().has_value() ||
973 Opts.disable_loop_idiom_vectorize_find_first_byte)
974 return false;
975
976 // We exclude loops with trip counts > minimum page size via runtime checks,
977 // so make sure that the minimum page size is something sensible such that
978 // induction variables cannot overflow.
979 if (uint64_t(*TTI->getMinPageSize()) >
980 (std::numeric_limits<uint64_t>::max() / 2))
981 return false;
982
983 // Define some constants we need throughout.
984 BasicBlock *Header = CurLoop->getHeader();
985 LLVMContext &Ctx = Header->getContext();
986
987 // We are expecting the four blocks defined below: Header, MatchBB, InnerBB,
988 // and OuterBB. For now, we will bail our for almost anything else. The Four
989 // blocks contain one nested loop.
990 if (CurLoop->getNumBackEdges() != 1 || CurLoop->getNumBlocks() != 4 ||
991 CurLoop->getSubLoops().size() != 1)
992 return false;
993
994 auto *InnerLoop = CurLoop->getSubLoops().front();
995 Function &F = *InnerLoop->getHeader()->getParent();
996
997 // Bail if vectorization is disabled on inner loop.
998 LoopVectorizeHints Hints(Opts, InnerLoop, /*InterleaveOnlyWhenForced=*/true,
999 ORE);
1000 if (!Hints.allowVectorization(&F, InnerLoop,
1001 /*VectorizeOnlyWhenForced=*/false)) {
1002 LLVM_DEBUG(dbgs() << DEBUG_TYPE << " is disabled on inner loop "
1003 << InnerLoop->getName()
1004 << " due to vectorization hints\n");
1005 return false;
1006 }
1007
1008 PHINode *IndPhi = dyn_cast<PHINode>(&Header->front());
1009 if (!IndPhi || IndPhi->getNumIncomingValues() != 2)
1010 return false;
1011
1012 // Check instruction counts.
1013 auto LoopBlocks = CurLoop->getBlocks();
1014 if (LoopBlocks[0]->size() > 3 || LoopBlocks[1]->size() > 4 ||
1015 LoopBlocks[2]->size() > 3 || LoopBlocks[3]->size() > 3)
1016 return false;
1017
1018 // Check that no instruction other than IndPhi has outside uses.
1019 for (BasicBlock *BB : LoopBlocks)
1020 for (Instruction &I : *BB)
1021 if (&I != IndPhi)
1022 for (User *U : I.users())
1023 if (!CurLoop->contains(cast<Instruction>(U)))
1024 return false;
1025
1026 // Match the branch instruction in the header. We are expecting an
1027 // unconditional branch to the inner loop.
1028 //
1029 // Header:
1030 // %14 = phi ptr [ %24, %OuterBB ], [ %3, %Header.preheader ]
1031 // %15 = load i8, ptr %14, align 1
1032 // br label %MatchBB
1033 BasicBlock *MatchBB;
1034 if (!match(Header->getTerminator(), m_UnconditionalBr(MatchBB)) ||
1035 !InnerLoop->contains(MatchBB))
1036 return false;
1037
1038 // MatchBB should be the entrypoint into the inner loop containing the
1039 // comparison between a search element and a needle.
1040 //
1041 // MatchBB:
1042 // %20 = phi ptr [ %7, %Header ], [ %17, %InnerBB ]
1043 // %21 = load i8, ptr %20, align 1
1044 // %22 = icmp eq i8 %15, %21
1045 // br i1 %22, label %ExitSucc, label %InnerBB
1046 BasicBlock *ExitSucc, *InnerBB;
1047 Value *LoadSearch, *LoadNeedle;
1048 CmpPredicate MatchPred;
1049 if (!match(MatchBB->getTerminator(),
1050 m_Br(m_ICmp(MatchPred, m_Value(LoadSearch), m_Value(LoadNeedle)),
1051 m_BasicBlock(ExitSucc), m_BasicBlock(InnerBB))) ||
1052 MatchPred != ICmpInst::ICMP_EQ || !InnerLoop->contains(InnerBB))
1053 return false;
1054
1055 // We expect outside uses of `IndPhi' in ExitSucc (and only there).
1056 for (User *U : IndPhi->users())
1057 if (!CurLoop->contains(cast<Instruction>(U))) {
1058 auto *PN = dyn_cast<PHINode>(U);
1059 if (!PN || PN->getParent() != ExitSucc)
1060 return false;
1061 }
1062
1063 // Match the loads and check they are simple. The loads come from two PHIs,
1064 // each with two incoming values.
1065 PHINode *PSearch, *PNeedle;
1066 if (!match(LoadSearch, m_Load(m_Phi(PSearch))) ||
1067 !match(LoadNeedle, m_Load(m_Phi(PNeedle))) ||
1068 !cast<LoadInst>(LoadSearch)->isSimple() ||
1069 !cast<LoadInst>(LoadNeedle)->isSimple())
1070 return false;
1071
1072 // Check we are loading valid characters.
1073 Type *CharTy = LoadSearch->getType();
1074 if (!CharTy->isIntegerTy() || LoadNeedle->getType() != CharTy)
1075 return false;
1076
1077 // Pick the vectorisation factor based on CharTy, work out the cost of the
1078 // match intrinsic and decide if we should use it.
1079 // Note: For the time being we assume 128-bit vectors.
1080 unsigned VF = 128 / CharTy->getIntegerBitWidth();
1082 ScalableVectorType::get(CharTy, VF), FixedVectorType::get(CharTy, VF),
1084 IntrinsicCostAttributes Attrs(Intrinsic::experimental_vector_match, Args[2],
1085 Args);
1086 if (TTI->getIntrinsicInstrCost(Attrs, TTI::TCK_SizeAndLatency) > 4)
1087 return false;
1088
1089 if (PSearch->getNumIncomingValues() != 2 ||
1090 PNeedle->getNumIncomingValues() != 2)
1091 return false;
1092
1093 // One PHI comes from the outer loop (PSearch), the other one from the inner
1094 // loop (PNeedle). PSearch effectively corresponds to IndPhi.
1095 if (InnerLoop->contains(PSearch))
1096 std::swap(PSearch, PNeedle);
1097 if (PSearch != &Header->front() || PNeedle != &MatchBB->front())
1098 return false;
1099
1100 // The incoming values of both PHI nodes should be a gep of 1.
1101 Value *SearchStart = PSearch->getIncomingValue(0);
1102 Value *SearchIndex = PSearch->getIncomingValue(1);
1103 if (CurLoop->contains(PSearch->getIncomingBlock(0)))
1104 std::swap(SearchStart, SearchIndex);
1105
1106 Value *NeedleStart = PNeedle->getIncomingValue(0);
1107 Value *NeedleIndex = PNeedle->getIncomingValue(1);
1108 if (InnerLoop->contains(PNeedle->getIncomingBlock(0)))
1109 std::swap(NeedleStart, NeedleIndex);
1110
1111 // Match the GEPs.
1112 if (!match(SearchIndex, m_GEP(m_Specific(PSearch), m_One())) ||
1113 !match(NeedleIndex, m_GEP(m_Specific(PNeedle), m_One())))
1114 return false;
1115
1116 // Check the GEPs result type matches `CharTy'.
1117 GetElementPtrInst *GEPSearch = cast<GetElementPtrInst>(SearchIndex);
1118 GetElementPtrInst *GEPNeedle = cast<GetElementPtrInst>(NeedleIndex);
1119 if (GEPSearch->getResultElementType() != CharTy ||
1120 GEPNeedle->getResultElementType() != CharTy)
1121 return false;
1122
1123 // InnerBB should increment the address of the needle pointer.
1124 //
1125 // InnerBB:
1126 // %17 = getelementptr inbounds i8, ptr %20, i64 1
1127 // %18 = icmp eq ptr %17, %10
1128 // br i1 %18, label %OuterBB, label %MatchBB
1129 BasicBlock *OuterBB;
1130 Value *NeedleEnd;
1131 if (!match(InnerBB->getTerminator(),
1133 m_Value(NeedleEnd)),
1134 m_BasicBlock(OuterBB), m_Specific(MatchBB))) ||
1135 !CurLoop->contains(OuterBB))
1136 return false;
1137
1138 // OuterBB should increment the address of the search element pointer.
1139 //
1140 // OuterBB:
1141 // %24 = getelementptr inbounds i8, ptr %14, i64 1
1142 // %25 = icmp eq ptr %24, %6
1143 // br i1 %25, label %ExitFail, label %Header
1144 BasicBlock *ExitFail;
1145 Value *SearchEnd;
1146 if (!match(OuterBB->getTerminator(),
1148 m_Value(SearchEnd)),
1149 m_BasicBlock(ExitFail), m_Specific(Header))))
1150 return false;
1151
1152 if (!CurLoop->isLoopInvariant(SearchStart) ||
1153 !CurLoop->isLoopInvariant(SearchEnd) ||
1154 !CurLoop->isLoopInvariant(NeedleStart) ||
1155 !CurLoop->isLoopInvariant(NeedleEnd))
1156 return false;
1157
1158 LLVM_DEBUG(dbgs() << "Found idiom in loop: \n" << *CurLoop << "\n\n");
1159
1160 transformFindFirstByte(IndPhi, VF, CharTy, ExitSucc, ExitFail, SearchStart,
1161 SearchEnd, NeedleStart, NeedleEnd);
1162 return true;
1163}
1164
1165Value *LoopIdiomVectorize::expandFindFirstByte(
1166 IRBuilder<> &Builder, DomTreeUpdater &DTU, unsigned VF, Type *CharTy,
1167 Value *IndPhi, BasicBlock *ExitSucc, BasicBlock *ExitFail,
1168 Value *SearchStart, Value *SearchEnd, Value *NeedleStart,
1169 Value *NeedleEnd) {
1170 // Set up some types and constants that we intend to reuse.
1171 auto *I64Ty = Builder.getInt64Ty();
1172 auto *PredVTy = ScalableVectorType::get(Builder.getInt1Ty(), VF);
1173 auto *CharVTy = ScalableVectorType::get(CharTy, VF);
1174 auto *ConstVF = ConstantInt::get(I64Ty, VF);
1175
1176 // Other common arguments.
1177 BasicBlock *Preheader = CurLoop->getLoopPreheader();
1178 LLVMContext &Ctx = Preheader->getContext();
1179 Value *Passthru = ConstantInt::getNullValue(CharVTy);
1180
1181 // Split block in the original loop preheader.
1182 // SPH is the new preheader to the old scalar loop.
1183 BasicBlock *SPH = SplitBlock(Preheader, Preheader->getTerminator(), DT, LI,
1184 nullptr, "scalar_preheader");
1185
1186 // Create the blocks that we're going to use.
1187 //
1188 // We will have the following loops:
1189 // (O) Outer loop where we iterate over the elements of the search array.
1190 // (I) Inner loop where we iterate over the elements of the needle array.
1191 //
1192 // Overall, the blocks do the following:
1193 // (0) Check if the arrays can't cross page boundaries. If so go to (1),
1194 // otherwise fall back to the original scalar loop.
1195 // (1) Load the search array. Go to (2).
1196 // (2) (a) Load the needle array.
1197 // (b) Splat the first element to the inactive lanes.
1198 // (c) Accumulate any matches found. If we haven't reached the end of the
1199 // needle array loop back to (2), otherwise go to (3).
1200 // (3) Test if we found any match. If so go to (4), otherwise go to (5).
1201 // (4) Compute the index of the first match and exit.
1202 // (5) Check if we've reached the end of the search array. If not loop back to
1203 // (1), otherwise exit.
1204 // Blocks (0,4) are not part of any loop. Blocks (1,3,5) and (2) belong to the
1205 // outer and inner loops, respectively.
1206 BasicBlock *BB0 = BasicBlock::Create(Ctx, "mem_check", SPH->getParent(), SPH);
1207 BasicBlock *BB1 =
1208 BasicBlock::Create(Ctx, "find_first_vec_header", SPH->getParent(), SPH);
1209 BasicBlock *BB2 =
1210 BasicBlock::Create(Ctx, "needle_check_vec", SPH->getParent(), SPH);
1211 BasicBlock *BB3 =
1212 BasicBlock::Create(Ctx, "match_check_vec", SPH->getParent(), SPH);
1213 BasicBlock *BB4 =
1214 BasicBlock::Create(Ctx, "calculate_match", SPH->getParent(), SPH);
1215 BasicBlock *BB5 =
1216 BasicBlock::Create(Ctx, "search_check_vec", SPH->getParent(), SPH);
1217
1218 // Update LoopInfo with the new loops.
1219 auto OuterLoop = LI->AllocateLoop();
1220 auto InnerLoop = LI->AllocateLoop();
1221
1222 if (auto ParentLoop = CurLoop->getParentLoop()) {
1223 ParentLoop->addBasicBlockToLoop(BB0, *LI);
1224 ParentLoop->addChildLoop(OuterLoop);
1225 } else {
1226 LI->addTopLevelLoop(OuterLoop);
1227 }
1228
1229 // BB4 branches only to ExitSucc, so it belongs to the innermost enclosing
1230 // loop that contains ExitSucc. That is not necessarily CurLoop's parent: a
1231 // match can exit several levels out, or out of every loop.
1232 Loop *ExitLoop = CurLoop->getParentLoop();
1233 while (ExitLoop && !ExitLoop->contains(ExitSucc))
1234 ExitLoop = ExitLoop->getParentLoop();
1235 if (ExitLoop)
1236 ExitLoop->addBasicBlockToLoop(BB4, *LI);
1237
1238 // Add the inner loop to the outer.
1239 OuterLoop->addChildLoop(InnerLoop);
1240
1241 // Add the new basic blocks to the corresponding loops.
1242 OuterLoop->addBasicBlockToLoop(BB1, *LI);
1243 OuterLoop->addBasicBlockToLoop(BB3, *LI);
1244 OuterLoop->addBasicBlockToLoop(BB5, *LI);
1245 InnerLoop->addBasicBlockToLoop(BB2, *LI);
1246
1247 // Update the terminator added by SplitBlock to branch to the first block.
1248 Preheader->getTerminator()->setSuccessor(0, BB0);
1249 DTU.applyUpdates({{DominatorTree::Delete, Preheader, SPH},
1250 {DominatorTree::Insert, Preheader, BB0}});
1251
1252 // (0) Check if we could be crossing a page boundary; if so, fallback to the
1253 // old scalar loops. Also create a predicate of VF elements to be used in the
1254 // vector loops.
1255 Builder.SetInsertPoint(BB0);
1256 Value *ISearchStart =
1257 Builder.CreatePtrToInt(SearchStart, I64Ty, "search_start_int");
1258 Value *ISearchEnd =
1259 Builder.CreatePtrToInt(SearchEnd, I64Ty, "search_end_int");
1260 Value *SearchIdxInit = Constant::getNullValue(I64Ty);
1261 Value *SearchTripCount =
1262 Builder.CreateZExt(Builder.CreatePtrDiff(CharTy, SearchEnd, SearchStart,
1263 "search_trip_count"),
1264 I64Ty);
1265 Value *INeedleStart =
1266 Builder.CreatePtrToInt(NeedleStart, I64Ty, "needle_start_int");
1267 Value *INeedleEnd =
1268 Builder.CreatePtrToInt(NeedleEnd, I64Ty, "needle_end_int");
1269 Value *NeedleIdxInit = Constant::getNullValue(I64Ty);
1270 Value *NeedleTripCount =
1271 Builder.CreateZExt(Builder.CreatePtrDiff(CharTy, NeedleEnd, NeedleStart,
1272 "needle_trip_count"),
1273 I64Ty);
1274 Value *PredVF =
1275 Builder.CreateIntrinsic(Intrinsic::get_active_lane_mask, {PredVTy, I64Ty},
1276 {ConstantInt::get(I64Ty, 0), ConstVF});
1277
1278 const uint64_t MinPageSize = TTI->getMinPageSize().value();
1279 const uint64_t AddrShiftAmt = llvm::Log2_64(MinPageSize);
1280 Value *SearchStartPage =
1281 Builder.CreateLShr(ISearchStart, AddrShiftAmt, "search_start_page");
1282 Value *SearchEndPage =
1283 Builder.CreateLShr(ISearchEnd, AddrShiftAmt, "search_end_page");
1284 Value *NeedleStartPage =
1285 Builder.CreateLShr(INeedleStart, AddrShiftAmt, "needle_start_page");
1286 Value *NeedleEndPage =
1287 Builder.CreateLShr(INeedleEnd, AddrShiftAmt, "needle_end_page");
1288 Value *SearchPageCmp =
1289 Builder.CreateICmpNE(SearchStartPage, SearchEndPage, "search_page_cmp");
1290 Value *NeedlePageCmp =
1291 Builder.CreateICmpNE(NeedleStartPage, NeedleEndPage, "needle_page_cmp");
1292
1293 Value *CombinedPageCmp =
1294 Builder.CreateOr(SearchPageCmp, NeedlePageCmp, "combined_page_cmp");
1295 CondBrInst *CombinedPageBr = Builder.CreateCondBr(CombinedPageCmp, SPH, BB1);
1296 CombinedPageBr->setMetadata(LLVMContext::MD_prof,
1297 MDBuilder(Ctx).createBranchWeights(10, 90));
1298 DTU.applyUpdates(
1299 {{DominatorTree::Insert, BB0, SPH}, {DominatorTree::Insert, BB0, BB1}});
1300
1301 // (1) Load the search array and branch to the inner loop.
1302 Builder.SetInsertPoint(BB1);
1303 PHINode *SearchIdx = Builder.CreatePHI(I64Ty, 2, "search_idx");
1304 Value *PredSearch = Builder.CreateIntrinsic(
1305 Intrinsic::get_active_lane_mask, {PredVTy, I64Ty},
1306 {SearchIdx, SearchTripCount}, nullptr, "search_pred");
1307 PredSearch = Builder.CreateAnd(PredVF, PredSearch, "search_masked");
1308 Value *Search = Builder.CreateGEP(CharTy, SearchStart, SearchIdx, "psearch");
1309 Value *LoadSearch = Builder.CreateMaskedLoad(
1310 CharVTy, Search, Align(1), PredSearch, Passthru, "search_load_vec");
1311 Value *MatchInit = Constant::getNullValue(PredVTy);
1312 Builder.CreateBr(BB2);
1313 DTU.applyUpdates({{DominatorTree::Insert, BB1, BB2}});
1314
1315 // (2) Inner loop.
1316 Builder.SetInsertPoint(BB2);
1317 PHINode *NeedleIdx = Builder.CreatePHI(I64Ty, 2, "needle_idx");
1318 PHINode *Match = Builder.CreatePHI(PredVTy, 2, "pmatch");
1319
1320 // (2.a) Load the needle array.
1321 Value *PredNeedle = Builder.CreateIntrinsic(
1322 Intrinsic::get_active_lane_mask, {PredVTy, I64Ty},
1323 {NeedleIdx, NeedleTripCount}, nullptr, "needle_pred");
1324 PredNeedle = Builder.CreateAnd(PredVF, PredNeedle, "needle_masked");
1325 Value *Needle = Builder.CreateGEP(CharTy, NeedleStart, NeedleIdx, "pneedle");
1326 Value *LoadNeedle = Builder.CreateMaskedLoad(
1327 CharVTy, Needle, Align(1), PredNeedle, Passthru, "needle_load_vec");
1328
1329 // (2.b) Splat the first element to the inactive lanes.
1330 Value *Needle0 =
1331 Builder.CreateExtractElement(LoadNeedle, uint64_t(0), "needle0");
1332 Value *Needle0Splat = Builder.CreateVectorSplat(ElementCount::getScalable(VF),
1333 Needle0, "needle0");
1334 LoadNeedle = Builder.CreateSelect(PredNeedle, LoadNeedle, Needle0Splat,
1335 "needle_splat");
1336 LoadNeedle = Builder.CreateExtractVector(
1337 FixedVectorType::get(CharTy, VF), LoadNeedle, uint64_t(0), "needle_vec");
1338
1339 // (2.c) Accumulate matches.
1340 Value *MatchSeg = Builder.CreateIntrinsic(
1341 Intrinsic::experimental_vector_match, {CharVTy, LoadNeedle->getType()},
1342 {LoadSearch, LoadNeedle, PredSearch}, nullptr, "match_segment");
1343 Value *MatchAcc = Builder.CreateOr(Match, MatchSeg, "match_accumulator");
1344 Value *NextNeedleIdx =
1345 Builder.CreateAdd(NeedleIdx, ConstVF, "needle_idx_next");
1346 Builder.CreateCondBr(Builder.CreateICmpULT(NextNeedleIdx, NeedleTripCount),
1347 BB2, BB3);
1348 DTU.applyUpdates(
1349 {{DominatorTree::Insert, BB2, BB2}, {DominatorTree::Insert, BB2, BB3}});
1350
1351 // (3) Check if we found a match.
1352 Builder.SetInsertPoint(BB3);
1353 PHINode *MatchPredAccLCSSA = Builder.CreatePHI(PredVTy, 1, "match_pred");
1354 Value *IfAnyMatch = Builder.CreateOrReduce(MatchPredAccLCSSA);
1355 Builder.CreateCondBr(IfAnyMatch, BB4, BB5);
1356 DTU.applyUpdates(
1357 {{DominatorTree::Insert, BB3, BB4}, {DominatorTree::Insert, BB3, BB5}});
1358
1359 // (4) We found a match. Compute the index of its location and exit.
1360 Builder.SetInsertPoint(BB4);
1361 PHINode *MatchLCSSA =
1362 Builder.CreatePHI(SearchStart->getType(), 1, "match_start");
1363 PHINode *MatchPredLCSSA = Builder.CreatePHI(PredVTy, 1, "match_vec");
1364 Value *MatchCnt = Builder.CreateIntrinsic(
1365 Intrinsic::experimental_cttz_elts, {I64Ty, PredVTy},
1366 {MatchPredLCSSA, /*ZeroIsPoison=*/Builder.getInt1(true)}, nullptr,
1367 "match_idx");
1368 Value *MatchVal =
1369 Builder.CreateGEP(CharTy, MatchLCSSA, MatchCnt, "match_res");
1370 Builder.CreateBr(ExitSucc);
1371 DTU.applyUpdates({{DominatorTree::Insert, BB4, ExitSucc}});
1372
1373 // (5) Check if we've reached the end of the search array.
1374 Builder.SetInsertPoint(BB5);
1375 Value *NextSearchIdx =
1376 Builder.CreateAdd(SearchIdx, ConstVF, "search_idx_next");
1377 Builder.CreateCondBr(Builder.CreateICmpULT(NextSearchIdx, SearchTripCount),
1378 BB1, ExitFail);
1379 DTU.applyUpdates({{DominatorTree::Insert, BB5, BB1},
1380 {DominatorTree::Insert, BB5, ExitFail}});
1381
1382 // Set up the PHI nodes.
1383 SearchIdx->addIncoming(SearchIdxInit, BB0);
1384 SearchIdx->addIncoming(NextSearchIdx, BB5);
1385 NeedleIdx->addIncoming(NeedleIdxInit, BB1);
1386 NeedleIdx->addIncoming(NextNeedleIdx, BB2);
1387 Match->addIncoming(MatchInit, BB1);
1388 Match->addIncoming(MatchAcc, BB2);
1389 // These are needed to retain LCSSA form.
1390 MatchPredAccLCSSA->addIncoming(MatchAcc, BB2);
1391 MatchLCSSA->addIncoming(Search, BB3);
1392 MatchPredLCSSA->addIncoming(MatchPredAccLCSSA, BB3);
1393
1394 // Ensure all Phis in the successors of BB4/BB5 have an incoming value from
1395 // them.
1396 fixSuccessorPhis(CurLoop, IndPhi, MatchVal, ExitSucc, BB4);
1397 if (ExitSucc != ExitFail)
1398 fixSuccessorPhis(CurLoop, IndPhi, MatchVal, ExitFail, BB5);
1399
1400 if (Opts.loop_idiom_vectorize_verify) {
1401 OuterLoop->verifyLoop();
1402 InnerLoop->verifyLoop();
1403 if (!OuterLoop->isRecursivelyLCSSAForm(*DT, *LI))
1404 report_fatal_error("Loops must remain in LCSSA form!");
1405 }
1406
1407 return MatchVal;
1408}
1409
1410void LoopIdiomVectorize::transformFindFirstByte(
1411 PHINode *IndPhi, unsigned VF, Type *CharTy, BasicBlock *ExitSucc,
1412 BasicBlock *ExitFail, Value *SearchStart, Value *SearchEnd,
1413 Value *NeedleStart, Value *NeedleEnd) {
1414 // Insert the find first byte code at the end of the preheader block.
1415 BasicBlock *Preheader = CurLoop->getLoopPreheader();
1416 UncondBrInst *PHBranch = cast<UncondBrInst>(Preheader->getTerminator());
1417 IRBuilder<> Builder(PHBranch);
1418 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
1419 Builder.SetCurrentDebugLocation(PHBranch->getDebugLoc());
1420
1421 expandFindFirstByte(Builder, DTU, VF, CharTy, IndPhi, ExitSucc, ExitFail,
1422 SearchStart, SearchEnd, NeedleStart, NeedleEnd);
1423
1424 if (Opts.loop_idiom_vectorize_verify && CurLoop->getParentLoop()) {
1425 CurLoop->getParentLoop()->verifyLoop();
1426 if (!CurLoop->getParentLoop()->isRecursivelyLCSSAForm(*DT, *LI))
1427 report_fatal_error("Loops must remain in LCSSA form!");
1428 }
1429}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define DEBUG_TYPE
static MDNode * createBranchWeights(LLVMContext &Context, uint64_t TrueWeight, uint64_t FalseWeight)
static void fixSuccessorPhis(Loop *L, Value *ScalarRes, Value *VectorRes, BasicBlock *SuccBB, BasicBlock *IncBB)
This file defines the LoopVectorizationLegality class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define LLVM_DEBUG(...)
Definition Debug.h:119
static cl::opt< unsigned > MinPageSize("min-page-size", cl::init(0), cl::Hidden, cl::desc("Use this to override the target's minimum page size."))
This pass exposes codegen information to IR-level passes.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
Definition BasicBlock.h:509
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
const Instruction & front() const
Definition BasicBlock.h:463
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
Conditional Branch instruction.
static CondBrInst * Create(Value *Cond, BasicBlock *IfTrue, BasicBlock *IfFalse, InsertPosition InsertBefore=nullptr)
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:309
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:843
void applyUpdates(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
LLVM_ABI bool isInBounds() const
Determine whether the GEP has the inbounds flag.
Type * getResultElementType() const
unsigned getNumIndices() const
Module * getParent()
Get the module that this global value is contained inside of...
ConstantInt * getInt1(bool V)
Get a constant value representing either true or false.
Definition IRBuilder.h:440
Value * CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2398
IntegerType * getInt1Ty()
Fetch the type representing a single bit.
Definition IRBuilder.h:507
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2657
CondBrInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
Definition IRBuilder.h:1212
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
ConstantInt * getTrue()
Get the constant value for i1 true.
Definition IRBuilder.h:445
LLVM_ABI CallInst * CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Load intrinsic.
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
void SetCurrentDebugLocation(const DebugLoc &L)
Set location information used by debugging information.
Definition IRBuilder.h:228
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1528
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition IRBuilder.h:522
Value * CreateExtractVector(Type *DstType, Value *SrcVec, Value *Idx, const Twine &Name="")
Create a call to the vector.extract intrinsic.
Definition IRBuilder.h:1108
Value * CreateVScale(Type *Ty, const Twine &Name="")
Create a call to llvm.vscale.<Ty>().
Definition IRBuilder.h:932
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Definition IRBuilder.h:527
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2386
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition IRBuilder.h:2011
UncondBrInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
Definition IRBuilder.h:1206
LLVM_ABI Value * CreateOrReduce(Value *Src)
Create a vector int OR reduction intrinsic of the source vector.
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Definition IRBuilder.h:2547
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2382
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
Definition IRBuilder.h:147
Value * CreateCountTrailingZeroElems(Type *ResTy, Value *Mask, bool ZeroIsPoison=true, const Twine &Name="")
Create a call to llvm.experimental_cttz_elts.
Definition IRBuilder.h:1150
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1435
LLVM_ABI Value * CreatePtrDiff(Value *LHS, Value *RHS, const Twine &Name="", bool IsNUW=false)
Return the difference between two pointer values.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition IRBuilder.h:1907
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Definition IRBuilder.h:2121
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1566
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1418
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2233
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Definition IRBuilder.h:2107
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition IRBuilder.h:196
Value * CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2402
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1588
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Definition IRBuilder.h:512
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1452
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2909
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *BB)
Update the specified successor to point at the provided block.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
This class provides an interface for updating the loop pass manager based on mutations to the loop ne...
An instruction for reading from memory.
bool isSimple() const
bool contains(const LoopT *L) const
Return true if the specified loop is contained within this loop.
void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase< BlockT, LoopT > &LI)
This method is used by other analyses to update loop information.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
LLVM_ABI PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U)
Utility class for getting and setting loop vectorizer hints in the form of loop metadata.
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
LLVM_ABI MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight, bool IsExpected=false)
Return metadata containing two branch weights.
Definition MDBuilder.cpp:38
The optimization diagnostic interface.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
This class represents an analyzed expression in the program.
Class to represent scalable SIMD vectors.
static LLVM_ABI ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
Definition Type.cpp:865
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
@ TCK_SizeAndLatency
The weighted sum of size and latency.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI unsigned getIntegerBitWidth() const
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:297
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:296
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
Unconditional Branch instruction.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
bool hasOneUse() const
Return true if there is exactly one use of this value.
Definition Value.h:441
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:260
iterator_range< user_iterator > users()
Definition Value.h:428
Base class of all SIMD vector types.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
const ParentTy * getParent() const
Definition ilist_node.h:34
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
match_bind< PHINode > m_Phi(PHINode *&PN)
Match a PHI node, capturing it if we match.
br_match m_UnconditionalBr(BasicBlock *&Succ)
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
auto m_BasicBlock()
Match an arbitrary basic block value and ignore it.
auto m_Value()
Match an arbitrary value and ignore it.
auto m_GEP(const OperandTypes &...Ops)
Matches GetElementPtrInst.
SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
bool isSimple(Instruction *I)
Definition SLPUtils.cpp:846
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
AnalysisManager< Loop, LoopStandardAnalysisResults & > LoopAnalysisManager
The loop analysis manager.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
OuterAnalysisManagerProxy< FunctionAnalysisManager, Loop, LoopStandardAnalysisResults & > FunctionAnalysisManagerLoopProxy
A proxy from a FunctionAnalysisManager to a Loop.
TargetTransformInfo TTI
LLVM_ABI BasicBlock * SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the specified block at the specified instruction.
DWARFExpression::Operation Op
const VectorizeOptions & getVectorizeOptions(const LLVMContext &C)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...