[llvm-commits] [llvm] r44300 - in /llvm/trunk: include/llvm/Target/TargetLowering.h lib/CodeGen/SelectionDAG/LegalizeDAG.cpp lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp lib/Target/ARM/ARMISelLowering.cpp lib/Target/ARM/ARMISelLowering.h lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86ISelLowering.h

Chris Lattner sabre at nondot.org
Fri Nov 23 23:07:02 PST 2007


Author: lattner
Date: Sat Nov 24 01:07:01 2007
New Revision: 44300

URL: http://llvm.org/viewvc/llvm-project?rev=44300&view=rev
Log:
Several changes:
1) Change the interface to TargetLowering::ExpandOperationResult to 
   take and return entire NODES that need a result expanded, not just
   the value.  This allows us to handle things like READCYCLECOUNTER,
   which returns two values.
2) Implement (extremely limited) support in LegalizeDAG::ExpandOp for MERGE_VALUES.
3) Reimplement custom lowering in LegalizeDAGTypes in terms of the new
   ExpandOperationResult.  This makes the result simpler and fully 
   general.
4) Implement (fully general) expand support for MERGE_VALUES in LegalizeDAGTypes.
5) Implement ExpandOperationResult support for ARM f64->i64 bitconvert and ARM
   i64 shifts, allowing them to work with LegalizeDAGTypes.
6) Implement ExpandOperationResult support for X86 READCYCLECOUNTER and FP_TO_SINT,
   allowing them to work with LegalizeDAGTypes.

LegalizeDAGTypes now passes several more X86 codegen tests when enabled and when
type legalization in LegalizeDAG is ifdef'd out.


Modified:
    llvm/trunk/include/llvm/Target/TargetLowering.h
    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
    llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
    llvm/trunk/lib/Target/ARM/ARMISelLowering.h
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.h

Modified: llvm/trunk/include/llvm/Target/TargetLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=44300&r1=44299&r2=44300&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Target/TargetLowering.h (original)
+++ llvm/trunk/include/llvm/Target/TargetLowering.h Sat Nov 24 01:07:01 2007
@@ -910,12 +910,16 @@
 
   /// ExpandOperationResult - This callback is invoked for operations that are 
   /// unsupported by the target, which are registered to use 'custom' lowering,
-  /// and whose result type needs to be expanded.
+  /// and whose result type needs to be expanded.  This must return a node whose
+  /// results precisely match the results of the input node.  This typically
+  /// involves a MERGE_VALUES node and/or BUILD_PAIR.
   ///
   /// If the target has no operations that require custom lowering, it need not
   /// implement this.  The default implementation of this aborts.
-  virtual std::pair<SDOperand,SDOperand> 
-    ExpandOperationResult(SDNode *N, SelectionDAG &DAG);
+  virtual SDNode *ExpandOperationResult(SDNode *N, SelectionDAG &DAG) {
+    assert(0 && "ExpandOperationResult not implemented for this target!");
+    return 0;
+  }
   
   /// IsEligibleForTailCallOptimization - Check whether the call is eligible for
   /// tail call optimization. Targets which want to do tail call optimization

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=44300&r1=44299&r2=44300&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Sat Nov 24 01:07:01 2007
@@ -5187,10 +5187,21 @@
     // Otherwise, try a larger type.
   }
 
-  // Okay, we found the operation and type to use.  Truncate the result of the
-  // extended FP_TO_*INT operation to the desired size.
-  return DAG.getNode(ISD::TRUNCATE, DestVT,
-                     DAG.getNode(OpToUse, NewOutTy, LegalOp));
+  
+  // Okay, we found the operation and type to use.
+  SDOperand Operation = DAG.getNode(OpToUse, NewOutTy, LegalOp);
+  
+  // If the operation produces an invalid type, it must be custom lowered.  Use
+  // the target lowering hooks to expand it.  Just keep the low part of the
+  // expanded operation, we know that we're truncating anyway.
+  if (getTypeAction(NewOutTy) == Expand) {
+    Operation = SDOperand(TLI.ExpandOperationResult(Operation.Val, DAG), 0);
+    assert(Operation.Val && "Didn't return anything");
+  }
+  
+  // Truncate the result of the extended FP_TO_*INT operation to the desired
+  // size.
+  return DAG.getNode(ISD::TRUNCATE, DestVT, Operation);
 }
 
 /// ExpandBSWAP - Open code the operations for BSWAP of the specified operation.
@@ -5388,6 +5399,16 @@
     Lo = Node->getOperand(0);
     Hi = Node->getOperand(1);
     break;
