+/// 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) {
+ // If the high half is not needed, just compute the low half.
+ bool HiExists = N->hasAnyUseOfValue(1);
+ if (!HiExists &&
+ (!AfterLegalize ||
+ TLI.isOperationLegal(LoOp, N->getValueType(0)))) {
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0),
+ DAG.getNode(LoOp, N->getValueType(0),
+ N->op_begin(),
+ N->getNumOperands()));
+ return true;
+ }
+
+ // If the low half is not needed, just compute the high half.
+ bool LoExists = N->hasAnyUseOfValue(0);
+ if (!LoExists &&
+ (!AfterLegalize ||
+ TLI.isOperationLegal(HiOp, N->getValueType(1)))) {
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1),
+ DAG.getNode(HiOp, N->getValueType(1),
+ N->op_begin(),
+ N->getNumOperands()));
+ return true;
+ }
+
+ // If both halves are used, return as it is.
+ if (LoExists && HiExists)
+ return false;
+
+ // If the two computed results can be simplified separately, separate them.
+ bool RetVal = false;
+ if (LoExists) {
+ SDOperand Lo = DAG.getNode(LoOp, N->getValueType(0),
+ N->op_begin(), N->getNumOperands());
+ SDOperand LoOpt = combine(Lo.Val);
+ if (LoOpt.Val && LoOpt != Lo &&
+ TLI.isOperationLegal(LoOpt.getOpcode(), LoOpt.getValueType())) {
+ RetVal = true;
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), LoOpt);
+ } else
+ DAG.DeleteNode(Lo.Val);
+ }
+
+ if (HiExists) {
+ SDOperand Hi = DAG.getNode(HiOp, N->getValueType(1),
+ N->op_begin(), N->getNumOperands());
+ SDOperand HiOpt = combine(Hi.Val);
+ if (HiOpt.Val && HiOpt != Hi &&
+ TLI.isOperationLegal(HiOpt.getOpcode(), HiOpt.getValueType())) {
+ RetVal = true;
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), HiOpt);
+ } else
+ DAG.DeleteNode(Hi.Val);
+ }
+
+ return RetVal;
+}
+
+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();
+}
+