@@ -7204,6 +7204,39 @@ static SDValue foldLogicTreeOfShifts(SDNode *N, SDValue LeftHand,
7204
7204
return DAG.getNode(LogicOpcode, DL, VT, CombinedShifts, W);
7205
7205
}
7206
7206
7207
+ /// Fold "masked merge" expressions like `(m & x) | (~m & y)` and its DeMorgan
7208
+ /// variant `(~m | x) & (m | y)` into the equivalent `((x ^ y) & m) ^ y)`
7209
+ /// pattern. This is typically a better representation for targets without a
7210
+ /// fused "and-not" operation.
7211
+ static SDValue foldMaskedMerge(SDNode *Node, SelectionDAG &DAG,
7212
+ const TargetLowering &TLI, const SDLoc &DL) {
7213
+ // Note that masked-merge variants using XOR or ADD expressions are
7214
+ // normalized to OR by InstCombine so we only check for OR or AND.
7215
+ assert(Node->getOpcode() == ISD::OR ||
7216
+ Node->getOpcode() == ISD::AND &&
7217
+ "Must be called with ISD::OR or ISD::AND node");
7218
+
7219
+ // If the target supports and-not, don't fold this.
7220
+ if (TLI.hasAndNot(SDValue(Node, 0)))
7221
+ return SDValue();
7222
+
7223
+ SDValue M, X, Y;
7224
+
7225
+ if (sd_match(Node,
7226
+ m_Or(m_OneUse(m_And(m_OneUse(m_Not(m_Value(M))), m_Value(Y))),
7227
+ m_OneUse(m_And(m_Deferred(M), m_Value(X))))) ||
7228
+ sd_match(Node,
7229
+ m_And(m_OneUse(m_Or(m_OneUse(m_Not(m_Value(M))), m_Value(X))),
7230
+ m_OneUse(m_Or(m_Deferred(M), m_Value(Y)))))) {
7231
+ EVT VT = M.getValueType();
7232
+ SDValue Xor = DAG.getNode(ISD::XOR, DL, VT, X, Y);
7233
+ SDValue And = DAG.getNode(ISD::AND, DL, VT, Xor, M);
7234
+ return DAG.getNode(ISD::XOR, DL, VT, And, Y);
7235
+ }
7236
+
7237
+ return SDValue();
7238
+ }
7239
+
7207
7240
SDValue DAGCombiner::visitAND(SDNode *N) {
7208
7241
SDValue N0 = N->getOperand(0);
7209
7242
SDValue N1 = N->getOperand(1);
@@ -7644,6 +7677,10 @@ SDValue DAGCombiner::visitAND(SDNode *N) {
7644
7677
if (SDValue R = foldLogicTreeOfShifts(N, N0, N1, DAG))
7645
7678
return R;
7646
7679
7680
+ if (VT.isScalarInteger() && VT != MVT::i1)
7681
+ if (SDValue R = foldMaskedMerge(N, DAG, TLI, DL))
7682
+ return R;
7683
+
7647
7684
return SDValue();
7648
7685
}
7649
7686
@@ -8128,32 +8165,6 @@ static SDValue visitORCommutative(SelectionDAG &DAG, SDValue N0, SDValue N1,
8128
8165
return SDValue();
8129
8166
}
8130
8167
8131
- /// Fold "masked merge" expressions like `(m & x) | (~m & y)` into the
8132
- /// equivalent `((x ^ y) & m) ^ y)` pattern.
8133
- /// This is typically a better representation for targets without a fused
8134
- /// "and-not" operation.
8135
- static SDValue foldMaskedMerge(SDNode *Node, SelectionDAG &DAG,
8136
- const TargetLowering &TLI, const SDLoc &DL) {
8137
- // Note that masked-merge variants using XOR or ADD expressions are
8138
- // normalized to OR by InstCombine so we only check for OR.
8139
- assert(Node->getOpcode() == ISD::OR && "Must be called with ISD::OR node");
8140
-
8141
- // If the target supports and-not, don't fold this.
8142
- if (TLI.hasAndNot(SDValue(Node, 0)))
8143
- return SDValue();
8144
-
8145
- SDValue M, X, Y;
8146
- if (sd_match(Node,
8147
- m_Or(m_OneUse(m_And(m_OneUse(m_Not(m_Value(M))), m_Value(Y))),
8148
- m_OneUse(m_And(m_Deferred(M), m_Value(X)))))) {
8149
- EVT VT = M.getValueType();
8150
- SDValue Xor = DAG.getNode(ISD::XOR, DL, VT, X, Y);
8151
- SDValue And = DAG.getNode(ISD::AND, DL, VT, Xor, M);
8152
- return DAG.getNode(ISD::XOR, DL, VT, And, Y);
8153
- }
8154
- return SDValue();
8155
- }
8156
-
8157
8168
SDValue DAGCombiner::visitOR(SDNode *N) {
8158
8169
SDValue N0 = N->getOperand(0);
8159
8170
SDValue N1 = N->getOperand(1);
0 commit comments