+      
+  case ISD::MERGE_VALUES:
+    // FIXME: For now only expand i64,chain = MERGE_VALUES (x, y)
+    assert(Op.ResNo == 0 && Node->getNumValues() == 2 &&
+           Op.getValue(1).getValueType() == MVT::Other &&
+           "unhandled MERGE_VALUES");
+    ExpandOp(Op.getOperand(0), Lo, Hi);
+    // Remember that we legalized the chain.
+    AddLegalizedOperand(Op.getValue(1), LegalizeOp(Op.getOperand(1)));
+    break;
     
   case ISD::SIGN_EXTEND_INREG:
     ExpandOp(Node->getOperand(0), Lo, Hi);
@@ -5652,16 +5673,17 @@
     break;
   }
 
-  case ISD::READCYCLECOUNTER:
+  case ISD::READCYCLECOUNTER: {
     assert(TLI.getOperationAction(ISD::READCYCLECOUNTER, VT) == 
                  TargetLowering::Custom &&
            "Must custom expand ReadCycleCounter");
-    Lo = TLI.LowerOperation(Op, DAG);
-    assert(Lo.Val && "Node must be custom expanded!");
-    Hi = Lo.getValue(1);
+    SDOperand Tmp = TLI.LowerOperation(Op, DAG);
+    assert(Tmp.Val && "Node must be custom expanded!");
+    ExpandOp(Tmp.getValue(0), Lo, Hi);
     AddLegalizedOperand(SDOperand(Node, 1), // Remember we legalized the chain.
-                        LegalizeOp(Lo.getValue(2)));
+                        LegalizeOp(Tmp.getValue(1)));
     break;
+  }
 
     // These operators cannot be expanded directly, emit them as calls to
     // library functions.

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp?rev=44300&r1=44299&r2=44300&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp Sat Nov 24 01:07:01 2007
@@ -115,7 +115,8 @@
 private:
   void MarkNewNodes(SDNode *N);
   
-  void ReplaceLegalValueWith(SDOperand From, SDOperand To);
+  void ReplaceValueWith(SDOperand From, SDOperand To);
+  void ReplaceNodeWith(SDNode *From, SDNode *To);
 
   void RemapNode(SDOperand &N);
 
