[llvm] [InstCombine] Fold dependent IVs (PR #81151)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 19 08:03:36 PST 2024


================
@@ -1378,6 +1378,47 @@ static Value *simplifyUsingControlFlow(InstCombiner &Self, PHINode &PN,
   return nullptr;
 }
 
+// Fold  iv = phi(start, iv.next = iv2.next + start)
+// where iv2 = phi(iv2.start, iv2.next = iv2 + iv2.step)
+// to    iv = iv2 + start
+static Value *foldDependentIVs(PHINode &PN, IRBuilderBase &Builder) {
+  BasicBlock *BB = PN.getParent();
+  if (PN.getNumIncomingValues() != 2)
+    return nullptr;
+
+  Value *Start;
+  Instruction *IvNext;
+  BinaryOperator *Iv2Next;
+  auto MatchOuterIV = [&](Value *V1, Value *V2) {
+    if (match(V2, m_c_Add(m_Specific(V1), m_BinOp(Iv2Next))) ||
----------------
nikic wrote:

It's a bit more complicated than that. I've updated the comment above the transform to be a bit more precise about what the precondition here is. We need `iv2.start op start = start` to hold, which is true when `op` is `+` and `iv2.start` is 0. It's also true for xor. For sub it depends on which operand it is. For `&` this is invalid -- but would be valid if `iv2.start` is -1 instead.

It would be possible to fully generalize this by doing a simplifyInstruction with the iv2.next operand replaced by iv2.start and checking that it's equal to start, and then instead of creating new instructions instead clone the existing one and replace operands. But this adds extra complexity, and it's not clear it is useful. Based on @dtcxzyw's tests, the GEP case actually accounts for the vast majority of occurrences of this pattern.

https://github.com/llvm/llvm-project/pull/81151


More information about the llvm-commits mailing list