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