@@ -167,6 +168,7 @@
   void ExpandResult_UNDEF      (SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_Constant   (SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_BUILD_PAIR (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+  void ExpandResult_MERGE_VALUES(SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_ZERO_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void ExpandResult_SIGN_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi);
@@ -391,10 +393,10 @@
     Worklist.push_back(N);
 }
 
-/// ReplaceLegalValueWith - The specified value with a legal type was legalized
-/// to the specified other value.  If they are different, update the DAG and
-/// NodeIDs replacing any uses of From to use To instead.
-void DAGTypeLegalizer::ReplaceLegalValueWith(SDOperand From, SDOperand To) {
+/// ReplaceValueWith - The specified value was legalized to the specified other
+/// value.  If they are different, update the DAG and NodeIDs replacing any uses
+/// of From to use To instead.
+void DAGTypeLegalizer::ReplaceValueWith(SDOperand From, SDOperand To) {
   if (From == To) return;
   
   // If expansion produced new nodes, make sure they are properly marked.
@@ -410,8 +412,8 @@
   ReplacedNodes[From] = To;
 
   // Since we just made an unstructured update to the DAG, which could wreak
-  // general havoc on anything that once used N and now uses Res, walk all users
-  // of the result, updating their flags.
+  // general havoc on anything that once used From and now uses To, walk all
+  // users of the result, updating their flags.
   for (SDNode::use_iterator I = To.Val->use_begin(), E = To.Val->use_end();
        I != E; ++I) {
     SDNode *User = *I;
@@ -425,14 +427,51 @@
   }
 }
 
+/// ReplaceNodeWith - Replace uses of the 'from' node's results with the 'to'
+/// node's results.  The from and to node must define identical result types.
+void DAGTypeLegalizer::ReplaceNodeWith(SDNode *From, SDNode *To) {
+  if (From == To) return;
+  assert(From->getNumValues() == To->getNumValues() &&
+         "Node results don't match");
+  
+  // If expansion produced new nodes, make sure they are properly marked.
+  if (To->getNodeId() == NewNode)
+    MarkNewNodes(To);
+  
+  // Anything that used the old node should now use the new one.  Note that this
+  // can potentially cause recursive merging.
+  DAG.ReplaceAllUsesWith(From, To);
+  
+  // The old node may still be present in ExpandedNodes or PromotedNodes.
+  // Inform them about the replacement.
+  for (unsigned i = 0, e = From->getNumValues(); i != e; ++i) {
+    assert(From->getValueType(i) == To->getValueType(i) &&
+           "Node results don't match");
+    ReplacedNodes[SDOperand(From, i)] = SDOperand(To, i);
+  }
+  
+  // Since we just made an unstructured update to the DAG, which could wreak
+  // general havoc on anything that once used From and now uses To, walk all
+  // users of the result, updating their flags.
+  for (SDNode::use_iterator I = To->use_begin(), E = To->use_end();I != E; ++I){
+    SDNode *User = *I;
+    // If the node isn't already processed or in the worklist, mark it as new,
+    // then use MarkNewNodes to recompute its ID.
+    int NodeId = User->getNodeId();
+    if (NodeId != ReadyToProcess && NodeId != Processed) {
+      User->setNodeId(NewNode);
+      MarkNewNodes(User);
+    }
+  }
+}
+
+
 /// RemapNode - If the specified value was already legalized to another value,
 /// replace it by that value.
 void DAGTypeLegalizer::RemapNode(SDOperand &N) {
-  DenseMap<SDOperand, SDOperand>::iterator I = ReplacedNodes.find(N);
-  if (I != ReplacedNodes.end()) {
-    RemapNode(I->second);
+  for (DenseMap<SDOperand, SDOperand>::iterator I = ReplacedNodes.find(N);
+       I != ReplacedNodes.end(); I = ReplacedNodes.find(N))
     N = I->second;
-  }
 }
 
 void DAGTypeLegalizer::SetPromotedOp(SDOperand Op, SDOperand Result) {
@@ -712,7 +751,7 @@
 
   // Legalized the chain result - switch anything that used the old chain to
   // use the new one.
-  ReplaceLegalValueWith(SDOperand(N, 1), Res.getValue(1));
+  ReplaceValueWith(SDOperand(N, 1), Res.getValue(1));
   return Res;
 }
 
@@ -798,15 +837,14 @@
   SDOperand Lo, Hi;
   Lo = Hi = SDOperand();
 
-  // If this is a single-result node, see if the target wants to custom expand
-  // it.
-  if (N->getNumValues() == 1 &&
-      TLI.getOperationAction(N->getOpcode(),
-                             N->getValueType(0)) == TargetLowering::Custom) {
+  // See if the target wants to custom expand this node.
+  if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == 
+          TargetLowering::Custom) {
     // If the target wants to, allow it to lower this itself.
-    std::pair<SDOperand,SDOperand> P = TLI.ExpandOperationResult(N, DAG);
-    if (P.first.Val) {
-      SetExpandedOp(SDOperand(N, ResNo), P.first, P.second);
+    if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) {
+      // Everything that once used N now uses P.  P had better not require
+      // custom expansion.
+      ReplaceNodeWith(N, P);
       return;
     }
   }
@@ -817,12 +855,13 @@
     cerr << "ExpandResult #" << ResNo << ": ";
     N->dump(&DAG); cerr << "\n";
 #endif
-    assert(0 && "Do not know how to expand this operator!");
+    assert(0 && "Do not know how to expand the result of this operator!");
     abort();
       
   case ISD::UNDEF:       ExpandResult_UNDEF(N, Lo, Hi); break;
   case ISD::Constant:    ExpandResult_Constant(N, Lo, Hi); break;
   case ISD::BUILD_PAIR:  ExpandResult_BUILD_PAIR(N, Lo, Hi); break;
+  case ISD::MERGE_VALUES: ExpandResult_MERGE_VALUES(N, Lo, Hi); break;
   case ISD::ANY_EXTEND:  ExpandResult_ANY_EXTEND(N, Lo, Hi); break;
   case ISD::ZERO_EXTEND: ExpandResult_ZERO_EXTEND(N, Lo, Hi); break;
   case ISD::SIGN_EXTEND: ExpandResult_SIGN_EXTEND(N, Lo, Hi); break;
@@ -846,7 +885,6 @@
   case ISD::SHL:
   case ISD::SRA:
   case ISD::SRL:         ExpandResult_Shift(N, Lo, Hi); break;
-
   }
   
   // If Lo/Hi is null, the sub-method took care of registering results etc.
@@ -875,6 +913,27 @@
   Hi = N->getOperand(1);
 }
 
+void DAGTypeLegalizer::ExpandResult_MERGE_VALUES(SDNode *N,
+                                                 SDOperand &Lo, SDOperand &Hi) {
+  // A MERGE_VALUES node can produce any number of values.  We know that the
+  // first illegal one needs to be expanded into Lo/Hi.
+  unsigned i;
+  
+  // The string of legal results gets turns into the input operands, which have
+  // the same type.
+  for (i = 0; isTypeLegal(N->getValueType(i)); ++i)
+    ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i)));
+
+  // The first illegal result must be the one that needs to be expanded.
+  GetExpandedOp(N->getOperand(i), Lo, Hi);
+
+  // Legalize the rest of the results into the input operands whether they are
+  // legal or not.
+  unsigned e = N->getNumValues();
+  for (++i; i != e; ++i)
+    ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i)));
+}
+
 void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N,
                                                SDOperand &Lo, SDOperand &Hi) {
   MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
@@ -1096,7 +1155,7 @@
 
   // Legalized the chain result - switch anything that used the old chain to
   // use the new one.
-  ReplaceLegalValueWith(SDOperand(N, 1), Ch);
+  ReplaceValueWith(SDOperand(N, 1), Ch);
 }
 
 void DAGTypeLegalizer::ExpandResult_Logical(SDNode *N,
@@ -1184,7 +1243,7 @@
 
   // Legalized the flag result - switch anything that used the old flag to
   // use the new one.
-  ReplaceLegalValueWith(SDOperand(N, 1), Hi.getValue(1));
+  ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1));
 }
 
 void DAGTypeLegalizer::ExpandResult_ADDSUBE(SDNode *N,
@@ -1203,7 +1262,7 @@
 
   // Legalized the flag result - switch anything that used the old flag to
   // use the new one.
-  ReplaceLegalValueWith(SDOperand(N, 1), Hi.getValue(1));
+  ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1));
 }
 
 void DAGTypeLegalizer::ExpandResult_MUL(SDNode *N,
@@ -1537,7 +1596,7 @@
   assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
          "Invalid operand expansion");
   
