Fix up the logic for result expanding the various extension
authorDuncan Sands <baldrick@free.fr>
Mon, 22 Oct 2007 18:26:21 +0000 (18:26 +0000)
committerDuncan Sands <baldrick@free.fr>
Mon, 22 Oct 2007 18:26:21 +0000 (18:26 +0000)
operations so they work right for integers with funky
bit-widths.  For example, consider extending i48 to i64
on a 32 bit machine.  The i64 result is expanded to 2 x i32.
We know that the i48 operand will be promoted to i64, then
also expanded to 2 x i32.  If we had the expanded promoted
operand to hand, then expanding the result would be trivial.
Unfortunately at this stage we can only get hold of the
promoted operand.  So instead we kind of hand-expand, doing
explicit shifting and truncating to get the top and bottom
halves of the i64 operand into 2 x i32, which are then used
to expand the result.  This is harmless, because when the
promoted operand is finally expanded all this bit fiddling
turns into trivial operations which are eliminated either
by the expansion code itself or the DAG combiner.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43223 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp

index aa2a91426d284508929bf2c06e2be0641fa90e2a..f056f6f3f728dfed22707ad1d3d6c7c35dc606d5 100644 (file)
@@ -133,7 +133,8 @@ private:
   // Common routines.
   SDOperand CreateStackStoreLoad(SDOperand Op, MVT::ValueType DestVT);
   SDOperand HandleMemIntrinsic(SDNode *N);
   // Common routines.
   SDOperand CreateStackStoreLoad(SDOperand Op, MVT::ValueType DestVT);
   SDOperand HandleMemIntrinsic(SDNode *N);
-  
+  void SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
+
   // Result Promotion.
   void PromoteResult(SDNode *N, unsigned ResNo);
   SDOperand PromoteResult_UNDEF(SDNode *N);
   // Result Promotion.
   void PromoteResult(SDNode *N, unsigned ResNo);
   SDOperand PromoteResult_UNDEF(SDNode *N);
@@ -498,6 +499,20 @@ SDOperand DAGTypeLegalizer::HandleMemIntrinsic(SDNode *N) {
   return DAG.UpdateNodeOperands(SDOperand(N, 0), Ops, 6);
 }
 
   return DAG.UpdateNodeOperands(SDOperand(N, 0), Ops, 6);
 }
 
+/// SplitOp - Return the lower and upper halves of Op's bits in a value type
+/// half the size of Op's.
+void DAGTypeLegalizer::SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) {
+  unsigned NVTBits = MVT::getSizeInBits(Op.getValueType())/2;
+  assert(MVT::getSizeInBits(Op.getValueType()) == 2*NVTBits &&
+         "Cannot split odd sized integer type");
+  MVT::ValueType NVT = MVT::getIntegerType(NVTBits);
+  Lo = DAG.getNode(ISD::TRUNCATE, NVT, Op);
+  Hi = DAG.getNode(ISD::SRL, Op.getValueType(), Op,
+                   DAG.getConstant(NVTBits, TLI.getShiftAmountTy()));
+  Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi);
+}
+
+
 //===----------------------------------------------------------------------===//
 //  Result Promotion
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 //  Result Promotion
 //===----------------------------------------------------------------------===//
@@ -805,33 +820,77 @@ void DAGTypeLegalizer::ExpandResult_BUILD_PAIR(SDNode *N,
   Hi = N->getOperand(1);
 }
 
   Hi = N->getOperand(1);
 }
 
