Skip to content

Commit

Permalink
[clang][AArc64][SVE] Add support for comparison operators on SVE types
Browse files Browse the repository at this point in the history
Comparison operators on SVE types return a signed integer vector
of the same width as the incoming SVE type. This matches the existing
behaviour for NEON types.

Differential Revision: https://reviews.llvm.org/D122404
  • Loading branch information
DavidTruby committed Apr 5, 2022
1 parent 60c6e96 commit 4be1ec9
Show file tree
Hide file tree
Showing 7 changed files with 1,567 additions and 20 deletions.
4 changes: 4 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -11976,9 +11976,13 @@ class Sema final {
bool AllowBothBool, bool AllowBoolConversion,
bool AllowBoolOperation, bool ReportInvalid);
QualType GetSignedVectorType(QualType V);
QualType GetSignedSizelessVectorType(QualType V);
QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc);
QualType CheckSizelessVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc);
QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc);

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1390,8 +1390,8 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,

if (isa<llvm::VectorType>(SrcTy) || isa<llvm::VectorType>(DstTy)) {
// Allow bitcast from vector to integer/fp of the same size.
unsigned SrcSize = SrcTy->getPrimitiveSizeInBits();
unsigned DstSize = DstTy->getPrimitiveSizeInBits();
llvm::TypeSize SrcSize = SrcTy->getPrimitiveSizeInBits();
llvm::TypeSize DstSize = DstTy->getPrimitiveSizeInBits();
if (SrcSize == DstSize)
return Builder.CreateBitCast(Src, DstTy, "conv");

Expand Down
72 changes: 66 additions & 6 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@
#include "clang/Sema/Template.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/TypeSize.h"

using namespace clang;
using namespace sema;
Expand Down Expand Up @@ -12153,6 +12155,10 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
RHS.get()->getType()->isVectorType())
return CheckVectorCompareOperands(LHS, RHS, Loc, Opc);

if (LHS.get()->getType()->isVLSTBuiltinType() ||
RHS.get()->getType()->isVLSTBuiltinType())
return CheckSizelessVectorCompareOperands(LHS, RHS, Loc, Opc);

diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc);
diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc);

Expand Down Expand Up @@ -12614,6 +12620,18 @@ QualType Sema::GetSignedVectorType(QualType V) {
VectorType::GenericVector);
}

QualType Sema::GetSignedSizelessVectorType(QualType V) {
const BuiltinType *VTy = V->castAs<BuiltinType>();
assert(VTy->isSizelessBuiltinType() && "expected sizeless type");

const QualType ETy = V->getSveEltType(Context);
const auto TypeSize = Context.getTypeSize(ETy);

const QualType IntTy = Context.getIntTypeForBitwidth(TypeSize, true);
const llvm::ElementCount VecSize = Context.getBuiltinVectorTypeInfo(VTy).EC;
return Context.getScalableVectorType(IntTy, VecSize.getKnownMinValue());
}

/// 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
Expand Down Expand Up @@ -12680,6 +12698,48 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
return GetSignedVectorType(vType);
}

QualType Sema::CheckSizelessVectorCompareOperands(ExprResult &LHS,
ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc) {
if (Opc == BO_Cmp) {
Diag(Loc, diag::err_three_way_vector_comparison);
return QualType();
}

// 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 = CheckSizelessVectorOperands(
LHS, RHS, Loc, /*isCompAssign*/ false, ACK_Comparison);

if (vType.isNull())
return vType;

QualType LHSType = LHS.get()->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.
diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc);

// Check for comparisons of floating point operands using != and ==.
if (BinaryOperator::isEqualityOp(Opc) &&
LHSType->hasFloatingRepresentation()) {
assert(RHS.get()->getType()->hasFloatingRepresentation());
CheckFloatComparison(Loc, LHS.get(), RHS.get(), Opc);
}

const BuiltinType *LHSBuiltinTy = LHSType->getAs<BuiltinType>();
const BuiltinType *RHSBuiltinTy = RHS.get()->getType()->getAs<BuiltinType>();

if (LHSBuiltinTy && RHSBuiltinTy && LHSBuiltinTy->isSVEBool() &&
RHSBuiltinTy->isSVEBool())
return LHSType;

// Return a signed type for the vector.
return GetSignedSizelessVectorType(vType);
}

static void diagnoseXorMisusedAsPow(Sema &S, const ExprResult &XorLHS,
const ExprResult &XorRHS,
const SourceLocation Loc) {
Expand Down Expand Up @@ -12986,7 +13046,8 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc) {
// Check vector operands differently.
if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType())
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType())
return CheckVectorLogicalOperands(LHS, RHS, Loc);

bool EnumConstantInBoolContext = false;
Expand Down Expand Up @@ -13020,14 +13081,13 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
!RHS.get()->getExprLoc().isMacroID()) ||
(Result != 0 && Result != 1)) {
Diag(Loc, diag::warn_logical_instead_of_bitwise)
<< RHS.get()->getSourceRange()
<< (Opc == BO_LAnd ? "&&" : "||");
<< RHS.get()->getSourceRange() << (Opc == BO_LAnd ? "&&" : "||");
// Suggest replacing the logical operator with the bitwise version
Diag(Loc, diag::note_logical_instead_of_bitwise_change_operator)
<< (Opc == BO_LAnd ? "&" : "|")
<< FixItHint::CreateReplacement(SourceRange(
Loc, getLocForEndOfToken(Loc)),
Opc == BO_LAnd ? "&" : "|");
<< FixItHint::CreateReplacement(
SourceRange(Loc, getLocForEndOfToken(Loc)),
Opc == BO_LAnd ? "&" : "|");
if (Opc == BO_LAnd)
// Suggest replacing "Foo() && kNonZero" with "Foo()"
Diag(Loc, diag::note_logical_instead_of_bitwise_remove_constant)
Expand Down
Loading

0 comments on commit 4be1ec9

Please sign in to comment.