]> granicus.if.org Git - clang/commitdiff
http://llvm.org/bugs/show_bug.cgi?id=2523
authorNate Begeman <natebegeman@mac.com>
Mon, 14 Jul 2008 18:02:46 +0000 (18:02 +0000)
committerNate Begeman <natebegeman@mac.com>
Mon, 14 Jul 2008 18:02:46 +0000 (18:02 +0000)
Add some code to handle vector comparisons, which is the language side
of the llvm vicmp/vfcmp instructions.  Also make the vector-vector and
vector-scalar asign checks a bit more sane under the presence of lax vector
conversions.

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

lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
test/Sema/vector-assign.c

index 9df94d4ae40a833ed6403b480a98083ea88a555d..c19daded7c33f04433b8541c6ab40f3fbac4dcf9 100644 (file)
@@ -812,7 +812,6 @@ private:
     
   /// type checking binary operators (subroutines of ActOnBinOp).
   inline QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex);
-  inline QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex);
   inline QualType CheckMultiplyDivideOperands( // C99 6.5.5
     Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); 
   inline QualType CheckRemainderOperands( // C99 6.5.5
@@ -838,6 +837,11 @@ private:
     Expr *&lex, Expr *&rex, SourceLocation OpLoc);
   inline QualType CheckConditionalOperands( // C99 6.5.15
     Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
+
+  /// type checking for vector binary operators.
+  inline QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex);
+  inline QualType CheckVectorCompareOperands(Expr *&lex, Expr *&rx,
+                                             SourceLocation l, bool isRel);
   
   /// type checking unary operators (subroutines of ActOnUnaryOp).
   /// C99 6.5.3.1, 6.5.3.2, 6.5.3.4
index 71f7717e5d801a2a66f2c751e938d376766eb19f..7e3319a9427caedbf91c71f3179fca7210c44206 100644 (file)
@@ -1370,24 +1370,19 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
     return Incompatible;
   }
 
-  if (isa<VectorType>(lhsType) || isa<VectorType>(rhsType)) {
+  if (lhsType->isVectorType() || rhsType->isVectorType()) {
     // For ExtVector, allow vector splats; float -> <n x float>
-    if (const ExtVectorType *LV = dyn_cast<ExtVectorType>(lhsType)) {
-      if (LV->getElementType().getTypePtr() == rhsType.getTypePtr())
+    if (const ExtVectorType *LV = lhsType->getAsExtVectorType())
+      if (LV->getElementType() == rhsType)
         return Compatible;
-    }
 
-    // If LHS and RHS are both vectors of integer or both vectors of floating
-    // point types, and the total vector length is the same, allow the
-    // conversion.  This is a bitcast; no bits are changed but the result type
-    // is different.
+    // If we are allowing lax vector conversions, and LHS and RHS are both
+    // vectors, the total size only needs to be the same. This is a bitcast; 
+    // no bits are changed but the result type is different.
     if (getLangOptions().LaxVectorConversions &&
         lhsType->isVectorType() && rhsType->isVectorType()) {
-      if ((lhsType->isIntegerType() && rhsType->isIntegerType()) ||
-          (lhsType->isRealFloatingType() && rhsType->isRealFloatingType())) {
-        if (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))
-          return Compatible;
-      }
+      if (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))
+        return Compatible;
     }
     return Incompatible;
   }      
