aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp154
1 files changed, 137 insertions, 17 deletions
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index af4ee83981..b77b810bac 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -101,6 +101,10 @@ namespace {
WorkList.end());
}
+ /// visit - call the node-specific routine that knows how to fold each
+ /// particular type of node.
+ SDOperand visit(SDNode *N);
+
public:
/// AddToWorkList - Add to the work list making sure it's instance is at the
/// the back (next to be processed.)
@@ -201,9 +205,10 @@ namespace {
bool CombineToPostIndexedLoadStore(SDNode *N);
- /// visit - call the node-specific routine that knows how to fold each
- /// particular type of node.
- SDOperand visit(SDNode *N);
+ /// combine - call the node-specific routine that knows how to fold each
+ /// particular type of node. If that doesn't do anything, try the
+ /// target-specific DAG combines.
+ SDOperand combine(SDNode *N);
// Visitation implementation - Implement dag node combining for different
// node types. The semantics are as follows:
@@ -224,6 +229,10 @@ namespace {
SDOperand visitUREM(SDNode *N);
SDOperand visitMULHU(SDNode *N);
SDOperand visitMULHS(SDNode *N);
+ SDOperand visitSMUL_LOHI(SDNode *N);
+ SDOperand visitUMUL_LOHI(SDNode *N);
+ SDOperand visitSDIVREM(SDNode *N);
+ SDOperand visitUDIVREM(SDNode *N);
SDOperand visitAND(SDNode *N);
SDOperand visitOR(SDNode *N);
SDOperand visitXOR(SDNode *N);
@@ -279,6 +288,7 @@ namespace {
bool NotExtCompare = false);
SDOperand SimplifySetCC(MVT::ValueType VT, SDOperand N0, SDOperand N1,
ISD::CondCode Cond, bool foldBooleans = true);
+ bool SimplifyNodeWithTwoResults(SDNode *N, unsigned LoOp, unsigned HiOp);
SDOperand ConstantFoldBIT_CONVERTofBUILD_VECTOR(SDNode *, MVT::ValueType);
SDOperand BuildSDIV(SDNode *N);
SDOperand BuildUDIV(SDNode *N);
@@ -555,10 +565,6 @@ void DAGCombiner::Run(bool RunningAfterLegalize) {
// done. Set it to null to avoid confusion.
DAG.setRoot(SDOperand());
- /// DagCombineInfo - Expose the DAG combiner to the target combiner impls.
- TargetLowering::DAGCombinerInfo
- DagCombineInfo(DAG, !RunningAfterLegalize, false, this);
-
// while the worklist isn't empty, inspect the node on the end of it and
// try and combine it.
while (!WorkList.empty()) {
@@ -576,16 +582,7 @@ void DAGCombiner::Run(bool RunningAfterLegalize) {
continue;
}
- SDOperand RV = visit(N);
-
- // If nothing happened, try a target-specific DAG combine.
- if (RV.Val == 0) {
- assert(N->getOpcode() != ISD::DELETED_NODE &&
- "Node was deleted but visit returned NULL!");
- if (N->getOpcode() >= ISD::BUILTIN_OP_END ||
- TLI.hasTargetDAGCombine((ISD::NodeType)N->getOpcode()))
- RV = TLI.PerformDAGCombine(N, DagCombineInfo);
- }
+ SDOperand RV = combine(N);
if (RV.Val) {
++NodesCombined;
@@ -645,6 +642,10 @@ SDOperand DAGCombiner::visit(SDNode *N) {
case ISD::UREM: return visitUREM(N);
case ISD::MULHU: return visitMULHU(N);
case ISD::MULHS: return visitMULHS(N);
+ case ISD::SMUL_LOHI: return visitSMUL_LOHI(N);
+ case ISD::UMUL_LOHI: return visitUMUL_LOHI(N);
+ case ISD::SDIVREM: return visitSDIVREM(N);
+ case ISD::UDIVREM: return visitUDIVREM(N);
case ISD::AND: return visitAND(N);
case ISD::OR: return visitOR(N);
case ISD::XOR: return visitXOR(N);
@@ -691,6 +692,29 @@ SDOperand DAGCombiner::visit(SDNode *N) {
return SDOperand();
}
+SDOperand DAGCombiner::combine(SDNode *N) {
+
+ SDOperand RV = visit(N);
+
+ // If nothing happened, try a target-specific DAG combine.
+ if (RV.Val == 0) {
+ assert(N->getOpcode() != ISD::DELETED_NODE &&
+ "Node was deleted but visit returned NULL!");
+
+ if (N->getOpcode() >= ISD::BUILTIN_OP_END ||
+ TLI.hasTargetDAGCombine((ISD::NodeType)N->getOpcode())) {
+
+ // Expose the DAG combiner to the target combiner impls.
+ TargetLowering::DAGCombinerInfo
+ DagCombineInfo(DAG, !AfterLegalize, false, this);
+
+ RV = TLI.PerformDAGCombine(N, DagCombineInfo);
+ }
+ }
+
+ return RV;
+}
+
/// getInputChainForNode - Given a node, return its input chain if it has one,
/// otherwise return a null sd operand.
static SDOperand getInputChainForNode(SDNode *N) {
@@ -1382,6 +1406,102 @@ SDOperand DAGCombiner::visitMULHU(SDNode *N) {
return SDOperand();
}
+/// SimplifyNodeWithTwoResults - Perform optimizations common to nodes that
+/// compute two values. LoOp and HiOp give the opcodes for the two computations
+/// that are being performed. Return true if a simplification was made.
+///
+bool DAGCombiner::SimplifyNodeWithTwoResults(SDNode *N,
+ unsigned LoOp, unsigned HiOp) {
+ std::vector<SDNode*> NowDead;
+
+ // If the high half is not needed, just compute the low half.
+ if (!N->hasAnyUseOfValue(1) &&
+ (!AfterLegalize ||
+ TLI.isOperationLegal(LoOp, N->getValueType(0)))) {
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0),
+ DAG.getNode(LoOp, N->getValueType(0),
+ N->op_begin(),
+ N->getNumOperands()),
+ NowDead);
+ return true;
+ }
+
+ // If the low half is not needed, just compute the high half.
+ if (!N->hasAnyUseOfValue(0) &&
+ (!AfterLegalize ||
+ TLI.isOperationLegal(HiOp, N->getValueType(1)))) {
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1),
+ DAG.getNode(HiOp, N->getValueType(1),
+ N->op_begin(),
+ N->getNumOperands()),
+ NowDead);
+ return true;
+ }
+
+ // If the two computed results can be siplified separately, separate them.
+ SDOperand Lo = DAG.getNode(LoOp, N->getValueType(0),
+ N->op_begin(), N->getNumOperands());
+ SDOperand Hi = DAG.getNode(HiOp, N->getValueType(1),
+ N->op_begin(), N->getNumOperands());
+ unsigned LoExists = !Lo.use_empty();
+ unsigned HiExists = !Hi.use_empty();
+ SDOperand LoOpt = Lo;
+ SDOperand HiOpt = Hi;
+ if (!LoExists || !HiExists) {
+ SDOperand Pair = DAG.getNode(ISD::BUILD_PAIR, MVT::Other, Lo, Hi);
+ assert(Pair.use_empty() && "Pair with type MVT::Other already exists!");
+ LoOpt = combine(Lo.Val);
+ HiOpt = combine(Hi.Val);
+ if (!LoOpt.Val)
+ LoOpt = Pair.getOperand(0);
+ if (!HiOpt.Val)
+ HiOpt = Pair.getOperand(1);
+ DAG.DeleteNode(Pair.Val);
+ }
+ if ((LoExists || LoOpt != Lo) &&
+ (HiExists || HiOpt != Hi) &&
+ TLI.isOperationLegal(LoOpt.getOpcode(), LoOpt.getValueType()) &&
+ TLI.isOperationLegal(HiOpt.getOpcode(), HiOpt.getValueType())) {
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), LoOpt, NowDead);
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), HiOpt, NowDead);
+ return true;
+ }
+
+ return false;
+}
+
+SDOperand DAGCombiner::visitSMUL_LOHI(SDNode *N) {
+
+ if (SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHS))
+ return SDOperand();
+
+ return SDOperand();
+}
+
+SDOperand DAGCombiner::visitUMUL_LOHI(SDNode *N) {
+
+ if (SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHU))
+ return SDOperand();
+
+ return SDOperand();
+}
+
+SDOperand DAGCombiner::visitSDIVREM(SDNode *N) {
+
+ if (SimplifyNodeWithTwoResults(N, ISD::SDIV, ISD::SREM))
+ return SDOperand();
+
+ return SDOperand();
+}
+
+SDOperand DAGCombiner::visitUDIVREM(SDNode *N) {
+
+ if (SimplifyNodeWithTwoResults(N, ISD::UDIV, ISD::UREM))
+ return SDOperand();
+
+ return SDOperand();
+}
+
/// SimplifyBinOpWithSameOpcodeHands - If this is a binary operator with
/// two operands of the same opcode, try to simplify it.
SDOperand DAGCombiner::SimplifyBinOpWithSameOpcodeHands(SDNode *N) {