@@ -2875,6 +2875,93 @@ SDValue DAGCombiner::visitADDCARRY(SDNode *N) {
2875
2875
return SDValue();
2876
2876
}
2877
2877
2878
+ /**
2879
+ * If we are facing some sort of diamond carry propapagtion pattern try to
2880
+ * break it up to generate something like:
2881
+ * (addcarry X, 0, (addcarry A, B, Z):Carry)
2882
+ *
2883
+ * The end result is usually an increase in operation required, but because the
2884
+ * carry is now linearized, other tranforms can kick in and optimize the DAG.
2885
+ *
2886
+ * Patterns typically look something like
2887
+ * (uaddo A, B)
2888
+ * / \
2889
+ * Carry Sum
2890
+ * | \
2891
+ * | (addcarry *, 0, Z)
2892
+ * | /
2893
+ * \ Carry
2894
+ * | /
2895
+ * (addcarry X, *, *)
2896
+ *
2897
+ * But numerous variation exist. Our goal is to identify A, B, X and Z and
2898
+ * produce a combine with a single path for carry propagation.
2899
+ */
2900
+ static SDValue combineADDCARRYDiamond(DAGCombiner &Combiner, SelectionDAG &DAG,
2901
+ SDValue X, SDValue Carry0, SDValue Carry1,
2902
+ SDNode *N) {
2903
+ if (Carry1.getResNo() != 1 || Carry0.getResNo() != 1)
2904
+ return SDValue();
2905
+ if (Carry1.getOpcode() != ISD::UADDO)
2906
+ return SDValue();
2907
+
2908
+ SDValue Z;
2909
+
2910
+ /**
2911
+ * First look for a suitable Z. It will present itself in the form of
2912
+ * (addcarry Y, 0, Z) or its equivalent (uaddo Y, 1) for Z=true
2913
+ */
2914
+ if (Carry0.getOpcode() == ISD::ADDCARRY &&
2915
+ isNullConstant(Carry0.getOperand(1))) {
2916
+ Z = Carry0.getOperand(2);
2917
+ } else if (Carry0.getOpcode() == ISD::UADDO &&
2918
+ isOneConstant(Carry0.getOperand(1))) {
2919
+ EVT VT = Combiner.getSetCCResultType(Carry0.getValueType());
2920
+ Z = DAG.getConstant(1, SDLoc(Carry0.getOperand(1)), VT);
2921
+ } else {
2922
+ // We couldn't find a suitable Z.
2923
+ return SDValue();
2924
+ }
2925
+
2926
+
2927
+ auto cancelDiamond = [&](SDValue A,SDValue B) {
2928
+ SDLoc DL(N);
2929
+ SDValue NewY = DAG.getNode(ISD::ADDCARRY, DL, Carry0->getVTList(), A, B, Z);
2930
+ Combiner.AddToWorklist(NewY.getNode());
2931
+ return DAG.getNode(ISD::ADDCARRY, DL, N->getVTList(), X,
2932
+ DAG.getConstant(0, DL, X.getValueType()),
2933
+ NewY.getValue(1));
2934
+ };
2935
+
2936
+ /**
2937
+ * (uaddo A, B)
2938
+ * |
2939
+ * Sum
2940
+ * |
2941
+ * (addcarry *, 0, Z)
2942
+ */
2943
+ if (Carry0.getOperand(0) == Carry1.getValue(0)) {
2944
+ return cancelDiamond(Carry1.getOperand(0), Carry1.getOperand(1));
2945
+ }
2946
+
2947
+ /**
2948
+ * (addcarry A, 0, Z)
2949
+ * |
2950
+ * Sum
2951
+ * |
2952
+ * (uaddo *, B)
2953
+ */
2954
+ if (Carry1.getOperand(0) == Carry0.getValue(0)) {
2955
+ return cancelDiamond(Carry0.getOperand(0), Carry1.getOperand(1));
2956
+ }
2957
+
2958
+ if (Carry1.getOperand(1) == Carry0.getValue(0)) {
2959
+ return cancelDiamond(Carry1.getOperand(0), Carry0.getOperand(0));
2960
+ }
2961
+
2962
+ return SDValue();
2963
+ }
2964
+
2878
2965
SDValue DAGCombiner::visitADDCARRYLike(SDValue N0, SDValue N1, SDValue CarryIn,
2879
2966
SDNode *N) {
2880
2967
// Iff the flag result is dead:
@@ -2889,35 +2976,13 @@ SDValue DAGCombiner::visitADDCARRYLike(SDValue N0, SDValue N1, SDValue CarryIn,
2889
2976
* When one of the addcarry argument is itself a carry, we may be facing
2890
2977
* a diamond carry propagation. In which case we try to transform the DAG
2891
2978
* to ensure linear carry propagation if that is possible.
2892
- *
2893
- * We are trying to get:
2894
- * (addcarry X, 0, (addcarry A, B, Z):Carry)
2895
2979
*/
2896
2980
if (auto Y = getAsCarry(TLI, N1)) {
2897
- /**
2898
- * (uaddo A, B)
2899
- * / \
2900
- * Carry Sum
2901
- * | \
2902
- * | (addcarry *, 0, Z)
2903
- * | /
2904
- * \ Carry
2905
- * | /
2906
- * (addcarry X, *, *)
2907
- */
2908
- if (Y.getOpcode() == ISD::UADDO &&
2909
- CarryIn.getResNo() == 1 &&
2910
- CarryIn.getOpcode() == ISD::ADDCARRY &&
2911
- isNullConstant(CarryIn.getOperand(1)) &&
2912
- CarryIn.getOperand(0) == Y.getValue(0)) {
2913
- auto NewY = DAG.getNode(ISD::ADDCARRY, SDLoc(N), Y->getVTList(),
2914
- Y.getOperand(0), Y.getOperand(1),
2915
- CarryIn.getOperand(2));
2916
- AddToWorklist(NewY.getNode());
2917
- return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(), N0,
2918
- DAG.getConstant(0, SDLoc(N), N0.getValueType()),
2919
- NewY.getValue(1));
2920
- }
2981
+ // Because both are carries, Y and Z can be swapped.
2982
+ if (auto R = combineADDCARRYDiamond(*this, DAG, N0, Y, CarryIn, N))
2983
+ return R;
2984
+ if (auto R = combineADDCARRYDiamond(*this, DAG, N0, CarryIn, Y, N))
2985
+ return R;
2921
2986
}
2922
2987
2923
2988
return SDValue();
0 commit comments