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