Skip to content

Commit 0251fd9

Browse files
authored
[clang][x86][bytecode] Refactor BMI intrinsic wrappers to use interp__builtin_elementwise_int_binop (#160362)
Fixes #160281
1 parent e5d925f commit 0251fd9

File tree

1 file changed

+52
-93
lines changed

1 file changed

+52
-93
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 52 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,95 +1294,6 @@ static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC,
12941294
return true;
12951295
}
12961296

1297-
static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC,
1298-
const InterpFrame *Frame,
1299-
const CallExpr *Call) {
1300-
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1301-
!Call->getArg(1)->getType()->isIntegerType())
1302-
return false;
1303-
1304-
APSInt Index = popToAPSInt(S, Call->getArg(1));
1305-
APSInt Val = popToAPSInt(S, Call->getArg(0));
1306-
1307-
unsigned BitWidth = Val.getBitWidth();
1308-
uint64_t Shift = Index.extractBitsAsZExtValue(8, 0);
1309-
uint64_t Length = Index.extractBitsAsZExtValue(8, 8);
1310-
Length = Length > BitWidth ? BitWidth : Length;
1311-
1312-
// Handle out of bounds cases.
1313-
if (Length == 0 || Shift >= BitWidth) {
1314-
pushInteger(S, 0, Call->getType());
1315-
return true;
1316-
}
1317-
1318-
uint64_t Result = Val.getZExtValue() >> Shift;
1319-
Result &= llvm::maskTrailingOnes<uint64_t>(Length);
1320-
pushInteger(S, Result, Call->getType());
1321-
return true;
1322-
}
1323-
1324-
static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC,
1325-
const InterpFrame *Frame,
1326-
const CallExpr *Call) {
1327-
QualType CallType = Call->getType();
1328-
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1329-
!Call->getArg(1)->getType()->isIntegerType() ||
1330-
!CallType->isIntegerType())
1331-
return false;
1332-
1333-
APSInt Idx = popToAPSInt(S, Call->getArg(1));
1334-
APSInt Val = popToAPSInt(S, Call->getArg(0));
1335-
1336-
unsigned BitWidth = Val.getBitWidth();
1337-
uint64_t Index = Idx.extractBitsAsZExtValue(8, 0);
1338-
1339-
if (Index < BitWidth)
1340-
Val.clearHighBits(BitWidth - Index);
1341-
1342-
pushInteger(S, Val, CallType);
1343-
return true;
1344-
}
1345-
1346-
static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC,
1347-
const InterpFrame *Frame,
1348-
const CallExpr *Call) {
1349-
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1350-
!Call->getArg(1)->getType()->isIntegerType())
1351-
return false;
1352-
1353-
APSInt Mask = popToAPSInt(S, Call->getArg(1));
1354-
APSInt Val = popToAPSInt(S, Call->getArg(0));
1355-
1356-
unsigned BitWidth = Val.getBitWidth();
1357-
APInt Result = APInt::getZero(BitWidth);
1358-
for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
1359-
if (Mask[I])
1360-
Result.setBitVal(I, Val[P++]);
1361-
}
1362-
pushInteger(S, std::move(Result), Call->getType());
1363-
return true;
1364-
}
1365-
1366-
static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,
1367-
const InterpFrame *Frame,
1368-
const CallExpr *Call) {
1369-
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1370-
!Call->getArg(1)->getType()->isIntegerType())
1371-
return false;
1372-
1373-
APSInt Mask = popToAPSInt(S, Call->getArg(1));
1374-
APSInt Val = popToAPSInt(S, Call->getArg(0));
1375-
1376-
unsigned BitWidth = Val.getBitWidth();
1377-
APInt Result = APInt::getZero(BitWidth);
1378-
for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
1379-
if (Mask[I])
1380-
Result.setBitVal(P++, Val[I]);
1381-
}
1382-
pushInteger(S, std::move(Result), Call->getType());
1383-
return true;
1384-
}
1385-
13861297
/// (CarryIn, LHS, RHS, Result)
13871298
static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S,
13881299
CodePtr OpPC,
@@ -3275,11 +3186,37 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
32753186
case clang::X86::BI__builtin_ia32_bextr_u64:
32763187
case clang::X86::BI__builtin_ia32_bextri_u32:
32773188
case clang::X86::BI__builtin_ia32_bextri_u64:
3278-
return interp__builtin_ia32_bextr(S, OpPC, Frame, Call);
3189+
return interp__builtin_elementwise_int_binop(
3190+
S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) {
3191+
unsigned BitWidth = Val.getBitWidth();
3192+
uint64_t Shift = Idx.extractBitsAsZExtValue(8, 0);
3193+
uint64_t Length = Idx.extractBitsAsZExtValue(8, 8);
3194+
if (Length > BitWidth) {
3195+
Length = BitWidth;
3196+
}
3197+
3198+
// Handle out of bounds cases.
3199+
if (Length == 0 || Shift >= BitWidth)
3200+
return APInt(BitWidth, 0);
3201+
3202+
uint64_t Result = Val.getZExtValue() >> Shift;
3203+
Result &= llvm::maskTrailingOnes<uint64_t>(Length);
3204+
return APInt(BitWidth, Result);
3205+
});
32793206

32803207
case clang::X86::BI__builtin_ia32_bzhi_si:
32813208
case clang::X86::BI__builtin_ia32_bzhi_di:
3282-
return interp__builtin_ia32_bzhi(S, OpPC, Frame, Call);
3209+
return interp__builtin_elementwise_int_binop(
3210+
S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) {
3211+
unsigned BitWidth = Val.getBitWidth();
3212+
uint64_t Index = Idx.extractBitsAsZExtValue(8, 0);
3213+
APSInt Result = Val;
3214+
3215+
if (Index < BitWidth)
3216+
Result.clearHighBits(BitWidth - Index);
3217+
3218+
return Result;
3219+
});
32833220

32843221
case clang::X86::BI__builtin_ia32_lzcnt_u16:
32853222
case clang::X86::BI__builtin_ia32_lzcnt_u32:
@@ -3299,11 +3236,33 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
32993236

33003237
case clang::X86::BI__builtin_ia32_pdep_si:
33013238
case clang::X86::BI__builtin_ia32_pdep_di:
3302-
return interp__builtin_ia32_pdep(S, OpPC, Frame, Call);
3239+
return interp__builtin_elementwise_int_binop(
3240+
S, OpPC, Call, [](const APSInt &Val, const APSInt &Mask) {
3241+
unsigned BitWidth = Val.getBitWidth();
3242+
APInt Result = APInt::getZero(BitWidth);
3243+
3244+
for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
3245+
if (Mask[I])
3246+
Result.setBitVal(I, Val[P++]);
3247+
}
3248+
3249+
return Result;
3250+
});
33033251

33043252
case clang::X86::BI__builtin_ia32_pext_si:
33053253
case clang::X86::BI__builtin_ia32_pext_di:
3306-
return interp__builtin_ia32_pext(S, OpPC, Frame, Call);
3254+
return interp__builtin_elementwise_int_binop(
3255+
S, OpPC, Call, [](const APSInt &Val, const APSInt &Mask) {
3256+
unsigned BitWidth = Val.getBitWidth();
3257+
APInt Result = APInt::getZero(BitWidth);
3258+
3259+
for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
3260+
if (Mask[I])
3261+
Result.setBitVal(P++, Val[I]);
3262+
}
3263+
3264+
return Result;
3265+
});
33073266

33083267
case clang::X86::BI__builtin_ia32_addcarryx_u32:
33093268
case clang::X86::BI__builtin_ia32_addcarryx_u64:

0 commit comments

Comments
 (0)