@@ -2652,59 +2652,61 @@ SDValue DAGCombiner::visitPTRADD(SDNode *N) {
26522652 if (isNullConstant(N0))
26532653 return N1;
26542654
2655- if (N0.getOpcode() == ISD::PTRADD &&
2656- !reassociationCanBreakAddressingModePattern(ISD::PTRADD, DL, N, N0, N1)) {
2657- SDValue X = N0.getOperand(0);
2658- SDValue Y = N0.getOperand(1);
2659- SDValue Z = N1;
2660- bool N0OneUse = N0.hasOneUse();
2661- bool YIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Y);
2662- bool ZIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Z);
2663-
2664- // (ptradd (ptradd x, y), z) -> (ptradd x, (add y, z)) if:
2665- // * y is a constant and (ptradd x, y) has one use; or
2666- // * y and z are both constants.
2667- if ((YIsConstant && N0OneUse) || (YIsConstant && ZIsConstant)) {
2668- SDNodeFlags Flags;
2669- // If both additions in the original were NUW, the new ones are as well.
2670- if (N->getFlags().hasNoUnsignedWrap() &&
2671- N0->getFlags().hasNoUnsignedWrap())
2672- Flags |= SDNodeFlags::NoUnsignedWrap;
2673- SDValue Add = DAG.getNode(ISD::ADD, DL, IntVT, {Y, Z}, Flags);
2674- AddToWorklist(Add.getNode());
2675- return DAG.getMemBasePlusOffset(X, Add, DL, Flags);
2676- }
2655+ if (N0.getOpcode() != ISD::PTRADD ||
2656+ reassociationCanBreakAddressingModePattern(ISD::PTRADD, DL, N, N0, N1))
2657+ return SDValue();
26772658
2678- // TODO: There is another possible fold here that was proven useful.
2679- // It would be this:
2680- //
2681- // (ptradd (ptradd x, y), z) -> (ptradd (ptradd x, z), y) if:
2682- // * (ptradd x, y) has one use; and
2683- // * y is a constant; and
2684- // * z is not a constant.
2685- //
2686- // In some cases, specifically in AArch64's FEAT_CPA, it exposes the
2687- // opportunity to select more complex instructions such as SUBPT and
2688- // MSUBPT. However, a hypothetical corner case has been found that we could
2689- // not avoid. Consider this (pseudo-POSIX C):
2690- //
2691- // char *foo(char *x, int z) {return (x + LARGE_CONSTANT) + z;}
2692- // char *p = mmap(LARGE_CONSTANT);
2693- // char *q = foo(p, -LARGE_CONSTANT);
2694- //
2695- // Then x + LARGE_CONSTANT is one-past-the-end, so valid, and a
2696- // further + z takes it back to the start of the mapping, so valid,
2697- // regardless of the address mmap gave back. However, if mmap gives you an
2698- // address < LARGE_CONSTANT (ignoring high bits), x - LARGE_CONSTANT will
2699- // borrow from the high bits (with the subsequent + z carrying back into
2700- // the high bits to give you a well-defined pointer) and thus trip
2701- // FEAT_CPA's pointer corruption checks.
2702- //
2703- // We leave this fold as an opportunity for future work, addressing the
2704- // corner case for FEAT_CPA, as well as reconciling the solution with the
2705- // more general application of pointer arithmetic in other future targets.
2659+ SDValue X = N0.getOperand(0);
2660+ SDValue Y = N0.getOperand(1);
2661+ SDValue Z = N1;
2662+ bool N0OneUse = N0.hasOneUse();
2663+ bool YIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Y);
2664+ bool ZIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Z);
2665+
2666+ // (ptradd (ptradd x, y), z) -> (ptradd x, (add y, z)) if:
2667+ // * y is a constant and (ptradd x, y) has one use; or
2668+ // * y and z are both constants.
2669+ if ((YIsConstant && N0OneUse) || (YIsConstant && ZIsConstant)) {
2670+ SDNodeFlags Flags;
2671+ // If both additions in the original were NUW, the new ones are as well.
2672+ if (N->getFlags().hasNoUnsignedWrap() && N0->getFlags().hasNoUnsignedWrap())
2673+ Flags |= SDNodeFlags::NoUnsignedWrap;
2674+ SDValue Add = DAG.getNode(ISD::ADD, DL, IntVT, {Y, Z}, Flags);
2675+ AddToWorklist(Add.getNode());
2676+ return DAG.getMemBasePlusOffset(X, Add, DL, Flags);
27062677 }
27072678
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
2689+ // MSUBPT. However, a hypothetical corner case has been found that we could
2690+ // not 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.
2707+ // For now each architecture that wants this fold must implement it in the
2708+ // target-specific code (see e.g. SITargetLowering::performPtrAddCombine)
2709+
27082710 return SDValue();
27092711}
27102712
0 commit comments