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.cpp148
1 files changed, 147 insertions, 1 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index b706b14..7bf28d9 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11615,6 +11615,60 @@ static bool evalPackBuiltin(const CallExpr *E, EvalInfo &Info, APValue &Result,
return true;
}
+static bool evalPshufBuiltin(EvalInfo &Info, const CallExpr *Call,
+ bool IsShufHW, APValue &Out) {
+ APValue Vec;
+ APSInt Imm;
+ if (!EvaluateAsRValue(Info, Call->getArg(0), Vec))
+ return false;
+ if (!EvaluateInteger(Call->getArg(1), Imm, Info))
+ return false;
+
+ const auto *VT = Call->getType()->getAs<VectorType>();
+ if (!VT)
+ return false;
+
+ QualType ElemT = VT->getElementType();
+ unsigned ElemBits = Info.Ctx.getTypeSize(ElemT);
+ unsigned NumElts = VT->getNumElements();
+
+ unsigned LaneBits = 128u;
+ unsigned LaneElts = LaneBits / ElemBits;
+ if (!LaneElts || (NumElts % LaneElts) != 0)
+ return false;
+
+ uint8_t Ctl = static_cast<uint8_t>(Imm.getZExtValue());
+
+ SmallVector<APValue, 32> ResultElements;
+ ResultElements.reserve(NumElts);
+
+ for (unsigned Idx = 0; Idx != NumElts; Idx++) {
+ unsigned LaneBase = (Idx / LaneElts) * LaneElts;
+ unsigned LaneIdx = Idx % LaneElts;
+ unsigned SrcIdx = Idx;
+ unsigned Sel = (Ctl >> (2 * LaneIdx)) & 0x3;
+
+ if (ElemBits == 32) {
+ SrcIdx = LaneBase + Sel;
+ } else {
+ constexpr unsigned HalfSize = 4;
+ bool InHigh = LaneIdx >= HalfSize;
+ if (!IsShufHW && !InHigh) {
+ SrcIdx = LaneBase + Sel;
+ } else if (IsShufHW && InHigh) {
+ unsigned Rel = LaneIdx - HalfSize;
+ Sel = (Ctl >> (2 * Rel)) & 0x3;
+ SrcIdx = LaneBase + HalfSize + Sel;
+ }
+ }
+
+ ResultElements.push_back(Vec.getVectorElt(SrcIdx));
+ }
+
+ Out = APValue(ResultElements.data(), ResultElements.size());
+ return true;
+}
+
bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (!IsConstantEvaluatedBuiltinCall(E))
return ExprEvaluatorBaseTy::VisitCallExpr(E);
@@ -11868,7 +11922,6 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
-
case clang::X86::BI__builtin_ia32_vprotbi:
case clang::X86::BI__builtin_ia32_vprotdi:
case clang::X86::BI__builtin_ia32_vprotqi:
@@ -12087,6 +12140,34 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
+
+ case X86::BI__builtin_ia32_pshuflw:
+ case X86::BI__builtin_ia32_pshuflw256:
+ case X86::BI__builtin_ia32_pshuflw512: {
+ APValue R;
+ if (!evalPshufBuiltin(Info, E, false, R))
+ return false;
+ return Success(R, E);
+ }
+
+ case X86::BI__builtin_ia32_pshufhw:
+ case X86::BI__builtin_ia32_pshufhw256:
+ case X86::BI__builtin_ia32_pshufhw512: {
+ APValue R;
+ if (!evalPshufBuiltin(Info, E, true, R))
+ return false;
+ return Success(R, E);
+ }
+
+ case X86::BI__builtin_ia32_pshufd:
+ case X86::BI__builtin_ia32_pshufd256:
+ case X86::BI__builtin_ia32_pshufd512: {
+ APValue R;
+ if (!evalPshufBuiltin(Info, E, false, R))
+ return false;
+ return Success(R, E);
+ }
+
case Builtin::BI__builtin_elementwise_clzg:
case Builtin::BI__builtin_elementwise_ctzg: {
APValue SourceLHS;
@@ -12235,6 +12316,41 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
+
+ case clang::X86::BI__builtin_ia32_vec_set_v4hi:
+ case clang::X86::BI__builtin_ia32_vec_set_v16qi:
+ case clang::X86::BI__builtin_ia32_vec_set_v8hi:
+ case clang::X86::BI__builtin_ia32_vec_set_v4si:
+ case clang::X86::BI__builtin_ia32_vec_set_v2di:
+ case clang::X86::BI__builtin_ia32_vec_set_v32qi:
+ case clang::X86::BI__builtin_ia32_vec_set_v16hi:
+ case clang::X86::BI__builtin_ia32_vec_set_v8si:
+ case clang::X86::BI__builtin_ia32_vec_set_v4di: {
+ APValue VecVal;
+ APSInt Scalar, IndexAPS;
+ if (!EvaluateVector(E->getArg(0), VecVal, Info) ||
+ !EvaluateInteger(E->getArg(1), Scalar, Info) ||
+ !EvaluateInteger(E->getArg(2), IndexAPS, Info))
+ return false;
+
+ QualType ElemTy = E->getType()->castAs<VectorType>()->getElementType();
+ unsigned ElemWidth = Info.Ctx.getIntWidth(ElemTy);
+ bool ElemUnsigned = ElemTy->isUnsignedIntegerOrEnumerationType();
+ Scalar.setIsUnsigned(ElemUnsigned);
+ APSInt ElemAPS = Scalar.extOrTrunc(ElemWidth);
+ APValue ElemAV(ElemAPS);
+
+ unsigned NumElems = VecVal.getVectorLength();
+ unsigned Index =
+ static_cast<unsigned>(IndexAPS.getZExtValue() & (NumElems - 1));
+
+ SmallVector<APValue, 4> Elems;
+ Elems.reserve(NumElems);
+ for (unsigned ElemNum = 0; ElemNum != NumElems; ++ElemNum)
+ Elems.push_back(ElemNum == Index ? ElemAV : VecVal.getVectorElt(ElemNum));
+
+ return Success(APValue(Elems.data(), NumElems), E);
+ }
}
}
@@ -14822,6 +14938,25 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return HandleMaskBinOp(
[](const APSInt &LHS, const APSInt &RHS) { return LHS + RHS; });
}
+
+ case clang::X86::BI__builtin_ia32_vec_ext_v4hi:
+ case clang::X86::BI__builtin_ia32_vec_ext_v16qi:
+ case clang::X86::BI__builtin_ia32_vec_ext_v8hi:
+ case clang::X86::BI__builtin_ia32_vec_ext_v4si:
+ case clang::X86::BI__builtin_ia32_vec_ext_v2di:
+ case clang::X86::BI__builtin_ia32_vec_ext_v32qi:
+ case clang::X86::BI__builtin_ia32_vec_ext_v16hi:
+ case clang::X86::BI__builtin_ia32_vec_ext_v8si:
+ case clang::X86::BI__builtin_ia32_vec_ext_v4di: {
+ APValue Vec;
+ APSInt IdxAPS;
+ if (!EvaluateVector(E->getArg(0), Vec, Info) ||
+ !EvaluateInteger(E->getArg(1), IdxAPS, Info))
+ return false;
+ unsigned N = Vec.getVectorLength();
+ unsigned Idx = static_cast<unsigned>(IdxAPS.getZExtValue() & (N - 1));
+ return Success(Vec.getVectorElt(Idx).getInt(), E);
+ }
}
}
@@ -16638,6 +16773,17 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
(void)Result.fusedMultiplyAdd(SourceY, SourceZ, RM);
return true;
}
+
+ case clang::X86::BI__builtin_ia32_vec_ext_v4sf: {
+ APValue Vec;
+ APSInt IdxAPS;
+ if (!EvaluateVector(E->getArg(0), Vec, Info) ||
+ !EvaluateInteger(E->getArg(1), IdxAPS, Info))
+ return false;
+ unsigned N = Vec.getVectorLength();
+ unsigned Idx = static_cast<unsigned>(IdxAPS.getZExtValue() & (N - 1));
+ return Success(Vec.getVectorElt(Idx), E);
+ }
}
}