70 #define DEBUG_TYPE "wasm-fix-irreducible-control-flow" 77 : MF(MF), MLI(MLI), Loop(Loop) {}
95 using BlockPair = std::pair<MachineBasicBlock *, MachineBasicBlock *>;
103 if (InnerLoop == Loop) {
107 if (!LoopBlocks.
count(MBB)) {
135 Succ = canonicalizeSuccessor(Succ);
138 if (Reachable[MBB].insert(Succ).
second) {
144 if (canonicalizeSuccessor(MBB)) {
151 bool LoopFixer::run() {
157 LoopBlocks.insert(MBB);
160 for (
auto &MBB : MF) {
161 LoopBlocks.insert(&MBB);
168 for (
auto *MBB : LoopBlocks) {
171 if (InnerLoop ==
Loop) {
172 for (
auto *Succ : MBB->successors()) {
173 maybeInsert(MBB, Succ);
186 for (
auto *Succ : ExitBlocks) {
187 maybeInsert(MBB, Succ);
193 while (!WorkList.empty()) {
196 std::tie(MBB, Succ) = WorkList.pop_back_val();
202 assert(MBB == canonicalizeSuccessor(MBB));
213 if (Pred && Pred != MBB) {
214 maybeInsert(Pred, Succ);
221 for (
auto MBB : LoopBlocks) {
222 if (Reachable[MBB].
count(MBB)) {
233 for (
auto *Looper : Loopers) {
234 for (
auto *Pred : Looper->predecessors()) {
236 if (Pred && !Loopers.count(Pred)) {
237 Entries.insert(Looper);
257 for (
auto Block : SortedEntries)
258 assert(Block->getNumber() != -1);
259 if (SortedEntries.size() > 1) {
260 for (
auto I = SortedEntries.begin(),
E = SortedEntries.end() - 1;
262 auto ANum = (*I)->getNumber();
263 auto BNum = (*(std::next(
I)))->getNumber();
271 MF.
insert(MF.end(), Dispatch);
272 MLI.changeLoopFor(Dispatch,
Loop);
277 TII.get(WebAssembly::BR_TABLE_I32));
282 unsigned Reg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
288 for (
auto *MBB : SortedEntries) {
289 auto Pair = Indices.
insert(std::make_pair(MBB, 0));
295 Pair.first->second =
Index;
306 for (
auto *MBB : SortedEntries) {
307 for (
auto *Pred : MBB->predecessors()) {
308 if (Pred != Dispatch) {
316 for (
auto *Succ : MBB->successors()) {
317 if (!Entries.count(Succ)) {
326 MLI.changeLoopFor(Split,
Loop);
332 .addImm(Indices[Succ]);
340 for (
auto &
Op : Term.explicit_uses())
341 if (
Op.isMBB() && Indices.
count(
Op.getMBB()))
342 Op.setMBB(Map[
Op.getMBB()]);
343 for (
auto Rewrite : Map)
344 MBB->replaceSuccessor(Rewrite.first, Rewrite.second);
357 return "WebAssembly Fix Irreducible Control Flow";
373 if (LoopFixer(MF, MLI,
nullptr).run()) {
379 while (!Worklist.empty()) {
381 Worklist.append(Loop->
begin(), Loop->
end());
382 if (LoopFixer(MF, MLI, Loop).run()) {
398 "Removes irreducible control flow",
false,
false)
401 return new WebAssemblyFixIrreducibleControlFlow();
404 bool WebAssemblyFixIrreducibleControlFlow::runOnMachineFunction(
406 LLVM_DEBUG(
dbgs() <<
"********** Fixing Irreducible Control Flow **********\n" 407 "********** Function: " 410 bool Changed =
false;
411 auto &MLI = getAnalysis<MachineLoopInfo>();
423 getAnalysis<MachineDominatorTree>().runOnMachineFunction(MF);
424 MLI.runOnMachineFunction(MF);
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
This class represents lattice values for constants.
void RenumberBlocks(MachineBasicBlock *MBBFrom=nullptr)
RenumberBlocks - This discards all of the MachineBasicBlock numbers and recomputes them...
void push_back(const T &Elt)
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
#define LLVM_UNLIKELY(EXPR)
iterator begin()
Instruction iterator methods.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
AnalysisUsage & addRequired()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
BlockT * getHeader() const
void getExitBlocks(SmallVectorImpl< BlockT *> &ExitBlocks) const
Return all of the successor blocks of this loop.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
BasicBlockListType::iterator iterator
auto count(R &&Range, const E &Element) -> typename std::iterator_traits< decltype(adl_begin(Range))>::difference_type
Wrapper function around std::count to count the number of times an element Element occurs in the give...
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Control flow instructions. These all have token chains.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file provides WebAssembly-specific target descriptions.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
iterator_range< pred_iterator > predecessors()
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
void sort(IteratorTy Start, IteratorTy End)
This file declares the WebAssembly-specific subclass of TargetSubtarget.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly. ...
void setPreservesCFG()
This function should be called by the pass, iff they do not:
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createWebAssemblyFixIrreducibleControlFlow()
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
void emplace_back(ArgTypes &&... Args)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Represents a single loop in the control flow graph.
ArrayRef< BlockT * > getBlocks() const
Get a list of the basic blocks which make up this loop.
INITIALIZE_PASS(WebAssemblyFixIrreducibleControlFlow, DEBUG_TYPE, "Removes irreducible control flow", false, false) FunctionPass *llvm
This file declares WebAssembly-specific per-machine-function information.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MachineLoop * getLoopFor(const MachineBasicBlock *BB) const
Return the innermost loop that BB lives in.
#define LLVM_LIKELY(EXPR)
StringRef - Represent a constant reference to a string, i.e.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
static void Split(std::vector< std::string > &V, StringRef S)
Splits a string of comma separated items in to a vector of strings.
const MachineOperand & getOperand(unsigned i) const
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...