Implement expansion of unsigned i64 -> FP.
authorChris Lattner <sabre@nondot.org>
Wed, 13 Apr 2005 05:09:42 +0000 (05:09 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 13 Apr 2005 05:09:42 +0000 (05:09 +0000)
Note that this probably only works for little endian targets, but is enough
to get siod working :)

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

lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

index 1dceccaeccf5196ea9a4f73eea23d191f36e43e8..3df62447576f497e861ad68488ef9b80779a2611 100644 (file)
@@ -1822,7 +1822,37 @@ ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) {
     // signed, then adjust the result if the sign bit is set.
     SDOperand SignedConv = ExpandIntToFP(true, DestTy, Source);
 
-    assert(0 && "Unsigned casts not supported yet!");
+    assert(Source.getValueType() == MVT::i64 &&
+           "This only works for 64-bit -> FP");
+    // The 64-bit value loaded will be incorrectly if the 'sign bit' of the
+    // incoming integer is set.  To handle this, we dynamically test to see if
+    // it is set, and, if so, add a fudge factor.
+    SDOperand Lo, Hi;
+    ExpandOp(Source, Lo, Hi);
+
+    SDOperand SignSet = DAG.getSetCC(ISD::SETLT, TLI.getSetCCResultTy(), Hi,
+                                     DAG.getConstant(0, Hi.getValueType()));
+    SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4);
+    SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
+                                      SignSet, Four, Zero);
+    // FIXME: This is almost certainly broken for big-endian systems.  Should
+    // this just put the fudge factor in the low bits of the uint64 constant or?
+    static Constant *FudgeFactor =
+      ConstantUInt::get(Type::ULongTy, 0x5f800000ULL << 32);
+
+    MachineConstantPool *CP = DAG.getMachineFunction().getConstantPool();
+    SDOperand CPIdx = DAG.getConstantPool(CP->getConstantPoolIndex(FudgeFactor),
+                                          TLI.getPointerTy());
+    CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset);
+    SDOperand FudgeInReg;
+    if (DestTy == MVT::f32)
+      FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx);
+    else {
+      assert(DestTy == MVT::f64 && "Unexpected conversion");
+      FudgeInReg = DAG.getNode(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(),
+                               CPIdx, MVT::f32);
+    }
+    return DAG.getNode(ISD::ADD, DestTy, SignedConv, FudgeInReg);
   }
   SDOperand Callee = DAG.getExternalSymbol(FnName, TLI.getPointerTy());
 
@@ -1835,7 +1865,6 @@ ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) {
   // calls wherever we need them to satisfy data dependences.
   const Type *RetTy = MVT::getTypeForValueType(DestTy);
   return TLI.LowerCallTo(InChain, RetTy, false, Callee, Args, DAG).first;
-                         
 }