From: Nate Begeman Date: Mon, 14 Jul 2008 18:02:46 +0000 (+0000) Subject: http://llvm.org/bugs/show_bug.cgi?id=2523 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=be2341d3b8bd34a14e921c58b53abaf79b0b0cb2;p=clang http://llvm.org/bugs/show_bug.cgi?id=2523 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 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 9df94d4ae4..c19daded7c 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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 diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 71f7717e5d..7e3319a942 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1370,24 +1370,19 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { return Incompatible; } - if (isa(lhsType) || isa(rhsType)) { + if (lhsType->isVectorType() || rhsType->isVectorType()) { // For ExtVector, allow vector splats; float -> - if (const ExtVectorType *LV = dyn_cast(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(rex)) || + (eltType->isFloatingType() && isa(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(lex)) || + (eltType->isFloatingType() && isa(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(lex->IgnoreParens())) + if (DeclRefExpr* DRR = dyn_cast(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) { diff --git a/test/Sema/vector-assign.c b/test/Sema/vector-assign.c index f915603465..be447120c5 100644 --- a/test/Sema/vector-assign.c +++ b/test/Sema/vector-assign.c @@ -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