OSDN Git Service

Initial soft-float support for LegalizeTypes. I rewrote
authorDuncan Sands <baldrick@free.fr>
Wed, 12 Mar 2008 21:27:04 +0000 (21:27 +0000)
committerDuncan Sands <baldrick@free.fr>
Wed, 12 Mar 2008 21:27:04 +0000 (21:27 +0000)
the fcopysign expansion from LegalizeDAG to get rid of
what seems to be a bug: the use of sign extension means
that when copying the sign bit from an f32 to an f64,
the upper 32 bits of the f64 (now an i64) are set, not
just the top bit...  I also generalized it to work for
any sized floating point types, and removed the bogosity:
  SDOperand Mask1 = (SrcVT == MVT::f64)
    ? DAG.getConstantFP(BitsToDouble(1ULL << 63), SrcVT)
    : DAG.getConstantFP(BitsToFloat(1U << 31), SrcVT);
  Mask1 = DAG.getNode(ISD::BIT_CONVERT, SrcNVT, Mask1);
(here SrcNVT is an integer with the same size as SrcVT).
As far as I can see this takes a 1 << 63, converts to
a double, converts that to a floating point constant
then converts that to an integer constant, ending up
with... 1 << 63 as an integer constant!  So I just
generate this integer constant directly.

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

lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
lib/CodeGen/SelectionDAG/LegalizeTypes.h
lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp
lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp [new file with mode: 0644]
lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp
lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp

index d13fefa..cc9caf0 100644 (file)
@@ -79,6 +79,9 @@ void DAGTypeLegalizer::run() {
       case Expand:
         ExpandResult(N, i);
         goto NodeDone;
+      case FloatToInt:
+        FloatToIntResult(N, i);
+        goto NodeDone;
       case Scalarize:
         ScalarizeResult(N, i);
         goto NodeDone;
@@ -106,6 +109,9 @@ void DAGTypeLegalizer::run() {
       case Expand:
         NeedsRevisit = ExpandOperand(N, i);
         break;
+      case FloatToInt:
+        NeedsRevisit = FloatToIntOperand(N, i);
+        break;
       case Scalarize:
         NeedsRevisit = ScalarizeOperand(N, i);
         break;
@@ -355,6 +361,14 @@ void DAGTypeLegalizer::SetPromotedOp(SDOperand Op, SDOperand Result) {
   OpEntry = Result;
 }
 
+void DAGTypeLegalizer::SetIntegerOp(SDOperand Op, SDOperand Result) {
+  AnalyzeNewNode(Result.Val);
+
+  SDOperand &OpEntry = FloatToIntedNodes[Op];
+  assert(OpEntry.Val == 0 && "Node is already converted to integer!");
+  OpEntry = Result;
+}
+
 void DAGTypeLegalizer::SetScalarizedOp(SDOperand Op, SDOperand Result) {
   AnalyzeNewNode(Result.Val);
 
@@ -363,7 +377,6 @@ void DAGTypeLegalizer::SetScalarizedOp(SDOperand Op, SDOperand Result) {
   OpEntry = Result;
 }
 
-
 void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo, 
                                      SDOperand &Hi) {
   std::pair<SDOperand, SDOperand> &Entry = ExpandedNodes[Op];
@@ -408,6 +421,13 @@ void DAGTypeLegalizer::SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi) {
 }
 
 
+/// BitConvertToInteger - Convert to an integer of the same size.
+SDOperand DAGTypeLegalizer::BitConvertToInteger(SDOperand Op) {
+  return DAG.getNode(ISD::BIT_CONVERT,
+                     MVT::getIntegerType(MVT::getSizeInBits(Op.getValueType())),
+                     Op);
+}
+
 SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op, 
                                                  MVT::ValueType DestVT) {
   // Create the stack frame object.
index 35e72dd..b8047bc 100644 (file)
@@ -62,6 +62,7 @@ private:
     Legal,      // The target natively supports this type.
     Promote,    // This type should be executed in a larger type.
     Expand,     // This type should be split into two types of half the size.
+    FloatToInt, // Convert a floating point type to an integer of the same size.
     Scalarize,  // Replace this one-element vector type with its element type.
     Split       // This vector type should be split into smaller vectors.
   };
@@ -85,14 +86,20 @@ private:
     case TargetLowering::Promote:
       return Promote;
     case TargetLowering::Expand:
-      // Expand can mean 1) split integer in half 2) scalarize single-element
-      // vector 3) split vector in two.
-      if (!MVT::isVector(VT))
-        return Expand;
-      else if (MVT::getVectorNumElements(VT) == 1)
+      // Expand can mean
+      // 1) split scalar in half, 2) convert a float to an integer,
+      // 3) scalarize a single-element vector, 4) split a vector in two.
+      if (!MVT::isVector(VT)) {
+        if (MVT::getSizeInBits(VT) ==
+            MVT::getSizeInBits(TLI.getTypeToTransformTo(VT)))
+          return FloatToInt;
+        else
+          return Expand;
+      } else if (MVT::getVectorNumElements(VT) == 1) {
         return Scalarize;
-      else
+      } else {
         return Split;
+      }
     }
   }
 