-  ReplaceLegalValueWith(SDOperand(N, 0), Res);
+  ReplaceValueWith(SDOperand(N, 0), Res);
   return false;
 }
 
@@ -1759,7 +1818,7 @@
   assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
          "Invalid operand expansion");
   
-  ReplaceLegalValueWith(SDOperand(N, 0), Res);
+  ReplaceValueWith(SDOperand(N, 0), Res);
   return false;
 }
 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=44300&r1=44299&r2=44300&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Sat Nov 24 01:07:01 2007
@@ -1921,7 +1921,7 @@
   if (Cases.size()>=2)
     // Must recompute end() each iteration because it may be
     // invalidated by erase if we hold on to it
-    for (CaseItr I=Cases.begin(), J=next(Cases.begin()); J!=Cases.end(); ) {
+    for (CaseItr I=Cases.begin(), J=++(Cases.begin()); J!=Cases.end(); ) {
       int64_t nextValue = cast<ConstantInt>(J->Low)->getSExtValue();
       int64_t currentValue = cast<ConstantInt>(I->High)->getSExtValue();
       MachineBasicBlock* nextBB = J->BB;
@@ -4144,14 +4144,6 @@
   return SDOperand();
 }
 
-std::pair<SDOperand,SDOperand>
-TargetLowering::ExpandOperationResult(SDNode *N, SelectionDAG &DAG) {
-  assert(0 && "ExpandOperation not implemented for this target!");
-  abort();
-  return std::pair<SDOperand,SDOperand>();
-}
-
-
 SDOperand TargetLowering::CustomPromoteOperation(SDOperand Op,
                                                  SelectionDAG &DAG) {
   assert(0 && "CustomPromoteOperation not implemented for this target!");

Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=44300&r1=44299&r2=44300&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Sat Nov 24 01:07:01 2007
@@ -949,10 +949,8 @@
     vRegs[NumGPRs+1] = VReg;
     SDOperand ArgValue2 = DAG.getCopyFromReg(Root, VReg, MVT::i32);
 
-    if (ObjectVT == MVT::i64)
-      ArgValue = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, ArgValue, ArgValue2);
-    else
-      ArgValue = DAG.getNode(ARMISD::FMDRR, MVT::f64, ArgValue, ArgValue2);
+    assert(ObjectVT != MVT::i64 && "i64 should already be lowered");
+    ArgValue = DAG.getNode(ARMISD::FMDRR, MVT::f64, ArgValue, ArgValue2);
   }
   NumGPRs += ObjGPRs;
 
@@ -966,12 +964,9 @@
       if (ObjGPRs == 0)
         ArgValue = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
       else {
-        SDOperand ArgValue2 =
-          DAG.getLoad(MVT::i32, Root, FIN, NULL, 0);
-        if (ObjectVT == MVT::i64)
-          ArgValue= DAG.getNode(ISD::BUILD_PAIR, MVT::i64, ArgValue, ArgValue2);
-        else
-          ArgValue= DAG.getNode(ARMISD::FMDRR, MVT::f64, ArgValue, ArgValue2);
+        SDOperand ArgValue2 = DAG.getLoad(MVT::i32, Root, FIN, NULL, 0);
+        assert(ObjectVT != MVT::i64 && "i64 should already be lowered");
+        ArgValue = DAG.getNode(ARMISD::FMDRR, MVT::f64, ArgValue, ArgValue2);
       }
     } else {
       // Don't emit a dead load.
@@ -1256,51 +1251,6 @@
   return DAG.getNode(ARMISD::CNEG, VT, AbsVal, AbsVal, ARMCC, CCR, Cmp);
 }
 
