diff options
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 72 |
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> |