Skip to content

Commit 0ba7818

Browse files
authored
[X86] LowerSelect - generalize "select icmp(x,0), lhs, rhs" folding patterns [NFC] (#107374)
This patch proposes we add a LowerSELECTWithCmpZero helper, which allows us to fold the compare-with-zero from different condition nodes with minimal duplication. So far I've only handled the simple no-cmov case for or/xor nodes, but the intention is to convert more folds in future PRs. NFC preliminary patch for #107272
1 parent 80cd214 commit 0ba7818

File tree

1 file changed

+52
-35
lines changed

1 file changed

+52
-35
lines changed

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24074,6 +24074,55 @@ static bool isTruncWithZeroHighBitsInput(SDValue V, SelectionDAG &DAG) {
2407424074
return DAG.MaskedValueIsZero(VOp0, APInt::getHighBitsSet(InBits,InBits-Bits));
2407524075
}
2407624076

24077+
// Lower various (select (icmp CmpVal, 0), LHS, RHS) custom patterns.
24078+
static SDValue LowerSELECTWithCmpZero(SDValue CmpVal, SDValue LHS, SDValue RHS,
24079+
unsigned X86CC, const SDLoc &DL,
24080+
SelectionDAG &DAG,
24081+
const X86Subtarget &Subtarget) {
24082+
EVT CmpVT = CmpVal.getValueType();
24083+
EVT VT = LHS.getValueType();
24084+
if (!CmpVT.isScalarInteger() || !VT.isScalarInteger())
24085+
return SDValue();
24086+
24087+
if (!Subtarget.canUseCMOV() && X86CC == X86::COND_E &&
24088+
CmpVal.getOpcode() == ISD::AND && isOneConstant(CmpVal.getOperand(1))) {
24089+
SDValue Src1, Src2;
24090+
// true if RHS is XOR or OR operator and one of its operands
24091+
// is equal to LHS
24092+
// ( a , a op b) || ( b , a op b)
24093+
auto isOrXorPattern = [&]() {
24094+
if ((RHS.getOpcode() == ISD::XOR || RHS.getOpcode() == ISD::OR) &&
24095+
(RHS.getOperand(0) == LHS || RHS.getOperand(1) == LHS)) {
24096+
Src1 = RHS.getOperand(RHS.getOperand(0) == LHS ? 1 : 0);
24097+
Src2 = LHS;
24098+
return true;
24099+
}
24100+
return false;
24101+
};
24102+
24103+
if (isOrXorPattern()) {
24104+
SDValue Neg;
24105+
unsigned int CmpSz = CmpVT.getSizeInBits();
24106+
// we need mask of all zeros or ones with same size of the other
24107+
// operands.
24108+
if (CmpSz > VT.getSizeInBits())
24109+
Neg = DAG.getNode(ISD::TRUNCATE, DL, VT, CmpVal);
24110+
else if (CmpSz < VT.getSizeInBits())
24111+
Neg = DAG.getNode(
24112+
ISD::AND, DL, VT,
24113+
DAG.getNode(ISD::ANY_EXTEND, DL, VT, CmpVal.getOperand(0)),
24114+
DAG.getConstant(1, DL, VT));
24115+
else
24116+
Neg = CmpVal;
24117+
SDValue Mask = DAG.getNegative(Neg, DL, VT); // -(and (x, 0x1))
24118+
SDValue And = DAG.getNode(ISD::AND, DL, VT, Mask, Src1); // Mask & z
24119+
return DAG.getNode(RHS.getOpcode(), DL, VT, And, Src2); // And Op y
24120+
}
24121+
}
24122+
24123+
return SDValue();
24124+
}
24125+
2407724126
SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
2407824127
bool AddTest = true;
2407924128
SDValue Cond = Op.getOperand(0);
@@ -24218,41 +24267,9 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
2421824267
DAG.getTargetConstant(X86::COND_B, DL, MVT::i8),
2421924268
Sub.getValue(1));
2422024269
return DAG.getNode(ISD::OR, DL, VT, SBB, Y);
24221-
} else if (!Subtarget.canUseCMOV() && CondCode == X86::COND_E &&
24222-
CmpOp0.getOpcode() == ISD::AND &&
24223-
isOneConstant(CmpOp0.getOperand(1))) {
24224-
SDValue Src1, Src2;
24225-
// true if Op2 is XOR or OR operator and one of its operands
24226-
// is equal to Op1
24227-
// ( a , a op b) || ( b , a op b)
24228-
auto isOrXorPattern = [&]() {
24229-
if ((Op2.getOpcode() == ISD::XOR || Op2.getOpcode() == ISD::OR) &&
24230-
(Op2.getOperand(0) == Op1 || Op2.getOperand(1) == Op1)) {
24231-
Src1 =
24232-
Op2.getOperand(0) == Op1 ? Op2.getOperand(1) : Op2.getOperand(0);
24233-
Src2 = Op1;
24234-
return true;
24235-
}
24236-
return false;
24237-
};
24238-
24239-
if (isOrXorPattern()) {
24240-
SDValue Neg;
24241-
unsigned int CmpSz = CmpOp0.getSimpleValueType().getSizeInBits();
24242-
// we need mask of all zeros or ones with same size of the other
24243-
// operands.
24244-
if (CmpSz > VT.getSizeInBits())
24245-
Neg = DAG.getNode(ISD::TRUNCATE, DL, VT, CmpOp0);
24246-
else if (CmpSz < VT.getSizeInBits())
24247-
Neg = DAG.getNode(ISD::AND, DL, VT,
24248-
DAG.getNode(ISD::ANY_EXTEND, DL, VT, CmpOp0.getOperand(0)),
24249-
DAG.getConstant(1, DL, VT));
24250-
else
24251-
Neg = CmpOp0;
24252-
SDValue Mask = DAG.getNegative(Neg, DL, VT); // -(and (x, 0x1))
24253-
SDValue And = DAG.getNode(ISD::AND, DL, VT, Mask, Src1); // Mask & z
24254-
return DAG.getNode(Op2.getOpcode(), DL, VT, And, Src2); // And Op y
24255-
}
24270+
} else if (SDValue R = LowerSELECTWithCmpZero(CmpOp0, Op1, Op2, CondCode,
24271+
DL, DAG, Subtarget)) {
24272+
return R;
2425624273
} else if ((VT == MVT::i32 || VT == MVT::i64) && isNullConstant(Op2) &&
2425724274
Cmp.getNode()->hasOneUse() && (CmpOp0 == Op1) &&
2425824275
((CondCode == X86::COND_S) || // smin(x, 0)

0 commit comments

Comments
 (0)