[llvm-commits] [llvm] r48305 - in /llvm/trunk/lib/CodeGen/SelectionDAG: LegalizeTypes.cpp LegalizeTypes.h LegalizeTypesExpand.cpp LegalizeTypesFloatToInt.cpp LegalizeTypesPromote.cpp LegalizeTypesSplit.cpp

Duncan Sands baldrick at free.fr
Wed Mar 12 14:27:04 PDT 2008


Author: baldrick
Date: Wed Mar 12 16:27:04 2008
New Revision: 48305

URL: http://llvm.org/viewvc/llvm-project?rev=48305&view=rev
Log:
Initial soft-float support for LegalizeTypes.  I rewrote
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.

Added:
    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp
Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h
    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp

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

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp Wed Mar 12 16:27:04 2008
@@ -79,6 +79,9 @@
       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 @@
       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 @@
   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 @@
   OpEntry = Result;
 }
 
-
 void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo, 
                                      SDOperand &Hi) {
   std::pair<SDOperand, SDOperand> &Entry = ExpandedNodes[Op];
@@ -408,6 +421,13 @@
 }
 
 
+/// 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.

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h?rev=48305&r1=48304&r2=48305&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Wed Mar 12 16:27:04 2008
@@ -62,6 +62,7 @@
     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 @@
     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 @@
   /// 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 @@
   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 @@
                            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 @@
   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);

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

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp Wed Mar 12 16:27:04 2008
@@ -260,6 +260,12 @@
       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 @@
       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;

Added: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp?rev=48305&view=auto

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp (added)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp Wed Mar 12 16:27:04 2008
@@ -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)));
+}

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

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp Wed Mar 12 16:27:04 2008
@@ -234,25 +234,20 @@
     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);

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

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp Wed Mar 12 16:27:04 2008
@@ -263,6 +263,7 @@
   default:
     assert(false && "Unknown type action!");
   case Legal:
+  case FloatToInt:
   case Promote:
   case Scalarize:
     break;
@@ -289,15 +290,12 @@
   }
 
   // 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 @@
   // 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);





More information about the llvm-commits mailing list