Implement PR6845.  We allow matching constraints to have different
input and output types when the smaller value isn't mentioned in the
asm string.  Extend this support from integers to also allowing 
fp values to be mismatched (if not mentioned in the asm string).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102188 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 70cb1a2..b90e1c4 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -981,19 +981,18 @@
         unsigned InputNo;
         for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
           TargetInfo::ConstraintInfo &Input = InputConstraintInfos[InputNo];
-          if (Input.hasTiedOperand() &&
-              Input.getTiedOperand() == i)
+          if (Input.hasTiedOperand() && Input.getTiedOperand() == i)
             break;
         }
         assert(InputNo != S.getNumInputs() && "Didn't find matching input!");
 
         QualType InputTy = S.getInputExpr(InputNo)->getType();
-        QualType OutputTy = OutExpr->getType();
+        QualType OutputType = OutExpr->getType();
 
         uint64_t InputSize = getContext().getTypeSize(InputTy);
-        if (getContext().getTypeSize(OutputTy) < InputSize) {
-          // Form the asm to return the value as a larger integer type.
-          ResultRegTypes.back() = llvm::IntegerType::get(VMContext, (unsigned)InputSize);
+        if (getContext().getTypeSize(OutputType) < InputSize) {
+          // Form the asm to return the value as a larger integer or fp type.
+          ResultRegTypes.back() = ConvertType(InputTy);
         }
       }
     } else {
@@ -1043,18 +1042,20 @@
     // that is usually cheaper, but LLVM IR should really get an anyext someday.
     if (Info.hasTiedOperand()) {
       unsigned Output = Info.getTiedOperand();
-      QualType OutputTy = S.getOutputExpr(Output)->getType();
+      QualType OutputType = S.getOutputExpr(Output)->getType();
       QualType InputTy = InputExpr->getType();
 
-      if (getContext().getTypeSize(OutputTy) >
+      if (getContext().getTypeSize(OutputType) >
           getContext().getTypeSize(InputTy)) {
         // Use ptrtoint as appropriate so that we can do our extension.
         if (isa<llvm::PointerType>(Arg->getType()))
           Arg = Builder.CreatePtrToInt(Arg,
                            llvm::IntegerType::get(VMContext, LLVMPointerWidth));
-        unsigned OutputSize = (unsigned)getContext().getTypeSize(OutputTy);
-        Arg = Builder.CreateZExt(Arg,
-                                 llvm::IntegerType::get(VMContext, OutputSize));
+        const llvm::Type *OutputTy = ConvertType(OutputType);
+        if (isa<llvm::IntegerType>(OutputTy))
+          Arg = Builder.CreateZExt(Arg, OutputTy);
+        else
+          Arg = Builder.CreateFPExt(Arg, OutputTy);
       }
     }
 
@@ -1135,13 +1136,17 @@
     // the expression, do the conversion.
     if (ResultRegTypes[i] != ResultTruncRegTypes[i]) {
       const llvm::Type *TruncTy = ResultTruncRegTypes[i];
-      // Truncate the integer result to the right size, note that
-      // ResultTruncRegTypes can be a pointer.
-      uint64_t ResSize = CGM.getTargetData().getTypeSizeInBits(TruncTy);
-      Tmp = Builder.CreateTrunc(Tmp, llvm::IntegerType::get(VMContext, (unsigned)ResSize));
-
-      if (Tmp->getType() != TruncTy) {
-        assert(isa<llvm::PointerType>(TruncTy));
+      
+      // Truncate the integer result to the right size, note that TruncTy can be
+      // a pointer.
+      if (TruncTy->isFloatingPointTy())
+        Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
+      else if (!isa<llvm::PointerType>(TruncTy))
+        Tmp = Builder.CreateTrunc(Tmp, TruncTy);
+      else {
+        uint64_t ResSize = CGM.getTargetData().getTypeSizeInBits(TruncTy);
+        Tmp = Builder.CreateTrunc(Tmp, llvm::IntegerType::get(VMContext,
+                                                            (unsigned)ResSize));
         Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
       }
     }