51#define DEBUG_TYPE "scalarizer"
55 cl::desc(
"Allow the scalarizer pass to scalarize "
56 "insertelement/extractelement with variable index"));
63 cl::desc(
"Allow the scalarizer pass to scalarize loads and store"));
69 if (isa<PHINode>(Itr))
85using ScatterMap = std::map<std::pair<Value *, Type *>, ValueVector>;
95 Scatterer() =
default;
101 ValueVector *cachePtr =
nullptr);
104 Value *operator[](
unsigned I);
107 unsigned size()
const {
return Size; }
114 ValueVector *CachePtr;
122 FCmpSplitter(
FCmpInst &fci) : FCI(fci) {}
126 return Builder.CreateFCmp(FCI.getPredicate(), Op0, Op1,
Name);
135 ICmpSplitter(
ICmpInst &ici) : ICI(ici) {}
139 return Builder.CreateICmp(ICI.getPredicate(), Op0, Op1,
Name);
147struct UnarySplitter {
151 return Builder.CreateUnOp(UO.getOpcode(), Op,
Name);
159struct BinarySplitter {
164 return Builder.CreateBinOp(BO.getOpcode(), Op0, Op1,
Name);
175 Align getElemAlign(
unsigned I) {
183 Type *ElemTy =
nullptr;
193T getWithDefaultOverride(
const cl::opt<T> &ClOption,
194 const std::optional<T> &DefaultOverride) {
196 : DefaultOverride.value_or(ClOption);
199class ScalarizerVisitor :
public InstVisitor<ScalarizerVisitor, bool> {
201 ScalarizerVisitor(
unsigned ParallelLoopAccessMDKind,
DominatorTree *DT,
203 : ParallelLoopAccessMDKind(ParallelLoopAccessMDKind), DT(DT),
204 ScalarizeVariableInsertExtract(
206 Options.ScalarizeVariableInsertExtract)),
234 void gather(
Instruction *Op,
const ValueVector &CV);
236 bool canTransferMetadata(
unsigned Kind);
237 void transferMetadataAndIRFlags(
Instruction *Op,
const ValueVector &CV);
238 std::optional<VectorLayout> getVectorLayout(
Type *Ty,
Align Alignment,
242 template<
typename T>
bool splitUnary(
Instruction &,
const T &);
243 template<
typename T>
bool splitBinary(
Instruction &,
const T &);
247 ScatterMap Scattered;
253 unsigned ParallelLoopAccessMDKind;
257 const bool ScalarizeVariableInsertExtract;
258 const bool ScalarizeLoadStore;
279char ScalarizerLegacyPass::ID = 0;
281 "Scalarize vector operations",
false,
false)
287 Type *PtrElemTy, ValueVector *cachePtr)
288 : BB(bb), BBI(bbi), V(v), PtrElemTy(PtrElemTy), CachePtr(cachePtr) {
289 Type *Ty = V->getType();
291 assert(cast<PointerType>(Ty)->isOpaqueOrPointeeTypeMatches(PtrElemTy) &&
292 "Pointer element type mismatch");
295 Size = cast<FixedVectorType>(Ty)->getNumElements();
297 Tmp.resize(
Size,
nullptr);
298 else if (CachePtr->empty())
299 CachePtr->resize(
Size,
nullptr);
301 assert(
Size == CachePtr->size() &&
"Inconsistent vector sizes");
305Value *Scatterer::operator[](
unsigned I) {
306 ValueVector &CV = (CachePtr ? *CachePtr : Tmp);
312 Type *VectorElemTy = cast<VectorType>(PtrElemTy)->getElementType();
314 Type *NewPtrTy = PointerType::get(
315 VectorElemTy,
V->getType()->getPointerAddressSpace());
316 CV[0] =
Builder.CreateBitCast(V, NewPtrTy,
V->getName() +
".i0");
319 CV[
I] =
Builder.CreateConstGEP1_32(VectorElemTy, CV[0],
I,
320 V->getName() +
".i" +
Twine(
I));
332 unsigned J =
Idx->getZExtValue();
335 CV[J] =
Insert->getOperand(1);
341 CV[J] =
Insert->getOperand(1);
345 V->getName() +
".i" +
Twine(
I));
350bool ScalarizerLegacyPass::runOnFunction(
Function &
F) {
355 unsigned ParallelLoopAccessMDKind =
356 M.getContext().getMDKindID(
"llvm.mem.parallel_loop_access");
357 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
359 return Impl.visit(
F);
363 return new ScalarizerLegacyPass();
366bool ScalarizerVisitor::visit(
Function &
F) {
367 assert(Gathered.empty() && Scattered.empty());
379 if (
Done &&
I->getType()->isVoidTy())
380 I->eraseFromParent();
390 if (
Argument *VArg = dyn_cast<Argument>(V)) {
395 return Scatterer(BB, BB->
begin(), V, PtrElemTy, &Scattered[{V, PtrElemTy}]);
412 PtrElemTy, &Scattered[{
V, PtrElemTy}]);
423void ScalarizerVisitor::gather(
Instruction *Op,
const ValueVector &CV) {
424 transferMetadataAndIRFlags(Op, CV);
428 ValueVector &SV = Scattered[{
Op,
nullptr}];
430 for (
unsigned I = 0,
E = SV.size();
I !=
E; ++
I) {
432 if (V ==
nullptr || SV[
I] == CV[
I])
436 if (isa<Instruction>(CV[
I]))
437 CV[
I]->takeName(Old);
439 PotentiallyDeadInstrs.emplace_back(Old);
443 Gathered.push_back(GatherList::value_type(Op, &SV));
449 Op->replaceAllUsesWith(CV);
450 PotentiallyDeadInstrs.emplace_back(Op);
457bool ScalarizerVisitor::canTransferMetadata(
unsigned Tag) {
458 return (
Tag == LLVMContext::MD_tbaa
459 ||
Tag == LLVMContext::MD_fpmath
460 ||
Tag == LLVMContext::MD_tbaa_struct
461 ||
Tag == LLVMContext::MD_invariant_load
462 ||
Tag == LLVMContext::MD_alias_scope
463 ||
Tag == LLVMContext::MD_noalias
464 ||
Tag == ParallelLoopAccessMDKind
465 ||
Tag == LLVMContext::MD_access_group);
470void ScalarizerVisitor::transferMetadataAndIRFlags(
Instruction *Op,
471 const ValueVector &CV) {
473 Op->getAllMetadataOtherThanDebugLoc(MDs);
474 for (
unsigned I = 0,
E = CV.size();
I !=
E; ++
I) {
476 for (
const auto &MD : MDs)
477 if (canTransferMetadata(MD.first))
478 New->setMetadata(MD.first, MD.second);
479 New->copyIRFlags(Op);
480 if (
Op->getDebugLoc() && !
New->getDebugLoc())
481 New->setDebugLoc(
Op->getDebugLoc());
489std::optional<VectorLayout>
490ScalarizerVisitor::getVectorLayout(
Type *Ty,
Align Alignment,
494 Layout.VecTy = dyn_cast<FixedVectorType>(Ty);
498 Layout.ElemTy = Layout.VecTy->getElementType();
499 if (!
DL.typeSizeEqualsStoreSize(Layout.ElemTy))
501 Layout.VecAlign = Alignment;
502 Layout.ElemSize =
DL.getTypeStoreSize(Layout.ElemTy);
508template<
typename Splitter>
509bool ScalarizerVisitor::splitUnary(
Instruction &
I,
const Splitter &Split) {
510 auto *VT = dyn_cast<FixedVectorType>(
I.getType());
514 unsigned NumElems = VT->getNumElements();
516 Scatterer
Op = scatter(&
I,
I.getOperand(0));
517 assert(
Op.size() == NumElems &&
"Mismatched unary operation");
519 Res.resize(NumElems);
520 for (
unsigned Elem = 0; Elem < NumElems; ++Elem)
521 Res[Elem] =
Split(Builder, Op[Elem],
I.getName() +
".i" +
Twine(Elem));
528template<
typename Splitter>
529bool ScalarizerVisitor::splitBinary(
Instruction &
I,
const Splitter &Split) {
530 auto *VT = dyn_cast<FixedVectorType>(
I.getType());
534 unsigned NumElems = VT->getNumElements();
536 Scatterer VOp0 = scatter(&
I,
I.getOperand(0));
537 Scatterer VOp1 = scatter(&
I,
I.getOperand(1));
538 assert(VOp0.size() == NumElems &&
"Mismatched binary operation");
539 assert(VOp1.size() == NumElems &&
"Mismatched binary operation");
541 Res.resize(NumElems);
542 for (
unsigned Elem = 0; Elem < NumElems; ++Elem) {
543 Value *Op0 = VOp0[Elem];
544 Value *Op1 = VOp1[Elem];
545 Res[Elem] =
Split(Builder, Op0, Op1,
I.getName() +
".i" +
Twine(Elem));
564bool ScalarizerVisitor::splitCall(
CallInst &CI) {
565 auto *VT = dyn_cast<FixedVectorType>(CI.
getType());
577 unsigned NumElems = VT->getNumElements();
580 ValueVector ScalarOperands(NumArgs);
583 Scattered.resize(NumArgs);
590 for (
unsigned I = 0;
I != NumArgs; ++
I) {
593 Scattered[
I] = scatter(&CI, OpI);
594 assert(Scattered[
I].
size() == NumElems &&
"mismatched call operands");
598 ScalarOperands[
I] = OpI;
604 ValueVector Res(NumElems);
605 ValueVector ScalarCallOps(NumArgs);
611 for (
unsigned Elem = 0; Elem < NumElems; ++Elem) {
612 ScalarCallOps.clear();
614 for (
unsigned J = 0; J != NumArgs; ++J) {
616 ScalarCallOps.push_back(ScalarOperands[J]);
618 ScalarCallOps.push_back(Scattered[J][Elem]);
621 Res[Elem] =
Builder.CreateCall(NewIntrin, ScalarCallOps,
629bool ScalarizerVisitor::visitSelectInst(
SelectInst &SI) {
630 auto *VT = dyn_cast<FixedVectorType>(
SI.getType());
634 unsigned NumElems = VT->getNumElements();
636 Scatterer VOp1 = scatter(&SI,
SI.getOperand(1));
637 Scatterer VOp2 = scatter(&SI,
SI.getOperand(2));
638 assert(VOp1.size() == NumElems &&
"Mismatched select");
639 assert(VOp2.size() == NumElems &&
"Mismatched select");
641 Res.resize(NumElems);
643 if (
SI.getOperand(0)->getType()->isVectorTy()) {
644 Scatterer VOp0 = scatter(&SI,
SI.getOperand(0));
645 assert(VOp0.size() == NumElems &&
"Mismatched select");
646 for (
unsigned I = 0;
I < NumElems; ++
I) {
650 Res[
I] =
Builder.CreateSelect(Op0, Op1, Op2,
655 for (
unsigned I = 0;
I < NumElems; ++
I) {
658 Res[
I] =
Builder.CreateSelect(Op0, Op1, Op2,
666bool ScalarizerVisitor::visitICmpInst(
ICmpInst &ICI) {
667 return splitBinary(ICI, ICmpSplitter(ICI));
670bool ScalarizerVisitor::visitFCmpInst(
FCmpInst &FCI) {
671 return splitBinary(FCI, FCmpSplitter(FCI));
674bool ScalarizerVisitor::visitUnaryOperator(
UnaryOperator &UO) {
675 return splitUnary(UO, UnarySplitter(UO));
679 return splitBinary(BO, BinarySplitter(BO));
683 auto *VT = dyn_cast<FixedVectorType>(GEPI.
getType());
688 unsigned NumElems = VT->getNumElements();
695 Op0 =
Builder.CreateVectorSplat(NumElems, Op0);
696 Scatterer
Base = scatter(&GEPI, Op0);
700 for (
unsigned I = 0;
I < NumIndices; ++
I) {
705 if (!
Op->getType()->isVectorTy())
706 Op =
Builder.CreateVectorSplat(NumElems, Op);
708 Ops[
I] = scatter(&GEPI, Op);
712 Res.resize(NumElems);
713 for (
unsigned I = 0;
I < NumElems; ++
I) {
715 Indices.
resize(NumIndices);
716 for (
unsigned J = 0; J < NumIndices; ++J)
717 Indices[J] = Ops[J][
I];
722 NewGEPI->setIsInBounds();
728bool ScalarizerVisitor::visitCastInst(
CastInst &CI) {
729 auto *VT = dyn_cast<FixedVectorType>(CI.
getDestTy());
733 unsigned NumElems = VT->getNumElements();
735 Scatterer Op0 = scatter(&CI, CI.
getOperand(0));
736 assert(Op0.size() == NumElems &&
"Mismatched cast");
738 Res.resize(NumElems);
739 for (
unsigned I = 0;
I < NumElems; ++
I)
746bool ScalarizerVisitor::visitBitCastInst(
BitCastInst &BCI) {
747 auto *DstVT = dyn_cast<FixedVectorType>(BCI.
getDestTy());
748 auto *SrcVT = dyn_cast<FixedVectorType>(BCI.
getSrcTy());
749 if (!DstVT || !SrcVT)
752 unsigned DstNumElems = DstVT->getNumElements();
753 unsigned SrcNumElems = SrcVT->getNumElements();
755 Scatterer Op0 = scatter(&BCI, BCI.
getOperand(0));
757 Res.resize(DstNumElems);
759 if (DstNumElems == SrcNumElems) {
760 for (
unsigned I = 0;
I < DstNumElems; ++
I)
761 Res[
I] =
Builder.CreateBitCast(Op0[
I], DstVT->getElementType(),
763 }
else if (DstNumElems > SrcNumElems) {
766 unsigned FanOut = DstNumElems / SrcNumElems;
769 for (
unsigned Op0I = 0; Op0I < SrcNumElems; ++Op0I) {
774 while ((VI = dyn_cast<Instruction>(V)) &&
775 VI->getOpcode() == Instruction::BitCast)
776 V =
VI->getOperand(0);
777 V =
Builder.CreateBitCast(V, MidTy,
V->getName() +
".cast");
778 Scatterer Mid = scatter(&BCI, V);
779 for (
unsigned MidI = 0; MidI < FanOut; ++MidI)
780 Res[ResI++] = Mid[MidI];
784 unsigned FanIn = SrcNumElems / DstNumElems;
787 for (
unsigned ResI = 0; ResI < DstNumElems; ++ResI) {
789 for (
unsigned MidI = 0; MidI < FanIn; ++MidI)
790 V =
Builder.CreateInsertElement(V, Op0[Op0I++],
Builder.getInt32(MidI),
792 +
".upto" +
Twine(MidI));
793 Res[ResI] =
Builder.CreateBitCast(V, DstVT->getElementType(),
802 auto *VT = dyn_cast<FixedVectorType>(IEI.
getType());
806 unsigned NumElems = VT->getNumElements();
808 Scatterer Op0 = scatter(&IEI, IEI.
getOperand(0));
813 Res.resize(NumElems);
815 if (
auto *CI = dyn_cast<ConstantInt>(InsIdx)) {
816 for (
unsigned I = 0;
I < NumElems; ++
I)
817 Res[
I] = CI->getValue().getZExtValue() ==
I ? NewElt : Op0[
I];
819 if (!ScalarizeVariableInsertExtract)
822 for (
unsigned I = 0;
I < NumElems; ++
I) {
823 Value *ShouldReplace =
827 Res[
I] =
Builder.CreateSelect(ShouldReplace, NewElt, OldElt,
841 unsigned NumSrcElems = VT->getNumElements();
843 Scatterer Op0 = scatter(&EEI, EEI.
getOperand(0));
846 if (
auto *CI = dyn_cast<ConstantInt>(ExtIdx)) {
847 Value *Res = Op0[CI->getValue().getZExtValue()];
848 replaceUses(&EEI, Res);
852 if (!ScalarizeVariableInsertExtract)
856 for (
unsigned I = 0;
I < NumSrcElems; ++
I) {
857 Value *ShouldExtract =
861 Res =
Builder.CreateSelect(ShouldExtract, Elt, Res,
864 replaceUses(&EEI, Res);
869 auto *VT = dyn_cast<FixedVectorType>(SVI.
getType());
873 unsigned NumElems = VT->getNumElements();
874 Scatterer Op0 = scatter(&SVI, SVI.
getOperand(0));
875 Scatterer Op1 = scatter(&SVI, SVI.
getOperand(1));
877 Res.resize(NumElems);
879 for (
unsigned I = 0;
I < NumElems; ++
I) {
883 else if (
unsigned(Selector) < Op0.size())
884 Res[
I] = Op0[Selector];
886 Res[
I] = Op1[Selector - Op0.size()];
892bool ScalarizerVisitor::visitPHINode(
PHINode &
PHI) {
893 auto *VT = dyn_cast<FixedVectorType>(
PHI.getType());
897 unsigned NumElems = cast<FixedVectorType>(VT)->getNumElements();
900 Res.resize(NumElems);
902 unsigned NumOps =
PHI.getNumOperands();
903 for (
unsigned I = 0;
I < NumElems; ++
I)
904 Res[
I] =
Builder.CreatePHI(VT->getElementType(), NumOps,
907 for (
unsigned I = 0;
I < NumOps; ++
I) {
908 Scatterer
Op = scatter(&
PHI,
PHI.getIncomingValue(
I));
910 for (
unsigned J = 0; J < NumElems; ++J)
911 cast<PHINode>(Res[J])->addIncoming(Op[J], IncomingBlock);
917bool ScalarizerVisitor::visitLoadInst(
LoadInst &LI) {
918 if (!ScalarizeLoadStore)
923 std::optional<VectorLayout> Layout = getVectorLayout(
928 unsigned NumElems = cast<FixedVectorType>(Layout->VecTy)->getNumElements();
932 Res.resize(NumElems);
934 for (
unsigned I = 0;
I < NumElems; ++
I)
935 Res[
I] =
Builder.CreateAlignedLoad(Layout->VecTy->getElementType(),
Ptr[
I],
936 Align(Layout->getElemAlign(
I)),
942bool ScalarizerVisitor::visitStoreInst(
StoreInst &SI) {
943 if (!ScalarizeLoadStore)
948 Value *FullValue =
SI.getValueOperand();
949 std::optional<VectorLayout> Layout = getVectorLayout(
950 FullValue->
getType(),
SI.getAlign(),
SI.getModule()->getDataLayout());
954 unsigned NumElems = cast<FixedVectorType>(Layout->VecTy)->getNumElements();
956 Scatterer VPtr = scatter(&SI,
SI.getPointerOperand(), FullValue->
getType());
957 Scatterer VVal = scatter(&SI, FullValue);
960 Stores.resize(NumElems);
961 for (
unsigned I = 0;
I < NumElems; ++
I) {
964 Stores[
I] =
Builder.CreateAlignedStore(Val,
Ptr, Layout->getElemAlign(
I));
966 transferMetadataAndIRFlags(&SI, Stores);
970bool ScalarizerVisitor::visitCallInst(
CallInst &CI) {
971 return splitCall(CI);
976bool ScalarizerVisitor::finish() {
979 if (Gathered.empty() && Scattered.empty() && !Scalarized)
981 for (
const auto &GMI : Gathered) {
983 ValueVector &CV = *GMI.second;
984 if (!
Op->use_empty()) {
988 if (
auto *Ty = dyn_cast<FixedVectorType>(
Op->getType())) {
990 unsigned Count = Ty->getNumElements();
992 if (isa<PHINode>(Op))
994 for (
unsigned I = 0;
I < Count; ++
I)
996 Op->getName() +
".upto" +
Twine(
I));
999 assert(CV.size() == 1 &&
Op->getType() == CV[0]->getType());
1004 Op->replaceAllUsesWith(Res);
1006 PotentiallyDeadInstrs.emplace_back(Op);
1019 unsigned ParallelLoopAccessMDKind =
1020 M.getContext().getMDKindID(
"llvm.mem.parallel_loop_access");
1022 ScalarizerVisitor Impl(ParallelLoopAccessMDKind, DT, Options);
1023 bool Changed = Impl.visit(
F);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
Module.h This file contains the declarations for the Module class.
#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 builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isTriviallyScalariable(Intrinsic::ID ID)
Scalarize vector operations
static cl::opt< bool > ClScalarizeVariableInsertExtract("scalarize-variable-insert-extract", cl::init(true), cl::Hidden, cl::desc("Allow the scalarizer pass to scalarize " "insertelement/extractelement with variable index"))
static Function * getScalarIntrinsicDeclaration(Module *M, Intrinsic::ID ID, ArrayRef< Type * > Tys)
static cl::opt< bool > ClScalarizeLoadStore("scalarize-load-store", cl::init(false), cl::Hidden, cl::desc("Allow the scalarizer pass to scalarize loads and store"))
This pass converts vector operations into scalar operations, in order to expose optimization opportun...
This file defines the SmallVector class.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
This class represents a no-op cast from one type to another.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
This is the base class for all instructions that perform data casts.
Type * getSrcTy() const
Return the source type, as a convenience.
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
Type * getDestTy() const
Return the destination type, as a convenience.
This is the shared class of boolean and integer constants.
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
This instruction compares its operands according to the predicate given to the constructor.
Class to represent fixed width SIMD vectors.
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
bool isInBounds() const
Determine whether the GEP has the inbounds flag.
Type * getSourceElementType() const
unsigned getNumIndices() const
This instruction compares its operands according to the predicate given to the constructor.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This instruction inserts a single (scalar) element into a VectorType value.
VectorType * getType() const
Overload to return most specific vector type.
Base class for instruction visitors.
RetTy visitFCmpInst(FCmpInst &I)
RetTy visitExtractElementInst(ExtractElementInst &I)
RetTy visitShuffleVectorInst(ShuffleVectorInst &I)
RetTy visitBitCastInst(BitCastInst &I)
void visit(Iterator Start, Iterator End)
RetTy visitPHINode(PHINode &I)
RetTy visitUnaryOperator(UnaryOperator &I)
RetTy visitStoreInst(StoreInst &I)
RetTy visitInsertElementInst(InsertElementInst &I)
RetTy visitBinaryOperator(BinaryOperator &I)
RetTy visitICmpInst(ICmpInst &I)
RetTy visitCallInst(CallInst &I)
RetTy visitCastInst(CastInst &I)
RetTy visitSelectInst(SelectInst &I)
RetTy visitGetElementPtrInst(GetElementPtrInst &I)
void visitInstruction(Instruction &I)
RetTy visitLoadInst(LoadInst &I)
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
const BasicBlock * getParent() const
An instruction for reading from memory.
Value * getPointerOperand()
Align getAlign() const
Return the alignment of the access that is being performed.
A Module instance is used to store all the information related to an LLVM module.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserve()
Mark an analysis as preserved.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
This class represents the LLVM 'select' instruction.
This instruction constructs a fixed permutation of two input vectors.
int getMaskValue(unsigned Elt) const
Return the shuffle mask value of this instruction for the given element index.
VectorType * getType() const
Overload to return most specific vector 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.
An instruction for storing to memory.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
int getNumOccurrences() const
self_iterator getIterator()
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID, unsigned OpdIdx)
Identifies if the vector form of the intrinsic has a operand that has an overloaded type.
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.
BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It)
Advance It while it points to a debug instruction and return the result.
FunctionPass * createScalarizerPass()
Create a legacy pass manager instance of the Scalarizer pass.
bool RecursivelyDeleteTriviallyDeadInstructionsPermissive(SmallVectorImpl< WeakTrackingVH > &DeadInsts, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
Same functionality as RecursivelyDeleteTriviallyDeadInstructions, but allow instructions that are not...
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
bool isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID, unsigned ScalarOpdIdx)
Identifies if the vector form of the intrinsic has a scalar operand.
bool isTriviallyVectorizable(Intrinsic::ID ID)
Identify if the intrinsic is trivially vectorizable.
void initializeScalarizerLegacyPassPass(PassRegistry &)
This struct is a compact representation of a valid (non-zero power of two) alignment.