@@ -2548,9 +2548,9 @@ static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,
2548
2548
return true ;
2549
2549
}
2550
2550
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 ) {
2554
2554
assert (Call->getNumArgs () == 2 );
2555
2555
2556
2556
// Single integer case.
@@ -2560,15 +2560,7 @@ static bool interp__builtin_elementwise_int_binop(InterpState &S, CodePtr OpPC,
2560
2560
S.Stk , *S.getContext ().classify (Call->getArg (1 )->getType ()));
2561
2561
APSInt LHS = popToAPSInt (
2562
2562
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);
2572
2564
pushInteger (S, APSInt (std::move (Result), !LHS.isSigned ()), Call->getType ());
2573
2565
return true ;
2574
2566
}
@@ -2587,8 +2579,6 @@ static bool interp__builtin_elementwise_int_binop(InterpState &S, CodePtr OpPC,
2587
2579
const Pointer &LHS = S.Stk .pop <Pointer>();
2588
2580
const Pointer &Dst = S.Stk .peek <Pointer>();
2589
2581
PrimType ElemT = *S.getContext ().classify (VT->getElementType ());
2590
- bool DestUnsigned =
2591
- VT->getElementType ()->isUnsignedIntegerOrEnumerationType ();
2592
2582
unsigned NumElems = VT->getNumElements ();
2593
2583
for (unsigned I = 0 ; I != NumElems; ++I) {
2594
2584
APSInt Elem1;
@@ -2598,61 +2588,9 @@ static bool interp__builtin_elementwise_int_binop(InterpState &S, CodePtr OpPC,
2598
2588
Elem2 = RHS.elem <T>(I).toAPSInt ();
2599
2589
});
2600
2590
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 ());
2656
2594
2657
2595
INT_TYPE_SWITCH_NO_BOOL (ElemT,
2658
2596
{ Dst.elem <T>(I) = static_cast <T>(Result); });
@@ -3289,24 +3227,62 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
3289
3227
return interp__builtin_is_within_lifetime (S, OpPC, Call);
3290
3228
3291
3229
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
+
3292
3235
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
+
3293
3241
case clang::X86::BI__builtin_ia32_pmulhuw128:
3294
3242
case clang::X86::BI__builtin_ia32_pmulhuw256:
3295
3243
case clang::X86::BI__builtin_ia32_pmulhuw512:
3244
+ return interp__builtin_elementwise_int_binop (S, OpPC, Call, BuiltinID,
3245
+ llvm::APIntOps::mulhu);
3246
+
3296
3247
case clang::X86::BI__builtin_ia32_pmulhw128:
3297
3248
case clang::X86::BI__builtin_ia32_pmulhw256:
3298
3249
case clang::X86::BI__builtin_ia32_pmulhw512:
3250
+ return interp__builtin_elementwise_int_binop (S, OpPC, Call, BuiltinID,
3251
+ llvm::APIntOps::mulhs);
3252
+
3299
3253
case clang::X86::BI__builtin_ia32_psllv2di:
3300
3254
case clang::X86::BI__builtin_ia32_psllv4di:
3301
3255
case clang::X86::BI__builtin_ia32_psllv4si:
3302
3256
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
+
3303
3265
case clang::X86::BI__builtin_ia32_psrav4si:
3304
3266
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
+
3305
3275
case clang::X86::BI__builtin_ia32_psrlv2di:
3306
3276
case clang::X86::BI__builtin_ia32_psrlv4di:
3307
3277
case clang::X86::BI__builtin_ia32_psrlv4si:
3308
3278
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
+ });
3310
3286
3311
3287
case Builtin::BI__builtin_elementwise_max:
3312
3288
case Builtin::BI__builtin_elementwise_min:
0 commit comments