@@ -109,6 +116,10 @@ private:
   /// which operands are the expanded version of the input.
   DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > ExpandedNodes;
 
+  /// FloatToIntedNodes - For floating point nodes converted to integers of
+  /// the same size, this map indicates the converted value to use.
+  DenseMap<SDOperand, SDOperand> FloatToIntedNodes;
+
   /// ScalarizedNodes - For nodes that are <1 x ty>, this map indicates the
   /// scalar value of type 'ty' to use.
   DenseMap<SDOperand, SDOperand> ScalarizedNodes;
@@ -152,6 +163,7 @@ private:
   void RemapNode(SDOperand &N);
 
   // Common routines.
+  SDOperand BitConvertToInteger(SDOperand Op);
   SDOperand CreateStackStoreLoad(SDOperand Op, MVT::ValueType DestVT);
   SDOperand HandleMemIntrinsic(SDNode *N);
   SDOperand JoinIntegers(SDOperand Lo, SDOperand Hi);
@@ -282,6 +294,28 @@ private:
                            ISD::CondCode &CCCode);
   
   //===--------------------------------------------------------------------===//
+  // Float to Integer Conversion Support: LegalizeTypesFloatToInt.cpp
+  //===--------------------------------------------------------------------===//
+
+  SDOperand GetIntegerOp(SDOperand Op) {
+    SDOperand &IntegerOp = FloatToIntedNodes[Op];
+    RemapNode(IntegerOp);
+    assert(IntegerOp.Val && "Operand wasn't converted to integer?");
+    return IntegerOp;
+  }
+  void SetIntegerOp(SDOperand Op, SDOperand Result);
+
+  // Result Float to Integer Conversion.
+  void FloatToIntResult(SDNode *N, unsigned OpNo);
+  SDOperand FloatToIntRes_BIT_CONVERT(SDNode *N);
+  SDOperand FloatToIntRes_BUILD_PAIR(SDNode *N);
+  SDOperand FloatToIntRes_FCOPYSIGN(SDNode *N);
+
+  // Operand Float to Integer Conversion.
+  bool FloatToIntOperand(SDNode *N, unsigned OpNo);
+  SDOperand FloatToIntOp_BIT_CONVERT(SDNode *N);
+
+  //===--------------------------------------------------------------------===//
   // Scalarization Support: LegalizeTypesScalarize.cpp
   //===--------------------------------------------------------------------===//
   
@@ -336,7 +370,7 @@ private:
   void SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi);
   void SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
   
-  // Operand Vector Scalarization: <128 x ty> -> 2 x <64 x ty>.
+  // Operand Vector Splitting: <128 x ty> -> 2 x <64 x ty>.
   bool SplitOperand(SDNode *N, unsigned OpNo);
 
   SDOperand SplitOp_BIT_CONVERT(SDNode *N);
index 15d25e6..e4ae071 100644 (file)
@@ -260,6 +260,12 @@ void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N,
       Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
       Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
       return;
+    case FloatToInt:
+      // Convert the integer operand instead.
+      SplitInteger(GetIntegerOp(InOp), Lo, Hi);
+      Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
+      Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
+      return;
     case Split:
       // Convert the split parts of the input if it was split in two.
       GetSplitOp(InOp, Lo, Hi);
@@ -273,10 +279,7 @@ void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N,
       break;
     case Scalarize:
       // Convert the element instead.
