@@ -484,6 +484,7 @@ namespace {
484484 SDValue visitCTTZ_ZERO_UNDEF(SDNode *N);
485485 SDValue visitCTPOP(SDNode *N);
486486 SDValue visitSELECT(SDNode *N);
487+ SDValue visitCTSELECT(SDNode *N);
487488 SDValue visitVSELECT(SDNode *N);
488489 SDValue visitVP_SELECT(SDNode *N);
489490 SDValue visitSELECT_CC(SDNode *N);
@@ -1898,6 +1899,7 @@ void DAGCombiner::Run(CombineLevel AtLevel) {
18981899}
18991900
19001901SDValue DAGCombiner::visit(SDNode *N) {
1902+
19011903 // clang-format off
19021904 switch (N->getOpcode()) {
19031905 default: break;
@@ -1968,6 +1970,7 @@ SDValue DAGCombiner::visit(SDNode *N) {
19681970 case ISD::CTTZ_ZERO_UNDEF: return visitCTTZ_ZERO_UNDEF(N);
19691971 case ISD::CTPOP: return visitCTPOP(N);
19701972 case ISD::SELECT: return visitSELECT(N);
1973+ case ISD::CTSELECT: return visitCTSELECT(N);
19711974 case ISD::VSELECT: return visitVSELECT(N);
19721975 case ISD::SELECT_CC: return visitSELECT_CC(N);
19731976 case ISD::SETCC: return visitSETCC(N);
@@ -6032,6 +6035,7 @@ static SDValue isSaturatingMinMax(SDValue N0, SDValue N1, SDValue N2,
60326035 N0CC = cast<CondCodeSDNode>(N0.getOperand(4))->get();
60336036 break;
60346037 case ISD::SELECT:
6038+ case ISD::CTSELECT:
60356039 case ISD::VSELECT:
60366040 if (N0.getOperand(0).getOpcode() != ISD::SETCC)
60376041 return SDValue();
@@ -12184,8 +12188,9 @@ template <class MatchContextClass>
1218412188static SDValue foldBoolSelectToLogic(SDNode *N, const SDLoc &DL,
1218512189 SelectionDAG &DAG) {
1218612190 assert((N->getOpcode() == ISD::SELECT || N->getOpcode() == ISD::VSELECT ||
12187- N->getOpcode() == ISD::VP_SELECT) &&
12188- "Expected a (v)(vp.)select");
12191+ N->getOpcode() == ISD::VP_SELECT ||
12192+ N->getOpcode() == ISD::CTSELECT) &&
12193+ "Expected a (v)(vp.)(ct) select");
1218912194 SDValue Cond = N->getOperand(0);
1219012195 SDValue T = N->getOperand(1), F = N->getOperand(2);
1219112196 EVT VT = N->getValueType(0);
@@ -12547,6 +12552,109 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) {
1254712552 return SDValue();
1254812553}
1254912554
12555+ SDValue DAGCombiner::visitCTSELECT(SDNode *N) {
12556+ SDValue N0 = N->getOperand(0);
12557+ SDValue N1 = N->getOperand(1);
12558+ SDValue N2 = N->getOperand(2);
12559+ EVT VT = N->getValueType(0);
12560+ EVT VT0 = N0.getValueType();
12561+ SDLoc DL(N);
12562+ SDNodeFlags Flags = N->getFlags();
12563+
12564+ if (SDValue V = foldBoolSelectToLogic<EmptyMatchContext>(N, DL, DAG))
12565+ return V;
12566+
12567+ // ctselect (not Cond), N1, N2 -> ctselect Cond, N2, N1
12568+ if (SDValue F = extractBooleanFlip(N0, DAG, TLI, false)) {
12569+ SDValue SelectOp = DAG.getNode(ISD::CTSELECT, DL, VT, F, N2, N1);
12570+ SelectOp->setFlags(Flags);
12571+ return SelectOp;
12572+ }
12573+
12574+ if (VT0 == MVT::i1) {
12575+ // The code in this block deals with the following 2 equivalences:
12576+ // select(C0|C1, x, y) <=> select(C0, x, select(C1, x, y))
12577+ // select(C0&C1, x, y) <=> select(C0, select(C1, x, y), y)
12578+ // The target can specify its preferred form with the
12579+ // shouldNormalizeToSelectSequence() callback. However we always transform
12580+ // to the right anyway if we find the inner select exists in the DAG anyway
12581+ // and we always transform to the left side if we know that we can further
12582+ // optimize the combination of the conditions.
12583+ bool normalizeToSequence =
12584+ TLI.shouldNormalizeToSelectSequence(*DAG.getContext(), VT);
12585+ // ctselect (and Cond0, Cond1), X, Y
12586+ // -> ctselect Cond0, (ctselect Cond1, X, Y), Y
12587+ if (N0->getOpcode() == ISD::AND && N0->hasOneUse()) {
12588+ SDValue Cond0 = N0->getOperand(0);
12589+ SDValue Cond1 = N0->getOperand(1);
12590+ SDValue InnerSelect = DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(),
12591+ Cond1, N1, N2, Flags);
12592+ if (normalizeToSequence || !InnerSelect.use_empty())
12593+ return DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(), Cond0,
12594+ InnerSelect, N2, Flags);
12595+ // Cleanup on failure.
12596+ if (InnerSelect.use_empty())
12597+ recursivelyDeleteUnusedNodes(InnerSelect.getNode());
12598+ }
12599+ // ctselect (or Cond0, Cond1), X, Y -> ctselect Cond0, X, (ctselect Cond1,
12600+ // X, Y)
12601+ if (N0->getOpcode() == ISD::OR && N0->hasOneUse()) {
12602+ SDValue Cond0 = N0->getOperand(0);
12603+ SDValue Cond1 = N0->getOperand(1);
12604+ SDValue InnerSelect = DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(),
12605+ Cond1, N1, N2, Flags);
12606+ if (normalizeToSequence || !InnerSelect.use_empty())
12607+ return DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(), Cond0, N1,
12608+ InnerSelect, Flags);
12609+ // Cleanup on failure.
12610+ if (InnerSelect.use_empty())
12611+ recursivelyDeleteUnusedNodes(InnerSelect.getNode());
12612+ }
12613+
12614+ // ctselect Cond0, (ctselect Cond1, X, Y), Y -> ctselect (and Cond0, Cond1),
12615+ // X, Y
12616+ if (N1->getOpcode() == ISD::CTSELECT && N1->hasOneUse()) {
12617+ SDValue N1_0 = N1->getOperand(0);
12618+ SDValue N1_1 = N1->getOperand(1);
12619+ SDValue N1_2 = N1->getOperand(2);
12620+ if (N1_2 == N2 && N0.getValueType() == N1_0.getValueType()) {
12621+ // Create the actual and node if we can generate good code for it.
12622+ if (!normalizeToSequence) {
12623+ SDValue And = DAG.getNode(ISD::AND, DL, N0.getValueType(), N0, N1_0);
12624+ return DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(), And, N1_1,
12625+ N2, Flags);
12626+ }
12627+ // Otherwise see if we can optimize the "and" to a better pattern.
12628+ if (SDValue Combined = visitANDLike(N0, N1_0, N)) {
12629+ return DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(), Combined,
12630+ N1_1, N2, Flags);
12631+ }
12632+ }
12633+ }
12634+ // ctselect Cond0, X, (ctselect Cond1, X, Y) -> ctselect (or Cond0, Cond1),
12635+ // X, Y
12636+ if (N2->getOpcode() == ISD::CTSELECT && N2->hasOneUse()) {
12637+ SDValue N2_0 = N2->getOperand(0);
12638+ SDValue N2_1 = N2->getOperand(1);
12639+ SDValue N2_2 = N2->getOperand(2);
12640+ if (N2_1 == N1 && N0.getValueType() == N2_0.getValueType()) {
12641+ // Create the actual or node if we can generate good code for it.
12642+ if (!normalizeToSequence) {
12643+ SDValue Or = DAG.getNode(ISD::OR, DL, N0.getValueType(), N0, N2_0);
12644+ return DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(), Or, N1, N2_2,
12645+ Flags);
12646+ }
12647+ // Otherwise see if we can optimize to a better pattern.
12648+ if (SDValue Combined = visitORLike(N0, N2_0, DL))
12649+ return DAG.getNode(ISD::CTSELECT, DL, N1.getValueType(), Combined, N1,
12650+ N2_2, Flags);
12651+ }
12652+ }
12653+ }
12654+
12655+ return SDValue();
12656+ }
12657+
1255012658// This function assumes all the vselect's arguments are CONCAT_VECTOR
1255112659// nodes and that the condition is a BV of ConstantSDNodes (or undefs).
1255212660static SDValue ConvertSelectToConcatVector(SDNode *N, SelectionDAG &DAG) {
0 commit comments