-static SDOperand LowerBIT_CONVERT(SDOperand Op, SelectionDAG &DAG) {
-  // Turn f64->i64 into FMRRD.
-  assert(Op.getValueType() == MVT::i64 &&
-         Op.getOperand(0).getValueType() == MVT::f64);
-
-  Op = Op.getOperand(0);
-  SDOperand Cvt = DAG.getNode(ARMISD::FMRRD, DAG.getVTList(MVT::i32, MVT::i32),
-                              &Op, 1);
-  
-  // Merge the pieces into a single i64 value.
-  return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Cvt, Cvt.getValue(1));
-}
-
-static SDOperand LowerSRx(SDOperand Op, SelectionDAG &DAG,
-                          const ARMSubtarget *ST) {
-  assert(Op.getValueType() == MVT::i64 &&
-         (Op.getOpcode() == ISD::SRL || Op.getOpcode() == ISD::SRA) &&
-         "Unknown shift to lower!");
-  
-  // We only lower SRA, SRL of 1 here, all others use generic lowering.
-  if (!isa<ConstantSDNode>(Op.getOperand(1)) ||
-      cast<ConstantSDNode>(Op.getOperand(1))->getValue() != 1)
-    return SDOperand();
-  
-  // If we are in thumb mode, we don't have RRX.
-  if (ST->isThumb()) return SDOperand();
-  
-  // Okay, we have a 64-bit SRA or SRL of 1.  Lower this to an RRX expr.
-  SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
-                             DAG.getConstant(0, MVT::i32));
-  SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
-                             DAG.getConstant(1, MVT::i32));
-
-  // First, build a SRA_FLAG/SRL_FLAG op, which shifts the top part by one and
-  // captures the result into a carry flag.
-  unsigned Opc = Op.getOpcode() == ISD::SRL ? ARMISD::SRL_FLAG:ARMISD::SRA_FLAG;
-  Hi = DAG.getNode(Opc, DAG.getVTList(MVT::i32, MVT::Flag), &Hi, 1);
-  
-  // The low part is an ARMISD::RRX operand, which shifts the carry in.
-  Lo = DAG.getNode(ARMISD::RRX, MVT::i32, Lo, Hi.getValue(1));
-  
-  // Merge the pieces into a single i64 value.
-  return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi);
-}
-
 SDOperand ARMTargetLowering::LowerMEMCPYInline(SDOperand Chain,
                                                SDOperand Dest,
                                                SDOperand Source,
@@ -1396,6 +1346,51 @@
   return DAG.getNode(ISD::TokenFactor, MVT::Other, &TFOps[0], i);
 }
 
+static SDNode *ExpandBIT_CONVERT(SDNode *N, SelectionDAG &DAG) {
+  // Turn f64->i64 into FMRRD.
+  assert(N->getValueType(0) == MVT::i64 &&
+         N->getOperand(0).getValueType() == MVT::f64);
+  
+  SDOperand Op = N->getOperand(0);
+  SDOperand Cvt = DAG.getNode(ARMISD::FMRRD, DAG.getVTList(MVT::i32, MVT::i32),
+                              &Op, 1);
+  
+  // Merge the pieces into a single i64 value.
+  return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Cvt, Cvt.getValue(1)).Val;
+}
+
+static SDNode *ExpandSRx(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST) {
+  assert(N->getValueType(0) == MVT::i64 &&
+         (N->getOpcode() == ISD::SRL || N->getOpcode() == ISD::SRA) &&
+         "Unknown shift to lower!");
+  
+  // We only lower SRA, SRL of 1 here, all others use generic lowering.
+  if (!isa<ConstantSDNode>(N->getOperand(1)) ||
+      cast<ConstantSDNode>(N->getOperand(1))->getValue() != 1)
+    return 0;
+  
+  // If we are in thumb mode, we don't have RRX.
+  if (ST->isThumb()) return 0;
+  
+  // Okay, we have a 64-bit SRA or SRL of 1.  Lower this to an RRX expr.
+  SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, N->getOperand(0),
+                             DAG.getConstant(0, MVT::i32));
+  SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, N->getOperand(0),
+                             DAG.getConstant(1, MVT::i32));
+  
+  // First, build a SRA_FLAG/SRL_FLAG op, which shifts the top part by one and
+  // captures the result into a carry flag.
+  unsigned Opc = N->getOpcode() == ISD::SRL ? ARMISD::SRL_FLAG:ARMISD::SRA_FLAG;
+  Hi = DAG.getNode(Opc, DAG.getVTList(MVT::i32, MVT::Flag), &Hi, 1);
+  
+  // The low part is an ARMISD::RRX operand, which shifts the carry in.
+  Lo = DAG.getNode(ARMISD::RRX, MVT::i32, Lo, Hi.getValue(1));
+  
+  // Merge the pieces into a single i64 value.
+ return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi).Val;
+}
+
+
 SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   switch (Op.getOpcode()) {
   default: assert(0 && "Don't know how to custom lower this!"); abort();
@@ -1415,20 +1410,35 @@
   case ISD::FP_TO_SINT:
   case ISD::FP_TO_UINT:    return LowerFP_TO_INT(Op, DAG);
   case ISD::FCOPYSIGN:     return LowerFCOPYSIGN(Op, DAG);
-  case ISD::BIT_CONVERT:   return LowerBIT_CONVERT(Op, DAG);
-  case ISD::SRL:
-  case ISD::SRA:           return LowerSRx(Op, DAG, Subtarget);
-  case ISD::FORMAL_ARGUMENTS:
-    return LowerFORMAL_ARGUMENTS(Op, DAG);
+  case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
   case ISD::RETURNADDR:    break;
   case ISD::FRAMEADDR:     break;
   case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);
   case ISD::MEMCPY:        return LowerMEMCPY(Op, DAG);
   case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
