@@ -6822,6 +6822,81 @@ static unsigned getExtOpcodeForPromotedOp(SDValue Op) {
6822
6822
}
6823
6823
}
6824
6824
6825
+ SDValue SITargetLowering::combineAnd(SDValue Op,
6826
+ DAGCombinerInfo &DCI) const {
6827
+ const unsigned Opc = Op.getOpcode();
6828
+ assert(Opc == ISD::AND);
6829
+
6830
+ auto &DAG = DCI.DAG;
6831
+ SDLoc DL(Op);
6832
+
6833
+ if(hasAndNot(Op)) {
6834
+ SDValue LHS = Op->getOperand(0);
6835
+ SDValue RHS = Op->getOperand(1);
6836
+
6837
+ // (and LHS, (or Y, ~Z))
6838
+ if (RHS.getOpcode() == ISD::OR && RHS.hasOneUse()) {
6839
+ SDValue Y = RHS->getOperand(0);
6840
+ SDValue NotZ = RHS->getOperand(1);
6841
+
6842
+ if (NotZ.getOpcode() == ISD::XOR && isAllOnesConstant(NotZ->getOperand(1))) {
6843
+ SDValue Z = NotZ->getOperand(0);
6844
+
6845
+ if (!isa<ConstantSDNode>(Y)) {
6846
+ SDValue NotY = DAG.getNOT(DL, Y, Y.getValueType());
6847
+ SDValue AndNotYZ = DAG.getNode(ISD::AND, DL, Y.getValueType(), NotY, Z);
6848
+ SDValue NotAndNotYZ = DAG.getNOT(DL, AndNotYZ, AndNotYZ.getValueType());
6849
+ SDValue NewAnd = DAG.getNode(ISD::AND, DL, Op.getValueType(), LHS, NotAndNotYZ);
6850
+ return NewAnd;
6851
+ }
6852
+ }
6853
+ }
6854
+ }
6855
+
6856
+ EVT OpTy = (Opc != ISD::SETCC) ? Op.getValueType()
6857
+ : Op->getOperand(0).getValueType();
6858
+ auto ExtTy = OpTy.changeElementType(MVT::i32);
6859
+
6860
+ if (DCI.isBeforeLegalizeOps() ||
6861
+ isNarrowingProfitable(Op.getNode(), ExtTy, OpTy))
6862
+ return SDValue();
6863
+
6864
+ SDValue LHS;
6865
+ SDValue RHS;
6866
+ if (Opc == ISD::SELECT) {
6867
+ LHS = Op->getOperand(1);
6868
+ RHS = Op->getOperand(2);
6869
+ } else {
6870
+ LHS = Op->getOperand(0);
6871
+ RHS = Op->getOperand(1);
6872
+ }
6873
+
6874
+ const unsigned ExtOp = getExtOpcodeForPromotedOp(Op);
6875
+ LHS = DAG.getNode(ExtOp, DL, ExtTy, {LHS});
6876
+
6877
+ // Special case: for shifts, the RHS always needs a zext.
6878
+ if (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA)
6879
+ RHS = DAG.getNode(ISD::ZERO_EXTEND, DL, ExtTy, {RHS});
6880
+ else
6881
+ RHS = DAG.getNode(ExtOp, DL, ExtTy, {RHS});
6882
+
6883
+ // setcc always return i1/i1 vec so no need to truncate after.
6884
+ if (Opc == ISD::SETCC) {
6885
+ ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
6886
+ return DAG.getSetCC(DL, Op.getValueType(), LHS, RHS, CC);
6887
+ }
6888
+
6889
+ // For other ops, we extend the operation's return type as well so we need to
6890
+ // truncate back to the original type.
6891
+ SDValue NewVal;
6892
+ if (Opc == ISD::SELECT)
6893
+ NewVal = DAG.getNode(ISD::SELECT, DL, ExtTy, {Op->getOperand(0), LHS, RHS});
6894
+ else
6895
+ NewVal = DAG.getNode(Opc, DL, ExtTy, {LHS, RHS});
6896
+
6897
+ return DAG.getZExtOrTrunc(NewVal, DL, OpTy);
6898
+ }
6899
+
6825
6900
SDValue SITargetLowering::promoteUniformOpToI32(SDValue Op,
6826
6901
DAGCombinerInfo &DCI) const {
6827
6902
const unsigned Opc = Op.getOpcode();
@@ -14797,16 +14872,19 @@ SDValue SITargetLowering::performClampCombine(SDNode *N,
14797
14872
return SDValue(CSrc, 0);
14798
14873
}
14799
14874
14800
-
14801
14875
SDValue SITargetLowering::PerformDAGCombine(SDNode *N,
14802
14876
DAGCombinerInfo &DCI) const {
14877
+ SelectionDAG &DAG = DCI.DAG;
14803
14878
switch (N->getOpcode()) {
14879
+ case ISD::AND:
14880
+ if (auto Res = combineAnd(SDValue(N, 0), DCI))
14881
+ return Res;
14882
+ break;
14804
14883
case ISD::ADD:
14805
14884
case ISD::SUB:
14806
14885
case ISD::SHL:
14807
14886
case ISD::SRL:
14808
14887
case ISD::SRA:
14809
- case ISD::AND:
14810
14888
case ISD::OR:
14811
14889
case ISD::XOR:
14812
14890
case ISD::MUL:
@@ -14910,7 +14988,6 @@ SDValue SITargetLowering::PerformDAGCombine(SDNode *N,
14910
14988
case AMDGPUISD::CLAMP:
14911
14989
return performClampCombine(N, DCI);
14912
14990
case ISD::SCALAR_TO_VECTOR: {
14913
- SelectionDAG &DAG = DCI.DAG;
14914
14991
EVT VT = N->getValueType(0);
14915
14992
14916
14993
// v2i16 (scalar_to_vector i16:x) -> v2i16 (bitcast (any_extend i16:x))
@@ -16892,8 +16969,8 @@ SITargetLowering::lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *AI) const {
16892
16969
}
16893
16970
16894
16971
bool SITargetLowering::hasAndNot(SDValue Op) const {
16895
- // Return false if the operation is divergent, as AND-NOT optimization
16896
- // requires uniform behavior across threads .
16972
+ // Return false if the operation is divergent, as AND-NOT is a scalar-only
16973
+ // instruction .
16897
16974
if (Op->isDivergent())
16898
16975
return false;
16899
16976
0 commit comments