@@ -1184,6 +1184,7 @@ bool AArch64InstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
11841184 break ;
11851185 case AArch64::PTEST_PP:
11861186 case AArch64::PTEST_PP_ANY:
1187+ case AArch64::PTEST_PP_FIRST:
11871188 SrcReg = MI.getOperand (0 ).getReg ();
11881189 SrcReg2 = MI.getOperand (1 ).getReg ();
11891190 // Not sure about the mask and value for now...
@@ -1355,12 +1356,25 @@ static bool areCFlagsAccessedBetweenInstrs(
13551356 return false ;
13561357}
13571358
1358- std::pair <bool , unsigned >
1359+ std::tuple <bool , unsigned , MachineInstr * >
13591360AArch64InstrInfo::canRemovePTestInstr (MachineInstr *PTest, MachineInstr *Mask,
13601361 MachineInstr *Pred,
13611362 const MachineRegisterInfo *MRI) const {
13621363 unsigned MaskOpcode = Mask->getOpcode ();
13631364 unsigned PredOpcode = Pred->getOpcode ();
1365+
1366+ // Handle a COPY from the LSB of the results of paired WHILEcc instruction.
1367+ if ((PredOpcode == TargetOpcode::COPY &&
1368+ Pred->getOperand (1 ).getSubReg () == AArch64::psub0) ||
1369+ // Handle unpack of the LSB of the result of a WHILEcc instruction.
1370+ PredOpcode == AArch64::PUNPKLO_PP) {
1371+ MachineInstr *MI = MRI->getUniqueVRegDef (Pred->getOperand (1 ).getReg ());
1372+ if (MI && isWhileOpcode (MI->getOpcode ())) {
1373+ Pred = MI;
1374+ PredOpcode = MI->getOpcode ();
1375+ }
1376+ }
1377+
13641378 bool PredIsPTestLike = isPTestLikeOpcode (PredOpcode);
13651379 bool PredIsWhileLike = isWhileOpcode (PredOpcode);
13661380
@@ -1369,17 +1383,18 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
13691383 // instruction and the condition is "any" since WHILcc does an implicit
13701384 // PTEST(ALL, PG) check and PG is always a subset of ALL.
13711385 if ((Mask == Pred) && PTest->getOpcode () == AArch64::PTEST_PP_ANY)
1372- return {true , 0 };
1386+ return {true , 0 , Pred };
13731387
1374- // For PTEST(PTRUE_ALL, WHILE), if the element size matches, the PTEST is
1375- // redundant since WHILE performs an implicit PTEST with an all active
1376- // mask .
1388+ // For PTEST(PTRUE_ALL, WHILE), since WHILE performs an implicit PTEST
1389+ // with an all active mask, the PTEST is redundant if ether the element
1390+ // size matches or the PTEST condition is "first" .
13771391 if (isPTrueOpcode (MaskOpcode) && Mask->getOperand (1 ).getImm () == 31 &&
1378- getElementSizeForOpcode (MaskOpcode) ==
1379- getElementSizeForOpcode (PredOpcode))
1380- return {true , 0 };
1392+ (PTest->getOpcode () == AArch64::PTEST_PP_FIRST ||
1393+ getElementSizeForOpcode (MaskOpcode) ==
1394+ getElementSizeForOpcode (PredOpcode)))
1395+ return {true , 0 , Pred};
13811396
1382- return {false , 0 };
1397+ return {false , 0 , nullptr };
13831398 }
13841399
13851400 if (PredIsPTestLike) {
@@ -1388,7 +1403,7 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
13881403 // "any" since PG is always a subset of the governing predicate of the
13891404 // ptest-like instruction.
13901405 if ((Mask == Pred) && PTest->getOpcode () == AArch64::PTEST_PP_ANY)
1391- return {true , 0 };
1406+ return {true , 0 , Pred };
13921407
13931408 // For PTEST(PTRUE_ALL, PTEST_LIKE), the PTEST is redundant if the
13941409 // the element size matches and either the PTEST_LIKE instruction uses
@@ -1398,7 +1413,7 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
13981413 getElementSizeForOpcode (PredOpcode)) {
13991414 auto PTestLikeMask = MRI->getUniqueVRegDef (Pred->getOperand (1 ).getReg ());
14001415 if (Mask == PTestLikeMask || PTest->getOpcode () == AArch64::PTEST_PP_ANY)
1401- return {true , 0 };
1416+ return {true , 0 , Pred };
14021417 }
14031418
14041419 // For PTEST(PG, PTEST_LIKE(PG, ...)), the PTEST is redundant since the
@@ -1427,9 +1442,9 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
14271442 uint64_t PredElementSize = getElementSizeForOpcode (PredOpcode);
14281443 if (Mask == PTestLikeMask && (PredElementSize == AArch64::ElementSizeB ||
14291444 PTest->getOpcode () == AArch64::PTEST_PP_ANY))
1430- return {true , 0 };
1445+ return {true , 0 , Pred };
14311446
1432- return {false , 0 };
1447+ return {false , 0 , nullptr };
14331448 }
14341449
14351450 // If OP in PTEST(PG, OP(PG, ...)) has a flag-setting variant change the
@@ -1451,7 +1466,7 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
14511466 // may be different and we can't remove the ptest.
14521467 auto *PredMask = MRI->getUniqueVRegDef (Pred->getOperand (1 ).getReg ());
14531468 if (Mask != PredMask)
1454- return {false , 0 };
1469+ return {false , 0 , nullptr };
14551470 break ;
14561471 }
14571472 case AArch64::BRKN_PPzP: {
@@ -1460,18 +1475,18 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
14601475 // PTEST(PTRUE_B(31), BRKN(PG, A, B)) -> BRKNS(PG, A, B).
14611476 if ((MaskOpcode != AArch64::PTRUE_B) ||
14621477 (Mask->getOperand (1 ).getImm () != 31 ))
1463- return {false , 0 };
1478+ return {false , 0 , nullptr };
14641479 break ;
14651480 }
14661481 case AArch64::PTRUE_B:
14671482 // PTEST(OP=PTRUE_B(A), OP) -> PTRUES_B(A)
14681483 break ;
14691484 default :
14701485 // Bail out if we don't recognize the input
1471- return {false , 0 };
1486+ return {false , 0 , nullptr };
14721487 }
14731488
1474- return {true , convertToFlagSettingOpc (PredOpcode)};
1489+ return {true , convertToFlagSettingOpc (PredOpcode), Pred };
14751490}
14761491
14771492// / optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
@@ -1481,7 +1496,10 @@ bool AArch64InstrInfo::optimizePTestInstr(
14811496 const MachineRegisterInfo *MRI) const {
14821497 auto *Mask = MRI->getUniqueVRegDef (MaskReg);
14831498 auto *Pred = MRI->getUniqueVRegDef (PredReg);
1484- auto [canRemove, NewOp] = canRemovePTestInstr (PTest, Mask, Pred, MRI);
1499+ bool canRemove;
1500+ unsigned NewOp;
1501+ std::tie (canRemove, NewOp, Pred) =
1502+ canRemovePTestInstr (PTest, Mask, Pred, MRI);
14851503 if (!canRemove)
14861504 return false ;
14871505
@@ -1559,7 +1577,8 @@ bool AArch64InstrInfo::optimizeCompareInstr(
15591577 }
15601578
15611579 if (CmpInstr.getOpcode () == AArch64::PTEST_PP ||
1562- CmpInstr.getOpcode () == AArch64::PTEST_PP_ANY)
1580+ CmpInstr.getOpcode () == AArch64::PTEST_PP_ANY ||
1581+ CmpInstr.getOpcode () == AArch64::PTEST_PP_FIRST)
15631582 return optimizePTestInstr (&CmpInstr, SrcReg, SrcReg2, MRI);
15641583
15651584 if (SrcReg2 != 0 )
0 commit comments