[PATCH] D55467: [WebAssembly] Optimize Irreducible Control Flow

Heejin Ahn via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 13 09:08:24 PST 2018


aheejin added a comment.

First brief look at the pass.. mostly low-level nits

- Nit: Could you wrap comments to 80 cols? Some lines end prematurely now. (clang-format does not do that for us.. In vim you can use `gq`, but not sure about other editors)
- There are many lambda functions that can be made into plain static functions or class member functions. I think it is more conventional and readable that way unless they are very short or are meant to be passed into arguments to another function.. I feel it's not very easy to read when other several lambda function definitions are interleaved with the function body.



================
Comment at: lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp:85
     AU.addRequired<MachineDominatorTree>();
     AU.addPreserved<MachineDominatorTree>();
     AU.addRequired<MachineLoopInfo>();
----------------
I don't think we need dominator tree anymore, so I think we can delete these two lines.


================
Comment at: lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp:87
     AU.addRequired<MachineLoopInfo>();
     AU.addPreserved<MachineLoopInfo>();
     MachineFunctionPass::getAnalysisUsage(AU);
----------------
Do we preserve loop info?


================
Comment at: lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp:109
 
-namespace {
-
-/// A utility for walking the blocks of a loop, handling a nested inner
-/// loop as a monolithic conceptual block.
-class MetaBlock {
-  MachineBasicBlock *Block;
-  SmallVector<MachineBasicBlock *, 2> Preds;
-  SmallVector<MachineBasicBlock *, 2> Succs;
-
-public:
-  explicit MetaBlock(MachineBasicBlock *MBB)
-      : Block(MBB), Preds(MBB->pred_begin(), MBB->pred_end()),
-        Succs(MBB->succ_begin(), MBB->succ_end()) {}
-
-  explicit MetaBlock(MachineLoop *Loop) : Block(Loop->getHeader()) {
-    Loop->getExitBlocks(Succs);
-    for (MachineBasicBlock *Pred : Block->predecessors())
-      if (!Loop->contains(Pred))
-        Preds.push_back(Pred);
-  }
-
-  MachineBasicBlock *getBlock() const { return Block; }
+bool WebAssemblyFixIrreducibleControlFlow::VisitLoop(MachineFunction &MF,
+                                                     MachineLoopInfo &MLI,
----------------
Nit: [[ https://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly | LLVM coding standards ]] say function names should start with a lowercase letter.


================
Comment at: lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp:159
+  // Compute which (canonicalized) blocks each block can reach.
+  typedef std::unordered_set<MachineBasicBlock *> BlockSet;
+  std::unordered_map<MachineBasicBlock *, BlockSet> Reachable;
----------------
Nit: `using` instead of `typedef`


================
Comment at: lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp:160
+  typedef std::unordered_set<MachineBasicBlock *> BlockSet;
+  std::unordered_map<MachineBasicBlock *, BlockSet> Reachable;
+
----------------
[[ https://llvm.org/docs/CodingStandards.html#beware-of-non-determinism-due-to-ordering-of-pointers | LLVM coding standards ]] warn against uses of non-deterministic containers. Also LLVM progamming manual prevents the uses of `unordered_set` or `unordered_map`. ([[ http://llvm.org/docs/ProgrammersManual.html#other-set-like-container-options | ref1 ]], [[ http://llvm.org/docs/ProgrammersManual.html#other-map-like-container-options | ref2 ]])

Maybe we can choose from other [[ http://llvm.org/docs/ProgrammersManual.html#set-like-containers-std-set-smallset-setvector-etc | set-like containers ]] and [[ http://llvm.org/docs/ProgrammersManual.html#other-map-like-container-options | map-like containers ]]?


================
Comment at: lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp:164
+  // added a link a => b.
+  typedef std::pair<MachineBasicBlock *, MachineBasicBlock *> BlockPair;
+  std::vector<BlockPair> WorkList;
----------------
Nit: `using` instead of `typedef`


================
Comment at: lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp:179
+      if (CanonicalizeSuccessor(MBB)) {
+        WorkList.push_back(BlockPair(MBB, Succ));
+      }
----------------
Nit: You can do
```
WorkList.emplace_back(MBB, Succ);
```


================
Comment at: lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp:214
+    auto *MBB = Pair.first;
+    auto *Succ = Pair.second;
+    assert(MBB);
----------------
Nit: You can merge these lines maybe with
```
auto *MBB, *Succ;
std::tie(MBB, Succ) = WorkList.pop_back_val()
```


================
Comment at: lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp:382
+        MF.RenumberBlocks();
+        getAnalysis<MachineDominatorTree>().runOnMachineFunction(MF);
+        MLI.runOnMachineFunction(MF);
----------------
Should we recompute these three every time we make a change?
- This pass does not use liveness info, so I think we can do this at the end of the whole pass if any change was made.
- I don't think we need to do renumbering? We only use BB numbers at CFGSort / CFGStackify and CFGSort recomputes all numbers itself before doing anything.
- This pass does not seem to use dominator tree, right? Then deleting `AU.addPreserved<MachineDominatorTree>();` in `getAnalysisUsage()` should be sufficient. I don't think we even need to require it.


================
Comment at: lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp:383
+        getAnalysis<MachineDominatorTree>().runOnMachineFunction(MF);
+        MLI.runOnMachineFunction(MF);
+        return Changed = true;
----------------
Should we recompute loop info for the whole function every time we make any change? `MachineLoopInfo` class seems to have [[ https://github.com/llvm-mirror/llvm/blob/2ca3d46c8a27e6de8a99de6bdc08e0884e8e6a85/include/llvm/CodeGen/MachineLoopInfo.h#L142-L169 | various modifier functions ]]. Can we use these on-the-fly during the pass?


================
Comment at: lib/Target/WebAssembly/WebAssemblyFixIrreducibleControlFlow.cpp:405
 
-  // If we made any changes, completely recompute everything.
-  if (LLVM_UNLIKELY(Changed)) {
-    LLVM_DEBUG(dbgs() << "Recomputing dominators and loops.\n");
-    MF.getRegInfo().invalidateLiveness();
-    MF.RenumberBlocks();
-    getAnalysis<MachineDominatorTree>().runOnMachineFunction(MF);
-    MLI.runOnMachineFunction(MF);
+  while (Iteration()) {
   }
----------------
How about flattening `Iteration` and `DoVisitLoop` into this while loop, like this? I find nested lambdas a bit hard to read.

```                   
  while (...) {                                                                 
    SmallVector<MachineLoop *, 8> Worklist;                                                    
    // Visit the function body, which is identified as a null loop.              
    Worklist.push_back(nullptr);                                                 
    // Visit all the loops.                                                      
    Worklist.append(MLI.begin(), MLI.end());      
                               
    while (!Worklist.empty()) {                                                  
      MachineLoop *Loop = Worklist.pop_back_val();                               
      Worklist.append(Loop->begin(), Loop->end());                                                          
      if (VisitLoop(MF, MLI, Loop)) {           
        ...                                 
      }                                                                     
    }                                                                            
  }
```


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55467/new/

https://reviews.llvm.org/D55467





More information about the llvm-commits mailing list