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