Skip to content

Commit 3a97d81

Browse files
committed
Fold (a | b) == a -> (a & ~b) == 0 when and-not exists
This is especially helpful for AArch64, which simplifies ands cmp to tst.
1 parent e83cb31 commit 3a97d81

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5800,6 +5800,8 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
58005800
private:
58015801
SDValue foldSetCCWithAnd(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond,
58025802
const SDLoc &DL, DAGCombinerInfo &DCI) const;
5803+
SDValue foldSetCCWithOr(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond,
5804+
const SDLoc &DL, DAGCombinerInfo &DCI) const;
58035805
SDValue foldSetCCWithBinOp(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond,
58045806
const SDLoc &DL, DAGCombinerInfo &DCI) const;
58055807

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4212,6 +4212,56 @@ SDValue TargetLowering::foldSetCCWithAnd(EVT VT, SDValue N0, SDValue N1,
42124212
return SDValue();
42134213
}
42144214

4215+
/// This helper function of SimplifySetCC tries to optimize the comparison when
4216+
/// either operand of the SetCC node is a bitwise-or instruction.
4217+
SDValue TargetLowering::foldSetCCWithOr(EVT VT, SDValue N0, SDValue N1,
4218+
ISD::CondCode Cond, const SDLoc &DL,
4219+
DAGCombinerInfo &DCI) const {
4220+
if (N1.getOpcode() == ISD::OR && N0.getOpcode() != ISD::OR)
4221+
std::swap(N0, N1);
4222+
4223+
SelectionDAG &DAG = DCI.DAG;
4224+
EVT OpVT = N0.getValueType();
4225+
if (N0.getOpcode() != ISD::OR || !OpVT.isInteger() ||
4226+
(Cond != ISD::SETEQ && Cond != ISD::SETNE))
4227+
return SDValue();
4228+
4229+
// Match these patterns in any of their permutations:
4230+
// (X | Y) == Y
4231+
// (X | Y) != Y
4232+
SDValue X, Y;
4233+
if (N0.getOperand(0) == N1) {
4234+
X = N0.getOperand(1);
4235+
Y = N0.getOperand(0);
4236+
} else if (N0.getOperand(1) == N1) {
4237+
X = N0.getOperand(0);
4238+
Y = N0.getOperand(1);
4239+
} else {
4240+
return SDValue();
4241+
}
4242+
4243+
SDValue Zero = DAG.getConstant(0, DL, OpVT);
4244+
if (N0.hasOneUse() && hasAndNotCompare(Y)) {
4245+
// If the target supports an 'and-not' or 'and-complement' logic operation,
4246+
// try to use that to make a comparison operation more efficient.
4247+
// But don't do this transform if the mask is a single bit because there are
4248+
// more efficient ways to deal with that case (for example, 'bt' on x86 or
4249+
// 'rlwinm' on PPC).
4250+
4251+
// Bail out if the compare operand that we want to turn into a zero is
4252+
// already a zero (otherwise, infinite loop).
4253+
if (isNullConstant(Y))
4254+
return SDValue();
4255+
4256+
// Transform this into: X & ~Y == 0.
4257+
SDValue NotY = DAG.getNOT(SDLoc(Y), Y, OpVT);
4258+
SDValue NewAnd = DAG.getNode(ISD::AND, SDLoc(N0), OpVT, X, NotY);
4259+
return DAG.getSetCC(DL, VT, NewAnd, Zero, Cond);
4260+
}
4261+
4262+
return SDValue();
4263+
}
4264+
42154265
/// There are multiple IR patterns that could be checking whether certain
42164266
/// truncation of a signed number would be lossy or not. The pattern which is
42174267
/// best at IR level, may not lower optimally. Thus, we want to unfold it.
@@ -5507,6 +5557,9 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
55075557

55085558
if (SDValue V = foldSetCCWithAnd(VT, N0, N1, Cond, dl, DCI))
55095559
return V;
5560+
5561+
if (SDValue V = foldSetCCWithOr(VT, N0, N1, Cond, dl, DCI))
5562+
return V;
55105563
}
55115564

55125565
// Fold remainder of division by a constant.

0 commit comments

Comments
 (0)