@@ -2548,9 +2548,9 @@ static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,
25482548 return true ;
25492549}
25502550
2551- static bool interp__builtin_elementwise_int_binop (InterpState &S, CodePtr OpPC,
2552- const CallExpr *Call,
2553- unsigned BuiltinID ) {
2551+ static bool interp__builtin_elementwise_int_binop (
2552+ InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned BuiltinID ,
2553+ llvm::function_ref<APInt( const APSInt &, const APSInt &)> Fn ) {
25542554 assert (Call->getNumArgs () == 2 );
25552555
25562556 // Single integer case.
@@ -2560,15 +2560,7 @@ static bool interp__builtin_elementwise_int_binop(InterpState &S, CodePtr OpPC,
25602560 S.Stk , *S.getContext ().classify (Call->getArg (1 )->getType ()));
25612561 APSInt LHS = popToAPSInt (
25622562 S.Stk , *S.getContext ().classify (Call->getArg (0 )->getType ()));
2563- APInt Result;
2564- if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) {
2565- Result = LHS.isSigned () ? LHS.sadd_sat (RHS) : LHS.uadd_sat (RHS);
2566- } else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) {
2567- Result = LHS.isSigned () ? LHS.ssub_sat (RHS) : LHS.usub_sat (RHS);
2568- } else {
2569- llvm_unreachable (" Wrong builtin ID" );
2570- }
2571-
2563+ APInt Result = Fn (LHS, RHS);
25722564 pushInteger (S, APSInt (std::move (Result), !LHS.isSigned ()), Call->getType ());
25732565 return true ;
25742566 }
@@ -2587,8 +2579,6 @@ static bool interp__builtin_elementwise_int_binop(InterpState &S, CodePtr OpPC,
25872579 const Pointer &LHS = S.Stk .pop <Pointer>();
25882580 const Pointer &Dst = S.Stk .peek <Pointer>();
25892581 PrimType ElemT = *S.getContext ().classify (VT->getElementType ());
2590- bool DestUnsigned =
2591- VT->getElementType ()->isUnsignedIntegerOrEnumerationType ();
25922582 unsigned NumElems = VT->getNumElements ();
25932583 for (unsigned I = 0 ; I != NumElems; ++I) {
25942584 APSInt Elem1;
@@ -2598,61 +2588,9 @@ static bool interp__builtin_elementwise_int_binop(InterpState &S, CodePtr OpPC,
25982588 Elem2 = RHS.elem <T>(I).toAPSInt ();
25992589 });
26002590
2601- APSInt Result;
2602- switch (BuiltinID) {
2603- case Builtin::BI__builtin_elementwise_add_sat:
2604- Result = APSInt (Elem1.isSigned () ? Elem1.sadd_sat (Elem2)
2605- : Elem1.uadd_sat (Elem2),
2606- Call->getType ()->isUnsignedIntegerOrEnumerationType ());
2607- break ;
2608- case Builtin::BI__builtin_elementwise_sub_sat:
2609- Result = APSInt (Elem1.isSigned () ? Elem1.ssub_sat (Elem2)
2610- : Elem1.usub_sat (Elem2),
2611- Call->getType ()->isUnsignedIntegerOrEnumerationType ());
2612- break ;
2613- case clang::X86::BI__builtin_ia32_pmulhuw128:
2614- case clang::X86::BI__builtin_ia32_pmulhuw256:
2615- case clang::X86::BI__builtin_ia32_pmulhuw512:
2616- Result = APSInt (llvm::APIntOps::mulhu (Elem1, Elem2),
2617- /* isUnsigned=*/ true );
2618- break ;
2619- case clang::X86::BI__builtin_ia32_pmulhw128:
2620- case clang::X86::BI__builtin_ia32_pmulhw256:
2621- case clang::X86::BI__builtin_ia32_pmulhw512:
2622- Result = APSInt (llvm::APIntOps::mulhs (Elem1, Elem2),
2623- /* isUnsigned=*/ false );
2624- break ;
2625- case clang::X86::BI__builtin_ia32_psllv2di:
2626- case clang::X86::BI__builtin_ia32_psllv4di:
2627- case clang::X86::BI__builtin_ia32_psllv4si:
2628- case clang::X86::BI__builtin_ia32_psllv8si:
2629- if (Elem2.uge (Elem2.getBitWidth ())) {
2630- Result = APSInt (APInt::getZero (Elem2.getBitWidth ()), DestUnsigned);
2631- break ;
2632- }
2633- Result = APSInt (Elem1.shl (Elem2.getZExtValue ()), DestUnsigned);
2634- break ;
2635- case clang::X86::BI__builtin_ia32_psrav4si:
2636- case clang::X86::BI__builtin_ia32_psrav8si:
2637- if (Elem2.uge (Elem2.getBitWidth ())) {
2638- Result = APSInt (Elem1.ashr (Elem2.getBitWidth () - 1 ), DestUnsigned);
2639- break ;
2640- }
2641- Result = APSInt (Elem1.ashr (Elem2.getZExtValue ()), DestUnsigned);
2642- break ;
2643- case clang::X86::BI__builtin_ia32_psrlv2di:
2644- case clang::X86::BI__builtin_ia32_psrlv4di:
2645- case clang::X86::BI__builtin_ia32_psrlv4si:
2646- case clang::X86::BI__builtin_ia32_psrlv8si:
2647- if (Elem2.uge (Elem2.getBitWidth ())) {
2648- Result = APSInt (APInt::getZero (Elem2.getBitWidth ()), DestUnsigned);
2649- break ;
2650- }
2651- Result = APSInt (Elem1.lshr (Elem2.getZExtValue ()), DestUnsigned);
2652- break ;
2653- default :
2654- llvm_unreachable (" Wrong builtin ID" );
2655- }
2591+ APSInt Result =
2592+ APSInt (Fn (Elem1, Elem2),
2593+ Call->getType ()->isUnsignedIntegerOrEnumerationType ());
26562594
26572595 INT_TYPE_SWITCH_NO_BOOL (ElemT,
26582596 { Dst.elem <T>(I) = static_cast <T>(Result); });
@@ -3289,24 +3227,62 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
32893227 return interp__builtin_is_within_lifetime (S, OpPC, Call);
32903228
32913229 case Builtin::BI__builtin_elementwise_add_sat:
3230+ return interp__builtin_elementwise_int_binop (
3231+ S, OpPC, Call, BuiltinID, [](const APSInt &LHS, const APSInt &RHS) {
3232+ return LHS.isSigned () ? LHS.sadd_sat (RHS) : LHS.uadd_sat (RHS);
3233+ });
3234+
32923235 case Builtin::BI__builtin_elementwise_sub_sat:
3236+ return interp__builtin_elementwise_int_binop (
3237+ S, OpPC, Call, BuiltinID, [](const APSInt &LHS, const APSInt &RHS) {
3238+ return LHS.isSigned () ? LHS.ssub_sat (RHS) : LHS.usub_sat (RHS);
3239+ });
3240+
32933241 case clang::X86::BI__builtin_ia32_pmulhuw128:
32943242 case clang::X86::BI__builtin_ia32_pmulhuw256:
32953243 case clang::X86::BI__builtin_ia32_pmulhuw512:
3244+ return interp__builtin_elementwise_int_binop (S, OpPC, Call, BuiltinID,
3245+ llvm::APIntOps::mulhu);
3246+
32963247 case clang::X86::BI__builtin_ia32_pmulhw128:
32973248 case clang::X86::BI__builtin_ia32_pmulhw256:
32983249 case clang::X86::BI__builtin_ia32_pmulhw512:
3250+ return interp__builtin_elementwise_int_binop (S, OpPC, Call, BuiltinID,
3251+ llvm::APIntOps::mulhs);
3252+
32993253 case clang::X86::BI__builtin_ia32_psllv2di:
33003254 case clang::X86::BI__builtin_ia32_psllv4di:
33013255 case clang::X86::BI__builtin_ia32_psllv4si:
33023256 case clang::X86::BI__builtin_ia32_psllv8si:
3257+ return interp__builtin_elementwise_int_binop (
3258+ S, OpPC, Call, BuiltinID, [](const APSInt &LHS, const APSInt &RHS) {
3259+ if (RHS.uge (RHS.getBitWidth ())) {
3260+ return APInt::getZero (RHS.getBitWidth ());
3261+ }
3262+ return LHS.shl (RHS.getZExtValue ());
3263+ });
3264+
33033265 case clang::X86::BI__builtin_ia32_psrav4si:
33043266 case clang::X86::BI__builtin_ia32_psrav8si:
3267+ return interp__builtin_elementwise_int_binop (
3268+ S, OpPC, Call, BuiltinID, [](const APSInt &LHS, const APSInt &RHS) {
3269+ if (RHS.uge (RHS.getBitWidth ())) {
3270+ return LHS.ashr (RHS.getBitWidth () - 1 );
3271+ }
3272+ return LHS.ashr (RHS.getZExtValue ());
3273+ });
3274+
33053275 case clang::X86::BI__builtin_ia32_psrlv2di:
33063276 case clang::X86::BI__builtin_ia32_psrlv4di:
33073277 case clang::X86::BI__builtin_ia32_psrlv4si:
33083278 case clang::X86::BI__builtin_ia32_psrlv8si:
3309- return interp__builtin_elementwise_int_binop (S, OpPC, Call, BuiltinID);
3279+ return interp__builtin_elementwise_int_binop (
3280+ S, OpPC, Call, BuiltinID, [](const APSInt &LHS, const APSInt &RHS) {
3281+ if (RHS.uge (RHS.getBitWidth ())) {
3282+ return APInt::getZero (RHS.getBitWidth ());
3283+ }
3284+ return LHS.lshr (RHS.getZExtValue ());
3285+ });
33103286
33113287 case Builtin::BI__builtin_elementwise_max:
33123288 case Builtin::BI__builtin_elementwise_min:
0 commit comments