diff options
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/ByteCode/InterpBuiltin.cpp | 119 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 48 |
2 files changed, 127 insertions, 40 deletions
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 1eea813..9125250 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -678,30 +678,6 @@ static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC, return true; } -static bool interp__builtin_parity(InterpState &S, CodePtr OpPC, - const InterpFrame *Frame, - const CallExpr *Call) { - APSInt Val = popToAPSInt(S, Call->getArg(0)); - pushInteger(S, Val.popcount() % 2, Call->getType()); - return true; -} - -static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC, - const InterpFrame *Frame, - const CallExpr *Call) { - APSInt Val = popToAPSInt(S, Call->getArg(0)); - pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType()); - return true; -} - -static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC, - const InterpFrame *Frame, - const CallExpr *Call) { - APSInt Val = popToAPSInt(S, Call->getArg(0)); - pushInteger(S, Val.reverseBits(), Call->getType()); - return true; -} - static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { @@ -736,16 +712,6 @@ static bool interp__builtin_expect(InterpState &S, CodePtr OpPC, return true; } -static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC, - const InterpFrame *Frame, - const CallExpr *Call) { - APSInt Value = popToAPSInt(S, Call->getArg(0)); - - uint64_t N = Value.countr_zero(); - pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType()); - return true; -} - static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { @@ -2583,6 +2549,44 @@ static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC, return true; } +static bool interp__builtin_ia32_pmadd( + InterpState &S, CodePtr OpPC, const CallExpr *Call, + llvm::function_ref<APInt(const APSInt &, const APSInt &, const APSInt &, + const APSInt &)> + Fn) { + assert(Call->getArg(0)->getType()->isVectorType() && + Call->getArg(1)->getType()->isVectorType()); + const Pointer &RHS = S.Stk.pop<Pointer>(); + const Pointer &LHS = S.Stk.pop<Pointer>(); + const Pointer &Dst = S.Stk.peek<Pointer>(); + + const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>(); + PrimType ElemT = *S.getContext().classify(VT->getElementType()); + unsigned NumElems = VT->getNumElements(); + const auto *DestVT = Call->getType()->castAs<VectorType>(); + PrimType DestElemT = *S.getContext().classify(DestVT->getElementType()); + bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType(); + + unsigned DstElem = 0; + for (unsigned I = 0; I != NumElems; I += 2) { + APSInt Result; + INT_TYPE_SWITCH_NO_BOOL(ElemT, { + APSInt LoLHS = LHS.elem<T>(I).toAPSInt(); + APSInt HiLHS = LHS.elem<T>(I + 1).toAPSInt(); + APSInt LoRHS = RHS.elem<T>(I).toAPSInt(); + APSInt HiRHS = RHS.elem<T>(I + 1).toAPSInt(); + Result = APSInt(Fn(LoLHS, HiLHS, LoRHS, HiRHS), DestUnsigned); + }); + + INT_TYPE_SWITCH_NO_BOOL(DestElemT, + { Dst.elem<T>(DstElem) = static_cast<T>(Result); }); + ++DstElem; + } + + Dst.initializeAllElements(); + return true; +} + static bool interp__builtin_ia32_pmul(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned BuiltinID) { @@ -3158,18 +3162,25 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case Builtin::BI__builtin_parity: case Builtin::BI__builtin_parityl: case Builtin::BI__builtin_parityll: - return interp__builtin_parity(S, OpPC, Frame, Call); - + return interp__builtin_elementwise_int_unaryop( + S, OpPC, Call, [](const APSInt &Val) -> APInt { + return APInt(Val.getBitWidth(), Val.popcount() % 2); + }); case Builtin::BI__builtin_clrsb: case Builtin::BI__builtin_clrsbl: case Builtin::BI__builtin_clrsbll: - return interp__builtin_clrsb(S, OpPC, Frame, Call); - + return interp__builtin_elementwise_int_unaryop( + S, OpPC, Call, [](const APSInt &Val) -> APInt { + return APInt(Val.getBitWidth(), + Val.getBitWidth() - Val.getSignificantBits()); + }); case Builtin::BI__builtin_bitreverse8: case Builtin::BI__builtin_bitreverse16: case Builtin::BI__builtin_bitreverse32: case Builtin::BI__builtin_bitreverse64: - return interp__builtin_bitreverse(S, OpPC, Frame, Call); + return interp__builtin_elementwise_int_unaryop( + S, OpPC, Call, + [](const APSInt &Val) -> APInt { return Val.reverseBits(); }); case Builtin::BI__builtin_classify_type: return interp__builtin_classify_type(S, OpPC, Frame, Call); @@ -3209,7 +3220,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case Builtin::BI__builtin_ffs: case Builtin::BI__builtin_ffsl: case Builtin::BI__builtin_ffsll: - return interp__builtin_ffs(S, OpPC, Frame, Call); + return interp__builtin_elementwise_int_unaryop( + S, OpPC, Call, [](const APSInt &Val) { + return APInt(Val.getBitWidth(), + Val.isZero() ? 0u : Val.countTrailingZeros() + 1u); + }); case Builtin::BIaddressof: case Builtin::BI__addressof: @@ -3494,6 +3509,30 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, return interp__builtin_elementwise_int_binop(S, OpPC, Call, llvm::APIntOps::avgCeilU); + case clang::X86::BI__builtin_ia32_pmaddubsw128: + case clang::X86::BI__builtin_ia32_pmaddubsw256: + case clang::X86::BI__builtin_ia32_pmaddubsw512: + return interp__builtin_ia32_pmadd( + S, OpPC, Call, + [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS, + const APSInt &HiRHS) { + unsigned BitWidth = 2 * LoLHS.getBitWidth(); + return (LoLHS.zext(BitWidth) * LoRHS.sext(BitWidth)) + .sadd_sat((HiLHS.zext(BitWidth) * HiRHS.sext(BitWidth))); + }); + + case clang::X86::BI__builtin_ia32_pmaddwd128: + case clang::X86::BI__builtin_ia32_pmaddwd256: + case clang::X86::BI__builtin_ia32_pmaddwd512: + return interp__builtin_ia32_pmadd( + S, OpPC, Call, + [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS, + const APSInt &HiRHS) { + unsigned BitWidth = 2 * LoLHS.getBitWidth(); + return (LoLHS.sext(BitWidth) * LoRHS.sext(BitWidth)) + + (HiLHS.sext(BitWidth) * HiRHS.sext(BitWidth)); + }); + case clang::X86::BI__builtin_ia32_pmulhuw128: case clang::X86::BI__builtin_ia32_pmulhuw256: case clang::X86::BI__builtin_ia32_pmulhuw512: diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 618e163..35a866e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -11778,6 +11778,54 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { case clang::X86::BI__builtin_ia32_pavgw512: return EvaluateBinOpExpr(llvm::APIntOps::avgCeilU); + case clang::X86::BI__builtin_ia32_pmaddubsw128: + case clang::X86::BI__builtin_ia32_pmaddubsw256: + case clang::X86::BI__builtin_ia32_pmaddubsw512: + case clang::X86::BI__builtin_ia32_pmaddwd128: + case clang::X86::BI__builtin_ia32_pmaddwd256: + case clang::X86::BI__builtin_ia32_pmaddwd512: { + APValue SourceLHS, SourceRHS; + if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) || + !EvaluateAsRValue(Info, E->getArg(1), SourceRHS)) + return false; + + auto *DestTy = E->getType()->castAs<VectorType>(); + QualType DestEltTy = DestTy->getElementType(); + unsigned SourceLen = SourceLHS.getVectorLength(); + bool DestUnsigned = DestEltTy->isUnsignedIntegerOrEnumerationType(); + SmallVector<APValue, 4> ResultElements; + ResultElements.reserve(SourceLen / 2); + + for (unsigned EltNum = 0; EltNum < SourceLen; EltNum += 2) { + const APSInt &LoLHS = SourceLHS.getVectorElt(EltNum).getInt(); + const APSInt &HiLHS = SourceLHS.getVectorElt(EltNum + 1).getInt(); + const APSInt &LoRHS = SourceRHS.getVectorElt(EltNum).getInt(); + const APSInt &HiRHS = SourceRHS.getVectorElt(EltNum + 1).getInt(); + unsigned BitWidth = 2 * LoLHS.getBitWidth(); + + switch (E->getBuiltinCallee()) { + case clang::X86::BI__builtin_ia32_pmaddubsw128: + case clang::X86::BI__builtin_ia32_pmaddubsw256: + case clang::X86::BI__builtin_ia32_pmaddubsw512: + ResultElements.push_back(APValue( + APSInt((LoLHS.zext(BitWidth) * LoRHS.sext(BitWidth)) + .sadd_sat((HiLHS.zext(BitWidth) * HiRHS.sext(BitWidth))), + DestUnsigned))); + break; + case clang::X86::BI__builtin_ia32_pmaddwd128: + case clang::X86::BI__builtin_ia32_pmaddwd256: + case clang::X86::BI__builtin_ia32_pmaddwd512: + ResultElements.push_back( + APValue(APSInt((LoLHS.sext(BitWidth) * LoRHS.sext(BitWidth)) + + (HiLHS.sext(BitWidth) * HiRHS.sext(BitWidth)), + DestUnsigned))); + break; + } + } + + return Success(APValue(ResultElements.data(), ResultElements.size()), E); + } + case clang::X86::BI__builtin_ia32_pmulhuw128: case clang::X86::BI__builtin_ia32_pmulhuw256: case clang::X86::BI__builtin_ia32_pmulhuw512: |