-void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N, 
+void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N,
                                                SDOperand &Lo, SDOperand &Hi) {
                                                SDOperand &Lo, SDOperand &Hi) {
-  
   MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
   MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
-  // The low part is any extension of the input (which degenerates to a copy).
-  Lo = DAG.getNode(ISD::ANY_EXTEND, NVT, N->getOperand(0));
-  Hi = DAG.getNode(ISD::UNDEF, NVT);   // The high part is undefined.
+  SDOperand Op = N->getOperand(0);
+  if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(NVT)) {
+    // The low part is any extension of the input (which degenerates to a copy).
+    Lo = DAG.getNode(ISD::ANY_EXTEND, NVT, Op);
+    Hi = DAG.getNode(ISD::UNDEF, NVT);   // The high part is undefined.
+  } else {
+    // For example, extension of an i48 to an i64.  The operand type necessarily
+    // promotes to the result type, so will end up being expanded too.
+    assert(getTypeAction(Op.getValueType()) == Promote &&
+           "Don't know how to expand this result!");
+    SDOperand Res = GetPromotedOp(Op);
+    assert(Res.getValueType() == N->getValueType(0) &&
+           "Operand over promoted?");
+    // Split the promoted operand.  This will simplify when it is expanded.
+    SplitOp(Res, Lo, Hi);
+  }
 }
 
 void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N,
                                                 SDOperand &Lo, SDOperand &Hi) {
   MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
 }
 
 void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N,
                                                 SDOperand &Lo, SDOperand &Hi) {
   MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
-  // The low part is zero extension of the input (which degenerates to a copy).
-  Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0));
-  Hi = DAG.getConstant(0, NVT);   // The high part is just a zero.
+  SDOperand Op = N->getOperand(0);
+  if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(NVT)) {
+    // The low part is zero extension of the input (which degenerates to a copy).
+    Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0));
+    Hi = DAG.getConstant(0, NVT);   // The high part is just a zero.
+  } else {
+    // For example, extension of an i48 to an i64.  The operand type necessarily
+    // promotes to the result type, so will end up being expanded too.
+    assert(getTypeAction(Op.getValueType()) == Promote &&
+           "Don't know how to expand this result!");
+    SDOperand Res = GetPromotedOp(Op);
+    assert(Res.getValueType() == N->getValueType(0) &&
+           "Operand over promoted?");
+    // Split the promoted operand.  This will simplify when it is expanded.
+    SplitOp(Res, Lo, Hi);
+    unsigned ExcessBits =
+      MVT::getSizeInBits(Op.getValueType()) - MVT::getSizeInBits(NVT);
+    Hi = DAG.getZeroExtendInReg(Hi, MVT::getIntegerType(ExcessBits));
+  }
 }
 
 void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N,
                                                 SDOperand &Lo, SDOperand &Hi) {
   MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
 }
 
 void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N,
                                                 SDOperand &Lo, SDOperand &Hi) {
   MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
-  // The low part is sign extension of the input (which degenerates to a copy).
-  Lo = DAG.getNode(ISD::SIGN_EXTEND, NVT, N->getOperand(0));
-
-  // The high part is obtained by SRA'ing all but one of the bits of low part.
-  unsigned LoSize = MVT::getSizeInBits(NVT);
-  Hi = DAG.getNode(ISD::SRA, NVT, Lo,
-                   DAG.getConstant(LoSize-1, TLI.getShiftAmountTy()));
+  SDOperand Op = N->getOperand(0);
+  if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(NVT)) {
+    // The low part is sign extension of the input (which degenerates to a copy).
+    Lo = DAG.getNode(ISD::SIGN_EXTEND, NVT, N->getOperand(0));
+    // The high part is obtained by SRA'ing all but one of the bits of low part.
+    unsigned LoSize = MVT::getSizeInBits(NVT);
+    Hi = DAG.getNode(ISD::SRA, NVT, Lo,
+                     DAG.getConstant(LoSize-1, TLI.getShiftAmountTy()));
+  } else {
+    // For example, extension of an i48 to an i64.  The operand type necessarily
+    // promotes to the result type, so will end up being expanded too.
+    assert(getTypeAction(Op.getValueType()) == Promote &&
+           "Don't know how to expand this result!");
+    SDOperand Res = GetPromotedOp(Op);
+    assert(Res.getValueType() == N->getValueType(0) &&
+           "Operand over promoted?");
+    // Split the promoted operand.  This will simplify when it is expanded.
+    SplitOp(Res, Lo, Hi);
+    unsigned ExcessBits =
+      MVT::getSizeInBits(Op.getValueType()) - MVT::getSizeInBits(NVT);
+    Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
+                     DAG.getValueType(MVT::getIntegerType(ExcessBits)));
+  }
 }
 
 void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N,
 }
 
 void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N,
@@ -844,19 +903,28 @@ void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N,
 void DAGTypeLegalizer::
 ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
   GetExpandedOp(N->getOperand(0), Lo, Hi);
 void DAGTypeLegalizer::
 ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
   GetExpandedOp(N->getOperand(0), Lo, Hi);
-  
-  // sext_inreg the low part if needed.
-  Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, Lo.getValueType(), Lo,
-                   N->getOperand(1));
-  
-  // The high part gets the sign extension from the lo-part.  This handles
-  // things like sextinreg V:i64 from i8.
-  Hi = DAG.getNode(ISD::SRA, Hi.getValueType(), Lo,
-                   DAG.getConstant(MVT::getSizeInBits(Hi.getValueType())-1,
-                                   TLI.getShiftAmountTy()));
+  MVT::ValueType EVT = N->getOperand(1).getValueType();
+
+  if (MVT::getSizeInBits(EVT) <= MVT::getSizeInBits(Lo.getValueType())) {
+    // sext_inreg the low part if needed.
+    Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, Lo.getValueType(), Lo,
+                     N->getOperand(1));
+
+    // The high part gets the sign extension from the lo-part.  This handles
+    // things like sextinreg V:i64 from i8.
+    Hi = DAG.getNode(ISD::SRA, Hi.getValueType(), Lo,
+                     DAG.getConstant(MVT::getSizeInBits(Hi.getValueType())-1,
+                                     TLI.getShiftAmountTy()));
+  } else {
+    // For example, extension of an i48 to an i64.  Leave the low part alone,
+    // sext_inreg the high part.
+    unsigned ExcessBits =
+      MVT::getSizeInBits(EVT) - MVT::getSizeInBits(Lo.getValueType());
+    Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
+                     DAG.getValueType(MVT::getIntegerType(ExcessBits)));
+  }
 }
 
 }
 
-
 void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
   MVT::ValueType VT = N->getValueType(0);
 void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,
                                          SDOperand &Lo, SDOperand &Hi) {
   MVT::ValueType VT = N->getValueType(0);