aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r--clang/lib/AST/ExprConstant.cpp72
1 files changed, 70 insertions, 2 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d10e2af..b706b14 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11575,6 +11575,46 @@ static bool handleVectorElementCast(EvalInfo &Info, const FPOptions FPO,
return false;
}
+static bool evalPackBuiltin(const CallExpr *E, EvalInfo &Info, APValue &Result,
+ llvm::function_ref<APInt(const APSInt &)> PackFn) {
+ APValue LHS, RHS;
+ if (!EvaluateAsRValue(Info, E->getArg(0), LHS) ||
+ !EvaluateAsRValue(Info, E->getArg(1), RHS))
+ return false;
+
+ unsigned LHSVecLen = LHS.getVectorLength();
+ unsigned RHSVecLen = RHS.getVectorLength();
+
+ assert(LHSVecLen != 0 && LHSVecLen == RHSVecLen &&
+ "pack builtin LHSVecLen must equal to RHSVecLen");
+
+ const VectorType *VT0 = E->getArg(0)->getType()->castAs<VectorType>();
+ const unsigned SrcBits = Info.Ctx.getIntWidth(VT0->getElementType());
+
+ const VectorType *DstVT = E->getType()->castAs<VectorType>();
+ QualType DstElemTy = DstVT->getElementType();
+ const bool DstIsUnsigned = DstElemTy->isUnsignedIntegerType();
+
+ const unsigned SrcPerLane = 128 / SrcBits;
+ const unsigned Lanes = LHSVecLen * SrcBits / 128;
+
+ SmallVector<APValue, 64> Out;
+ Out.reserve(LHSVecLen + RHSVecLen);
+
+ for (unsigned Lane = 0; Lane != Lanes; ++Lane) {
+ unsigned base = Lane * SrcPerLane;
+ for (unsigned I = 0; I != SrcPerLane; ++I)
+ Out.emplace_back(APValue(
+ APSInt(PackFn(LHS.getVectorElt(base + I).getInt()), DstIsUnsigned)));
+ for (unsigned I = 0; I != SrcPerLane; ++I)
+ Out.emplace_back(APValue(
+ APSInt(PackFn(RHS.getVectorElt(base + I).getInt()), DstIsUnsigned)));
+ }
+
+ Result = APValue(Out.data(), Out.size());
+ return true;
+}
+
bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (!IsConstantEvaluatedBuiltinCall(E))
return ExprEvaluatorBaseTy::VisitCallExpr(E);
@@ -11768,7 +11808,29 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
return LHS.lshr(RHS.getZExtValue());
});
-
+ case X86::BI__builtin_ia32_packsswb128:
+ case X86::BI__builtin_ia32_packsswb256:
+ case X86::BI__builtin_ia32_packsswb512:
+ case X86::BI__builtin_ia32_packssdw128:
+ case X86::BI__builtin_ia32_packssdw256:
+ case X86::BI__builtin_ia32_packssdw512:
+ return evalPackBuiltin(E, Info, Result, [](const APSInt &Src) {
+ return APSInt(Src).truncSSat(Src.getBitWidth() / 2);
+ });
+ case X86::BI__builtin_ia32_packusdw128:
+ case X86::BI__builtin_ia32_packusdw256:
+ case X86::BI__builtin_ia32_packusdw512:
+ case X86::BI__builtin_ia32_packuswb128:
+ case X86::BI__builtin_ia32_packuswb256:
+ case X86::BI__builtin_ia32_packuswb512:
+ return evalPackBuiltin(E, Info, Result, [](const APSInt &Src) {
+ unsigned DstBits = Src.getBitWidth() / 2;
+ if (Src.isNegative())
+ return APInt::getZero(DstBits);
+ if (Src.isIntN(DstBits))
+ return APInt((Src).trunc(DstBits));
+ return APInt::getAllOnes(DstBits);
+ });
case clang::X86::BI__builtin_ia32_pmuldq128:
case clang::X86::BI__builtin_ia32_pmuldq256:
case clang::X86::BI__builtin_ia32_pmuldq512:
@@ -18843,9 +18905,15 @@ std::optional<std::string> Expr::tryEvaluateString(ASTContext &Ctx) const {
uint64_t Result;
std::string StringResult;
+ if (Info.EnableNewConstInterp) {
+ if (!Info.Ctx.getInterpContext().evaluateString(Info, this, StringResult))
+ return std::nullopt;
+ return StringResult;
+ }
+
if (EvaluateBuiltinStrLen(this, Result, Info, &StringResult))
return StringResult;
- return {};
+ return std::nullopt;
}
template <typename T>