-      InOp = DAG.getNode(ISD::BIT_CONVERT,
-                         MVT::getIntegerType(MVT::getSizeInBits(InVT)),
-                         GetScalarizedOp(InOp));
-      SplitInteger(InOp, Lo, Hi);
+      SplitInteger(BitConvertToInteger(GetScalarizedOp(InOp)), Lo, Hi);
       Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
       Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
       return;
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp
new file mode 100644 (file)
index 0000000..53f3143
--- /dev/null
@@ -0,0 +1,168 @@
+//===-- LegalizeTypesFloatToInt.cpp - LegalizeTypes float to int support --===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements float to integer conversion for LegalizeTypes.  This
+// is the act of turning a computation in an invalid floating point type into
+// a computation in an integer type of the same size.  For example, turning
+// f32 arithmetic into operations using i32.  Also known as "soft float".
+//
+//===----------------------------------------------------------------------===//
+
+#include "LegalizeTypes.h"
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+//  Result Float to Integer Conversion.
+//===----------------------------------------------------------------------===//
+
+void DAGTypeLegalizer::FloatToIntResult(SDNode *N, unsigned ResNo) {
+  DEBUG(cerr << "FloatToInt node result " << ResNo << ": "; N->dump(&DAG);
+        cerr << "\n");
+  SDOperand R = SDOperand();
+
+  // FIXME: Custom lowering for float-to-int?
+#if 0
+  // See if the target wants to custom convert this node to an integer.
+  if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
+      TargetLowering::Custom) {
+    // If the target wants to, allow it to lower this itself.
+    if (SDNode *P = TLI.FloatToIntOperationResult(N, DAG)) {
+      // Everything that once used N now uses P.  We are guaranteed that the
+      // result value types of N and the result value types of P match.
+      ReplaceNodeWith(N, P);
+      return;
+    }
+  }
+#endif
+
+  switch (N->getOpcode()) {
+  default:
+#ifndef NDEBUG
+    cerr << "FloatToIntResult #" << ResNo << ": ";
+    N->dump(&DAG); cerr << "\n";
+#endif
+    assert(0 && "Do not know how to convert the result of this operator!");
+    abort();
+
+    case ISD::BIT_CONVERT: R = FloatToIntRes_BIT_CONVERT(N); break;
+    case ISD::BUILD_PAIR:  R = FloatToIntRes_BUILD_PAIR(N); break;
+    case ISD::FCOPYSIGN:   R = FloatToIntRes_FCOPYSIGN(N); break;
+  }
+
+  // If R is null, the sub-method took care of registering the result.
+  if (R.Val)
+    SetIntegerOp(SDOperand(N, ResNo), R);
+}
+
+SDOperand DAGTypeLegalizer::FloatToIntRes_BIT_CONVERT(SDNode *N) {
+  return BitConvertToInteger(N->getOperand(0));
+}
+
+SDOperand DAGTypeLegalizer::FloatToIntRes_BUILD_PAIR(SDNode *N) {
+  // Convert the inputs to integers, and build a new pair out of them.
+  return DAG.getNode(ISD::BUILD_PAIR,
+                     TLI.getTypeToTransformTo(N->getValueType(0)),
+                     BitConvertToInteger(N->getOperand(0)),
+                     BitConvertToInteger(N->getOperand(1)));
+}
+
+SDOperand DAGTypeLegalizer::FloatToIntRes_FCOPYSIGN(SDNode *N) {
+  SDOperand LHS = GetIntegerOp(N->getOperand(0));
+  SDOperand RHS = BitConvertToInteger(N->getOperand(1));
+
+  MVT::ValueType LVT = LHS.getValueType();
+  MVT::ValueType RVT = RHS.getValueType();
+
+  unsigned LSize = MVT::getSizeInBits(LVT);
+  unsigned RSize = MVT::getSizeInBits(RVT);
+
+  // First get the sign bit of second operand.
+  SDOperand SignBit = DAG.getNode(ISD::SHL, RVT, DAG.getConstant(1, RVT),
+                                  DAG.getConstant(RSize - 1,
+                                                  TLI.getShiftAmountTy()));
+  SignBit = DAG.getNode(ISD::AND, RVT, RHS, SignBit);
+
+  // Shift right or sign-extend it if the two operands have different types.
+  int SizeDiff = MVT::getSizeInBits(RVT) - MVT::getSizeInBits(LVT);
+  if (SizeDiff > 0) {
+    SignBit = DAG.getNode(ISD::SRL, RVT, SignBit,
+                          DAG.getConstant(SizeDiff, TLI.getShiftAmountTy()));
+    SignBit = DAG.getNode(ISD::TRUNCATE, LVT, SignBit);
+  } else if (SizeDiff < 0) {
+    SignBit = DAG.getNode(ISD::ANY_EXTEND, LVT, SignBit);
+    SignBit = DAG.getNode(ISD::SHL, LVT, SignBit,
+                          DAG.getConstant(-SizeDiff, TLI.getShiftAmountTy()));
+  }
+
+  // Clear the sign bit of the first operand.
+  SDOperand Mask = DAG.getNode(ISD::SHL, LVT, DAG.getConstant(1, LVT),
+                               DAG.getConstant(LSize - 1,
+                                               TLI.getShiftAmountTy()));
+  Mask = DAG.getNode(ISD::SUB, LVT, Mask, DAG.getConstant(1, LVT));
+  LHS = DAG.getNode(ISD::AND, LVT, LHS, Mask);
+
+  // Or the value with the sign bit.
+  return DAG.getNode(ISD::OR, LVT, LHS, SignBit);
+}
+
+
+//===----------------------------------------------------------------------===//
+//  Operand Float to Integer Conversion..
+//===----------------------------------------------------------------------===//
+
+bool DAGTypeLegalizer::FloatToIntOperand(SDNode *N, unsigned OpNo) {
+  DEBUG(cerr << "FloatToInt node operand " << OpNo << ": "; N->dump(&DAG);
+        cerr << "\n");
+  SDOperand Res(0, 0);
+
+  // FIXME: Custom lowering for float-to-int?
+#if 0
+  if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
+      == TargetLowering::Custom)
+    Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
+#endif
+
+  if (Res.Val == 0) {
+    switch (N->getOpcode()) {
+    default:
+#ifndef NDEBUG
+      cerr << "FloatToIntOperand Op #" << OpNo << ": ";
+      N->dump(&DAG); cerr << "\n";
+#endif
+      assert(0 && "Do not know how to convert this operator's operand!");
+      abort();
+
+      case ISD::BIT_CONVERT: Res = FloatToIntOp_BIT_CONVERT(N); break;
+    }
+  }
+
+  // If the result is null, the sub-method took care of registering results etc.
+  if (!Res.Val) return false;
+
+  // If the result is N, the sub-method updated N in place.  Check to see if any
+  // operands are new, and if so, mark them.
+  if (Res.Val == N) {
+    // Mark N as new and remark N and its operands.  This allows us to correctly
+    // revisit N if it needs another step of promotion and allows us to visit
+    // any new operands to N.
+    ReanalyzeNode(N);
+    return true;
+  }
+
+  assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
+         "Invalid operand expansion");
+
+  ReplaceValueWith(SDOperand(N, 0), Res);
+  return false;
+}
+
+SDOperand DAGTypeLegalizer::FloatToIntOp_BIT_CONVERT(SDNode *N) {
+  return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0),
+                     GetIntegerOp(N->getOperand(0)));
+}
index 1a0dfe7..eef7a83 100644 (file)
@@ -234,25 +234,20 @@ SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) {
     break;
   case Expand:
     break;
+  case FloatToInt:
+    // Promote the integer operand by hand.
+    return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetIntegerOp(InOp));
   case Scalarize:
     // Convert the element to an integer and promote it by hand.
