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