Rules for determining if a SCEV expression is pointer-typed:
- SCEVUnknown is a pointer if and only if the LLVM IR value is a pointer.
- SCEVPtrToInt is never a pointer.
- If any other SCEV expression has no pointer operands, the result is an integer.
- If a SCEVAddExpr has exactly one pointer operand, the result is a pointer.
- If a SCEVAddRecExpr's first operand is a pointer, and it has no other pointer operands, the result is a pointer.
- If a SCEVMinMaxExpr has all pointer operands, the result is a pointer.
- Otherwise, the SCEV expression is invalid.
I'm not sure how useful rule 6 is in practice. If we exclude it, we can
guarantee that ScalarEvolution::getPointerBase always returns a
SCEVUnknown, which might be a helpful property. Anyway, I'll leave that
for a followup.
Currently has some regression test failures related to LSR; the
generated code is changing. scev-custom-dl.ll currently crashes because
getPointerDiff() can return SCEVCouldNotCompute for exotic pointers.
Otherwise passes regression tests.
Open questions:
- Is it worth keeping getPointerDiff separate from getMinusSCEV? It's an extra SCEV entry point which is in some sense redundant. But one advantage is that the new API lets us land the changes to various transforms incrementally.
- How do we want to deal with ScalarEvolution::isImpliedCond? Currently, I have a few targeted bailouts for pointers, but we could just ptrtoint all the operands.
- What do we do about exotic pointers? None of the places that use getPointerDiff have any handling for failure.
- What do we do about LSR? CollectFixupsAndInitialFormulae() subtracts two pointers to model an icmp; using getPointerDiff here is correct, but wrecks a bunch of the heuristics because "ptrtoint %x" is not the same SCEV expression as "%x". And LSR is really fragile; touching almost anything to try to address that will affect other tests. Not sure what to do here.