@@ -2583,6 +2583,50 @@ static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC,
25832583 return true ;
25842584}
25852585
2586+ static bool interp__builtin_ia32_pmul (InterpState &S, CodePtr OpPC,
2587+ const CallExpr *Call,
2588+ unsigned BuiltinID) {
2589+ assert (Call->getArg (0 )->getType ()->isVectorType () &&
2590+ Call->getArg (1 )->getType ()->isVectorType ());
2591+ const Pointer &RHS = S.Stk .pop <Pointer>();
2592+ const Pointer &LHS = S.Stk .pop <Pointer>();
2593+ const Pointer &Dst = S.Stk .peek <Pointer>();
2594+
2595+ const auto *VT = Call->getArg (0 )->getType ()->castAs <VectorType>();
2596+ PrimType ElemT = *S.getContext ().classify (VT->getElementType ());
2597+ unsigned SourceLen = VT->getNumElements ();
2598+ SmallVector<APValue, 4 > ResultElements;
2599+ ResultElements.reserve (SourceLen / 2 );
2600+
2601+ for (unsigned I = 0 ; I != SourceLen; I += 2 ) {
2602+ APSInt Elem1;
2603+ APSInt Elem2;
2604+ INT_TYPE_SWITCH_NO_BOOL (ElemT, {
2605+ Elem1 = LHS.elem <T>(I).toAPSInt ();
2606+ Elem2 = RHS.elem <T>(I).toAPSInt ();
2607+ });
2608+
2609+ APSInt Result;
2610+ switch (BuiltinID) {
2611+ case clang::X86::BI__builtin_ia32_pmuludq128:
2612+ case clang::X86::BI__builtin_ia32_pmuludq256:
2613+ case clang::X86::BI__builtin_ia32_pmuludq512:
2614+ Result = APSInt (llvm::APIntOps::muluExtended (Elem1, Elem2), true );
2615+ break ;
2616+ case clang::X86::BI__builtin_ia32_pmuldq128:
2617+ case clang::X86::BI__builtin_ia32_pmuldq256:
2618+ case clang::X86::BI__builtin_ia32_pmuldq512:
2619+ Result = APSInt (llvm::APIntOps::mulsExtended (Elem1, Elem2), false );
2620+ break ;
2621+ }
2622+ INT_TYPE_SWITCH_NO_BOOL (ElemT,
2623+ { Dst.elem <T>(I) = static_cast <T>(Result); });
2624+ }
2625+
2626+ Dst.initializeAllElements ();
2627+ return true ;
2628+ }
2629+
25862630bool InterpretBuiltin (InterpState &S, CodePtr OpPC, const CallExpr *Call,
25872631 uint32_t BuiltinID) {
25882632 if (!S.getASTContext ().BuiltinInfo .isConstantEvaluated (BuiltinID))
@@ -3003,6 +3047,13 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
30033047 case Builtin::BI__builtin_elementwise_min:
30043048 return interp__builtin_elementwise_maxmin (S, OpPC, Call, BuiltinID);
30053049
3050+ case clang::X86::BI__builtin_ia32_pmuldq128:
3051+ case clang::X86::BI__builtin_ia32_pmuldq256:
3052+ case clang::X86::BI__builtin_ia32_pmuldq512:
3053+ case clang::X86::BI__builtin_ia32_pmuludq128:
3054+ case clang::X86::BI__builtin_ia32_pmuludq256:
3055+ return interp__builtin_ia32_pmul (S, OpPC, Call, BuiltinID);
3056+
30063057 default :
30073058 S.FFDiag (S.Current ->getLocation (OpPC),
30083059 diag::note_invalid_subexpr_in_const_expr)
0 commit comments