24#define DEBUG_TYPE "spirv-regularizer"
56char SPIRVRegularizer::ID = 0;
69void SPIRVRegularizer::runLowerConstExpr(
Function &
F) {
71 std::list<Instruction *> WorkList;
73 WorkList.push_back(&
II);
75 auto FBegin =
F.begin();
76 while (!WorkList.empty()) {
82 auto *CE = cast<ConstantExpr>(V);
84 auto ReplInst = CE->getAsInstruction();
85 auto InsPoint =
II->getParent() == &*FBegin ?
II : &FBegin->back();
86 ReplInst->insertBefore(InsPoint);
88 std::vector<Instruction *>
Users;
90 for (
auto U : CE->users()) {
91 LLVM_DEBUG(
dbgs() <<
"[lowerConstantExpressions] Use: " << *U <<
'\n');
92 auto InstUser = dyn_cast<Instruction>(U);
94 if (InstUser && InstUser->getParent()->getParent() == &
F)
95 Users.push_back(InstUser);
98 if (ReplInst->getParent() ==
User->getParent() &&
99 User->comesBefore(ReplInst))
100 ReplInst->moveBefore(
User);
106 WorkList.pop_front();
107 auto LowerConstantVec = [&
II, &LowerOp, &WorkList,
109 unsigned NumOfOp) ->
Value * {
110 if (std::all_of(Vec->op_begin(), Vec->op_end(), [](
Value *V) {
111 return isa<ConstantExpr>(V) || isa<Function>(V);
115 std::list<Value *> OpList;
116 std::transform(Vec->op_begin(), Vec->op_end(),
117 std::back_inserter(OpList),
118 [LowerOp](
Value *V) { return LowerOp(V); });
119 Value *Repl =
nullptr;
121 auto *PhiII = dyn_cast<PHINode>(
II);
123 PhiII ? &PhiII->getIncomingBlock(NumOfOp)->back() :
II;
124 std::list<Instruction *> ReplList;
125 for (
auto V : OpList) {
126 if (
auto *Inst = dyn_cast<Instruction>(V))
127 ReplList.push_back(Inst);
132 WorkList.splice(WorkList.begin(), ReplList);
137 for (
unsigned OI = 0, OE =
II->getNumOperands(); OI != OE; ++OI) {
138 auto *
Op =
II->getOperand(OI);
139 if (
auto *Vec = dyn_cast<ConstantVector>(
Op)) {
140 Value *ReplInst = LowerConstantVec(Vec, OI);
142 II->replaceUsesOfWith(
Op, ReplInst);
143 }
else if (
auto CE = dyn_cast<ConstantExpr>(
Op)) {
144 WorkList.push_front(cast<Instruction>(LowerOp(CE)));
145 }
else if (
auto MDAsVal = dyn_cast<MetadataAsValue>(
Op)) {
146 auto ConstMD = dyn_cast<ConstantAsMetadata>(MDAsVal->getMetadata());
150 Value *ReplInst =
nullptr;
151 if (
auto *Vec = dyn_cast<ConstantVector>(
C))
152 ReplInst = LowerConstantVec(Vec, OI);
153 if (
auto *CE = dyn_cast<ConstantExpr>(
C))
154 ReplInst = LowerOp(CE);
159 II->setOperand(OI, RepMDVal);
160 WorkList.push_front(cast<Instruction>(ReplInst));
168void SPIRVRegularizer::visitCallInst(
CallInst &CI) {
173 auto MangledName =
F->getName();
180 if (DemangledName.starts_with(
"fmin") || DemangledName.starts_with(
"fmax") ||
181 DemangledName.starts_with(
"min") || DemangledName.starts_with(
"max"))
182 visitCallScalToVec(&CI, MangledName, DemangledName);
191 auto IsArg0Vector = isa<VectorType>(Arg0Ty);
192 for (
unsigned I = 1, E = CI->
arg_size(); Uniform && (
I != E); ++
I)
199 if (!Old2NewFuncs.count(OldF)) {
203 FunctionType::get(OldF->getReturnType(), ArgTypes, OldF->isVarArg());
208 for (
auto &Arg : OldF->args()) {
210 NewFArgIt->setName(ArgName);
211 VMap[&Arg] = &(*NewFArgIt++);
215 CloneFunctionChangeType::LocalChangesOnly, Returns);
217 Old2NewFuncs[OldF] = NewF;
219 NewF = Old2NewFuncs[OldF];
239 ElementCount VecElemCount = cast<VectorType>(Arg0Ty)->getElementCount();
247bool SPIRVRegularizer::runOnFunction(
Function &
F) {
248 runLowerConstExpr(
F);
250 for (
auto &OldNew : Old2NewFuncs) {
260 return new SPIRVRegularizer();
Expand Atomic instructions
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
iv Induction Variable Users
uint64_t IntrinsicInst * II
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represent the analysis usage information of a pass.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
void mutateFunctionType(FunctionType *FTy)
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
Constant Vector Declarations.
static Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
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.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
FunctionType * getFunctionType() const
Returns the FunctionType for me.
AttributeList getAttributes() const
Return the attribute list for this Function.
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
static InsertElementInst * Create(Value *Vec, Value *NewElt, Value *Idx, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Base class for instruction visitors.
RetTy visitCallInst(CallInst &I)
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
This is an important class for using LLVM in a threaded context.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
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...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
In order to facilitate speculative execution, many instructions do not invoke immediate undefined beh...
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
This instruction constructs a fixed permutation of two input vectors.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
static IntegerType * getInt32Ty(LLVMContext &C)
bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVMContext & getContext() const
All values hold a context through their type.
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
char * itaniumDemangle(std::string_view mangled_name, bool ParseParams=true)
Returns a non-NULL pointer to a NUL-terminated C style string that should be explicitly freed,...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void initializeSPIRVRegularizerPass(PassRegistry &)
FunctionPass * createSPIRVRegularizerPass()
void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, CloneFunctionChangeType Changes, SmallVectorImpl< ReturnInst * > &Returns, const char *NameSuffix="", ClonedCodeInfo *CodeInfo=nullptr, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)
Clone OldFunc into NewFunc, transforming the old arguments into references to VMap values.