@@ -1472,25 +1467,40 @@ inline QualType Sema::CheckVectorOperands(SourceLocation loc, Expr *&lex,
   QualType lhsType = lex->getType().getCanonicalType().getUnqualifiedType();
   QualType rhsType = rex->getType().getCanonicalType().getUnqualifiedType();
   
-  // make sure the vector types are identical. 
+  // If the vector types are identical, return.
   if (lhsType == rhsType)
     return lhsType;
 
-  // if the lhs is an extended vector and the rhs is a scalar of the same type,
-  // promote the rhs to the vector type.
+  // Handle the case of a vector & extvector type of the same size and element
+  // type.  It would be nice if we only had one vector type someday.
+  if (getLangOptions().LaxVectorConversions)
+    if (const VectorType *LV = lhsType->getAsVectorType())
+      if (const VectorType *RV = rhsType->getAsVectorType())
+        if (LV->getElementType() == RV->getElementType() &&
+            LV->getNumElements() == RV->getNumElements())
+          return lhsType->isExtVectorType() ? lhsType : rhsType;
+
+  // If the lhs is an extended vector and the rhs is a scalar of the same type
+  // or a literal, promote the rhs to the vector type.
   if (const ExtVectorType *V = lhsType->getAsExtVectorType()) {
-    if (V->getElementType().getCanonicalType().getTypePtr()
-        == rhsType.getCanonicalType().getTypePtr()) {
+    QualType eltType = V->getElementType();
+    
+    if ((eltType->getAsBuiltinType() == rhsType->getAsBuiltinType()) || 
+        (eltType->isIntegerType() && isa<IntegerLiteral>(rex)) ||
+        (eltType->isFloatingType() && isa<FloatingLiteral>(rex))) {
       ImpCastExprToType(rex, lhsType);
       return lhsType;
     }
   }
 
-  // if the rhs is an extended vector and the lhs is a scalar of the same type,
+  // If the rhs is an extended vector and the lhs is a scalar of the same type,
   // promote the lhs to the vector type.
   if (const ExtVectorType *V = rhsType->getAsExtVectorType()) {
-    if (V->getElementType().getCanonicalType().getTypePtr()
-        == lhsType.getCanonicalType().getTypePtr()) {
+    QualType eltType = V->getElementType();
+
+    if ((eltType->getAsBuiltinType() == lhsType->getAsBuiltinType()) || 
+        (eltType->isIntegerType() && isa<IntegerLiteral>(lex)) ||
+        (eltType->isFloatingType() && isa<FloatingLiteral>(lex))) {
       ImpCastExprToType(lex, rhsType);
       return rhsType;
     }
@@ -1656,6 +1666,9 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation loc,
 // C99 6.5.8
 QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation loc,
                                     bool isRelational) {
+  if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+    return CheckVectorCompareOperands(lex, rex, loc, isRelational);
+  
   // C99 6.5.8p3 / C99 6.5.9p4
   if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
     UsualArithmeticConversions(lex, rex);
@@ -1740,6 +1753,55 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation loc,
   return InvalidOperands(loc, lex, rex);
 }
 
+/// CheckVectorCompareOperands - vector comparisons are a clang extension that
+/// operates on extended vector types.  Instead of producing an IntTy result, 
+/// like a scalar comparison, a vector comparison produces a vector of integer
+/// types.
+QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
+                                          SourceLocation loc,
+                                          bool isRelational) {
+  // Check to make sure we're operating on vectors of the same type and width,
+  // Allowing one side to be a scalar of element type.
+  QualType vType = CheckVectorOperands(loc, lex, rex);
+  if (vType.isNull())
+    return vType;
+  
+  QualType lType = lex->getType();
+  QualType rType = rex->getType();
+  
+  // For non-floating point types, check for self-comparisons of the form
+  // x == x, x != x, x < x, etc.  These always evaluate to a constant, and
+  // often indicate logic errors in the program.
+  if (!lType->isFloatingType()) {
+    if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
+      if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
+        if (DRL->getDecl() == DRR->getDecl())
+          Diag(loc, diag::warn_selfcomparison);      
+  }
+  
+  // Check for comparisons of floating point operands using != and ==.
+  if (!isRelational && lType->isFloatingType()) {
+    assert (rType->isFloatingType());
+    CheckFloatComparison(loc,lex,rex);
+  }
+  
+  // Return the type for the comparison, which is the same as vector type for
+  // integer vectors, or an integer type of identical size and number of
+  // elements for floating point vectors.
+  if (lType->isIntegerType())
+    return lType;
+  
+  const VectorType *VTy = lType->getAsVectorType();
+
+  // FIXME: need to deal with non-32b int / non-64b long long
+  unsigned TypeSize = Context.getTypeSize(VTy->getElementType());
+  if (TypeSize == 32) {
+    return Context.getExtVectorType(Context.IntTy, VTy->getNumElements());
+  }
+  assert(TypeSize == 64 && "Unhandled vector element size in vector compare");
+  return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements());
+}
+
 inline QualType Sema::CheckBitwiseOperands(
   Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign) 
 {
index f915603465dbf09d4294f9d901c6b5eaf6d4b821..be447120c51ce383925bb75e1a6962f965eb8927 100644 (file)
@@ -14,12 +14,12 @@ void f() {
   
   v1 = v2; 
   v1 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2s'}}
-  v1 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v2s'}}
+  v1 = v4; 
   v1 = v5;
   
   v2 = v1;
   v2 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2u'}}
-  v2 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v2u'}}
+  v2 = v4; 
   v2 = v5;
   
   v3 = v1; // expected-error {{incompatible type assigning 'v2s', expected 'v1s'}}
@@ -27,15 +27,15 @@ void f() {
   v3 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v1s'}}
   v3 = v5; // expected-error {{incompatible type assigning 'v4ss', expected 'v1s'}}
   
-  v4 = v1; // expected-error {{incompatible type assigning 'v2s', expected 'v2f'}}
-  v4 = v2; // expected-error {{incompatible type assigning 'v2u', expected 'v2f'}}
+  v4 = v1; 
+  v4 = v2; 
   v4 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2f'}}
-  v4 = v5; // expected-error {{incompatible type assigning 'v4ss', expected 'v2f'}}
+  v4 = v5;
   
   v5 = v1;
   v5 = v2;
   v5 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v4ss'}}
-  v5 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v4ss'}}
+  v5 = v4;
 }
 
 // PR2263