-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][bytecode] Implement constexpr vector unary operators +, -, ~, ! #105996
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: yronglin <[email protected]>
@llvm/pr-subscribers-clang Author: None (yronglin) ChangesPatch is 22.02 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/105996.diff 8 Files Affected:
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 58a820508da42b..01dbf62a3db88c 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1558,6 +1558,14 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Return a WebAssembly externref type.
QualType getWebAssemblyExternrefType() const;
+ /// Return a signed ext_vector_type that is of identical size and number of
+ /// elements. For floating point vectors, return an integer type of identical
+ /// size and number of elements. In the non ext_vector_type case, search from
+ /// the largest type to the smallest type to avoid cases where long long ==
+ /// long, where long gets picked over long long.
+ QualType GetSignedVectorType(QualType V);
+ QualType GetSignedSizelessVectorType(QualType V);
+
/// Return the unique reference to a vector type of the specified
/// element type and size.
///
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1f7e555d1b8717..dd637ef3dd822b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7393,14 +7393,6 @@ class Sema final : public SemaBase {
bool AllowBothBool, bool AllowBoolConversion,
bool AllowBoolOperation, bool ReportInvalid);
- /// Return a signed ext_vector_type that is of identical size and number of
- /// elements. For floating point vectors, return an integer type of identical
- /// size and number of elements. In the non ext_vector_type case, search from
- /// the largest type to the smallest type to avoid cases where long long ==
- /// long, where long gets picked over long long.
- QualType GetSignedVectorType(QualType V);
- QualType GetSignedSizelessVectorType(QualType V);
-
/// 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
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b201d201e1ea6a..408d4b006a7469 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -4444,6 +4444,56 @@ QualType ASTContext::getScalableVectorType(QualType EltTy, unsigned NumElts,
return QualType();
}
+QualType ASTContext::GetSignedVectorType(QualType V) {
+ const VectorType *VTy = V->castAs<VectorType>();
+ unsigned TypeSize = getTypeSize(VTy->getElementType());
+
+ if (isa<ExtVectorType>(VTy)) {
+ if (VTy->isExtVectorBoolType())
+ return getExtVectorType(BoolTy, VTy->getNumElements());
+ if (TypeSize == getTypeSize(CharTy))
+ return getExtVectorType(CharTy, VTy->getNumElements());
+ if (TypeSize == getTypeSize(ShortTy))
+ return getExtVectorType(ShortTy, VTy->getNumElements());
+ if (TypeSize == getTypeSize(IntTy))
+ return getExtVectorType(IntTy, VTy->getNumElements());
+ if (TypeSize == getTypeSize(Int128Ty))
+ return getExtVectorType(Int128Ty, VTy->getNumElements());
+ if (TypeSize == getTypeSize(LongTy))
+ return getExtVectorType(LongTy, VTy->getNumElements());
+ assert(TypeSize == getTypeSize(LongLongTy) &&
+ "Unhandled vector element size in vector compare");
+ return getExtVectorType(LongLongTy, VTy->getNumElements());
+ }
+
+ if (TypeSize == getTypeSize(Int128Ty))
+ return getVectorType(Int128Ty, VTy->getNumElements(), VectorKind::Generic);
+ if (TypeSize == getTypeSize(LongLongTy))
+ return getVectorType(LongLongTy, VTy->getNumElements(),
+ VectorKind::Generic);
+ if (TypeSize == getTypeSize(LongTy))
+ return getVectorType(LongTy, VTy->getNumElements(), VectorKind::Generic);
+ if (TypeSize == getTypeSize(IntTy))
+ return getVectorType(IntTy, VTy->getNumElements(), VectorKind::Generic);
+ if (TypeSize == getTypeSize(ShortTy))
+ return getVectorType(ShortTy, VTy->getNumElements(), VectorKind::Generic);
+ assert(TypeSize == getTypeSize(CharTy) &&
+ "Unhandled vector element size in vector compare");
+ return getVectorType(CharTy, VTy->getNumElements(), VectorKind::Generic);
+}
+
+QualType ASTContext::GetSignedSizelessVectorType(QualType V) {
+ const BuiltinType *VTy = V->castAs<BuiltinType>();
+ assert(VTy->isSizelessBuiltinType() && "expected sizeless type");
+
+ const QualType ETy = V->getSveEltType(*this);
+ const auto TypeSize = getTypeSize(ETy);
+
+ const QualType IntTy = getIntTypeForBitwidth(TypeSize, true);
+ const llvm::ElementCount VecSize = getBuiltinVectorTypeInfo(VTy).EC;
+ return getScalableVectorType(IntTy, VecSize.getKnownMinValue());
+}
+
/// getVectorType - Return the unique reference to a vector type of
/// the specified element type and size. VectorType must be a built-in type.
QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 0fc942a4f1bc4f..fa329fa8ccc979 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -4991,6 +4991,8 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
const Expr *SubExpr = E->getSubExpr();
if (SubExpr->getType()->isAnyComplexType())
return this->VisitComplexUnaryOperator(E);
+ if (SubExpr->getType()->isVectorType())
+ return this->VisitVectorUnaryOp(E);
std::optional<PrimType> T = classify(SubExpr->getType());
switch (E->getOpcode()) {
@@ -5312,6 +5314,145 @@ bool Compiler<Emitter>::VisitComplexUnaryOperator(const UnaryOperator *E) {
return true;
}
+template <class Emitter>
+bool Compiler<Emitter>::VisitVectorUnaryOp(const UnaryOperator *E) {
+ const Expr *SubExpr = E->getSubExpr();
+ assert(SubExpr->getType()->isVectorType());
+
+ if (DiscardResult)
+ return this->discard(SubExpr);
+
+ std::optional<PrimType> ResT = classify(E);
+ auto prepareResult = [=]() -> bool {
+ if (!ResT && !Initializing) {
+ std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);
+ if (!LocalIndex)
+ return false;
+ return this->emitGetPtrLocal(*LocalIndex, E);
+ }
+
+ return true;
+ };
+
+ // The offset of the temporary, if we created one.
+ unsigned SubExprOffset = ~0u;
+ auto createTemp = [=, &SubExprOffset]() -> bool {
+ SubExprOffset = this->allocateLocalPrimitive(SubExpr, PT_Ptr, true, false);
+ if (!this->visit(SubExpr))
+ return false;
+ return this->emitSetLocal(PT_Ptr, SubExprOffset, E);
+ };
+
+ const auto *VecT = SubExpr->getType()->getAs<VectorType>();
+ PrimType ElemT = classifyVectorElementType(SubExpr->getType());
+ auto getElem = [=](unsigned Offset, unsigned Index) -> bool {
+ if (!this->emitGetLocal(PT_Ptr, Offset, E))
+ return false;
+ return this->emitArrayElemPop(ElemT, Index, E);
+ };
+
+ switch (E->getOpcode()) {
+ case UO_Plus: // +x
+ return this->delegate(SubExpr);
+ case UO_Minus:
+ if (!prepareResult())
+ return false;
+ if (!createTemp())
+ return false;
+ for (unsigned I = 0; I != VecT->getNumElements(); ++I) {
+ if (!getElem(SubExprOffset, I))
+ return false;
+ if (!this->emitNeg(ElemT, E))
+ return false;
+ if (!this->emitInitElem(ElemT, I, E))
+ return false;
+ }
+ break;
+ case UO_LNot: { // !x
+ if (!prepareResult())
+ return false;
+ if (!createTemp())
+ return false;
+
+ // In C++, the logic operators !, &&, || are available for vectors. !v is equivalent to v == 0.
+ // https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
+ QualType SignedVecT = Ctx.getASTContext().GetSignedVectorType(SubExpr->getType());
+ PrimType SignedElemT = classifyPrim(SignedVecT->getAs<VectorType>()->getElementType());
+ for (unsigned I = 0; I != VecT->getNumElements(); ++I) {
+ if (!getElem(SubExprOffset, I))
+ return false;
+
+ // operator ! on vectors returns -1 for 'truth', so negate it.
+ if (isIntegralType(ElemT)) {
+ if (!this->emitPrimCast(ElemT, PT_Bool, Ctx.getASTContext().BoolTy, E))
+ return false;
+ if (!this->emitInv(E))
+ return false;
+ if (!this->emitPrimCast(PT_Bool, ElemT, VecT->getElementType(), E))
+ return false;
+ if (!this->emitNeg(ElemT, E))
+ return false;
+ if (ElemT != SignedElemT &&
+ !this->emitPrimCast(ElemT, SignedElemT, SignedVecT, E))
+ return false;
+ } else {
+ // Float types result in an int of the same size, but -1 for true, or 0 for
+ // false.
+ auto &FpSemantics = Ctx.getFloatSemantics(VecT->getElementType());
+ unsigned NumBits = Ctx.getBitWidth(SignedVecT->getAs<VectorType>()->getElementType());
+ auto Zero = APFloat::getZero(FpSemantics);
+ APSInt SIntZero(APSInt::getZero(NumBits));
+ APSInt SIntAllOne(APSInt::getAllOnes(NumBits));
+ // Emit operations equivalent to isZero(Vec[I]) ? -1 : 0
+ if (!this->emitConstFloat(Zero, E))
+ return false;
+ if (!this->emitEQ(ElemT, E))
+ return false;
+ LabelTy LabelFalse = this->getLabel();
+ LabelTy LabelEnd = this->getLabel();
+ if (!this->jumpFalse(LabelFalse))
+ return false;
+ if (!this->emitConst(SIntAllOne, SignedElemT, E))
+ return false;
+ if (!this->jump(LabelEnd))
+ return false;
+ this->emitLabel(LabelFalse);
+ if (!this->emitConst(SIntZero, SignedElemT, E))
+ return false;
+ this->fallthrough(LabelEnd);
+ this->emitLabel(LabelEnd);
+ }
+ if (!this->emitInitElem(SignedElemT, I, E))
+ return false;
+ }
+ break;
+ }
+ case UO_Not: // ~x
+ if (!prepareResult())
+ return false;
+ if (!createTemp())
+ return false;
+ for (unsigned I = 0; I != VecT->getNumElements(); ++I) {
+ if (!getElem(SubExprOffset, I))
+ return false;
+ if (ElemT == PT_Bool) {
+ if (!this->emitInv(E))
+ return false;
+ } else {
+ if (!this->emitComp(ElemT, E))
+ return false;
+ }
+ if (!this->emitInitElem(ElemT, I, E))
+ return false;
+ }
+ break;
+ default:
+ return this->emitInvalid(E);
+ }
+
+ return true;
+}
+
template <class Emitter>
bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
if (DiscardResult)
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 5acfe3c41796c4..b695b3e8e592f9 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -139,6 +139,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
bool VisitGNUNullExpr(const GNUNullExpr *E);
bool VisitCXXThisExpr(const CXXThisExpr *E);
bool VisitUnaryOperator(const UnaryOperator *E);
+ bool VisitVectorUnaryOp(const UnaryOperator *E);
bool VisitComplexUnaryOperator(const UnaryOperator *E);
bool VisitDeclRefExpr(const DeclRefExpr *E);
bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E);
@@ -349,6 +350,11 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
return *this->classify(ElemType);
}
+ PrimType classifyVectorElementType(QualType T) const {
+ assert(T->isVectorType());
+ return *this->classify(T->getAs<VectorType>()->getElementType());
+ }
+
bool emitComplexReal(const Expr *SubExpr);
bool emitComplexBoolCast(const Expr *E);
bool emitComplexComparison(const Expr *LHS, const Expr *RHS,
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ee143381cf4f79..6fec88da40e526 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -4906,7 +4906,7 @@ bool Sema::BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
// TODO: When all classification function are implemented with is_fpclass,
// vector argument can be supported in all of them.
if (ElementTy->isVectorType() && IsFPClass) {
- VectorResultTy = GetSignedVectorType(ElementTy);
+ VectorResultTy = Context.GetSignedVectorType(ElementTy);
ElementTy = ElementTy->castAs<VectorType>()->getElementType();
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ea57316ad8014e..bd2ff6c828525a 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -12534,61 +12534,6 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
return InvalidOperands(Loc, LHS, RHS);
}
-QualType Sema::GetSignedVectorType(QualType V) {
- const VectorType *VTy = V->castAs<VectorType>();
- unsigned TypeSize = Context.getTypeSize(VTy->getElementType());
-
- if (isa<ExtVectorType>(VTy)) {
- if (VTy->isExtVectorBoolType())
- return Context.getExtVectorType(Context.BoolTy, VTy->getNumElements());
- if (TypeSize == Context.getTypeSize(Context.CharTy))
- return Context.getExtVectorType(Context.CharTy, VTy->getNumElements());
- if (TypeSize == Context.getTypeSize(Context.ShortTy))
- return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements());
- if (TypeSize == Context.getTypeSize(Context.IntTy))
- return Context.getExtVectorType(Context.IntTy, VTy->getNumElements());
- if (TypeSize == Context.getTypeSize(Context.Int128Ty))
- return Context.getExtVectorType(Context.Int128Ty, VTy->getNumElements());
- if (TypeSize == Context.getTypeSize(Context.LongTy))
- return Context.getExtVectorType(Context.LongTy, VTy->getNumElements());
- assert(TypeSize == Context.getTypeSize(Context.LongLongTy) &&
- "Unhandled vector element size in vector compare");
- return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements());
- }
-
- if (TypeSize == Context.getTypeSize(Context.Int128Ty))
- return Context.getVectorType(Context.Int128Ty, VTy->getNumElements(),
- VectorKind::Generic);
- if (TypeSize == Context.getTypeSize(Context.LongLongTy))
- return Context.getVectorType(Context.LongLongTy, VTy->getNumElements(),
- VectorKind::Generic);
- if (TypeSize == Context.getTypeSize(Context.LongTy))
- return Context.getVectorType(Context.LongTy, VTy->getNumElements(),
- VectorKind::Generic);
- if (TypeSize == Context.getTypeSize(Context.IntTy))
- return Context.getVectorType(Context.IntTy, VTy->getNumElements(),
- VectorKind::Generic);
- if (TypeSize == Context.getTypeSize(Context.ShortTy))
- return Context.getVectorType(Context.ShortTy, VTy->getNumElements(),
- VectorKind::Generic);
- assert(TypeSize == Context.getTypeSize(Context.CharTy) &&
- "Unhandled vector element size in vector compare");
- return Context.getVectorType(Context.CharTy, VTy->getNumElements(),
- VectorKind::Generic);
-}
-
-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());
-}
-
QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc) {
@@ -12647,7 +12592,7 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
}
// Return a signed type for the vector.
- return GetSignedVectorType(vType);
+ return Context.GetSignedVectorType(vType);
}
QualType Sema::CheckSizelessVectorCompareOperands(ExprResult &LHS,
@@ -12688,7 +12633,7 @@ QualType Sema::CheckSizelessVectorCompareOperands(ExprResult &LHS,
return LHSType;
// Return a signed type for the vector.
- return GetSignedSizelessVectorType(vType);
+ return Context.GetSignedSizelessVectorType(vType);
}
static void diagnoseXorMisusedAsPow(Sema &S, const ExprResult &XorLHS,
@@ -12835,7 +12780,7 @@ QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
!(isa<ExtVectorType>(vType->getAs<VectorType>())))
return InvalidLogicalVectorOperands(Loc, LHS, RHS);
- return GetSignedVectorType(LHS.get()->getType());
+ return Context.GetSignedVectorType(LHS.get()->getType());
}
QualType Sema::CheckMatrixElementwiseOperands(ExprResult &LHS, ExprResult &RHS,
@@ -14535,7 +14480,7 @@ static ExprResult convertHalfVecBinOp(Sema &S, ExprResult LHS, ExprResult RHS,
// If Opc is a comparison, ResultType is a vector of shorts. In that case,
// change BinOpResTy to a vector of ints.
if (isVector(ResultTy, Context.ShortTy))
- BinOpResTy = S.GetSignedVectorType(BinOpResTy);
+ BinOpResTy = S.Context.GetSignedVectorType(BinOpResTy);
if (IsCompAssign)
return CompoundAssignOperator::Create(Context, LHS.get(), RHS.get(), Opc,
@@ -15449,7 +15394,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
<< resultType << Input.get()->getSourceRange());
}
// Vector logical not returns the signed variant of the operand type.
- resultType = GetSignedVectorType(resultType);
+ resultType = Context.GetSignedVectorType(resultType);
break;
} else if (Context.getLangOpts().CPlusPlus &&
resultType->isVectorType()) {
@@ -15459,7 +15404,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
<< resultType << Input.get()->getSourceRange());
// Vector logical not returns the signed variant of the operand type.
- resultType = GetSignedVectorType(resultType);
+ resultType = Context.GetSignedVectorType(resultType);
break;
} else {
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
diff --git a/clang/test/AST/ByteCode/constexpr-vectors.cpp b/clang/test/AST/ByteCode/constexpr-vectors.cpp
new file mode 100644
index 00000000000000..9c396d580bfc5d
--- /dev/null
+++ b/clang/test/AST/ByteCode/constexpr-vectors.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -fexperimental-new-constant-interpreter -Wno-uninitialized -std=c++14 -fsyntax-only -verify
+
+// expected-no-diagnostics
+
+using FourCharsVecSize __attribute__((vector_size(4))) = char;
+using FourIntsVecSize __attribute__((vector_size(16))) = int;
+using FourLongLongsVecSize __attribute__((vector_size(32))) = long long;
+using FourFloatsVecSize __attribute__((vector_size(16))) = float;
+using FourDoublesVecSize __attribute__((vector_size(32))) = double;
+using FourI128VecSize __attribute__((vector_size(64))) = __int128;
+
+using FourCharsExtVec __attribute__((ext_vector_type(4))) = char;
+using FourIntsExtVec __attribute__((ext_vector_type(4))) = int;
+using FourI128ExtVec __attribute__((ext_vector_type(4))) = __int128;
+
+// Only int vs float makes a difference here, so we only need to test 1 of each.
+// Test Char to make sure the mixed-nature of shifts around char is evident.
+void CharUsage() {
+ constexpr auto H = FourCharsVecSize{-1, -1, 0, -1};
+ constexpr auto InvH = -H;
+ static_assert(InvH[0] == 1 && InvH[1] == 1 && InvH[2] == 0 && InvH[3] == 1, "");
+
+ constexpr auto ae = ~FourCharsVecSize{1, 2, 10, 20};
+ static_assert(ae[0] == -2 && ae[1] == -3 && ae[2] == -11 && ae[3] == -21, "");
+
+ constexpr auto af = !FourCharsVecSize{0, 1, 8, -1};
+ static_assert(af[0] == -1 && af[1] == 0 && af[2] == 0 && af[3] == 0, "");
+}
+
+void CharExtVecUsage() {
+ constexpr auto H = FourCharsExtVec{-1, -1, 0, -1};
+ constexpr auto InvH = -H;
+ static_assert(InvH[0] == 1 && InvH[1] == 1 && InvH[2] == 0 && InvH[3] == 1, "");
+
+ constexpr auto ae = ~FourCharsExtVec{1, 2, 10, 20};
+ static_assert(ae[0] == -2 && ae[1] == -3 && ae[2] == -11 && ae[3] == -21, "");
+
+ constexpr auto af = !FourCharsExtVec{0, 1, 8, -1};
+ static_assert(af[0] == -1 && af[1] == 0 && af[2] == 0 && af[3] == 0, "");
+}
+
+void FloatUsage() {
+ constexpr auto Y = FourFloats...
[truncated]
|
Signed-off-by: yronglin <[email protected]>
✅ With the latest revision this PR passed the C/C++ code formatter. |
Signed-off-by: yronglin <[email protected]>
Signed-off-by: yronglin <[email protected]>
…t signed vector type from E Signed-off-by: yronglin <[email protected]>
Thank you for your review! I have reverted the modification of ASTContext. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these the only unary operators supported on vectors or are more to come? Since all (except for +
, which doesn't do anything) cases call prepareResult()
and createTemp()
unconditionally, it would probably be cleaner to reject the unhandled cases via emitInvalid
first, then do the prepareResult()
+ createTemp()
(which don't even need to be lambdas anymore), then handle the actual operation.
Signed-off-by: yronglin <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If CI comes back, the rest looks good to me, thanks!
Signed-off-by: yronglin <[email protected]>
The PR #105996 broke taking the address of a vector: **compound-literal.c** ```C typedef int v4i32 __attribute((vector_size(16))); v4i32 *y = &(v4i32){1,2,3,4}; ``` That because the current interpreter handle vector unary operator as a fallback when the generic code path fail. but the new interpreter was not. we need to handle `UO_AddrOf` in `Compiler<Emitter>::VisitVectorUnaryOperator`. Signed-off-by: yronglin <[email protected]>
…4014f0059 Local branch amd-gfx 4684014 Merged main:898d52b819496ba70d0ca29cc7b60237108ae2b4 into amd-gfx:a6bdf8d91f90 Remote branch main ee0d706 [clang][bytecode] Implement constexpr vector unary operators +, -, ~, ! (llvm#105996)
Implement constexpr vector unary operators +, -, ~ and ! .