+      
+      
+  // FIXME: Remove these when LegalizeDAGTypes lands.
+  case ISD::BIT_CONVERT:   return SDOperand(ExpandBIT_CONVERT(Op.Val, DAG), 0);
+  case ISD::SRL:
+  case ISD::SRA:           return SDOperand(ExpandSRx(Op.Val, DAG,Subtarget),0);
   }
   return SDOperand();
 }
 
+
+/// ExpandOperationResult - Provide custom lowering hooks for expanding
+/// operations.
+SDNode *ARMTargetLowering::ExpandOperationResult(SDNode *N, SelectionDAG &DAG) {
+  switch (N->getOpcode()) {
+  default: assert(0 && "Don't know how to custom expand this!"); abort();
+  case ISD::BIT_CONVERT:   return ExpandBIT_CONVERT(N, DAG);
+  case ISD::SRL:
+  case ISD::SRA:           return ExpandSRx(N, DAG, Subtarget);
+  }
+}
+  
+
 //===----------------------------------------------------------------------===//
 //                           ARM Scheduler Hooks
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.h?rev=44300&r1=44299&r2=44300&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.h Sat Nov 24 01:07:01 2007
@@ -76,6 +76,8 @@
     explicit ARMTargetLowering(TargetMachine &TM);
 
     virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
+    virtual SDNode *ExpandOperationResult(SDNode *N, SelectionDAG &DAG);
+        
     virtual const char *getTargetNodeName(unsigned Opcode) const;
 
     virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI,

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=44300&r1=44299&r2=44300&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Sat Nov 24 01:07:01 2007
@@ -1258,7 +1258,7 @@
 
     SDOperand AlignNode = DAG.getConstant(Align, MVT::i32);
     SDOperand  SizeNode = DAG.getConstant(Size, MVT::i32);
-    SDOperand AlwaysInline = DAG.getConstant(1, MVT::i1);
+    SDOperand AlwaysInline = DAG.getConstant(1, MVT::i32);
 
     return DAG.getMemcpy(Chain, PtrOff, Arg, SizeNode, AlignNode,
                          AlwaysInline);
@@ -3918,22 +3918,22 @@
   return Result;
 }
 
