LLVM 24.0.0git
AArch64PredicateAsCounterLoopRewrites.cpp
Go to the documentation of this file.
1//===- AArch64PredicateAsCounterLoopRewrites.cpp --------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM
4// Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9//
10// Rewrites IR for loop-carried wide masks that can be represented as
11// predicate-as-counter values. This applies when the mask is used by load/store
12// operations that can be mapped to multi-vector instructions (with +sve2p1).
13//
14// For example, a loop like:
15//
16// entry:
17// %step = vscale x 64
18// %mask.entry = @get.active.lane.mask(0, %n)
19//
20// loop:
21// %iv = phi i64 [0, entry], [%iv.next, loop]
22// %mask = phi <vscale x 64 x i1> [%mask.entry, entry],
23// [%mask.next, loop]
24//
25// %load = load <vscale x 64 x i8> %src[%iv], %mask
26// store <vscale x 64 x i8> %load, %dst[%iv], %mask
27//
28// %iv.next = %iv + %step
29// %mask.next = @get.active.lane.mask(%iv.next, %n)
30// br first.active(%mask.next), loop, exit
31//
32// Could be rewritten to:
33//
34// entry:
35// %step = vscale x 64
36// %mask.entry = @whilelo.c8(0, %n, VLx4)
37//
38// loop:
39// %iv = phi i64 [0, entry], [%iv.next, loop]
40// %mask = phi target("aarch64.svcount") [%mask.entry, entry],
41// [%mask.next, loop]
42//
43// %load = @ld1.pn.x4 <4 x <vscale x 16 x i8>> %src[%iv], %mask
44// @st1.pn.x4 <4 x <vscale x 16 x i8>> %load, %dest[%iv], %mask
45//
46// %iv.next = %iv + %step
47// %mask.next = @whilelo.c8(%iv.next, %n, VLx4)
48// br first.active(@pext(%mask.next, 0)), loop, exit
49//
50// This replaces the `get.active.lane.mask` intrinsics with AArch64
51// predicate-as-counter `whilelo` intrinsics and updates the mask phi to use the
52// `aarch64.svcount` target type. Within the loop, load/store users are mapped
53// to multi-vector load/store intrinsics where possible. Users that cannot be
54// mapped to multi-vector instructions materialize vector masks using the `pext`
55// intrinsic (which extracts vector predicates from a predicate-as-counter).
56//
57// This pass may be a temporary solution that is removed if we gain support
58// for target-specific VPlan transforms in the loop vectorizer.
59//
60//===----------------------------------------------------------------------===//
61
62#include "AArch64.h"
63#include "AArch64Subtarget.h"
66#include "llvm/ADT/Statistic.h"
70#include "llvm/IR/Attributes.h"
71#include "llvm/IR/DataLayout.h"
72#include "llvm/IR/IRBuilder.h"
74#include "llvm/IR/Intrinsics.h"
75#include "llvm/IR/IntrinsicsAArch64.h"
76#include "llvm/IR/Module.h"
78#include "llvm/Pass.h"
79#include "llvm/Support/Debug.h"
82#include <optional>
83
84using namespace llvm;
85
86#define DEBUG_TYPE "aarch64-pn-loop-rewrites"
87namespace {
88
89STATISTIC(LoopsRewritten, "Number of loops rewritten");
90
91struct MaskRewriteCandidate {
92 /// The mask phi node (used by masked operations within the loop).
93 PHINode *MaskPhi = nullptr;
94 /// The initial value for the mask (incoming value from the preheader).
95 IntrinsicInst *StartMask = nullptr;
96 /// The updated value for the mask (incoming value from the loop latch).
97 IntrinsicInst *NextMask = nullptr;
98 /// The multi-vector scale for the predicate-as-counter (2 or 4).
99 unsigned VectorScale = 0;
100 /// The element size (in bits) for the predicate-as-counter.
101 unsigned ElementSizeInBits = 0;
102};
103
104static void logLoopBailout(const Loop &L, const Twine &Reason) {
105 LLVM_DEBUG({
106 dbgs() << "PN loop rewrite: skipping loop with header ";
107 L.getHeader()->printAsOperand(dbgs(), /*PrintType=*/false);
108 dbgs() << ": " << Reason << "\n";
109 });
110}
111
112static void logMatchFailure(const PHINode &Phi, const Twine &Reason) {
113 LLVM_DEBUG({
114 dbgs() << "PN loop rewrite: failed to match mask phi ";
115 Phi.printAsOperand(dbgs(), /*PrintType=*/false);
116 dbgs() << ": " << Reason << "\n";
117 });
118}
119
120/// Returns the scalar size in bits for a type according to the data layout.
121static unsigned getScalarSizeInBits(const DataLayout &DL, Type *Ty) {
122 return DL.getTypeSizeInBits(Ty->getScalarType()).getFixedValue();
123}
124
125/// Returns the SVE element count for \p ElementSizeInBits.
126static ElementCount getSVEElementCount(unsigned ElementSizeInBits) {
128 ElementSizeInBits);
129}
130
131/// Returns the largest scalar access size of masked loads/stores in loop \p L
132/// where \p MaskPhi is used as the mask. TODO: This heuristic may need
133/// refinement based on the frequency of different access sizes.
134static unsigned getLargestMaskedMemAccessSizeInBits(const Loop &L,
135 PHINode &MaskPhi) {
136 const DataLayout &DL = MaskPhi.getModule()->getDataLayout();
137 unsigned LargestAccessSizeInBits = 0;
138
139 for (User *U : MaskPhi.users()) {
140 auto *II = dyn_cast<IntrinsicInst>(U);
141 if (!II || !L.contains(II))
142 continue;
143
144 Intrinsic::ID IID = II->getIntrinsicID();
145 if (IID != Intrinsic::masked_load && IID != Intrinsic::masked_store)
146 continue;
147
148 unsigned MaskOpIdx = IID == Intrinsic::masked_load ? 1 : 2;
149 if (II->getArgOperand(MaskOpIdx) != &MaskPhi)
150 continue;
151
152 unsigned AccessSizeInBits = getScalarSizeInBits(DL, II->getAccessType());
153 if (AccessSizeInBits > LargestAccessSizeInBits)
154 LargestAccessSizeInBits = AccessSizeInBits;
155 }
156
157 return LargestAccessSizeInBits;
158}
159
160/// Returns the predicate-as-counter whilelo intrinsic ID for
161/// \p ElementSizeInBits.
162static Intrinsic::ID getWhileLOIntrinsic(unsigned ElementSizeInBits) {
163 switch (ElementSizeInBits) {
164 case 8:
165 return Intrinsic::aarch64_sve_whilelo_c8;
166 case 16:
167 return Intrinsic::aarch64_sve_whilelo_c16;
168 case 32:
169 return Intrinsic::aarch64_sve_whilelo_c32;
170 case 64:
171 return Intrinsic::aarch64_sve_whilelo_c64;
172 default:
173 llvm_unreachable("unsupported predicate-as-counter element size");
174 }
175}
176
177/// Expands the predicate-as-counter mask \p Count into a wide vector mask.
178/// Masks are extracted from the counter using the paired pext intrinsics,
179/// then concatenated to form the wide mask value.
180static Value *buildWideMask(IRBuilder<> &Builder, const MaskRewriteCandidate &C,
181 Value *Count) {
182 ElementCount LegalEC = getSVEElementCount(C.ElementSizeInBits);
183 Type *LegalMaskTy = VectorType::get(Builder.getInt1Ty(), LegalEC);
184
185 Value *WideMask = PoisonValue::get(C.MaskPhi->getType());
186 for (unsigned PairOffset = 0; PairOffset != C.VectorScale / 2; ++PairOffset) {
187 auto *Pair =
188 Builder.CreateIntrinsic(Intrinsic::aarch64_sve_pext_x2, {LegalMaskTy},
189 {Count, Builder.getInt32(PairOffset)},
190 /*FMFSource=*/{}, "pn.pext.pair");
191 for (unsigned SliceInPair = 0; SliceInPair != 2; ++SliceInPair) {
192 Value *Part = Builder.CreateExtractValue(Pair, SliceInPair, "pn.pext");
193 unsigned Slice = PairOffset * 2 + SliceInPair;
194 WideMask = Builder.CreateInsertVector(
195 C.MaskPhi->getType(), WideMask, Part,
196 Slice * LegalEC.getKnownMinValue(), "pn.mask");
197 }
198 }
199
200 return WideMask;
201}
202
203/// Creates a predicate-as-counter whilelo for \p ElementSizeInBits between
204/// \p Start and \p End with multi-vector \p VectorScale (2 or 4).
205static Value *createWhileLO(IRBuilder<> &Builder, unsigned ElementSizeInBits,
206 Value *Start, Value *End, unsigned VectorScale) {
207 if (Start->getType()->getIntegerBitWidth() < 64) {
208 Start = Builder.CreateZExt(Start, Builder.getInt64Ty());
209 End = Builder.CreateZExt(End, Builder.getInt64Ty());
210 }
211
212 Intrinsic::ID WhileLO = getWhileLOIntrinsic(ElementSizeInBits);
213 return Builder.CreateIntrinsic(WhileLO,
214 {Start, End, Builder.getInt32(VectorScale)},
215 /*FMFSource=*/{}, "pn.mask");
216}
217
218/// If \p UserI is a masked-load user of the original loop mask, rewrite it to
219/// a masked multi-vector load (using the predicate-as-counter) if the load
220/// access size matches the predicate-as-counter element size.
221static bool tryRewriteMaskedLoad(Instruction &UserI,
222 const MaskRewriteCandidate &C, Value *Count) {
223 auto *II = dyn_cast<IntrinsicInst>(&UserI);
224 if (!II || II->getIntrinsicID() != Intrinsic::masked_load)
225 return false;
226
227 unsigned ElementSizeInBits =
228 getScalarSizeInBits(II->getModule()->getDataLayout(), II->getType());
229 if (ElementSizeInBits != C.ElementSizeInBits)
230 return false;
231
232 if (!isa<PoisonValue, UndefValue>(II->getArgOperand(2)))
233 return false;
234
235 IRBuilder<> Builder(II);
236
237 ElementCount LegalEC = getSVEElementCount(C.ElementSizeInBits);
238 Type *ScalarType = II->getType()->getScalarType();
239 auto *WideDataTy = VectorType::get(ScalarType, LegalEC * C.VectorScale);
240 auto *LegalDataTy = VectorType::get(ScalarType, LegalEC);
241
242 auto *PNLoad = cast<IntrinsicInst>(Builder.CreateIntrinsic(
243 C.VectorScale == 4 ? Intrinsic::aarch64_sve_ld1_pn_x4
244 : Intrinsic::aarch64_sve_ld1_pn_x2,
245 {LegalDataTy, II->getArgOperand(0)->getType()},
246 {Count, II->getArgOperand(0)},
247 /*FMFSource=*/{}, "pn.ld1"));
248
249 // Copy pointer parameter attributes.
250 for (Attribute ParamAttr : II->getParamAttributes(0))
251 PNLoad->addParamAttr(1, ParamAttr);
252
253 PNLoad->copyMetadata(*II);
254
255 // Concatenate all results into the original wide value.
256 Value *WideData = PoisonValue::get(WideDataTy);
257 for (unsigned Slice = 0; Slice != C.VectorScale; ++Slice) {
258 Value *Part = Builder.CreateExtractValue(PNLoad, Slice, "pn.data");
259 WideData = Builder.CreateInsertVector(WideDataTy, WideData, Part,
260 Slice * LegalEC.getKnownMinValue(),
261 "pn.vec");
262 }
263
264 II->replaceAllUsesWith(WideData);
265 II->eraseFromParent();
266 return true;
267}
268
269/// If \p UserI is a masked-store user of the original loop mask, rewrite it to
270/// a masked multi-vector store (using the predicate-as-counter) if the store
271/// access size matches the predicate-as-counter element size.
272static bool tryRewriteMaskedStore(Instruction &UserI,
273 const MaskRewriteCandidate &C, Value *Count) {
274 auto *II = dyn_cast<IntrinsicInst>(&UserI);
275 if (!II || II->getIntrinsicID() != Intrinsic::masked_store)
276 return false;
277
278 unsigned ElementSizeInBits = getScalarSizeInBits(
279 II->getModule()->getDataLayout(), II->getArgOperand(0)->getType());
280 if (ElementSizeInBits != C.ElementSizeInBits)
281 return false;
282
283 IRBuilder<> Builder(II);
284
285 Type *ScalarType = II->getArgOperand(0)->getType()->getScalarType();
286 ElementCount LegalEC = getSVEElementCount(C.ElementSizeInBits);
287 auto *LegalDataTy = VectorType::get(ScalarType, LegalEC);
288
289 SmallVector<Value *, 6> StoreArgs;
290 for (unsigned Slice = 0; Slice != C.VectorScale; ++Slice)
291 StoreArgs.push_back(Builder.CreateExtractVector(
292 LegalDataTy, II->getArgOperand(0), Slice * LegalEC.getKnownMinValue(),
293 "pn.data"));
294 StoreArgs.push_back(Count);
295 StoreArgs.push_back(II->getArgOperand(1));
296
297 auto *PNStore = cast<IntrinsicInst>(Builder.CreateIntrinsic(
298 C.VectorScale == 4 ? Intrinsic::aarch64_sve_st1_pn_x4
299 : Intrinsic::aarch64_sve_st1_pn_x2,
300 {LegalDataTy, II->getArgOperand(1)->getType()}, StoreArgs));
301
302 PNStore->copyMetadata(*II);
303
304 // Copy pointer parameter attributes.
305 for (Attribute ParamAttr : II->getParamAttributes(1))
306 PNStore->addParamAttr(C.VectorScale + 1, ParamAttr);
307
308 II->eraseFromParent();
309 return true;
310}
311
312/// If \p UserI is an extractelement use of the original loop mask, attempt to
313/// rewrite it to `extractelement(pext(count, 0), idx)` if the extract index is
314/// known to be within the first mask section (which means pext index = 0). If
315/// the user of the extract is a branch and the source of the mask is a whilelo,
316/// this form can be optimized into checking the status flags.
317static bool tryRewriteExtractElement(Instruction &UserI,
318 const MaskRewriteCandidate &C,
319 Value *Count) {
320 auto *EEI = dyn_cast<ExtractElementInst>(&UserI);
321 if (!EEI)
322 return false;
323
324 ElementCount LegalEC = getSVEElementCount(C.ElementSizeInBits);
325 auto *Idx = dyn_cast<ConstantInt>(EEI->getIndexOperand());
326 if (!Idx || Idx->getValue().uge(LegalEC.getKnownMinValue()))
327 return false;
328
329 IRBuilder<> Builder(EEI);
330
331 auto *ExtractMask = Builder.CreateIntrinsic(
332 Intrinsic::aarch64_sve_pext,
333 {VectorType::get(Builder.getInt1Ty(), LegalEC)},
334 {Count, Builder.getInt32(0)}, /*FMFSource=*/{}, "pn.pext");
335
336 Value *Extracted = Builder.CreateExtractElement(
337 ExtractMask, EEI->getIndexOperand(), EEI->getName() + ".pn");
338
339 EEI->replaceAllUsesWith(Extracted);
340 EEI->eraseFromParent();
341 return true;
342}
343
344class AArch64PredicateAsCounterLoopRewrites : public LoopPass {
345public:
346 static char ID;
347
348 AArch64PredicateAsCounterLoopRewrites() : LoopPass(ID) {}
349
350 void getAnalysisUsage(AnalysisUsage &AU) const override {
352 // Require loop simplify to ensure loops have a preheader.
355 AU.setPreservesCFG();
356 }
357
358 bool runOnLoop(Loop *L, LPPassManager &) override;
359
360private:
361 std::optional<MaskRewriteCandidate> matchMaskPhi(Loop &L, PHINode &Phi) const;
362 bool rewriteCandidate(const MaskRewriteCandidate &C, Loop &L) const;
363};
364
365} // end anonymous namespace
366
367char AArch64PredicateAsCounterLoopRewrites::ID = 0;
368
369INITIALIZE_PASS_BEGIN(AArch64PredicateAsCounterLoopRewrites, DEBUG_TYPE,
370 "AArch64 Predicate As Counter Loop Rewrites", false,
371 false)
373INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
374INITIALIZE_PASS_END(AArch64PredicateAsCounterLoopRewrites, DEBUG_TYPE,
375 "AArch64 Predicate As Counter Loop Rewrites", false, false)
376
378 return new AArch64PredicateAsCounterLoopRewrites();
379}
380
381bool AArch64PredicateAsCounterLoopRewrites::runOnLoop(Loop *L,
382 LPPassManager &) {
383 if (skipLoop(L)) {
384 logLoopBailout(*L, "skipLoop requested the loop to be skipped");
385 return false;
386 }
387
388 Function &F = *L->getHeader()->getParent();
389 auto &TPC = getAnalysis<TargetPassConfig>();
390 const AArch64Subtarget *ST =
391 TPC.getTM<AArch64TargetMachine>().getSubtargetImpl(F);
392 if (!ST->hasSVE2p1() && !(ST->hasSME2() && ST->isStreaming())) {
393 logLoopBailout(*L, "neither SVE2.1 nor SME2 is available");
394 return false;
395 }
396
397 if (!L->getLoopPreheader()) {
398 logLoopBailout(*L, "loop has no preheader");
399 return false;
400 }
401 if (!L->getLoopLatch()) {
402 logLoopBailout(*L, "loop has no latch");
403 return false;
404 }
405
406 bool Changed = false;
407 BasicBlock *Header = L->getHeader();
408 for (PHINode &Phi : make_early_inc_range(Header->phis())) {
409 if (std::optional<MaskRewriteCandidate> Candidate = matchMaskPhi(*L, Phi))
410 Changed |= rewriteCandidate(*Candidate, *L);
411 }
412
413 if (Changed)
414 ++LoopsRewritten;
415
416 return Changed;
417}
418
421 return II && II->getIntrinsicID() == Intrinsic::get_active_lane_mask
422 ? II
423 : nullptr;
424}
425
426std::optional<MaskRewriteCandidate>
427AArch64PredicateAsCounterLoopRewrites::matchMaskPhi(Loop &L,
428 PHINode &Phi) const {
429 auto *PhiTy = dyn_cast<ScalableVectorType>(Phi.getType());
430 if (!PhiTy || !PhiTy->getElementType()->isIntegerTy(1))
431 return std::nullopt;
432
433 if (Phi.getNumIncomingValues() != 2) {
434 logMatchFailure(Phi, Twine("phi has ") + Twine(Phi.getNumIncomingValues()) +
435 " incoming values; expected 2");
436 return std::nullopt;
437 }
438
439 Value *StartValue = Phi.getIncomingValueForBlock(L.getLoopPreheader());
440 Value *NextValue = Phi.getIncomingValueForBlock(L.getLoopLatch());
441 IntrinsicInst *StartMask = getGetActiveLaneMask(StartValue);
442 IntrinsicInst *NextMask = getGetActiveLaneMask(NextValue);
443 if (!StartMask) {
444 logMatchFailure(Phi,
445 "preheader incoming value is not get_active_lane_mask");
446 return std::nullopt;
447 }
448 if (!NextMask) {
449 logMatchFailure(Phi, "latch incoming value is not get_active_lane_mask");
450 return std::nullopt;
451 }
452
453 unsigned WideMaskElements = PhiTy->getMinNumElements();
454 if (!isPowerOf2_32(WideMaskElements)) {
455 logMatchFailure(Phi,
456 Twine("wide mask element count is not a power of 2: ") +
457 Twine(WideMaskElements));
458 return std::nullopt;
459 }
460
461 if (StartMask->getArgOperand(0)->getType()->getIntegerBitWidth() > 64) {
462 logMatchFailure(Phi, "start mask induction operand is wider than i64");
463 return std::nullopt;
464 }
465 if (NextMask->getArgOperand(0)->getType()->getIntegerBitWidth() > 64) {
466 logMatchFailure(Phi, "next mask induction operand is wider than i64");
467 return std::nullopt;
468 }
469
470 unsigned PreferredMaskElementSizeInBits =
471 getLargestMaskedMemAccessSizeInBits(L, Phi);
472
473 if (!is_contained({8u, 16u, 32u, 64u}, PreferredMaskElementSizeInBits)) {
474 logMatchFailure(Phi, Twine("unsupported element size in bits: ") +
475 Twine(PreferredMaskElementSizeInBits));
476 return std::nullopt;
477 }
478
479 unsigned SVEMaskElements =
480 AArch64::SVEBitsPerBlock / PreferredMaskElementSizeInBits;
481 if (WideMaskElements <= SVEMaskElements) {
482 logMatchFailure(Phi, Twine("wide mask element count ") +
483 Twine(WideMaskElements) +
484 " is not wider than the legal mask width " +
485 Twine(SVEMaskElements));
486 return std::nullopt;
487 }
488
489 unsigned VectorScale = WideMaskElements / SVEMaskElements;
490 if (VectorScale != 2 && VectorScale != 4) {
491 logMatchFailure(Phi, Twine("unsupported predicate-as-counter scale: ") +
492 Twine(VectorScale));
493 return std::nullopt;
494 }
495
496 return MaskRewriteCandidate{&Phi, StartMask, NextMask, VectorScale,
497 PreferredMaskElementSizeInBits};
498}
499
500bool AArch64PredicateAsCounterLoopRewrites::rewriteCandidate(
501 const MaskRewriteCandidate &C, Loop &L) const {
502 IRBuilder<> Builder(C.StartMask);
503 Value *NewStart =
504 createWhileLO(Builder, C.ElementSizeInBits, C.StartMask->getArgOperand(0),
505 C.StartMask->getArgOperand(1), C.VectorScale);
506 Builder.SetInsertPoint(C.NextMask);
507 Value *NewNext =
508 createWhileLO(Builder, C.ElementSizeInBits, C.NextMask->getArgOperand(0),
509 C.NextMask->getArgOperand(1), C.VectorScale);
510
511 Builder.SetInsertPoint(C.MaskPhi);
512 auto *NewPhi =
513 Builder.CreatePHI(NewStart->getType(), 2, C.MaskPhi->getName() + ".pn");
514 NewPhi->addIncoming(NewStart, L.getLoopPreheader());
515 NewPhi->addIncoming(NewNext, L.getLoopLatch());
516
517 auto RewriteUses = [&](Instruction *OldMask, Value *Count,
518 function_ref<bool(Use &U)> Predicate = nullptr) {
519 SmallVector<Use *, 8> UsesToRewrite;
520 for (Use &U : OldMask->uses()) {
521 if (!Predicate || Predicate(U))
522 UsesToRewrite.push_back(&U);
523 }
524
525 Value *WideMask = nullptr;
526 for (Use *U : UsesToRewrite) {
527 auto *UserI = cast<Instruction>(U->getUser());
528 if (tryRewriteMaskedLoad(*UserI, C, Count) ||
529 tryRewriteMaskedStore(*UserI, C, Count) ||
530 tryRewriteExtractElement(*UserI, C, Count))
531 continue;
532
533 if (!WideMask) {
534 BasicBlock::iterator InsertPt = OldMask->getIterator();
535 if (isa<PHINode>(OldMask))
536 InsertPt = OldMask->getParent()->getFirstNonPHIIt();
537
538 Builder.SetInsertPoint(InsertPt);
539 Builder.SetCurrentDebugLocation(OldMask->getDebugLoc());
540 WideMask = buildWideMask(Builder, C, Count);
541 }
542
543 U->set(WideMask);
544 }
545 };
546
547 // For the start/next mask, we only replace non-phi in-loop users. Due to CSE,
548 // these masks could be used by other loops, and replacing them with
549 // predicate-as-counter masks could prevent matching those loops.
550 auto IsNonPhiUseInLoop = [&](Use &U) {
551 auto *UseInst = cast<Instruction>(U.getUser());
552 return !isa<PHINode>(UseInst) && L.contains(UseInst);
553 };
554
555 RewriteUses(C.MaskPhi, NewPhi);
556 RewriteUses(C.StartMask, NewStart, IsNonPhiUseInLoop);
557 RewriteUses(C.NextMask, NewNext, IsNonPhiUseInLoop);
558
560 return true;
561}
static IntrinsicInst * getGetActiveLaneMask(Value *V)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
@ ParamAttr
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
static unsigned getScalarSizeInBits(Type *Ty)
Target-Independent Code Generator Pass Configuration Options pass.
Represent the analysis usage information of a pass.
LLVM_ABI AnalysisUsage & addRequiredID(const void *ID)
Definition Pass.cpp:294
AnalysisUsage & addPreservedID(const void *ID)
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:280
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:106
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
Value * getArgOperand(unsigned i) const
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:309
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2949
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
iterator_range< user_iterator > users()
A wrapper class for inspecting calls to intrinsic functions.
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition Module.h:325
Pass interface - Implemented by all 'passes'.
Definition Pass.h:97
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Target-Independent Code Generator Pass Configuration Options.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
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
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:548
iterator_range< use_iterator > uses()
Definition Value.h:382
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static constexpr unsigned SVEBitsPerBlock
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
NodeAddr< PhiNode * > Phi
Definition RDFGraph.h:390
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
Definition Local.cpp:522
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
Pass * createAArch64PredicateAsCounterLoopRewritesPass()
LLVM_ABI char & LoopSimplifyID
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320