[PATCH] D24805: [GVNSink] Initial GVNSink prototype

Matthias Braun via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 22 10:46:43 PDT 2016


MatzeB added a comment.

Just some coding style nitpicking.

- Still a bunch of FIXME comments around. I often feel that many of them could just as well have been removed if they didn't turn out out to be important enough to be addressed for the commit.


================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:10-32
@@ +9,25 @@
+//
+// This pass attempts to sink instructions into successors, reducing static
+// instruction count and enabling if-conversion.
+//
+// We use a variant of global value numbering to decide what can be sunk.
+// Consider:
+//
+// [ %a1 = add i32 %b, 1  ]   [ %c1 = add i32 %d, 1  ]
+// [ %a2 = xor i32 %a1, 1 ]   [ %c2 = xor i32 %c1, 1 ]
+//                  \           /
+//            [ %e = phi i32 %a2, %c2 ]
+//            [ add i32 %e, 4         ]
+//
+//
+// GVN would number %a1 and %c1 differently because they compute different
+// results - the VN of an instruction is a function of its opcode and the
+// transitive closure of its operands. This is the key property for hoisting
+// and CSE.
+//
+// What we want when sinking however is for a numbering that is a function of
+// the *uses* of an instruction, which allows us to answer the question "if I
+// replace %a1 with %c1, will it contribute in an equivalent way to all
+// successive instructions?". The PostValueTable class in GVN provides this
+// mapping.
+//
----------------
This could be

```
/// \file
/// This pass attempts...
```
to make the comment available to doxygen.

================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:68-79
@@ +67,14 @@
+
+// LockstepReverseIterator - Iterates through instructions in a set of blocks in
+// reverse order from the first non-terminator.
+// For example (assume all blocks have size n):
+//   LockstepReverseIterator I([B1, B2, B3]);
+//   *I-- = [B1[n], B2[n], B3[n]];
+//   *I-- = [B1[n-1], B2[n-1], B3[n-1]];
+//   *I-- = [B1[n-2], B2[n-2], B3[n-2]];
+//   ...
+//
+// It continues until all blocks have been exhausted. Use \c getActiveBlocks() to
+// determine which blocks are still going and the order they appear in the
+// list returned by operator*.
+class LockstepReverseIterator {
----------------
`///` for doxygen, do not repeat the type name in the comment.

================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:93
@@ +92,3 @@
+    ActiveBlocks.clear();
+    for (auto *BB : Blocks)
+      ActiveBlocks.insert(BB);
----------------
A matter of taste, but I think `BasicBlock *BB` instead of `auto *BB` is only slightly longer and has a higher documentation value. Similar in many following for loops.

================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:113
@@ +112,3 @@
+  void restrictToBlocks(SmallPtrSetImpl<BasicBlock*> &Blocks) {
+    auto II = Insts.begin();
+    for (; II != Insts.end();) {
----------------
I'd move that into the for loop to make the cope obvious.

================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:129
@@ +128,3 @@
+    SmallVector<Instruction*,4> NewInsts;
+    for (auto *&Inst : Insts) {
+      if (Inst == &Inst->getParent()->front())
----------------
Using a reference seems unnecessary (I don't see any modification).

================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:171
@@ +170,3 @@
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                              SinkingInstructionCandidate &C) {
+  OS << "<Candidate Cost=" << C.Cost << " #Blocks=" << C.NumBlocks
----------------
could be `const`

================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:187
@@ +186,3 @@
+  ModelledPHI() {}
+  ModelledPHI(PHINode *PN) {
+    for (unsigned I = 0, E = PN->getNumIncomingValues(); I != E; ++I)
----------------
could be `const PHINode &`

================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:198
@@ +197,3 @@
+
+  // Create a PHI from an array of incoming values and incoming blocks.
+  template <typename VArray, typename BArray>
----------------
doxygen `///`. More cases of this follow.

================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:250
@@ +249,3 @@
+};
+typedef std::unordered_set<ModelledPHI, /*Hash=*/ModelledPHI> ModelledPHISet;
+
----------------
Is there anything missing in llvms `DenseSet` or any other reason for `std::unordered_set`?


================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:523
@@ +522,3 @@
+    for (auto *V : NewPHI.getValues())
+	if (PHIContents.count(V))
+          // V exists in this PHI, but the whole PHI is different to NewPHI
----------------
Indentation

================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:610
@@ +609,3 @@
+    ModelledPHISet NeededPHIs;
+    std::set<Value*> PHIContents;
+    analyzeInitialPHIs(BBEnd, NeededPHIs, PHIContents);
----------------
Why not `SmallPtrSet`?

================
Comment at: lib/Transforms/Scalar/GVNSink.cpp:624-625
@@ +623,4 @@
+
+    std::stable_sort(Candidates.begin(), Candidates.end());
+    std::reverse(Candidates.begin(), Candidates.end());
+    DEBUG(
----------------
A custom reversed comparison operator should save the reverse() operation.


https://reviews.llvm.org/D24805





More information about the llvm-commits mailing list