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