[PATCH] D139109: [LoopUnswitch] Perform loop unswitching on select instructions

Max Kazantsev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 6 23:47:33 PST 2022


mkazantsev requested changes to this revision.
mkazantsev added inline comments.
This revision now requires changes to proceed.


================
Comment at: llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:2619
+  if (!isGuaranteedNotToBeUndefOrPoison(Cond, AC, SI, &DT))
+    Cond = new FreezeInst(Cond, Cond->getName() + ".fr", SI);
+  SplitBlockAndInsertIfThen(SI->getCondition(), SI, false,
----------------
Can we change the insertion point to right after the cond? Presumeably it's outside of loop.


================
Comment at: llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:2628
+
+  PHINode *Phi = PHINode::Create(SI->getType(), 2, "", SI);
+  Phi->addIncoming(SI->getTrueValue(), ThenBB);
----------------
This is wrong, you can't insert a Phi before SI if there is another instruction before it. Your insertion point should be smth like block.begin().


================
Comment at: llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:2724
   if (DT.dominates(CondBlock, Latch) &&
       (isGuard(&TI) ||
+       (TI.isTerminator() &&
----------------
This condition is growing weird, can we rewrite it to make it explicit that we choose between guard, select, terminator etc? Maybe factor out into a lambda.


================
Comment at: llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:2810
 
-    if (CollectGuards)
-      for (auto &I : *BB)
-        if (isGuard(&I)) {
-          auto *Cond =
-              skipTrivialSelect(cast<IntrinsicInst>(&I)->getArgOperand(0));
-          // TODO: Support AND, OR conditions and partial unswitching.
-          if (!isa<Constant>(Cond) && L.isLoopInvariant(Cond))
-            UnswitchCandidates.push_back({&I, {Cond}});
-        }
+    for (auto &I : *BB) {
+      if (auto *SI = dyn_cast<SelectInst>(&I)) {
----------------
Just for record: this will cost us compile time, turning the algorithm from `O(number of blocks)` to `O(number of instructions)` (if guards are off). Keep that in mind if you see compile time regressions.


================
Comment at: llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:2816
+        if (!isa<Constant>(Cond) && L.isLoopInvariant(Cond))
+          UnswitchCandidates.push_back({&I, {Cond}});
+      } else if (CollectGuards && isGuard(&I)) {
----------------
I would also filter out such obviously useless cases as:
- Select is not used
- Select is only used outside of the loop (and therefore can be sunk)
maybe smth else, give it some more thought.



================
Comment at: llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll:4393
+; Non-trivial loop unswitching of select instruction.
+define i32 @test34(i32 %N, i1 %cond) {
+; CHECK-LABEL: @test34(
----------------
To see what your tests are doing, I propose the following steps:
- Regenerate all checks in this file using update_test_checks.py script;
- Check in your new tests with checks as is (without your change in code)
- Then rebase your patch on top of it, to see what exactly your patch has changed.

Without this, it's hard to tell what's right or wrong here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D139109



More information about the llvm-commits mailing list