Skip to content

Commit fcc7867

Browse files
authored
[Clang][bytecode] interp__builtin_elementwise_int_binop - use APSInt callback instead of repeated switch statement (#155891)
Users of interp__builtin_elementwise_int_binop are going to be very well defined, we can use a simple callback mechanism (including existing llvm::APIntOps static methods) to perform the evaluation and avoid a repeated switch statement. Hopefully this will help keep interp__builtin_elementwise_int_binop clean as we add more uses
1 parent 448811d commit fcc7867

File tree

1 file changed

+46
-70
lines changed

1 file changed

+46
-70
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 46 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)