@@ -5143,6 +5143,113 @@ SDValue ARMTargetLowering::LowerUnsignedALUO(SDValue Op,
5143
5143
return DAG.getNode(ISD::MERGE_VALUES, dl, VTs, Value, Overflow);
5144
5144
}
5145
5145
5146
+ // Lower various (select (icmp CmpVal, 0), LHS, RHS) custom patterns.
5147
+ static SDValue LowerSELECTWithCmpZero(SDValue CmpVal, SDValue LHS, SDValue RHS,
5148
+ ISD::CondCode CC, const SDLoc &DL,
5149
+ SelectionDAG &DAG,
5150
+ const ARMSubtarget &Subtarget) {
5151
+ EVT CmpVT = CmpVal.getValueType();
5152
+ EVT VT = LHS.getValueType();
5153
+ if (!CmpVT.isScalarInteger() || !VT.isScalarInteger())
5154
+ return SDValue();
5155
+
5156
+ if (CC == ISD::SETEQ && CmpVal.getOpcode() == ISD::AND &&
5157
+ isOneConstant(CmpVal.getOperand(1))) {
5158
+ auto SplatLSB = [&](EVT SplatVT) {
5159
+ // we need mask of all zeros or ones with same size of the other
5160
+ // operands.
5161
+ SDValue Neg = CmpVal;
5162
+ if (CmpVT.bitsGT(SplatVT))
5163
+ Neg = DAG.getNode(ISD::TRUNCATE, DL, SplatVT, CmpVal);
5164
+ else if (CmpVT.bitsLT(SplatVT))
5165
+ Neg = DAG.getNode(
5166
+ ISD::AND, DL, SplatVT,
5167
+ DAG.getNode(ISD::ANY_EXTEND, DL, SplatVT, CmpVal.getOperand(0)),
5168
+ DAG.getConstant(1, DL, SplatVT));
5169
+ return DAG.getNegative(Neg, DL, SplatVT); // -(and (x, 0x1))
5170
+ };
5171
+
5172
+ // SELECT (AND(X,1) == 0), 0, -1 -> NEG(AND(X,1))
5173
+ if (isNullConstant(LHS) && isAllOnesConstant(RHS))
5174
+ return SplatLSB(VT);
5175
+
5176
+ // SELECT (AND(X,1) == 0), C1, C2 -> XOR(C1,AND(NEG(AND(X,1)),XOR(C1,C2))
5177
+ if (Subtarget.isThumb1Only() && isa<ConstantSDNode>(LHS) &&
5178
+ isa<ConstantSDNode>(RHS)) {
5179
+ SDValue Mask = SplatLSB(VT);
5180
+ SDValue Diff = DAG.getNode(ISD::XOR, DL, VT, LHS, RHS);
5181
+ SDValue Flip = DAG.getNode(ISD::AND, DL, VT, Mask, Diff);
5182
+ return DAG.getNode(ISD::XOR, DL, VT, LHS, Flip);
5183
+ }
5184
+
5185
+ SDValue Src1, Src2;
5186
+ auto isIdentityPatternZero = [&]() {
5187
+ switch (RHS.getOpcode()) {
5188
+ default:
5189
+ break;
5190
+ case ISD::OR:
5191
+ case ISD::XOR:
5192
+ case ISD::ADD:
5193
+ if (RHS.getOperand(0) == LHS || RHS.getOperand(1) == LHS) {
5194
+ Src1 = RHS.getOperand(RHS.getOperand(0) == LHS ? 1 : 0);
5195
+ Src2 = LHS;
5196
+ return true;
5197
+ }
5198
+ break;
5199
+ case ISD::SHL:
5200
+ case ISD::SRA:
5201
+ case ISD::SRL:
5202
+ case ISD::SUB:
5203
+ if (RHS.getOperand(0) == LHS) {
5204
+ Src1 = RHS.getOperand(1);
5205
+ Src2 = LHS;
5206
+ return true;
5207
+ }
5208
+ break;
5209
+ }
5210
+ return false;
5211
+ };
5212
+
5213
+ auto isIdentityPatternOnes = [&]() {
5214
+ switch (LHS.getOpcode()) {
5215
+ default:
5216
+ break;
5217
+ case ISD::AND:
5218
+ if (LHS.getOperand(0) == RHS || LHS.getOperand(1) == RHS) {
5219
+ Src1 = LHS.getOperand(LHS.getOperand(0) == RHS ? 1 : 0);
5220
+ Src2 = RHS;
5221
+ return true;
5222
+ }
5223
+ break;
5224
+ }
5225
+ return false;
5226
+ };
5227
+
5228
+ // Convert 'identity' patterns (iff X is 0 or 1):
5229
+ // SELECT (AND(X,1) == 0), Y, (OR Y, Z) -> (OR Y, (AND NEG(AND(X,1)), Z))
5230
+ // SELECT (AND(X,1) == 0), Y, (XOR Y, Z) -> (XOR Y, (AND NEG(AND(X,1)), Z))
5231
+ // SELECT (AND(X,1) == 0), Y, (ADD Y, Z) -> (ADD Y, (AND NEG(AND(X,1)), Z))
5232
+ // SELECT (AND(X,1) == 0), Y, (SUB Y, Z) -> (SUB Y, (AND NEG(AND(X,1)), Z))
5233
+ // SELECT (AND(X,1) == 0), Y, (SHL Y, Z) -> (SHL Y, (AND NEG(AND(X,1)), Z))
5234
+ // SELECT (AND(X,1) == 0), Y, (SRA Y, Z) -> (SRA Y, (AND NEG(AND(X,1)), Z))
5235
+ // SELECT (AND(X,1) == 0), Y, (SRL Y, Z) -> (SRL Y, (AND NEG(AND(X,1)), Z))
5236
+ if (Subtarget.isThumb1Only() && isIdentityPatternZero()) {
5237
+ SDValue Mask = SplatLSB(Src1.getValueType());
5238
+ SDValue And = DAG.getNode(ISD::AND, DL, Src1.getValueType(), Mask,
5239
+ Src1); // Mask & z
5240
+ return DAG.getNode(RHS.getOpcode(), DL, VT, Src2, And); // y Op And
5241
+ }
5242
+ // SELECT (AND(X,1) == 0), (AND Y, Z), Y -> (AND Y, (OR NEG(AND(X, 1)), Z))
5243
+ if (Subtarget.isThumb1Only() && isIdentityPatternOnes()) {
5244
+ SDValue Mask = SplatLSB(VT);
5245
+ SDValue Or = DAG.getNode(ISD::OR, DL, VT, Mask, Src1); // Mask | z
5246
+ return DAG.getNode(LHS.getOpcode(), DL, VT, Src2, Or); // y Op Or
5247
+ }
5248
+ }
5249
+
5250
+ return SDValue();
5251
+ }
5252
+
5146
5253
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG,
5147
5254
const ARMSubtarget *Subtarget) {
5148
5255
EVT VT = Op.getValueType();
@@ -5521,7 +5628,6 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
5521
5628
ConstantSDNode *CTVal = dyn_cast<ConstantSDNode>(TrueVal);
5522
5629
ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS);
5523
5630
if (Op.getValueType().isInteger()) {
5524
-
5525
5631
// Check for SMAX(lhs, 0) and SMIN(lhs, 0) patterns.
5526
5632
// (SELECT_CC setgt, lhs, 0, lhs, 0) -> (BIC lhs, (SRA lhs, typesize-1))
5527
5633
// (SELECT_CC setlt, lhs, 0, lhs, 0) -> (AND lhs, (SRA lhs, typesize-1))
@@ -5539,6 +5645,11 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
5539
5645
5540
5646
return DAG.getNode(ISD::AND, dl, VT, LHS, Shift);
5541
5647
}
5648
+ if (RHSC && RHSC->isZero()) {
5649
+ if (SDValue R = LowerSELECTWithCmpZero(LHS, TrueVal, FalseVal, CC, dl,
5650
+ DAG, *Subtarget))
5651
+ return R;
5652
+ }
5542
5653
}
5543
5654
5544
5655
if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
0 commit comments