[cfe-commits] r102188 - in /cfe/trunk: lib/CodeGen/CGStmt.cpp lib/Sema/SemaStmt.cpp test/CodeGen/asm.c

Chris Lattner sabre at nondot.org
Fri Apr 23 10:27:29 PDT 2010


Author: lattner
Date: Fri Apr 23 12:27:29 2010
New Revision: 102188

URL: http://llvm.org/viewvc/llvm-project?rev=102188&view=rev
Log:
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).

Modified:
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/test/CodeGen/asm.c

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=102188&r1=102187&r2=102188&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Fri Apr 23 12:27:29 2010
@@ -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);
       }
     }

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=102188&r1=102187&r2=102188&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri Apr 23 12:27:29 2010
@@ -1446,53 +1446,72 @@
     if (Context.hasSameType(InTy, OutTy))
       continue;  // All types can be tied to themselves.
 
-    // Int/ptr operands have some special cases that we allow.
-    if ((OutTy->isIntegerType() || OutTy->isPointerType()) &&
-        (InTy->isIntegerType() || InTy->isPointerType())) {
-
-      // They are ok if they are the same size.  Tying void* to int is ok if
-      // they are the same size, for example.  This also allows tying void* to
-      // int*.
-      uint64_t OutSize = Context.getTypeSize(OutTy);
-      uint64_t InSize = Context.getTypeSize(InTy);
-      if (OutSize == InSize)
-        continue;
-
-      // If the smaller input/output operand is not mentioned in the asm string,
-      // then we can promote it and the asm string won't notice.  Check this
-      // case now.
-      bool SmallerValueMentioned = false;
-      for (unsigned p = 0, e = Pieces.size(); p != e; ++p) {
-        AsmStmt::AsmStringPiece &Piece = Pieces[p];
-        if (!Piece.isOperand()) continue;
-
-        // If this is a reference to the input and if the input was the smaller
-        // one, then we have to reject this asm.
-        if (Piece.getOperandNo() == i+NumOutputs) {
-          if (InSize < OutSize) {
-            SmallerValueMentioned = true;
-            break;
-          }
-        }
+    // Decide if the input and output are in the same domain (integer/ptr or
+    // floating point.
+    enum AsmDomain {
+      AD_Int, AD_FP, AD_Other
+    } InputDomain, OutputDomain;
+    
+    if (InTy->isIntegerType() || InTy->isPointerType())
+      InputDomain = AD_Int;
+    else if (InTy->isFloatingType())
+      InputDomain = AD_FP;
+    else
+      InputDomain = AD_Other;
 
-        // If this is a reference to the input and if the input was the smaller
-        // one, then we have to reject this asm.
-        if (Piece.getOperandNo() == TiedTo) {
-          if (InSize > OutSize) {
-            SmallerValueMentioned = true;
-            break;
-          }
+    if (OutTy->isIntegerType() || OutTy->isPointerType())
+      OutputDomain = AD_Int;
+    else if (OutTy->isFloatingType())
+      OutputDomain = AD_FP;
+    else
+      OutputDomain = AD_Other;
+    
+    // They are ok if they are the same size and in the same domain.  This
+    // allows tying things like:
+    //   void* to int*
+    //   void* to int            if they are the same size.
+    //   double to long double   if they are the same size.
+    // 
+    uint64_t OutSize = Context.getTypeSize(OutTy);
+    uint64_t InSize = Context.getTypeSize(InTy);
+    if (OutSize == InSize && InputDomain == OutputDomain &&
+        InputDomain != AD_Other)
+      continue;
+    
+    // If the smaller input/output operand is not mentioned in the asm string,
+    // then we can promote it and the asm string won't notice.  Check this
+    // case now.
+    bool SmallerValueMentioned = false;
+    for (unsigned p = 0, e = Pieces.size(); p != e; ++p) {
+      AsmStmt::AsmStringPiece &Piece = Pieces[p];
+      if (!Piece.isOperand()) continue;
+
+      // If this is a reference to the input and if the input was the smaller
+      // one, then we have to reject this asm.
+      if (Piece.getOperandNo() == i+NumOutputs) {
+        if (InSize < OutSize) {
+          SmallerValueMentioned = true;
+          break;
         }
       }
 
-      // If the smaller value wasn't mentioned in the asm string, and if the
-      // output was a register, just extend the shorter one to the size of the
-      // larger one.
-      if (!SmallerValueMentioned &&
-          OutputConstraintInfos[TiedTo].allowsRegister())
-        continue;
+      // If this is a reference to the input and if the input was the smaller
+      // one, then we have to reject this asm.
+      if (Piece.getOperandNo() == TiedTo) {
+        if (InSize > OutSize) {
+          SmallerValueMentioned = true;
+          break;
+        }
+      }
     }
 
+    // If the smaller value wasn't mentioned in the asm string, and if the
+    // output was a register, just extend the shorter one to the size of the
+    // larger one.
+    if (!SmallerValueMentioned && InputDomain != AD_Other &&
+        OutputConstraintInfos[TiedTo].allowsRegister())
+      continue;
+
     Diag(InputExpr->getLocStart(),
          diag::err_asm_tying_incompatible_types)
       << InTy << OutTy << OutputExpr->getSourceRange()

Modified: cfe/trunk/test/CodeGen/asm.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/asm.c?rev=102188&r1=102187&r2=102188&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/asm.c (original)
+++ cfe/trunk/test/CodeGen/asm.c Fri Apr 23 12:27:29 2010
@@ -147,3 +147,24 @@
   // CHECK: = call {{.*}}asm "x$(abc$|def$|ghi$)z"
 }
 
+
+// PR6845 - Mismatching source/dest fp types.
+double t20(double x) {
+  register long double result;
+  __asm __volatile ("frndint"  : "=t" (result) : "0" (x));
+  return result;
+  
+  // CHECK: @t20
+  // CHECK: fpext double {{.*}} to x86_fp80
+  // CHECK-NEXT: call x86_fp80 asm sideeffect "frndint"
+  // CHECK: fptrunc x86_fp80 {{.*}} to double
+}
+
+float t21(long double x) {
+  register float result;
+  __asm __volatile ("frndint"  : "=t" (result) : "0" (x));
+  return result;
+  // CHECK: @t21
+  // CHECK: call x86_fp80 asm sideeffect "frndint"
+  // CHECK-NEXT: fptrunc x86_fp80 {{.*}} to float
+}





More information about the cfe-commits mailing list