[clang] [Clang][Interp] Implement constexpr vector unary operators +, -, ~, ! (PR #105996)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 27 10:03:49 PDT 2024
================
@@ -5312,6 +5314,147 @@ bool Compiler<Emitter>::VisitComplexUnaryOperator(const UnaryOperator *E) {
return true;
}
+template <class Emitter>
+bool Compiler<Emitter>::VisitVectorUnaryOperator(const UnaryOperator *E) {
+ const Expr *SubExpr = E->getSubExpr();
+ assert(SubExpr->getType()->isVectorType());
+
+ if (DiscardResult)
+ return this->discard(SubExpr);
+
+ auto prepareResult = [=]() -> bool {
+ if (!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 *VecTy = 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 != VecTy->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());
----------------
tbaederr wrote:
I've just added
```c++
assert(E->getType() == SignedVecT);
assert(E->getType()->getAs<VectorType>()->getElementType() == SignedVecT->getAs<VectorType>()->getElementType());
```
and it doesn't break when compiling the `constexpr-vectors.cpp`. When are the two types different?
https://github.com/llvm/llvm-project/pull/105996
More information about the cfe-commits
mailing list