-SDOperand X86TargetLowering::LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
+std::pair<SDOperand,SDOperand> X86TargetLowering::
+FP_TO_SINTHelper(SDOperand Op, SelectionDAG &DAG) {
   assert(Op.getValueType() <= MVT::i64 && Op.getValueType() >= MVT::i16 &&
          "Unknown FP_TO_SINT to lower!");
-  SDOperand Result;
 
   // These are really Legal.
   if (Op.getValueType() == MVT::i32 && 
       X86ScalarSSEf32 && Op.getOperand(0).getValueType() == MVT::f32)
-    return Result;
+    return std::make_pair(SDOperand(), SDOperand());
   if (Op.getValueType() == MVT::i32 && 
       X86ScalarSSEf64 && Op.getOperand(0).getValueType() == MVT::f64)
-    return Result;
+    return std::make_pair(SDOperand(), SDOperand());
   if (Subtarget->is64Bit() &&
       Op.getValueType() == MVT::i64 &&
       Op.getOperand(0).getValueType() != MVT::f80)
-    return Result;
+    return std::make_pair(SDOperand(), SDOperand());
 
   // We lower FP->sint64 into FISTP64, followed by a load, all to a temporary
   // stack slot.
@@ -3943,10 +3943,10 @@
   SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
   unsigned Opc;
   switch (Op.getValueType()) {
-    default: assert(0 && "Invalid FP_TO_SINT to lower!");
-    case MVT::i16: Opc = X86ISD::FP_TO_INT16_IN_MEM; break;
-    case MVT::i32: Opc = X86ISD::FP_TO_INT32_IN_MEM; break;
-    case MVT::i64: Opc = X86ISD::FP_TO_INT64_IN_MEM; break;
+  default: assert(0 && "Invalid FP_TO_SINT to lower!");
+  case MVT::i16: Opc = X86ISD::FP_TO_INT16_IN_MEM; break;
+  case MVT::i32: Opc = X86ISD::FP_TO_INT32_IN_MEM; break;
+  case MVT::i64: Opc = X86ISD::FP_TO_INT64_IN_MEM; break;
   }
 
   SDOperand Chain = DAG.getEntryNode();
@@ -3969,20 +3969,33 @@
   SDOperand Ops[] = { Chain, Value, StackSlot };
   SDOperand FIST = DAG.getNode(Opc, MVT::Other, Ops, 3);
 
-  // Load the result.  If this is an i64 load on an x86-32 host, expand the
-  // load.
-  if (Op.getValueType() != MVT::i64 || Subtarget->is64Bit())
-    return DAG.getLoad(Op.getValueType(), FIST, StackSlot, NULL, 0);
-  
-  SDOperand Lo = DAG.getLoad(MVT::i32, FIST, StackSlot, NULL, 0);
-  StackSlot = DAG.getNode(ISD::ADD, StackSlot.getValueType(), StackSlot,
-                          DAG.getConstant(StackSlot.getValueType(), 4));
-  SDOperand Hi = DAG.getLoad(MVT::i32, FIST, StackSlot, NULL, 0);
-  
+  return std::make_pair(FIST, StackSlot);
+}
+
+SDOperand X86TargetLowering::LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
+  assert((Op.getValueType() != MVT::i64 || Subtarget->is64Bit()) &&
+         "This FP_TO_SINT must be expanded!");
+
+  std::pair<SDOperand,SDOperand> Vals = FP_TO_SINTHelper(Op, DAG);
+  SDOperand FIST = Vals.first, StackSlot = Vals.second;
+  if (FIST.Val == 0) return SDOperand();
   
-  return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi);
+  // Load the result.
+  return DAG.getLoad(Op.getValueType(), FIST, StackSlot, NULL, 0);
 }
 
+SDNode *X86TargetLowering::ExpandFP_TO_SINT(SDNode *N, SelectionDAG &DAG) {
+  std::pair<SDOperand,SDOperand> Vals = FP_TO_SINTHelper(SDOperand(N, 0), DAG);
+  SDOperand FIST = Vals.first, StackSlot = Vals.second;
+  if (FIST.Val == 0) return 0;
+  
+  // Return an i64 load from the stack slot.
+  SDOperand Res = DAG.getLoad(MVT::i64, FIST, StackSlot, NULL, 0);
+
+  // Use a MERGE_VALUES node to drop the chain result value.
+  return DAG.getNode(ISD::MERGE_VALUES, MVT::i64, Res).Val;
+}  
+
 SDOperand X86TargetLowering::LowerFABS(SDOperand Op, SelectionDAG &DAG) {
   MVT::ValueType VT = Op.getValueType();
   MVT::ValueType EltVT = VT;
@@ -4587,32 +4600,36 @@
   return Chain;
 }
 
