[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