34#include "llvm/IR/IntrinsicsX86.h"
53#define DEBUG_TYPE "x86-lower-amx-intrinsics"
58 return FVT->getNumElements() == 256 &&
59 FVT->getElementType()->isIntegerTy(32);
65class X86LowerAMXIntrinsics {
69 X86LowerAMXIntrinsics(
Function &
F, DomTreeUpdater &DomTU, LoopInfo *LoopI)
70 : Func(
F), DTU(DomTU), LI(LoopI) {}
76 BasicBlock *createLoop(BasicBlock *Preheader, BasicBlock *Exit,
Value *Bound,
77 ConstantInt *Step, StringRef Name, IRBuilderBase &
B,
79 template <
bool IsTileLoad>
80 Value *createTileLoadStoreLoops(BasicBlock *Start, BasicBlock *End,
83 template <Intrinsic::ID IntrID>
84 std::enable_if_t<IntrID == Intrinsic::x86_tdpbssd_internal ||
85 IntrID == Intrinsic::x86_tdpbsud_internal ||
86 IntrID == Intrinsic::x86_tdpbusd_internal ||
87 IntrID == Intrinsic::x86_tdpbuud_internal ||
88 IntrID == Intrinsic::x86_tdpbf16ps_internal,
90 createTileDPLoops(BasicBlock *Start, BasicBlock *End, IRBuilderBase &
B,
93 template <
bool IsTileLoad>
94 bool lowerTileLoadStore(Instruction *TileLoadStore);
95 template <Intrinsic::ID IntrID>
96 std::enable_if_t<IntrID == Intrinsic::x86_tdpbssd_internal ||
97 IntrID == Intrinsic::x86_tdpbsud_internal ||
98 IntrID == Intrinsic::x86_tdpbusd_internal ||
99 IntrID == Intrinsic::x86_tdpbuud_internal ||
100 IntrID == Intrinsic::x86_tdpbf16ps_internal,
102 lowerTileDP(Instruction *TileDP);
103 bool lowerTileZero(Instruction *TileZero);
119 Type *I16Ty = Type::getInt16Ty(Ctx);
123 PHINode::Create(I16Ty, 2, Name +
".iv", Header->getTerminator()->getIterator());
124 IV->addIncoming(ConstantInt::get(I16Ty, 0), Preheader);
126 B.SetInsertPoint(Latch);
127 Value *Inc =
B.CreateAdd(
IV, Step, Name +
".step");
128 Value *
Cond =
B.CreateICmpNE(Inc, Bound, Name +
".cond");
133 "Expected a non-zero step size. This is chosen by the pass and "
134 "should always be non-zero to imply a finite loop.");
137 *BR, {BoundInt->getZExtValue() / Step->
getZExtValue(), 1},
false);
142 IV->addIncoming(Inc, Latch);
148 {DominatorTree::Delete, Preheader, Tmp},
149 {DominatorTree::Insert, Header, Body},
150 {DominatorTree::Insert, Body, Latch},
151 {DominatorTree::Insert, Latch, Header},
152 {DominatorTree::Insert, Latch,
Exit},
153 {DominatorTree::Insert, Preheader, Header},
156 L->addBasicBlockToLoop(Header, *LI);
157 L->addBasicBlockToLoop(Body, *LI);
158 L->addBasicBlockToLoop(Latch, *LI);
163template <
bool IsTileLoad>
164Value *X86LowerAMXIntrinsics::createTileLoadStoreLoops(
165 BasicBlock *Start, BasicBlock *End, IRBuilderBase &
B,
Value *Row,
167 std::string IntrinName = IsTileLoad ?
"tileload" :
"tilestore";
168 Loop *RowLoop =
nullptr;
169 Loop *ColLoop =
nullptr;
175 ParentL->addChildLoop(RowLoop);
180 BasicBlock *RowBody = createLoop(Start, End, Row,
B.getInt16(1),
181 IntrinName +
".scalarize.rows",
B, RowLoop);
184 BasicBlock *ColBody = createLoop(RowBody, RowLatch, Col,
B.getInt16(1),
185 IntrinName +
".scalarize.cols",
B, ColLoop);
192 Type *EltTy =
B.getInt32Ty();
199 Value *CurrentRowZExt =
B.CreateZExt(CurrentRow, Stride->
getType());
200 Value *CurrentColZExt =
B.CreateZExt(CurrentCol, Stride->
getType());
202 B.CreateAdd(
B.CreateMul(CurrentRowZExt, Stride), CurrentColZExt);
204 Value *Idx =
B.CreateAdd(
B.CreateMul(CurrentRow,
B.getInt16(16)), CurrentCol);
211 PHINode *VecCPhiRowLoop =
B.CreatePHI(V256I32Ty, 2,
"vec.phi.row");
218 PHINode *VecPhi =
B.CreatePHI(V256I32Ty, 2,
"vec.phi");
227 Value *Elt =
B.CreateLoad(EltTy, EltPtr);
228 Value *ResVec =
B.CreateInsertElement(VecPhi, Elt, Idx);
235 Value *Vec = BitCast->getOperand(0);
243 Value *Elt =
B.CreateExtractElement(Vec, Idx);
245 B.CreateStore(Elt, EltPtr);
250template <Intrinsic::ID IntrID>
251std::enable_if_t<IntrID == Intrinsic::x86_tdpbssd_internal ||
252 IntrID == Intrinsic::x86_tdpbsud_internal ||
253 IntrID == Intrinsic::x86_tdpbusd_internal ||
254 IntrID == Intrinsic::x86_tdpbuud_internal ||
255 IntrID == Intrinsic::x86_tdpbf16ps_internal,
257X86LowerAMXIntrinsics::createTileDPLoops(BasicBlock *Start, BasicBlock *End,
258 IRBuilderBase &
B,
Value *Row,
261 std::string IntrinName;
263 case Intrinsic::x86_tdpbssd_internal:
264 IntrinName =
"tiledpbssd";
266 case Intrinsic::x86_tdpbsud_internal:
267 IntrinName =
"tiledpbsud";
269 case Intrinsic::x86_tdpbusd_internal:
270 IntrinName =
"tiledpbusd";
272 case Intrinsic::x86_tdpbuud_internal:
273 IntrinName =
"tiledpbuud";
275 case Intrinsic::x86_tdpbf16ps_internal:
276 IntrinName =
"tiledpbf16ps";
279 Loop *RowLoop =
nullptr;
280 Loop *ColLoop =
nullptr;
281 Loop *InnerLoop =
nullptr;
289 ParentL->addChildLoop(RowLoop);
294 BasicBlock *RowBody = createLoop(Start, End, Row,
B.getInt16(1),
295 IntrinName +
".scalarize.rows",
B, RowLoop);
298 BasicBlock *ColBody = createLoop(RowBody, RowLatch, Col,
B.getInt16(1),
299 IntrinName +
".scalarize.cols",
B, ColLoop);
305 createLoop(ColBody, ColLoopLatch, K,
B.getInt16(1),
306 IntrinName +
".scalarize.inner",
B, InnerLoop);
314 Value *CurrentInner = &*InnerLoopHeader->
begin();
318 Value *VecC = BitCastAcc->getOperand(0);
324 Value *VecA = BitCastLHS->getOperand(0);
327 Value *VecB = BitCastRHS->getOperand(0);
337 PHINode *VecCPhiRowLoop =
B.CreatePHI(V256I32Ty, 2,
"vec.c.phi.row");
340 PHINode *VecDPhiRowLoop =
B.CreatePHI(V256I32Ty, 2,
"vec.d.phi.row");
354 PHINode *VecCPhiColLoop =
B.CreatePHI(V256I32Ty, 2,
"vec.c.phi.col");
355 VecCPhiColLoop->
addIncoming(VecCPhiRowLoop, RowBody);
356 PHINode *VecDPhiColLoop =
B.CreatePHI(V256I32Ty, 2,
"vec.d.phi.col");
357 VecDPhiColLoop->
addIncoming(VecDPhiRowLoop, RowBody);
359 B.CreateAdd(
B.CreateMul(CurrentRow,
B.getInt16(16)), CurrentCol);
367 PHINode *VecCPhi =
B.CreatePHI(V256I32Ty, 2,
"vec.c.inner.phi");
372 B.CreateAdd(
B.CreateMul(CurrentRow,
B.getInt16(16)), CurrentInner);
374 B.CreateAdd(
B.CreateMul(CurrentInner,
B.getInt16(16)), CurrentCol);
375 Value *NewVecC =
nullptr;
377 if (IntrID != Intrinsic::x86_tdpbf16ps_internal) {
394 Value *EltC =
B.CreateExtractElement(VecCPhi, IdxC);
395 Value *EltA =
B.CreateExtractElement(VecA, IdxA);
396 Value *SubVecA =
B.CreateBitCast(EltA, V4I8Ty);
397 Value *EltB =
B.CreateExtractElement(VecB, IdxB);
398 Value *SubVecB =
B.CreateBitCast(EltB, V4I8Ty);
399 Value *SEXTSubVecB =
nullptr;
400 Value *SEXTSubVecA =
nullptr;
402 case Intrinsic::x86_tdpbssd_internal:
403 SEXTSubVecB =
B.CreateSExt(SubVecB, V4I32Ty);
404 SEXTSubVecA =
B.CreateSExt(SubVecA, V4I32Ty);
406 case Intrinsic::x86_tdpbsud_internal:
407 SEXTSubVecB =
B.CreateZExt(SubVecB, V4I32Ty);
408 SEXTSubVecA =
B.CreateSExt(SubVecA, V4I32Ty);
410 case Intrinsic::x86_tdpbusd_internal:
411 SEXTSubVecB =
B.CreateSExt(SubVecB, V4I32Ty);
412 SEXTSubVecA =
B.CreateZExt(SubVecA, V4I32Ty);
414 case Intrinsic::x86_tdpbuud_internal:
415 SEXTSubVecB =
B.CreateZExt(SubVecB, V4I32Ty);
416 SEXTSubVecA =
B.CreateZExt(SubVecA, V4I32Ty);
421 Value *SubVecR =
B.CreateAddReduce(
B.CreateMul(SEXTSubVecA, SEXTSubVecB));
422 Value *ResElt =
B.CreateAdd(EltC, SubVecR);
423 NewVecC =
B.CreateInsertElement(VecCPhi, ResElt, IdxC);
449 Value *EltC =
B.CreateExtractElement(VecCPhi, IdxC);
450 Value *EltCF32 =
B.CreateBitCast(EltC,
B.getFloatTy());
451 Value *EltA =
B.CreateExtractElement(VecA, IdxA);
452 Value *SubVecA =
B.CreateBitCast(EltA, V2I16Ty);
453 Value *EltB =
B.CreateExtractElement(VecB, IdxB);
454 Value *SubVecB =
B.CreateBitCast(EltB, V2I16Ty);
456 int ShuffleMask[4] = {2, 0, 3, 1};
457 auto ShuffleArray =
ArrayRef(ShuffleMask);
458 Value *AV2F32 =
B.CreateBitCast(
459 B.CreateShuffleVector(SubVecA, ZeroV2I16, ShuffleArray), V2F32Ty);
460 Value *BV2F32 =
B.CreateBitCast(
461 B.CreateShuffleVector(SubVecB, ZeroV2I16, ShuffleArray), V2F32Ty);
462 Value *SubVecR =
B.CreateFAddReduce(EltCF32,
B.CreateFMul(AV2F32, BV2F32));
463 Value *ResElt =
B.CreateBitCast(SubVecR,
B.getInt32Ty());
464 NewVecC =
B.CreateInsertElement(VecCPhi, ResElt, IdxC);
472 Value *NewEltC =
B.CreateExtractElement(NewVecC, IdxC);
473 Value *NewVecD =
B.CreateInsertElement(VecDPhiColLoop, NewEltC, IdxC);
477 VecCPhiColLoop->
addIncoming(NewVecC, ColLoopLatch);
479 VecDPhiColLoop->
addIncoming(NewVecD, ColLoopLatch);
484template <Intrinsic::ID IntrID>
485std::enable_if_t<IntrID == Intrinsic::x86_tdpbssd_internal ||
486 IntrID == Intrinsic::x86_tdpbsud_internal ||
487 IntrID == Intrinsic::x86_tdpbusd_internal ||
488 IntrID == Intrinsic::x86_tdpbuud_internal ||
489 IntrID == Intrinsic::x86_tdpbf16ps_internal,
491X86LowerAMXIntrinsics::lowerTileDP(Instruction *TileDP) {
497 PreBuilder.SetInsertPoint(TileDP);
501 Value *NDWord = PreBuilder.CreateLShr(
N, PreBuilder.getInt16(2));
502 Value *KDWord = PreBuilder.CreateLShr(K, PreBuilder.getInt16(2));
507 Value *ResVec = createTileDPLoops<IntrID>(Start, End, Builder, M, NDWord,
513 Builder.CreateBitCast(ResVec, Type::getX86_AMXTy(Builder.getContext()));
519 I->replaceAllUsesWith(ResVec);
520 I->eraseFromParent();
528template <
bool IsTileLoad>
529bool X86LowerAMXIntrinsics::lowerTileLoadStore(Instruction *TileLoadStore) {
530 Value *
M, *
N, *Ptr, *Stride, *Tile;
542 PreBuilder.SetInsertPoint(TileLoadStore);
543 Value *NDWord = PreBuilder.CreateLShr(
N, PreBuilder.getInt16(2));
544 Value *StrideDWord = PreBuilder.CreateLShr(Stride, PreBuilder.getInt64(2));
549 Value *ResVec = createTileLoadStoreLoops<IsTileLoad>(
550 Start, End, Builder, M, NDWord, Ptr, StrideDWord,
551 IsTileLoad ?
nullptr : Tile);
557 Builder.CreateBitCast(ResVec, Type::getX86_AMXTy(Builder.getContext()));
563 I->replaceAllUsesWith(ResVec);
564 I->eraseFromParent();
573bool X86LowerAMXIntrinsics::lowerTileZero(Instruction *TileZero) {
581 I->replaceAllUsesWith(VecZero);
582 I->eraseFromParent();
589bool X86LowerAMXIntrinsics::visit() {
595 switch (Inst->getIntrinsicID()) {
596 case Intrinsic::x86_tdpbssd_internal:
597 case Intrinsic::x86_tdpbsud_internal:
598 case Intrinsic::x86_tdpbusd_internal:
599 case Intrinsic::x86_tdpbuud_internal:
600 case Intrinsic::x86_tileloadd64_internal:
601 case Intrinsic::x86_tilestored64_internal:
602 case Intrinsic::x86_tilezero_internal:
603 case Intrinsic::x86_tdpbf16ps_internal:
613 for (
auto *Inst : WorkList) {
614 switch (Inst->getIntrinsicID()) {
615 case Intrinsic::x86_tdpbssd_internal:
616 C = lowerTileDP<Intrinsic::x86_tdpbssd_internal>(Inst) ||
C;
618 case Intrinsic::x86_tdpbsud_internal:
619 C = lowerTileDP<Intrinsic::x86_tdpbsud_internal>(Inst) ||
C;
621 case Intrinsic::x86_tdpbusd_internal:
622 C = lowerTileDP<Intrinsic::x86_tdpbusd_internal>(Inst) ||
C;
624 case Intrinsic::x86_tdpbuud_internal:
625 C = lowerTileDP<Intrinsic::x86_tdpbuud_internal>(Inst) ||
C;
627 case Intrinsic::x86_tdpbf16ps_internal:
628 C = lowerTileDP<Intrinsic::x86_tdpbf16ps_internal>(Inst) ||
C;
630 case Intrinsic::x86_tileloadd64_internal:
631 C = lowerTileLoadStore<true>(Inst) ||
C;
633 case Intrinsic::x86_tilestored64_internal:
634 C = lowerTileLoadStore<false>(Inst) ||
C;
636 case Intrinsic::x86_tilezero_internal:
637 C = lowerTileZero(Inst) ||
C;
648bool shouldRunLowerAMXIntrinsics(
const Function &
F,
const TargetMachine *TM) {
649 const X86Options &CLOpts =
650 static_cast<const X86TargetMachine *
>(TM)->getCLOpts();
651 return CLOpts.enable_x86_scalar_amx &&
652 (
F.hasFnAttribute(Attribute::OptimizeNone) ||
656bool runLowerAMXIntrinsics(
Function &
F, DominatorTree *DT, LoopInfo *LI) {
657 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
659 X86LowerAMXIntrinsics LAT(
F, DTU, LI);
666 if (!shouldRunLowerAMXIntrinsics(
F, TM))
671 bool Changed = runLowerAMXIntrinsics(
F, &DT, &LI);
682class X86LowerAMXIntrinsicsLegacyPass :
public FunctionPass {
690 if (!shouldRunLowerAMXIntrinsics(
F, TM))
693 auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
694 auto *DT = DTWP ? &DTWP->getDomTree() :
nullptr;
695 auto *LIWP = getAnalysisIfAvailable<LoopInfoWrapperPass>();
696 auto *LI = LIWP ? &LIWP->getLoopInfo() :
nullptr;
697 return runLowerAMXIntrinsics(
F, DT, LI);
699 StringRef getPassName()
const override {
return "Lower AMX intrinsics"; }
701 void getAnalysisUsage(AnalysisUsage &AU)
const override {
709static const char PassName[] =
"Lower AMX intrinsics";
710char X86LowerAMXIntrinsicsLegacyPass::ID = 0;
718 return new X86LowerAMXIntrinsicsLegacyPass();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool runOnFunction(Function &F, bool PostInlining)
This header defines various interfaces for pass management in LLVM.
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file contains the declarations for profiling metadata utility functions.
const SmallVectorImpl< MachineOperand > & Cond
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
Target-Independent Code Generator Pass Configuration Options pass.
static bool isV256I32Ty(Type *Ty)
static const char PassName[]
static const uint32_t IV[8]
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
LLVM_ABI const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
InstListType::iterator iterator
Instruction iterators...
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.
static CondBrInst * Create(Value *Cond, BasicBlock *IfTrue, BasicBlock *IfFalse, InsertPosition InsertBefore=nullptr)
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
void applyUpdatesPermissive(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
Common base class shared among various IRBuilders.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Analysis pass that exposes the LoopInfo for a function.
void addChildLoop(LoopT *NewChild)
Add the specified loop to be a child of this loop.
void addTopLevelLoop(LoopT *New)
This adds the specified loop to the collection of top-level loops.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Represents a single loop in the control flow graph.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
Primary interface to the complete machine description for the target machine.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
Target-Independent Code Generator Pass Configuration Options.
The instances of the Type class are immutable: once they are created, they are never changed.
void setSuccessor(BasicBlock *NewSucc)
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
BasicBlock * getSuccessor(unsigned i=0) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< use_iterator > uses()
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
const ParentTy * getParent() const
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ BR
Control flow instructions. These all have token chains.
@ BasicBlock
Various leaf nodes.
bool match(Val *V, const Pattern &P)
auto m_Value()
Match an arbitrary value and ignore it.
CastOperator_match< OpTy, Instruction::BitCast > m_BitCast(const OpTy &Op)
Matches BitCast.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createX86LowerAMXIntrinsicsLegacyPass()
LLVM_ABI cl::opt< bool > ProfcheckDisableMetadataFixes
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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.
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void setFittedBranchWeights(Instruction &I, ArrayRef< uint64_t > Weights, bool IsExpected, bool ElideAllZero=false)
Variant of setBranchWeights where the Weights will be fit first to uint32_t by shifting right.