[clang] [Clang][RISCV] Add operator overloading for builtin RVV vector types (PR #192722)

via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 17 12:41:20 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-backend-risc-v

Author: Philip Reames (preames)

<details>
<summary>Changes</summary>

Enable arithmetic, bitwise, shift, unary, ternary, comparison, and subscript on RVV vector types, matching the existing SVE support as closely as can be managed with one exception.  The SVE support generates _unsigned_ comparison predicates for comparisons of _signed_ types.  This looks very unintuitive to me, so I changed it to use signed comparisons.  I think the SVE case may just be a bug?

One other point to highlight is that comparisons are producing the full width integer type (not a boolean predicate vector), and using the 0/1 convention used by SVE rather than the 0/-1 convention used by the gcc vector extension.

I have been verbally told that GCC has added analogous support though I have not seen patches.  I plan to seek confirmation of the comparison edge case before landing.

Previously discussed here:
https://github.com/riscv-non-isa/riscv-rvv-intrinsic-doc/issues/291

Originally written by Claude and heavily evolved by me, but fair warning that this is far outside my usual comfort zone.  I may have screwed something up majorly, careful review appreciated.

This change deliberately does not include the following:
- sizeof w/-mrvv-vector-bits=zvl
- explicit splats, or build vector syntax
- builtin elementwise operations

These may follow in separate patches, but I'm subsetting to minimize required review discussion.  Depending on reviewer preference I may drop the comparisons if the SVE divergence turns out to require too much thought.

---

Patch is 46.59 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/192722.diff


11 Files Affected:

- (modified) clang/include/clang/AST/TypeBase.h (+12-1) 
- (modified) clang/lib/AST/ExprConstant.cpp (+1-1) 
- (modified) clang/lib/AST/Type.cpp (+25-3) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+49-47) 
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+5-4) 
- (added) clang/test/CodeGen/RISCV/rvv-vector-arith-ops.c (+259) 
- (added) clang/test/CodeGen/RISCV/rvv-vector-bitwise-ops.c (+87) 
- (added) clang/test/CodeGen/RISCV/rvv-vector-compare-ops.c (+258) 
- (added) clang/test/CodeGen/RISCV/rvv-vector-shift-ops.c (+48) 
- (added) clang/test/CodeGen/RISCV/rvv-vector-subscript-ops.c (+99) 
- (added) clang/test/Sema/riscv-rvv-vector-arith-ops.c (+77) 


``````````diff
diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h
index a64bbb99b13d2..b7295b6958fa5 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -2506,6 +2506,11 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
   /// RVV vector or mask.
   bool isRVVVLSBuiltinType() const;
 
+  /// Determines if this is either an SVE or RVV sizeless builtin type.
+  bool isVLSBuiltinType() const {
+    return isSveVLSBuiltinType() || isRVVVLSBuiltinType();
+  }
+
   /// Returns the representative type for the element of an RVV builtin type.
   /// This is used to represent fixed-length RVV vectors created with the
   /// 'riscv_rvv_vector_bits' type attribute as VectorType.
