@@ -1351,48 +1351,52 @@ static bool areCFlagsAccessedBetweenInstrs(
13511351 return false ;
13521352}
13531353
1354- // / optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
1355- // / operation which could set the flags in an identical manner
1356- bool AArch64InstrInfo::optimizePTestInstr (
1357- MachineInstr *PTest, unsigned MaskReg, unsigned PredReg,
1358- const MachineRegisterInfo *MRI) const {
1359- auto *Mask = MRI->getUniqueVRegDef (MaskReg);
1360- auto *Pred = MRI->getUniqueVRegDef (PredReg);
1361- auto NewOp = Pred->getOpcode ();
1362- bool OpChanged = false ;
1363-
1354+ std::pair<bool , unsigned >
1355+ AArch64InstrInfo::canRemovePTestInstr (MachineInstr *PTest, MachineInstr *Mask,
1356+ MachineInstr *Pred,
1357+ const MachineRegisterInfo *MRI) const {
13641358 unsigned MaskOpcode = Mask->getOpcode ();
13651359 unsigned PredOpcode = Pred->getOpcode ();
13661360 bool PredIsPTestLike = isPTestLikeOpcode (PredOpcode);
13671361 bool PredIsWhileLike = isWhileOpcode (PredOpcode);
13681362
1369- if (isPTrueOpcode (MaskOpcode) && (PredIsPTestLike || PredIsWhileLike) &&
1370- getElementSizeForOpcode (MaskOpcode) ==
1371- getElementSizeForOpcode (PredOpcode) &&
1372- Mask->getOperand (1 ).getImm () == 31 ) {
1363+ if (PredIsWhileLike) {
1364+ // For PTEST(PG, PG), PTEST is redundant when PG is the result of a WHILEcc
1365+ // instruction and the condition is "any" since WHILcc does an implicit
1366+ // PTEST(ALL, PG) check and PG is always a subset of ALL.
1367+ if ((Mask == Pred) && PTest->getOpcode () == AArch64::PTEST_PP_ANY)
1368+ return {true , 0 };
1369+
13731370 // For PTEST(PTRUE_ALL, WHILE), if the element size matches, the PTEST is
13741371 // redundant since WHILE performs an implicit PTEST with an all active
1375- // mask. Must be an all active predicate of matching element size.
1372+ // mask.
1373+ if (isPTrueOpcode (MaskOpcode) && Mask->getOperand (1 ).getImm () == 31 &&
1374+ getElementSizeForOpcode (MaskOpcode) ==
1375+ getElementSizeForOpcode (PredOpcode))
1376+ return {true , 0 };
1377+
1378+ return {false , 0 };
1379+ }
1380+
1381+ if (PredIsPTestLike) {
1382+ // For PTEST(PG, PG), PTEST is redundant when PG is the result of an
1383+ // instruction that sets the flags as PTEST would and the condition is
1384+ // "any" since PG is always a subset of the governing predicate of the
1385+ // ptest-like instruction.
1386+ if ((Mask == Pred) && PTest->getOpcode () == AArch64::PTEST_PP_ANY)
1387+ return {true , 0 };
13761388
13771389 // For PTEST(PTRUE_ALL, PTEST_LIKE), the PTEST is redundant if the
1378- // PTEST_LIKE instruction uses the same all active mask and the element
1379- // size matches. If the PTEST has a condition of any then it is always
1380- // redundant.
1381- if (PredIsPTestLike) {
1390+ // the element size matches and either the PTEST_LIKE instruction uses
1391+ // the same all active mask or the condition is "any".
1392+ if (isPTrueOpcode (MaskOpcode) && Mask->getOperand (1 ).getImm () == 31 &&
1393+ getElementSizeForOpcode (MaskOpcode) ==
1394+ getElementSizeForOpcode (PredOpcode)) {
13821395 auto PTestLikeMask = MRI->getUniqueVRegDef (Pred->getOperand (1 ).getReg ());
1383- if (Mask != PTestLikeMask && PTest->getOpcode () ! = AArch64::PTEST_PP_ANY)
1384- return false ;
1396+ if (Mask == PTestLikeMask || PTest->getOpcode () = = AArch64::PTEST_PP_ANY)
1397+ return { true , 0 } ;
13851398 }
13861399
1387- // Fallthough to simply remove the PTEST.
1388- } else if ((Mask == Pred) && (PredIsPTestLike || PredIsWhileLike) &&
1389- PTest->getOpcode () == AArch64::PTEST_PP_ANY) {
1390- // For PTEST(PG, PG), PTEST is redundant when PG is the result of an
1391- // instruction that sets the flags as PTEST would. This is only valid when
1392- // the condition is any.
1393-
1394- // Fallthough to simply remove the PTEST.
1395- } else if (PredIsPTestLike) {
13961400 // For PTEST(PG, PTEST_LIKE(PG, ...)), the PTEST is redundant since the
13971401 // flags are set based on the same mask 'PG', but PTEST_LIKE must operate
13981402 // on 8-bit predicates like the PTEST. Otherwise, for instructions like
@@ -1417,55 +1421,65 @@ bool AArch64InstrInfo::optimizePTestInstr(
14171421 // identical regardless of element size.
14181422 auto PTestLikeMask = MRI->getUniqueVRegDef (Pred->getOperand (1 ).getReg ());
14191423 uint64_t PredElementSize = getElementSizeForOpcode (PredOpcode);
1420- if ((Mask != PTestLikeMask) ||
1421- (PredElementSize != AArch64::ElementSizeB &&
1422- PTest->getOpcode () != AArch64::PTEST_PP_ANY))
1423- return false ;
1424+ if (Mask == PTestLikeMask && (PredElementSize == AArch64::ElementSizeB ||
1425+ PTest->getOpcode () == AArch64::PTEST_PP_ANY))
1426+ return {true , 0 };
14241427
1425- // Fallthough to simply remove the PTEST.
1426- } else {
1427- // If OP in PTEST(PG, OP(PG, ...)) has a flag-setting variant change the
1428- // opcode so the PTEST becomes redundant.
1429- switch (PredOpcode) {
1430- case AArch64::AND_PPzPP:
1431- case AArch64::BIC_PPzPP:
1432- case AArch64::EOR_PPzPP:
1433- case AArch64::NAND_PPzPP:
1434- case AArch64::NOR_PPzPP:
1435- case AArch64::ORN_PPzPP:
1436- case AArch64::ORR_PPzPP:
1437- case AArch64::BRKA_PPzP:
1438- case AArch64::BRKPA_PPzPP:
1439- case AArch64::BRKB_PPzP:
1440- case AArch64::BRKPB_PPzPP:
1441- case AArch64::RDFFR_PPz: {
1442- // Check to see if our mask is the same. If not the resulting flag bits
1443- // may be different and we can't remove the ptest.
1444- auto *PredMask = MRI->getUniqueVRegDef (Pred->getOperand (1 ).getReg ());
1445- if (Mask != PredMask)
1446- return false ;
1447- break ;
1448- }
1449- case AArch64::BRKN_PPzP: {
1450- // BRKN uses an all active implicit mask to set flags unlike the other
1451- // flag-setting instructions.
1452- // PTEST(PTRUE_B(31), BRKN(PG, A, B)) -> BRKNS(PG, A, B).
1453- if ((MaskOpcode != AArch64::PTRUE_B) ||
1454- (Mask->getOperand (1 ).getImm () != 31 ))
1455- return false ;
1456- break ;
1457- }
1458- case AArch64::PTRUE_B:
1459- // PTEST(OP=PTRUE_B(A), OP) -> PTRUES_B(A)
1460- break ;
1461- default :
1462- // Bail out if we don't recognize the input
1463- return false ;
1464- }
1428+ return {false , 0 };
1429+ }
14651430
1466- NewOp = convertToFlagSettingOpc (PredOpcode);
1467- OpChanged = true ;
1431+ // If OP in PTEST(PG, OP(PG, ...)) has a flag-setting variant change the
1432+ // opcode so the PTEST becomes redundant.
1433+ switch (PredOpcode) {
1434+ case AArch64::AND_PPzPP:
1435+ case AArch64::BIC_PPzPP:
1436+ case AArch64::EOR_PPzPP:
1437+ case AArch64::NAND_PPzPP:
1438+ case AArch64::NOR_PPzPP:
1439+ case AArch64::ORN_PPzPP:
1440+ case AArch64::ORR_PPzPP:
1441+ case AArch64::BRKA_PPzP:
1442+ case AArch64::BRKPA_PPzPP:
1443+ case AArch64::BRKB_PPzP:
1444+ case AArch64::BRKPB_PPzPP:
1445+ case AArch64::RDFFR_PPz: {
1446+ // Check to see if our mask is the same. If not the resulting flag bits
1447+ // may be different and we can't remove the ptest.
1448+ auto *PredMask = MRI->getUniqueVRegDef (Pred->getOperand (1 ).getReg ());
1449+ if (Mask != PredMask)
1450+ return {false , 0 };
1451+ break ;
14681452 }
1453+ case AArch64::BRKN_PPzP: {
1454+ // BRKN uses an all active implicit mask to set flags unlike the other
1455+ // flag-setting instructions.
1456+ // PTEST(PTRUE_B(31), BRKN(PG, A, B)) -> BRKNS(PG, A, B).
1457+ if ((MaskOpcode != AArch64::PTRUE_B) ||
1458+ (Mask->getOperand (1 ).getImm () != 31 ))
1459+ return {false , 0 };
1460+ break ;
1461+ }
1462+ case AArch64::PTRUE_B:
1463+ // PTEST(OP=PTRUE_B(A), OP) -> PTRUES_B(A)
1464+ break ;
1465+ default :
1466+ // Bail out if we don't recognize the input
1467+ return {false , 0 };
1468+ }
1469+
1470+ return {true , convertToFlagSettingOpc (PredOpcode)};
1471+ }
1472+
1473+ // / optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
1474+ // / operation which could set the flags in an identical manner
1475+ bool AArch64InstrInfo::optimizePTestInstr (
1476+ MachineInstr *PTest, unsigned MaskReg, unsigned PredReg,
1477+ const MachineRegisterInfo *MRI) const {
1478+ auto *Mask = MRI->getUniqueVRegDef (MaskReg);
1479+ auto *Pred = MRI->getUniqueVRegDef (PredReg);
1480+ auto [canRemove, NewOp] = canRemovePTestInstr (PTest, Mask, Pred, MRI);
1481+ if (!canRemove)
1482+ return false ;
14691483
14701484 const TargetRegisterInfo *TRI = &getRegisterInfo ();
14711485
@@ -1478,9 +1492,9 @@ bool AArch64InstrInfo::optimizePTestInstr(
14781492 // as they are prior to PTEST. Sometimes this requires the tested PTEST
14791493 // operand to be replaced with an equivalent instruction that also sets the
14801494 // flags.
1481- Pred->setDesc (get (NewOp));
14821495 PTest->eraseFromParent ();
1483- if (OpChanged) {
1496+ if (NewOp) {
1497+ Pred->setDesc (get (NewOp));
14841498 bool succeeded = UpdateOperandRegClass (*Pred);
14851499 (void )succeeded;
14861500 assert (succeeded && " Operands have incompatible register classes!" );
0 commit comments