LLVM 22.0.0git
SPIRVRegularizer.cpp
Go to the documentation of this file.
1//===-- SPIRVRegularizer.cpp - regularize IR for SPIR-V ---------*- C++ -*-===//
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 regularization of LLVM IR for SPIR-V. The prototype of
10// the pass was taken from SPIRV-LLVM translator.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPIRV.h"
15#include "llvm/IR/Constants.h"
18#include "llvm/IR/PassManager.h"
19
20#include <list>
21
22#define DEBUG_TYPE "spirv-regularizer"
23
24using namespace llvm;
25
26namespace {
27struct SPIRVRegularizer : public FunctionPass {
28public:
29 static char ID;
30 SPIRVRegularizer() : FunctionPass(ID) {}
31 bool runOnFunction(Function &F) override;
32 StringRef getPassName() const override { return "SPIR-V Regularizer"; }
33
34 void getAnalysisUsage(AnalysisUsage &AU) const override {
36 }
37
38private:
39 void runLowerConstExpr(Function &F);
40};
41} // namespace
42
43char SPIRVRegularizer::ID = 0;
44
45INITIALIZE_PASS(SPIRVRegularizer, DEBUG_TYPE, "SPIR-V Regularizer", false,
46 false)
47
48// Since SPIR-V cannot represent constant expression, constant expressions
49// in LLVM IR need to be lowered to instructions. For each function,
50// the constant expressions used by instructions of the function are replaced
51// by instructions placed in the entry block since it dominates all other BBs.
52// Each constant expression only needs to be lowered once in each function
53// and all uses of it by instructions in that function are replaced by
54// one instruction.
55// TODO: remove redundant instructions for common subexpression.
56void SPIRVRegularizer::runLowerConstExpr(Function &F) {
57 LLVMContext &Ctx = F.getContext();
58 std::list<Instruction *> WorkList;
59 for (auto &II : instructions(F))
60 WorkList.push_back(&II);
61
62 auto FBegin = F.begin();
63 while (!WorkList.empty()) {
64 Instruction *II = WorkList.front();
65
66 auto LowerOp = [&II, &FBegin, &F](Value *V) -> Value * {
67 if (isa<Function>(V))
68 return V;
69 auto *CE = cast<ConstantExpr>(V);
70 LLVM_DEBUG(dbgs() << "[lowerConstantExpressions] " << *CE);
71 auto ReplInst = CE->getAsInstruction();
72 auto InsPoint = II->getParent() == &*FBegin ? II : &FBegin->back();
73 ReplInst->insertBefore(InsPoint->getIterator());
74 LLVM_DEBUG(dbgs() << " -> " << *ReplInst << '\n');
75 std::vector<Instruction *> Users;
76 // Do not replace use during iteration of use. Do it in another loop.
77 for (auto U : CE->users()) {
78 LLVM_DEBUG(dbgs() << "[lowerConstantExpressions] Use: " << *U << '\n');
79 auto InstUser = dyn_cast<Instruction>(U);
80 // Only replace users in scope of current function.
81 if (InstUser && InstUser->getParent()->getParent() == &F)
82 Users.push_back(InstUser);
83 }
84 for (auto &User : Users) {
85 if (ReplInst->getParent() == User->getParent() &&
86 User->comesBefore(ReplInst))
87 ReplInst->moveBefore(User->getIterator());
88 User->replaceUsesOfWith(CE, ReplInst);
89 }
90 return ReplInst;
91 };
92
93 WorkList.pop_front();
94 auto LowerConstantVec = [&II, &LowerOp, &WorkList,
95 &Ctx](ConstantVector *Vec,
96 unsigned NumOfOp) -> Value * {
97 if (std::all_of(Vec->op_begin(), Vec->op_end(), [](Value *V) {
98 return isa<ConstantExpr>(V) || isa<Function>(V);
99 })) {
100 // Expand a vector of constexprs and construct it back with
101 // series of insertelement instructions.
102 std::list<Value *> OpList;
103 std::transform(Vec->op_begin(), Vec->op_end(),
104 std::back_inserter(OpList),
105 [LowerOp](Value *V) { return LowerOp(V); });
106 Value *Repl = nullptr;
107 unsigned Idx = 0;
108 auto *PhiII = dyn_cast<PHINode>(II);
109 Instruction *InsPoint =
110 PhiII ? &PhiII->getIncomingBlock(NumOfOp)->back() : II;
111 std::list<Instruction *> ReplList;
112 for (auto V : OpList) {
113 if (auto *Inst = dyn_cast<Instruction>(V))
114 ReplList.push_back(Inst);
116 (Repl ? Repl : PoisonValue::get(Vec->getType())), V,
117 ConstantInt::get(Type::getInt32Ty(Ctx), Idx++), "",
118 InsPoint->getIterator());
119 }
120 WorkList.splice(WorkList.begin(), ReplList);
121 return Repl;
122 }
123 return nullptr;
124 };
125 for (unsigned OI = 0, OE = II->getNumOperands(); OI != OE; ++OI) {
126 auto *Op = II->getOperand(OI);
127 if (auto *Vec = dyn_cast<ConstantVector>(Op)) {
128 Value *ReplInst = LowerConstantVec(Vec, OI);
129 if (ReplInst)
130 II->replaceUsesOfWith(Op, ReplInst);
131 } else if (auto CE = dyn_cast<ConstantExpr>(Op)) {
132 WorkList.push_front(cast<Instruction>(LowerOp(CE)));
133 } else if (auto MDAsVal = dyn_cast<MetadataAsValue>(Op)) {
134 auto ConstMD = dyn_cast<ConstantAsMetadata>(MDAsVal->getMetadata());
135 if (!ConstMD)
136 continue;
137 Constant *C = ConstMD->getValue();
138 Value *ReplInst = nullptr;
139 if (auto *Vec = dyn_cast<ConstantVector>(C))
140 ReplInst = LowerConstantVec(Vec, OI);
141 if (auto *CE = dyn_cast<ConstantExpr>(C))
142 ReplInst = LowerOp(CE);
143 if (!ReplInst)
144 continue;
145 Metadata *RepMD = ValueAsMetadata::get(ReplInst);
146 Value *RepMDVal = MetadataAsValue::get(Ctx, RepMD);
147 II->setOperand(OI, RepMDVal);
148 WorkList.push_front(cast<Instruction>(ReplInst));
149 }
150 }
151 }
152}
153
154bool SPIRVRegularizer::runOnFunction(Function &F) {
155 runLowerConstExpr(F);
156 return true;
157}
158
160 return new SPIRVRegularizer();
161}
Expand Atomic instructions
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runOnFunction(Function &F, bool PostInlining)
#define DEBUG_TYPE
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
Represent the analysis usage information of a pass.
Constant Vector Declarations.
Definition Constants.h:522
FixedVectorType * getType() const
Specialize the getType() method to always return a FixedVectorType, which reduces the amount of casti...
Definition Constants.h:545
This is an important base class in LLVM.
Definition Constant.h:43
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
static InsertElementInst * Create(Value *Vec, Value *NewElt, Value *Idx, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:104
Root of the metadata hierarchy.
Definition Metadata.h:64
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition Pass.cpp:112
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:296
op_iterator op_begin()
Definition User.h:284
op_iterator op_end()
Definition User.h:286
static LLVM_ABI ValueAsMetadata * get(Value *V)
Definition Metadata.cpp:503
LLVM Value Representation.
Definition Value.h:75
self_iterator getIterator()
Definition ilist_node.h:123
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
FunctionPass * createSPIRVRegularizerPass()
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559