@@ -3292,6 +3297,12 @@ class BuiltinType : public Type {
 
   bool isSVECount() const { return getKind() == Kind::SveCount; }
 
+  bool isRVVBool() const {
+    return getKind() >= Kind::RvvBool1 && getKind() <= Kind::RvvBool64;
+  }
+
+  bool isSizelessVectorBool() const { return isSVEBool() || isRVVBool(); }
+
   /// Determines whether the given kind corresponds to a placeholder type.
   static bool isPlaceholderTypeKind(Kind K) {
     return K >= Overload;
@@ -8825,7 +8836,7 @@ inline bool Type::isConstantMatrixBoolType() const {
 }
 
 inline bool Type::isSubscriptableVectorType() const {
-  return isVectorType() || isSveVLSBuiltinType();
+  return isVectorType() || isVLSBuiltinType();
 }
 
 inline bool Type::isMatrixType() const {
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f2f9aeaec2588..d5706521a97e7 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9662,7 +9662,7 @@ bool LValueExprEvaluator::VisitExtVectorElementExpr(
 }
 
 bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
-  if (E->getBase()->getType()->isSveVLSBuiltinType())
+  if (E->getBase()->getType()->isVLSBuiltinType())
     return Error(E);
 
   APSInt Index;
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 1cc318697d936..0cf3a756f4407 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2092,7 +2092,8 @@ bool Type::hasIntegerRepresentation() const {
   }
   if (CanonicalType->isRVVVLSBuiltinType()) {
     const auto *VT = cast<BuiltinType>(CanonicalType);
-    return (VT->getKind() >= BuiltinType::RvvInt8mf8 &&
+    return VT->isRVVBool() ||
+           (VT->getKind() >= BuiltinType::RvvInt8mf8 &&
             VT->getKind() <= BuiltinType::RvvUint64m8);
   }
 
@@ -2275,8 +2276,18 @@ bool Type::isSignedIntegerOrEnumerationType() const {
 bool Type::hasSignedIntegerRepresentation() const {
   if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isSignedIntegerOrEnumerationType();
-  else
-    return isSignedIntegerOrEnumerationType();
+  if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+    switch (BT->getKind()) {
+#define RVV_VECTOR_TYPE_INT(Name, Id, SingletonId, NumEls, ElBits, NF,         \
+                            IsSigned)                                          \
+    case BuiltinType::Id:                                                      \
+      return IsSigned;
+#include "clang/Basic/RISCVVTypes.def"
+    default:
+      break;
+    }
+  }
+  return isSignedIntegerOrEnumerationType();
 }
 
 /// isUnsignedIntegerType - Return true if this is an integer type that is
@@ -2336,6 +2347,17 @@ bool Type::hasUnsignedIntegerRepresentation() const {
     return VT->getKind() >= BuiltinType::SveUint8 &&
            VT->getKind() <= BuiltinType::SveUint64;
   }
+  if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+    switch (BT->getKind()) {
+#define RVV_VECTOR_TYPE_INT(Name, Id, SingletonId, NumEls, ElBits, NF,         \
+                            IsSigned)                                          \
+    case BuiltinType::Id:                                                      \
+      return !IsSigned;
+#include "clang/Basic/RISCVVTypes.def"
+    default:
+      break;
+    }
+  }
   return isUnsignedIntegerOrEnumerationType();
 }
 
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index cf235095d489d..8b0c3f2b57ce5 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5453,13 +5453,13 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
     }
   } else if (LHSTy->isSubscriptableVectorType()) {
     if (LHSTy->isBuiltinType() &&
-        LHSTy->getAs<BuiltinType>()->isSveVLSBuiltinType()) {
+        LHSTy->getAs<BuiltinType>()->isVLSBuiltinType()) {
       const BuiltinType *BTy = LHSTy->getAs<BuiltinType>();
-      if (BTy->isSVEBool())
+      if (BTy->isSizelessVectorBool())
         return ExprError(Diag(LLoc, diag::err_subscript_svbool_t)
                          << LHSExp->getSourceRange()
                          << RHSExp->getSourceRange());
-      ResultType = BTy->getSveEltType(Context);
+      ResultType = LHSTy->getSizelessVectorEltType(Context);
     } else {
       const VectorType *VTy = LHSTy->getAs<VectorType>();
       ResultType = VTy->getElementType();
@@ -10587,11 +10587,10 @@ static bool tryGCCVectorConvertAndSplat(Sema &S, ExprResult *Scalar,
     assert(!isa<ExtVectorType>(VT) &&
            "ExtVectorTypes should not be handled here!");
     VectorEltTy = VT->getElementType();
-  } else if (VectorTy->isSveVLSBuiltinType()) {
-    VectorEltTy =
-        VectorTy->castAs<BuiltinType>()->getSveEltType(S.getASTContext());
+  } else if (VectorTy->isVLSBuiltinType()) {
+    VectorEltTy = VectorTy->getSizelessVectorEltType(S.getASTContext());
   } else {
-    llvm_unreachable("Only Fixed-Length and SVE Vector types are handled here");
+    llvm_unreachable("Only Fixed-Length and sizeless vector types are handled here");
   }
 
   // Reject cases where the vector element type or the scalar element type are
@@ -10957,9 +10956,11 @@ QualType Sema::CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS,
   const BuiltinType *RHSBuiltinTy = RHSType->getAs<BuiltinType>();
 
   unsigned DiagID = diag::err_typecheck_invalid_operands;
+
+
   if ((OperationKind == ArithConvKind::Arithmetic) &&
-      ((LHSBuiltinTy && LHSBuiltinTy->isSVEBool()) ||
-       (RHSBuiltinTy && RHSBuiltinTy->isSVEBool()))) {
+      ((LHSBuiltinTy && LHSBuiltinTy->isSizelessVectorBool()) ||
+       (RHSBuiltinTy && RHSBuiltinTy->isSizelessVectorBool()))) {
     Diag(Loc, DiagID) << LHSType << RHSType << LHS.get()->getSourceRange()
                       << RHS.get()->getSourceRange();
     return QualType();
@@ -10968,25 +10969,25 @@ QualType Sema::CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS,
   if (Context.hasSameType(LHSType, RHSType))
     return LHSType;
 
-  if (LHSType->isSveVLSBuiltinType() && !RHSType->isSveVLSBuiltinType()) {
+  if (LHSType->isVLSBuiltinType() && !RHSType->isVLSBuiltinType()) {
     if (!tryGCCVectorConvertAndSplat(*this, &RHS, &LHS))
       return LHSType;
   }
-  if (RHSType->isSveVLSBuiltinType() && !LHSType->isSveVLSBuiltinType()) {
+  if (RHSType->isVLSBuiltinType() && !LHSType->isVLSBuiltinType()) {
     if (LHS.get()->isLValue() ||
         !tryGCCVectorConvertAndSplat(*this, &LHS, &RHS))
       return RHSType;
   }
 
-  if ((!LHSType->isSveVLSBuiltinType() && !LHSType->isRealType()) ||
-      (!RHSType->isSveVLSBuiltinType() && !RHSType->isRealType())) {
+  if ((!LHSType->isVLSBuiltinType() && !LHSType->isRealType()) ||
+      (!RHSType->isVLSBuiltinType() && !RHSType->isRealType())) {
     Diag(Loc, diag::err_typecheck_vector_not_convertable_non_scalar)
         << LHSType << RHSType << LHS.get()->getSourceRange()
         << RHS.get()->getSourceRange();
     return QualType();
   }
 
-  if (LHSType->isSveVLSBuiltinType() && RHSType->isSveVLSBuiltinType() &&
+  if (LHSType->isVLSBuiltinType() && RHSType->isVLSBuiltinType() &&
       Context.getBuiltinVectorTypeInfo(LHSBuiltinTy).EC !=
           Context.getBuiltinVectorTypeInfo(RHSBuiltinTy).EC) {
     Diag(Loc, diag::err_typecheck_vector_lengths_not_equal)
@@ -10995,11 +10996,11 @@ QualType Sema::CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS,
     return QualType();
   }
 
-  if (LHSType->isSveVLSBuiltinType() || RHSType->isSveVLSBuiltinType()) {
-    QualType Scalar = LHSType->isSveVLSBuiltinType() ? RHSType : LHSType;
-    QualType Vector = LHSType->isSveVLSBuiltinType() ? LHSType : RHSType;
+  if (LHSType->isVLSBuiltinType() || RHSType->isVLSBuiltinType()) {
+    QualType Scalar = LHSType->isVLSBuiltinType() ? RHSType : LHSType;
+    QualType Vector = LHSType->isVLSBuiltinType() ? LHSType : RHSType;
     bool ScalarOrVector =
-        LHSType->isSveVLSBuiltinType() && RHSType->isSveVLSBuiltinType();
+        LHSType->isVLSBuiltinType() && RHSType->isVLSBuiltinType();
 
     Diag(Loc, diag::err_typecheck_vector_not_convertable_implict_truncation)
         << ScalarOrVector << Scalar << Vector;
@@ -11205,7 +11206,7 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
                                /*AllowBoolConversions*/ false,
                                /*AllowBooleanOperation*/ false,
                                /*ReportInvalid*/ true);
-  if (LHSTy->isSveVLSBuiltinType() || RHSTy->isSveVLSBuiltinType())
+  if (LHSTy->isVLSBuiltinType() || RHSTy->isVLSBuiltinType())
     return CheckSizelessVectorOperands(LHS, RHS, Loc, IsCompAssign,
                                        ArithConvKind::Arithmetic);
   if (!IsDiv &&
@@ -11271,8 +11272,8 @@ QualType Sema::CheckRemainderOperands(
     return InvalidOperands(Loc, LHS, RHS);
   }
 
-  if (LHS.get()->getType()->isSveVLSBuiltinType() ||
-      RHS.get()->getType()->isSveVLSBuiltinType()) {
+  if (LHS.get()->getType()->isVLSBuiltinType() ||
+      RHS.get()->getType()->isVLSBuiltinType()) {
     if (LHS.get()->getType()->hasIntegerRepresentation() &&
         RHS.get()->getType()->hasIntegerRepresentation())
       return CheckSizelessVectorOperands(LHS, RHS, Loc, IsCompAssign,
@@ -11598,8 +11599,8 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
     return compType;
   }
 
-  if (LHS.get()->getType()->isSveVLSBuiltinType() ||
-      RHS.get()->getType()->isSveVLSBuiltinType()) {
+  if (LHS.get()->getType()->isVLSBuiltinType() ||
+      RHS.get()->getType()->isVLSBuiltinType()) {
     QualType compType = CheckSizelessVectorOperands(LHS, RHS, Loc, CompLHSTy,
                                                     ArithConvKind::Arithmetic);
     if (CompLHSTy)
@@ -11725,8 +11726,8 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
     return compType;
   }
 
-  if (LHS.get()->getType()->isSveVLSBuiltinType() ||
-      RHS.get()->getType()->isSveVLSBuiltinType()) {
+  if (LHS.get()->getType()->isVLSBuiltinType() ||
+      RHS.get()->getType()->isVLSBuiltinType()) {
     QualType compType = CheckSizelessVectorOperands(LHS, RHS, Loc, CompLHSTy,
                                                     ArithConvKind::Arithmetic);
     if (CompLHSTy)
@@ -12080,19 +12081,20 @@ static QualType checkSizelessVectorShift(Sema &S, ExprResult &LHS,
 
   QualType LHSType = LHS.get()->getType();
   const BuiltinType *LHSBuiltinTy = LHSType->castAs<BuiltinType>();
-  QualType LHSEleType = LHSType->isSveVLSBuiltinType()
-                            ? LHSBuiltinTy->getSveEltType(S.getASTContext())
+
+  QualType LHSEleType = LHSType->isVLSBuiltinType()
+                            ? LHSType->getSizelessVectorEltType(S.getASTContext())
                             : LHSType;
 
   // Note that RHS might not be a vector
   QualType RHSType = RHS.get()->getType();
   const BuiltinType *RHSBuiltinTy = RHSType->castAs<BuiltinType>();
-  QualType RHSEleType = RHSType->isSveVLSBuiltinType()
-                            ? RHSBuiltinTy->getSveEltType(S.getASTContext())
+  QualType RHSEleType = RHSType->isVLSBuiltinType()
+                            ? RHSType->getSizelessVectorEltType(S.getASTContext())
                             : RHSType;
 
-  if ((LHSBuiltinTy && LHSBuiltinTy->isSVEBool()) ||
-      (RHSBuiltinTy && RHSBuiltinTy->isSVEBool())) {
+  if ((LHSBuiltinTy && LHSBuiltinTy->isSizelessVectorBool()) ||
+      (RHSBuiltinTy && RHSBuiltinTy->isSizelessVectorBool())) {
     S.Diag(Loc, diag::err_typecheck_invalid_operands)
         << LHSType << RHSType << LHS.get()->getSourceRange();
     return QualType();
@@ -12110,7 +12112,7 @@ static QualType checkSizelessVectorShift(Sema &S, ExprResult &LHS,
     return QualType();
   }
 
-  if (LHSType->isSveVLSBuiltinType() && RHSType->isSveVLSBuiltinType() &&
+  if (LHSType->isVLSBuiltinType() && RHSType->isVLSBuiltinType() &&
       (S.Context.getBuiltinVectorTypeInfo(LHSBuiltinTy).EC !=
        S.Context.getBuiltinVectorTypeInfo(RHSBuiltinTy).EC)) {
     S.Diag(Loc, diag::err_typecheck_invalid_operands)
@@ -12119,8 +12121,8 @@ static QualType checkSizelessVectorShift(Sema &S, ExprResult &LHS,
     return QualType();
   }
 
-  if (!LHSType->isSveVLSBuiltinType()) {
-    assert(RHSType->isSveVLSBuiltinType());
+  if (!LHSType->isVLSBuiltinType()) {
+    assert(RHSType->isVLSBuiltinType());
     if (IsCompAssign)
       return RHSType;
     if (LHSEleType != RHSEleType) {
@@ -12133,7 +12135,7 @@ static QualType checkSizelessVectorShift(Sema &S, ExprResult &LHS,
         S.Context.getScalableVectorType(LHSEleType, VecSize.getKnownMinValue());
     LHS = S.ImpCastExprToType(LHS.get(), VecTy, clang::CK_VectorSplat);
     LHSType = VecTy;
-  } else if (RHSBuiltinTy && RHSBuiltinTy->isSveVLSBuiltinType()) {
+  } else if (RHSBuiltinTy && RHSType->isVLSBuiltinType()) {
     if (S.Context.getTypeSize(RHSBuiltinTy) !=
         S.Context.getTypeSize(LHSBuiltinTy)) {
       S.Diag(Loc, diag::err_typecheck_vector_lengths_not_equal)
@@ -12179,8 +12181,8 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
     return checkVectorShift(*this, LHS, RHS, Loc, IsCompAssign);
   }
 
-  if (LHS.get()->getType()->isSveVLSBuiltinType() ||
-      RHS.get()->getType()->isSveVLSBuiltinType())
+  if (LHS.get()->getType()->isVLSBuiltinType() ||
+      RHS.get()->getType()->isVLSBuiltinType())
     return checkSizelessVectorShift(*this, LHS, RHS, Loc, IsCompAssign);
 
   // Shifts don't perform usual arithmetic conversions, they just do integer
@@ -12892,8 +12894,8 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
       RHS.get()->getType()->isVectorType())
     return CheckVectorCompareOperands(LHS, RHS, Loc, Opc);
 
-  if (LHS.get()->getType()->isSveVLSBuiltinType() ||
-      RHS.get()->getType()->isSveVLSBuiltinType())
+  if (LHS.get()->getType()->isVLSBuiltinType() ||
+      RHS.get()->getType()->isVLSBuiltinType())
     return CheckSizelessVectorCompareOperands(LHS, RHS, Loc, Opc);
 
   diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc);
@@ -13393,7 +13395,7 @@ QualType Sema::GetSignedSizelessVectorType(QualType V) {
   const BuiltinType *VTy = V->castAs<BuiltinType>();
   assert(VTy->isSizelessBuiltinType() && "expected sizeless type");
 
-  const QualType ETy = V->getSveEltType(Context);
+  const QualType ETy = V->getSizelessVectorEltType(Context);
   const auto TypeSize = Context.getTypeSize(ETy);
 
   const QualType IntTy = Context.getIntTypeForBitwidth(TypeSize, true);
@@ -13495,8 +13497,8 @@ QualType Sema::CheckSizelessVectorCompareOperands(ExprResult &LHS,
   const BuiltinType *LHSBuiltinTy = LHSType->getAs<BuiltinType>();
   const BuiltinType *RHSBuiltinTy = RHS.get()->getType()->getAs<BuiltinType>();
 
-  if (LHSBuiltinTy && RHSBuiltinTy && LHSBuiltinTy->isSVEBool() &&
-      RHSBuiltinTy->isSVEBool())
+  if (LHSBuiltinTy && RHSBuiltinTy && LHSBuiltinTy->isSizelessVectorBool() &&
+      RHSBuiltinTy->isSizelessVectorBool())
     return LHSType;
 
   // Return a signed type for the vector.
@@ -13798,8 +13800,8 @@ inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS,
     return InvalidOperands(Loc, LHS, RHS);
   }
 
-  if (LHS.get()->getType()->isSveVLSBuiltinType() ||
-      RHS.get()->getType()->isSveVLSBuiltinType()) {
+  if (LHS.get()->getType()->isVLSBuiltinType() ||
+      RHS.get()->getType()->isVLSBuiltinType()) {
     if (LHS.get()->getType()->hasIntegerRepresentation() &&
         RHS.get()->getType()->hasIntegerRepresentation())
       return CheckSizelessVectorOperands(LHS, RHS, Loc, IsCompAssign,
@@ -13807,8 +13809,8 @@ inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS,
     return InvalidOperands(Loc, LHS, RHS);
   }
 
-  if (LHS.get()->getType()->isSveVLSBuiltinType() ||
-      RHS.get()->getType()->isSveVLSBuiltinType()) {
+  if (LHS.get()->getType()->isVLSBuiltinType() ||
+      RHS.get()->getType()->isVLSBuiltinType()) {
     if (LHS.get()->getType()->hasIntegerRepresentation() &&
         RHS.get()->getType()->hasIntegerRepresentation())
       return CheckSizelessVectorOperands(LHS, RHS, Loc, IsCompAssign,
@@ -16239,7 +16241,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
                 resultType->castAs<VectorType>()->getVectorKind() !=
                     VectorKind::AltiVecBool))
         break;
-      else if (resultType->isSveVLSBuiltinType()) // SVE vectors allow + and -
+      else if (resultType->isVLSBuiltinType()) // Sizeless vectors allow + and -
         break;
       else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6
                Opc == UO_Plus && resultType->isPointerType())
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index e60d5d7748b44..f7426d2272a94 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5777,12 +5777,13 @@ static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
 // extension.
 static bool isValidVectorForConditionalCondition(ASTContext &Ctx,
                                                  QualType CondTy) {
-  bool IsSVEVectorType = CondTy->isSveVLSBuiltinType();
-  if (!CondTy->isVectorType() && !CondTy->isExtVectorType() && !IsSVEVectorType)
+  bool IsSizelessVectorType = CondTy->isVLSBuiltinType();
+  if (!CondTy->isVectorType() && !CondTy->isExtVectorType() &&
+      !IsSizelessVectorType)
     return false;
   const QualType EltTy =
-      IsSVEVectorType
-          ? cast<BuiltinType>(CondTy.getCanonicalType())->getSveEltType(Ctx)
+      IsSizelessVectorType
+          ? CondTy->getSizelessVectorEltType(Ctx)
           : cast<VectorType>(CondTy.getCanonicalType())->getElementType();
   assert(!EltTy->isEnumeralType() && "Vectors cant be enum types");
   return EltTy->isIntegralType(Ctx);
diff --git a/clang/test/CodeGen/RISCV/rvv-vector-arith-ops.c b/clang/test/CodeGen/RISCV/rvv-vector-arith-ops.c
new file mode 100644
index 0000000000000..ccd5b8ed00d0a
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-vector-arith-ops.c
@@ -0,0 +1,259 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +v \
+// RUN: -disable-O0-optnone \
+// RUN:  -emit-llvm -o - %s | opt -S -passes=sroa | FileCheck %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
+// RUN: -disable-O0-optnone \
+// RUN:  -emit-llvm -o - %s | opt -S -passes=sroa | FileCheck %s
+
+// REQUIRES: riscv-registered-target
+
+#include <riscv_vector.h>
+
+// SIGNED INTEGER
+
+// CHECK-LABEL: @add_i32(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ADD:%.*]] = add <vscale x 2 x i32> [[A:%.*]], [[B:%.*]]
+// CHECK-NEXT:    ret <vscale x 2 x i32> [[ADD]]
+//
+vint32m1_t add_i32(vint32m1_t a, vint32m1_t b) {
+  return a + b;
+}
+
+// CHECK-LABEL: @sub_i32(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[SUB:%.*]] = sub <vscale x 2 x i32> [[A:%.*]], [[B:%.*]]
+// CHECK-NEXT:    ret <vscale x 2 x i32> [[SUB]]
+//
+vint32m1_t sub_i32(vint32m1_t a, vint32m1_t b) {
+  return a - b;
+}
+
+// CHECK-LABEL: @mul_i32(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[MUL:%.*]] = mul <vscale x 2 x i32> [[A:%.*]], [[B:%.*]]
+// CHECK-NEXT:    ret <vscale x 2 x i32> [[MUL]]
+//
+vint32m1_t mul_i32(vint32m1_t a, vint32m1_t b) {
+  return a * b;
+}
+
+// CHECK-LABEL: @sdiv_i32(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[DIV:%.*]] = sdiv <vscale x 2 x i32> [[A:%.*]], [[B:%.*]]
+// CHECK-NEXT:    ret <vscale x 2 x i32> [[DIV]]
+//
+vint32m1_t sdiv_i32(vint32m1_t a, vint32m1_t b) {
+  return a / b;
+}
+
+// CHECK-LABEL: @srem_i32(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[REM:%.*]] =...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/192722


More information about the cfe-commits mailing list