-SDOperand
-X86TargetLowering::LowerREADCYCLCECOUNTER(SDOperand Op, SelectionDAG &DAG) {
+/// Expand the result of: i64,outchain = READCYCLECOUNTER inchain
+SDNode *X86TargetLowering::ExpandREADCYCLECOUNTER(SDNode *N, SelectionDAG &DAG){
   SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
-  SDOperand TheOp = Op.getOperand(0);
-  SDOperand rd = DAG.getNode(X86ISD::RDTSC_DAG, Tys, &TheOp, 1);
+  SDOperand TheChain = N->getOperand(0);
+  SDOperand rd = DAG.getNode(X86ISD::RDTSC_DAG, Tys, &TheChain, 1);
   if (Subtarget->is64Bit()) {
-    SDOperand Copy1 = 
-      DAG.getCopyFromReg(rd, X86::RAX, MVT::i64, rd.getValue(1));
-    SDOperand Copy2 = DAG.getCopyFromReg(Copy1.getValue(1), X86::RDX,
-                                         MVT::i64, Copy1.getValue(2));
-    SDOperand Tmp = DAG.getNode(ISD::SHL, MVT::i64, Copy2,
+    SDOperand rax = DAG.getCopyFromReg(rd, X86::RAX, MVT::i64, rd.getValue(1));
+    SDOperand rdx = DAG.getCopyFromReg(rax.getValue(1), X86::RDX,
+                                       MVT::i64, rax.getValue(2));
+    SDOperand Tmp = DAG.getNode(ISD::SHL, MVT::i64, rdx,
                                 DAG.getConstant(32, MVT::i8));
     SDOperand Ops[] = {
-      DAG.getNode(ISD::OR, MVT::i64, Copy1, Tmp), Copy2.getValue(1)
+      DAG.getNode(ISD::OR, MVT::i64, rax, Tmp), rdx.getValue(1)
     };
     
     Tys = DAG.getVTList(MVT::i64, MVT::Other);
-    return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 2);
+    return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 2).Val;
   }
   
-  SDOperand Copy1 = DAG.getCopyFromReg(rd, X86::EAX, MVT::i32, rd.getValue(1));
-  SDOperand Copy2 = DAG.getCopyFromReg(Copy1.getValue(1), X86::EDX,
-                                       MVT::i32, Copy1.getValue(2));
-  SDOperand Ops[] = { Copy1, Copy2, Copy2.getValue(1) };
-  Tys = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other);
-  return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 3);
+  SDOperand eax = DAG.getCopyFromReg(rd, X86::EAX, MVT::i32, rd.getValue(1));
+  SDOperand edx = DAG.getCopyFromReg(eax.getValue(1), X86::EDX,
+                                       MVT::i32, eax.getValue(2));
+  // Use a buildpair to merge the two 32-bit values into a 64-bit one. 
+  SDOperand Ops[] = { eax, edx };
+  Ops[0] = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Ops, 2);
+
+  // Use a MERGE_VALUES to return the value and chain.
+  Ops[1] = edx.getValue(1);
+  Tys = DAG.getVTList(MVT::i64, MVT::Other);
+  return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 2).Val;
 }
 
 SDOperand X86TargetLowering::LowerVASTART(SDOperand Op, SelectionDAG &DAG) {
@@ -5032,7 +5049,6 @@
   case ISD::FORMAL_ARGUMENTS:   return LowerFORMAL_ARGUMENTS(Op, DAG);
   case ISD::MEMSET:             return LowerMEMSET(Op, DAG);
   case ISD::MEMCPY:             return LowerMEMCPY(Op, DAG);
-  case ISD::READCYCLECOUNTER:   return LowerREADCYCLCECOUNTER(Op, DAG);
   case ISD::VASTART:            return LowerVASTART(Op, DAG);
   case ISD::VACOPY:             return LowerVACOPY(Op, DAG);
   case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
@@ -5044,8 +5060,21 @@
   case ISD::EH_RETURN:          return LowerEH_RETURN(Op, DAG);
   case ISD::TRAMPOLINE:         return LowerTRAMPOLINE(Op, DAG);
   case ISD::FLT_ROUNDS:         return LowerFLT_ROUNDS(Op, DAG);
+      
+      
+  // FIXME: REMOVE THIS WHEN LegalizeDAGTypes lands.
+  case ISD::READCYCLECOUNTER:
+    return SDOperand(ExpandREADCYCLECOUNTER(Op.Val, DAG), 0);
+  }
+}
+
+/// ExpandOperation - Provide custom lowering hooks for expanding operations.
+SDNode *X86TargetLowering::ExpandOperationResult(SDNode *N, SelectionDAG &DAG) {
+  switch (N->getOpcode()) {
+  default: assert(0 && "Should not custom lower this!");
+  case ISD::FP_TO_SINT:         return ExpandFP_TO_SINT(N, DAG);
+  case ISD::READCYCLECOUNTER:   return ExpandREADCYCLECOUNTER(N, DAG);
   }
-  return SDOperand();
 }
 
 const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=44300&r1=44299&r2=44300&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Sat Nov 24 01:07:01 2007
@@ -321,6 +321,12 @@
     ///
     virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
 
+    /// ExpandOperation - Custom lower the specified operation, splitting the
+    /// value into two pieces.
+    ///
+    virtual SDNode *ExpandOperationResult(SDNode *N, SelectionDAG &DAG);
+
+    
     virtual SDOperand PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
 
     virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI,
@@ -444,6 +450,9 @@
     SDOperand LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerFastCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC);
 
+    std::pair<SDOperand,SDOperand> FP_TO_SINTHelper(SDOperand Op, 
+                                                    SelectionDAG &DAG);
+    
     SDOperand LowerBUILD_VECTOR(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerEXTRACT_VECTOR_ELT(SDOperand Op, SelectionDAG &DAG);
@@ -471,7 +480,6 @@
     SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerDYNAMIC_STACKALLOC(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG);
-    SDOperand LowerREADCYCLCECOUNTER(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerVACOPY(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG);
@@ -481,6 +489,8 @@
     SDOperand LowerEH_RETURN(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerTRAMPOLINE(SDOperand Op, SelectionDAG &DAG);
     SDOperand LowerFLT_ROUNDS(SDOperand Op, SelectionDAG &DAG);
+    SDNode *ExpandFP_TO_SINT(SDNode *N, SelectionDAG &DAG);
+    SDNode *ExpandREADCYCLECOUNTER(SDNode *N, SelectionDAG &DAG);
   };
 }
 





More information about the llvm-commits mailing list