[llvm] r348501 - [DAGCombiner] refactor function that hoists bitwise logic; NFCI
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 6 09:08:03 PST 2018
Author: spatel
Date: Thu Dec 6 09:08:03 2018
New Revision: 348501
URL: http://llvm.org/viewvc/llvm-project?rev=348501&view=rev
Log:
[DAGCombiner] refactor function that hoists bitwise logic; NFCI
Added FIXME and TODO comments for lack of safety checks.
This function is a suspect in out-of-memory errors as discussed in
the follow-up thread to r347917:
http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20181203/608593.html
Modified:
llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=348501&r1=348500&r2=348501&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Thu Dec 6 09:08:03 2018
@@ -412,7 +412,7 @@ namespace {
SDValue foldVSelectOfConstants(SDNode *N);
SDValue foldBinOpIntoSelect(SDNode *BO);
bool SimplifySelectOps(SDNode *SELECT, SDValue LHS, SDValue RHS);
- SDValue SimplifyBinOpWithSameOpcodeHands(SDNode *N);
+ SDValue hoistLogicOpWithSameOpcodeHands(SDNode *N);
SDValue SimplifySelect(const SDLoc &DL, SDValue N0, SDValue N1, SDValue N2);
SDValue SimplifySelectCC(const SDLoc &DL, SDValue N0, SDValue N1,
SDValue N2, SDValue N3, ISD::CondCode CC,
@@ -3700,59 +3700,71 @@ SDValue DAGCombiner::visitIMINMAX(SDNode
return SDValue();
}
-/// If this is a binary operator with two operands of the same opcode, try to
-/// simplify it.
-SDValue DAGCombiner::SimplifyBinOpWithSameOpcodeHands(SDNode *N) {
+/// If this is a bitwise logic instruction and both operands have the same
+/// opcode, try to sink the other opcode after the logic instruction.
+SDValue DAGCombiner::hoistLogicOpWithSameOpcodeHands(SDNode *N) {
SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
EVT VT = N0.getValueType();
- assert(N0.getOpcode() == N1.getOpcode() && "Bad input!");
+ unsigned LogicOpcode = N->getOpcode();
+ unsigned HandOpcode = N0.getOpcode();
+ assert((LogicOpcode == ISD::AND || LogicOpcode == ISD::OR ||
+ LogicOpcode == ISD::XOR) && "Expected logic opcode");
+ assert(HandOpcode == N1.getOpcode() && "Bad input!");
// Bail early if none of these transforms apply.
- if (N0.getNumOperands() == 0) return SDValue();
+ if (N0.getNumOperands() == 0)
+ return SDValue();
+
+ // FIXME: We need to check number of uses of the operands to not increase
+ // the instruction count.
- // For each of OP in AND/OR/XOR:
- // fold (OP (zext x), (zext y)) -> (zext (OP x, y))
- // fold (OP (sext x), (sext y)) -> (sext (OP x, y))
- // fold (OP (aext x), (aext y)) -> (aext (OP x, y))
- // fold (OP (bswap x), (bswap y)) -> (bswap (OP x, y))
- // fold (OP (trunc x), (trunc y)) -> (trunc (OP x, y)) (if trunc isn't free)
- //
- // do not sink logical op inside of a vector extend, since it may combine
- // into a vsetcc.
EVT Op0VT = N0.getOperand(0).getValueType();
- if ((N0.getOpcode() == ISD::ZERO_EXTEND ||
- N0.getOpcode() == ISD::SIGN_EXTEND ||
- N0.getOpcode() == ISD::BSWAP ||
- // Avoid infinite looping with PromoteIntBinOp.
- (N0.getOpcode() == ISD::ANY_EXTEND &&
- (!LegalTypes || TLI.isTypeDesirableForOp(N->getOpcode(), Op0VT))) ||
- (N0.getOpcode() == ISD::TRUNCATE &&
- (!TLI.isZExtFree(VT, Op0VT) ||
- !TLI.isTruncateFree(Op0VT, VT)) &&
- TLI.isTypeLegal(Op0VT))) &&
- !VT.isVector() &&
- Op0VT == N1.getOperand(0).getValueType() &&
- (!LegalOperations || TLI.isOperationLegal(N->getOpcode(), Op0VT))) {
- SDValue ORNode = DAG.getNode(N->getOpcode(), SDLoc(N0),
- N0.getOperand(0).getValueType(),
- N0.getOperand(0), N1.getOperand(0));
- AddToWorklist(ORNode.getNode());
- return DAG.getNode(N0.getOpcode(), SDLoc(N), VT, ORNode);
+ switch (HandOpcode) {
+ case ISD::ANY_EXTEND:
+ case ISD::TRUNCATE:
+ case ISD::ZERO_EXTEND:
+ case ISD::SIGN_EXTEND:
+ case ISD::BSWAP:
+ // We need matching integer source types.
+ // Do not hoist logic op inside of a vector extend, since it may combine
+ // into a vsetcc.
+ // TODO: Should the vector check apply to truncate and bswap though?
+ if (VT.isVector() || Op0VT != N1.getOperand(0).getValueType())
+ return SDValue();
+ // Don't create an illegal op during or after legalization.
+ if (LegalOperations && !TLI.isOperationLegal(LogicOpcode, Op0VT))
+ return SDValue();
+ // Avoid infinite looping with PromoteIntBinOp.
+ if (HandOpcode == ISD::ANY_EXTEND && LegalTypes &&
+ !TLI.isTypeDesirableForOp(LogicOpcode, Op0VT))
+ return SDValue();
+ // Be extra careful sinking truncate.
+ // TODO: Should we apply desirable/legal constraints to all opcodes?
+ if (HandOpcode == ISD::TRUNCATE) {
+ if (TLI.isZExtFree(VT, Op0VT) && TLI.isTruncateFree(Op0VT, VT))
+ return SDValue();
+ if (!TLI.isTypeLegal(Op0VT))
+ return SDValue();
+ }
+ // logic_op (hand_op X), (hand_op Y) --> hand_op (logic_op X, Y)
+ SDValue Logic = DAG.getNode(LogicOpcode, SDLoc(N0), Op0VT,
+ N0.getOperand(0), N1.getOperand(0));
+ AddToWorklist(Logic.getNode());
+ return DAG.getNode(HandOpcode, SDLoc(N), VT, Logic);
}
// For each of OP in SHL/SRL/SRA/AND...
// fold (and (OP x, z), (OP y, z)) -> (OP (and x, y), z)
// fold (or (OP x, z), (OP y, z)) -> (OP (or x, y), z)
// fold (xor (OP x, z), (OP y, z)) -> (OP (xor x, y), z)
- if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL ||
- N0.getOpcode() == ISD::SRA || N0.getOpcode() == ISD::AND) &&
+ if ((HandOpcode == ISD::SHL || HandOpcode == ISD::SRL ||
+ HandOpcode == ISD::SRA || HandOpcode == ISD::AND) &&
N0.getOperand(1) == N1.getOperand(1)) {
- SDValue ORNode = DAG.getNode(N->getOpcode(), SDLoc(N0),
+ SDValue ORNode = DAG.getNode(LogicOpcode, SDLoc(N0),
N0.getOperand(0).getValueType(),
N0.getOperand(0), N1.getOperand(0));
AddToWorklist(ORNode.getNode());
- return DAG.getNode(N0.getOpcode(), SDLoc(N), VT,
- ORNode, N0.getOperand(1));
+ return DAG.getNode(HandOpcode, SDLoc(N), VT, ORNode, N0.getOperand(1));
}
// Simplify xor/and/or (bitcast(A), bitcast(B)) -> bitcast(op (A,B))
@@ -3762,8 +3774,7 @@ SDValue DAGCombiner::SimplifyBinOpWithSa
// we don't want to undo this promotion.
// We also handle SCALAR_TO_VECTOR because xor/or/and operations are cheaper
// on scalars.
- if ((N0.getOpcode() == ISD::BITCAST ||
- N0.getOpcode() == ISD::SCALAR_TO_VECTOR) &&
+ if ((HandOpcode == ISD::BITCAST || HandOpcode == ISD::SCALAR_TO_VECTOR) &&
Level <= AfterLegalizeTypes) {
SDValue In0 = N0.getOperand(0);
SDValue In1 = N1.getOperand(0);
@@ -3773,8 +3784,8 @@ SDValue DAGCombiner::SimplifyBinOpWithSa
// If both incoming values are integers, and the original types are the
// same.
if (In0Ty.isInteger() && In1Ty.isInteger() && In0Ty == In1Ty) {
- SDValue Op = DAG.getNode(N->getOpcode(), DL, In0Ty, In0, In1);
- SDValue BC = DAG.getNode(N0.getOpcode(), DL, VT, Op);
+ SDValue Op = DAG.getNode(LogicOpcode, DL, In0Ty, In0, In1);
+ SDValue BC = DAG.getNode(HandOpcode, DL, VT, Op);
AddToWorklist(Op.getNode());
return BC;
}
@@ -3792,7 +3803,7 @@ SDValue DAGCombiner::SimplifyBinOpWithSa
// If both shuffles use the same mask, and both shuffles have the same first
// or second operand, then it might still be profitable to move the shuffle
// after the xor/and/or operation.
- if (N0.getOpcode() == ISD::VECTOR_SHUFFLE && Level < AfterLegalizeDAG) {
+ if (HandOpcode == ISD::VECTOR_SHUFFLE && Level < AfterLegalizeDAG) {
ShuffleVectorSDNode *SVN0 = cast<ShuffleVectorSDNode>(N0);
ShuffleVectorSDNode *SVN1 = cast<ShuffleVectorSDNode>(N1);
@@ -3809,15 +3820,14 @@ SDValue DAGCombiner::SimplifyBinOpWithSa
// Don't try to fold this node if it requires introducing a
// build vector of all zeros that might be illegal at this stage.
- if (N->getOpcode() == ISD::XOR && !ShOp.isUndef()) {
+ if (LogicOpcode == ISD::XOR && !ShOp.isUndef())
ShOp = tryFoldToZero(SDLoc(N), TLI, VT, DAG, LegalOperations);
- }
// (AND (shuf (A, C), shuf (B, C))) -> shuf (AND (A, B), C)
// (OR (shuf (A, C), shuf (B, C))) -> shuf (OR (A, B), C)
// (XOR (shuf (A, C), shuf (B, C))) -> shuf (XOR (A, B), V_0)
if (N0.getOperand(1) == N1.getOperand(1) && ShOp.getNode()) {
- SDValue NewNode = DAG.getNode(N->getOpcode(), SDLoc(N), VT,
+ SDValue NewNode = DAG.getNode(LogicOpcode, SDLoc(N), VT,
N0->getOperand(0), N1->getOperand(0));
AddToWorklist(NewNode.getNode());
return DAG.getVectorShuffle(VT, SDLoc(N), NewNode, ShOp,
@@ -3827,15 +3837,14 @@ SDValue DAGCombiner::SimplifyBinOpWithSa
// Don't try to fold this node if it requires introducing a
// build vector of all zeros that might be illegal at this stage.
ShOp = N0->getOperand(0);
- if (N->getOpcode() == ISD::XOR && !ShOp.isUndef()) {
+ if (LogicOpcode == ISD::XOR && !ShOp.isUndef())
ShOp = tryFoldToZero(SDLoc(N), TLI, VT, DAG, LegalOperations);
- }
// (AND (shuf (C, A), shuf (C, B))) -> shuf (C, AND (A, B))
// (OR (shuf (C, A), shuf (C, B))) -> shuf (C, OR (A, B))
// (XOR (shuf (C, A), shuf (C, B))) -> shuf (V_0, XOR (A, B))
if (N0->getOperand(0) == N1->getOperand(0) && ShOp.getNode()) {
- SDValue NewNode = DAG.getNode(N->getOpcode(), SDLoc(N), VT,
+ SDValue NewNode = DAG.getNode(LogicOpcode, SDLoc(N), VT,
N0->getOperand(1), N1->getOperand(1));
AddToWorklist(NewNode.getNode());
return DAG.getVectorShuffle(VT, SDLoc(N), ShOp, NewNode,
@@ -4615,8 +4624,8 @@ SDValue DAGCombiner::visitAND(SDNode *N)
// Simplify: (and (op x...), (op y...)) -> (op (and x, y))
if (N0.getOpcode() == N1.getOpcode())
- if (SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N))
- return Tmp;
+ if (SDValue V = hoistLogicOpWithSameOpcodeHands(N))
+ return V;
// Masking the negated extension of a boolean is just the zero-extended
// boolean:
@@ -5174,8 +5183,8 @@ SDValue DAGCombiner::visitOR(SDNode *N)
// Simplify: (or (op x...), (op y...)) -> (op (or x, y))
if (N0.getOpcode() == N1.getOpcode())
- if (SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N))
- return Tmp;
+ if (SDValue V = hoistLogicOpWithSameOpcodeHands(N))
+ return V;
// See if this is some rotate idiom.
if (SDNode *Rot = MatchRotate(N0, N1, SDLoc(N)))
@@ -6166,8 +6175,8 @@ SDValue DAGCombiner::visitXOR(SDNode *N)
// Simplify: xor (op x...), (op y...) -> (op (xor x, y))
if (N0Opcode == N1.getOpcode())
- if (SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N))
- return Tmp;
+ if (SDValue V = hoistLogicOpWithSameOpcodeHands(N))
+ return V;
// Unfold ((x ^ y) & m) ^ y into (x & m) | (y & ~m) if profitable
if (SDValue MM = unfoldMaskedMerge(N))
More information about the llvm-commits
mailing list