@@ -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)
13871298static 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