@@ -2675,6 +2675,35 @@ SDValue DAGCombiner::visitPTRADD(SDNode *N) {
26752675
26762676 return DAG.getMemBasePlusOffset(X, Add, DL, SDNodeFlags());
26772677 }
2678+
2679+ // TODO: There is another possible fold here that was proven useful.
2680+ // It would be this:
2681+ //
2682+ // (ptradd (ptradd x, y), z) -> (ptradd (ptradd x, z), y) if:
2683+ // * (ptradd x, y) has one use; and
2684+ // * y is a constant; and
2685+ // * z is not a constant.
2686+ //
2687+ // In some cases, specifically in AArch64's FEAT_CPA, it exposes the
2688+ // opportunity to select more complex instructions such as SUBPT and MSUBPT
2689+ // However, a hypothetical corner case has been found that we could not
2690+ // avoid. Consider this (pseudo-POSIX C):
2691+ //
2692+ // char *foo(char *x, int z) {return (x + LARGE_CONSTANT) + z;}
2693+ // char *p = mmap(LARGE_CONSTANT);
2694+ // char *q = foo(p, -LARGE_CONSTANT);
2695+ //
2696+ // Then x + LARGE_CONSTANT is one-past-the-end, so valid, and a
2697+ // further + z takes it back to the start of the mapping, so valid,
2698+ // regardless of the address mmap gave back. However, if mmap gives you an
2699+ // address < LARGE_CONSTANT (ignoring high bits), x - LARGE_CONSTANT will
2700+ // borrow from the high bits (with the subsequent + z carrying back into
2701+ // the high bits to give you a well-defined pointer) and thus trip
2702+ // FEAT_CPA's pointer corruption checks.
2703+ //
2704+ // We leave this fold as an opportunity for future work, addressing the
2705+ // corner case for FEAT_CPA, as well as reconciling the solution with the
2706+ // more general application of pointer arithmetic in other future targets.
26782707 }
26792708
26802709 return SDValue();
0 commit comments