[PATCH] D77523: Add CanonicalizeFreezeInLoops pass

Johannes Doerfert via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 30 07:21:27 PDT 2020


jdoerfert added a comment.

I'm asking myself if it wouldn't be better to start with the freeze instructions and work our way up through the operands. At the end of the day we do a lot of work just to figure out there is no freeze or the instruction chains we build do not end in one. Am I missing something?

Also, could this drop flags of instructions not on the path between a phi and a freeze? So do we keep the `nsw` on the sub and mul in the following example:

  %iv = phi [0, ...] [%step, ...]
  %step = add nsw %iv, 1
  %f = freeze %step
  %not_step1 = sub nsw %iv, 1
  %not_step2 = mul nsw %step, 2



================
Comment at: llvm/lib/Transforms/Utils/CanonicalizeFreezeInLoops.cpp:77
+           Opc == Instruction::Mul;
+  }
+
----------------
Nit: I would call this `canHandleInst` or something similar. We can deal with various instructions I guess, some require us to drop flags but others not, e.g., freeze or bitcast.


================
Comment at: llvm/lib/Transforms/Utils/CanonicalizeFreezeInLoops.cpp:90
+    return {StepInst, StepInst->getOperand(0) == PHI};
+  }
+
----------------
What happens if the step value looks like this:

```
%iv = phi [0, ...] [%step, ...]
%step = add %iv, %iv
```
Just checking that we don't have a problem in this case.


================
Comment at: llvm/lib/Transforms/Utils/CanonicalizeFreezeInLoops.cpp:122
+    unsigned CurDepth) {
+  for (auto U = I->user_begin(), E = I->user_end(); U != E; ++U) {
+    Instruction *I2 = dyn_cast<Instruction>(*U);
----------------
Style: `for (const auto &U : I->users())` ? (w/ or w/o const)


================
Comment at: llvm/lib/Transforms/Utils/CanonicalizeFreezeInLoops.cpp:137
+    }
+    Visited[I2].insert(I);
+
----------------
Is the find stuff necessary or could you just check the return value of the `insert` call?


================
Comment at: llvm/lib/Transforms/Utils/CanonicalizeFreezeInLoops.cpp:140
+    if (CurDepth < MaxDepth)
+      getReachableInstsInsideLoop(I2, Visited, CurDepth + 1);
+  }
----------------
I think we often avoid such recursion in favor of worklists but if this doesn't show on the profile it's OK I guess.


================
Comment at: llvm/lib/Transforms/Utils/CanonicalizeFreezeInLoops.cpp:150
+  // so only visit instructions that are known how to be dealt with
+  getReachableInstsInsideLoop(&PHI, Insts, true);
+}
----------------
`true` is an unsigned for the callee, maybe `/* CurDepth */ 1` instead?


================
Comment at: llvm/lib/Transforms/Utils/CanonicalizeFreezeInLoops.cpp:165
+  SmallSet<Instruction *, 8> Visited;
+  std::queue<Instruction *> Queue;
+  Queue.push(FI);
----------------
Do we really need a queue or would LIFO (=smallvector) also work?


================
Comment at: llvm/lib/Transforms/Utils/CanonicalizeFreezeInLoops.cpp:281
+  SmallVector<FreezeInst *, 4> FIsToRemove;
+  SmallVector<Use *, 4> UsesToInsertFr;
+
----------------
Nit: I guess we could make all these class members, right? Unclear if that is better though.

Nit: DenseMap instead of std::map?

^ Both should be considered but can be kept this way too.


================
Comment at: llvm/lib/Transforms/Utils/CanonicalizeFreezeInLoops.cpp:302
+        continue;
+    }
+
----------------
Nit: StepI is checked twice for null.
Style: I'd use the braces around the inner conditional instead


================
Comment at: llvm/lib/Transforms/Utils/CanonicalizeFreezeInLoops.cpp:312
+  // pushed out of the loop.
+  for (auto Pair : InstsFromPHIs) {
+    auto *FI = dyn_cast<FreezeInst>(Pair.first);
----------------
`const auto &Pair`

I think `const` and `*` or `&` should be combined with `auto` whenever possible.



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D77523





More information about the llvm-commits mailing list