-    InOp = DAG.getNode(ISD::BIT_CONVERT,
-                       MVT::getIntegerType(MVT::getSizeInBits(InVT)),
-                       GetScalarizedOp(InOp));
-    InOp = DAG.getNode(ISD::ANY_EXTEND,
-                       MVT::getIntegerType(MVT::getSizeInBits(OutVT)), InOp);
-    return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp);
+    return DAG.getNode(ISD::ANY_EXTEND, OutVT,
+                       BitConvertToInteger(GetScalarizedOp(InOp)));
   case Split:
     // For example, i32 = BIT_CONVERT v2i16 on alpha.  Convert the split
     // pieces of the input into integers and reassemble in the final type.
     SDOperand Lo, Hi;
     GetSplitOp(N->getOperand(0), Lo, Hi);
-
-    unsigned LoBits = MVT::getSizeInBits(Lo.getValueType());
-    Lo = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(LoBits), Lo);
-
-    unsigned HiBits = MVT::getSizeInBits(Hi.getValueType());
-    Hi = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(HiBits), Hi);
+    Lo = BitConvertToInteger(Lo);
+    Hi = BitConvertToInteger(Hi);
 
     if (TLI.isBigEndian())
       std::swap(Lo, Hi);
index 2e76ceb..4a8c474 100644 (file)
@@ -263,6 +263,7 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N,
   default:
     assert(false && "Unknown type action!");
   case Legal:
+  case FloatToInt:
   case Promote:
   case Scalarize:
     break;
@@ -289,15 +290,12 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N,
   }
 
   // In the general case, convert the input to an integer and split it by hand.
-  InVT = MVT::getIntegerType(MVT::getSizeInBits(InVT));
-  InOp = DAG.getNode(ISD::BIT_CONVERT, InVT, InOp);
-
   MVT::ValueType LoIntVT = MVT::getIntegerType(MVT::getSizeInBits(LoVT));
   MVT::ValueType HiIntVT = MVT::getIntegerType(MVT::getSizeInBits(HiVT));
   if (TLI.isBigEndian())
     std::swap(LoIntVT, HiIntVT);
 
-  SplitInteger(InOp, LoIntVT, HiIntVT, Lo, Hi);
+  SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);
 
   if (TLI.isBigEndian())
     std::swap(Lo, Hi);
@@ -444,12 +442,8 @@ SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) {
   // split pieces into integers and reassemble.
   SDOperand Lo, Hi;
   GetSplitOp(N->getOperand(0), Lo, Hi);
-
-  unsigned LoBits = MVT::getSizeInBits(Lo.getValueType());
-  Lo = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(LoBits), Lo);
-
-  unsigned HiBits = MVT::getSizeInBits(Hi.getValueType());
-  Hi = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(HiBits), Hi);
+  Lo = BitConvertToInteger(Lo);
+  Hi = BitConvertToInteger(Hi);
 
   if (TLI.isBigEndian())
     std::swap(Lo, Hi);