[llvm-commits] [llvm] r42759 - /llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Dan Gohman djg at cray.com
Mon Oct 8 10:57:15 PDT 2007


Author: djg
Date: Mon Oct  8 12:57:15 2007
New Revision: 42759

URL: http://llvm.org/viewvc/llvm-project?rev=42759&view=rev
Log:
DAGCombiner support for UDIVREM/SDIVREM and UMUL_LOHI/SMUL_LOHI. 
Check if one of the two results unneeded so see if a simpler operator
could bs used. Also check to see if each of the two computations could be
simplified if they were split into separate operators. Factor out the code
that calls visit() so that it can be used for this purpose.

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=42759&r1=42758&r2=42759&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Oct  8 12:57:15 2007
@@ -101,6 +101,10 @@
                      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 @@
     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 @@
     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 @@
                                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 @@
   // 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 @@
       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 @@
   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 @@
   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 @@
   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) {





More information about the llvm-commits mailing list