diff options
author | Nate Begeman <natebegeman@mac.com> | 2008-07-14 18:02:46 +0000 |
---|---|---|
committer | Nate Begeman <natebegeman@mac.com> | 2008-07-14 18:02:46 +0000 |
commit | 191a6b1f1bf9d8c8e1e26735fc1059f2f002f103 (patch) | |
tree | 5fb698f45942d79b54840535b1da42e9b69d6677 /clang/lib/Sema | |
parent | 162668fa7836ec6fdde9d24216a4d0198d10c5cf (diff) | |
download | bcm5719-llvm-191a6b1f1bf9d8c8e1e26735fc1059f2f002f103.tar.gz bcm5719-llvm-191a6b1f1bf9d8c8e1e26735fc1059f2f002f103.zip |
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.
llvm-svn: 53565
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 104 |
2 files changed, 88 insertions, 22 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 9df94d4ae40..c19daded7c3 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 71f7717e5d8..7e3319a9427 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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) { |