diff options
Diffstat (limited to 'clang/lib/AST/ByteCode')
-rw-r--r-- | clang/lib/AST/ByteCode/InterpBuiltin.cpp | 139 |
1 files changed, 71 insertions, 68 deletions
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 1eea813..922d679 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,9 +2549,11 @@ static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC, return true; } -static bool interp__builtin_ia32_pmul(InterpState &S, CodePtr OpPC, - const CallExpr *Call, - unsigned BuiltinID) { +static bool interp__builtin_ia32_pmul( + 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>(); @@ -2594,35 +2562,23 @@ static bool interp__builtin_ia32_pmul(InterpState &S, CodePtr OpPC, const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>(); PrimType ElemT = *S.getContext().classify(VT->getElementType()); - unsigned SourceLen = VT->getNumElements(); + unsigned NumElems = VT->getNumElements(); + const auto *DestVT = Call->getType()->castAs<VectorType>(); + PrimType DestElemT = *S.getContext().classify(DestVT->getElementType()); + bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType(); - PrimType DstElemT = *S.getContext().classify( - Call->getType()->castAs<VectorType>()->getElementType()); unsigned DstElem = 0; - for (unsigned I = 0; I != SourceLen; I += 2) { - APSInt Elem1; - APSInt Elem2; + for (unsigned I = 0; I != NumElems; I += 2) { + APSInt Result; INT_TYPE_SWITCH_NO_BOOL(ElemT, { - Elem1 = LHS.elem<T>(I).toAPSInt(); - Elem2 = RHS.elem<T>(I).toAPSInt(); + 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); }); - APSInt Result; - switch (BuiltinID) { - case clang::X86::BI__builtin_ia32_pmuludq128: - case clang::X86::BI__builtin_ia32_pmuludq256: - case clang::X86::BI__builtin_ia32_pmuludq512: - Result = APSInt(llvm::APIntOps::muluExtended(Elem1, Elem2), - /*IsUnsigned=*/true); - break; - case clang::X86::BI__builtin_ia32_pmuldq128: - case clang::X86::BI__builtin_ia32_pmuldq256: - case clang::X86::BI__builtin_ia32_pmuldq512: - Result = APSInt(llvm::APIntOps::mulsExtended(Elem1, Elem2), - /*IsUnsigned=*/false); - break; - } - INT_TYPE_SWITCH_NO_BOOL(DstElemT, + INT_TYPE_SWITCH_NO_BOOL(DestElemT, { Dst.elem<T>(DstElem) = static_cast<T>(Result); }); ++DstElem; } @@ -3158,18 +3114,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 +3172,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 +3461,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_pmul( + 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_pmul( + 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: @@ -3638,10 +3629,22 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case clang::X86::BI__builtin_ia32_pmuldq128: case clang::X86::BI__builtin_ia32_pmuldq256: case clang::X86::BI__builtin_ia32_pmuldq512: + return interp__builtin_ia32_pmul( + S, OpPC, Call, + [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS, + const APSInt &HiRHS) { + return llvm::APIntOps::mulsExtended(LoLHS, LoRHS); + }); + case clang::X86::BI__builtin_ia32_pmuludq128: case clang::X86::BI__builtin_ia32_pmuludq256: case clang::X86::BI__builtin_ia32_pmuludq512: - return interp__builtin_ia32_pmul(S, OpPC, Call, BuiltinID); + return interp__builtin_ia32_pmul( + S, OpPC, Call, + [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS, + const APSInt &HiRHS) { + return llvm::APIntOps::muluExtended(LoLHS, LoRHS); + }); case Builtin::BI__builtin_elementwise_fma: return interp__builtin_elementwise_triop_fp( |