@@ -1184,6 +1184,7 @@ bool AArch64InstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
1184
1184
break ;
1185
1185
case AArch64::PTEST_PP:
1186
1186
case AArch64::PTEST_PP_ANY:
1187
+ case AArch64::PTEST_PP_FIRST:
1187
1188
SrcReg = MI.getOperand (0 ).getReg ();
1188
1189
SrcReg2 = MI.getOperand (1 ).getReg ();
1189
1190
// Not sure about the mask and value for now...
@@ -1355,12 +1356,25 @@ static bool areCFlagsAccessedBetweenInstrs(
1355
1356
return false ;
1356
1357
}
1357
1358
1358
- std::optional<unsigned >
1359
+ std::optional<std::pair< unsigned , MachineInstr *> >
1359
1360
AArch64InstrInfo::canRemovePTestInstr (MachineInstr *PTest, MachineInstr *Mask,
1360
1361
MachineInstr *Pred,
1361
1362
const MachineRegisterInfo *MRI) const {
1362
1363
unsigned MaskOpcode = Mask->getOpcode ();
1363
1364
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
+
1364
1378
bool PredIsPTestLike = isPTestLikeOpcode (PredOpcode);
1365
1379
bool PredIsWhileLike = isWhileOpcode (PredOpcode);
1366
1380
@@ -1369,15 +1383,16 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1369
1383
// instruction and the condition is "any" since WHILcc does an implicit
1370
1384
// PTEST(ALL, PG) check and PG is always a subset of ALL.
1371
1385
if ((Mask == Pred) && PTest->getOpcode () == AArch64::PTEST_PP_ANY)
1372
- return PredOpcode;
1386
+ return std::make_pair ( PredOpcode, Pred) ;
1373
1387
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" .
1377
1391
if (isPTrueOpcode (MaskOpcode) && Mask->getOperand (1 ).getImm () == 31 &&
1378
- getElementSizeForOpcode (MaskOpcode) ==
1379
- getElementSizeForOpcode (PredOpcode))
1380
- return PredOpcode;
1392
+ (PTest->getOpcode () == AArch64::PTEST_PP_FIRST ||
1393
+ getElementSizeForOpcode (MaskOpcode) ==
1394
+ getElementSizeForOpcode (PredOpcode)))
1395
+ return std::make_pair (PredOpcode, Pred);
1381
1396
1382
1397
return {};
1383
1398
}
@@ -1388,7 +1403,7 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1388
1403
// "any" since PG is always a subset of the governing predicate of the
1389
1404
// ptest-like instruction.
1390
1405
if ((Mask == Pred) && PTest->getOpcode () == AArch64::PTEST_PP_ANY)
1391
- return PredOpcode;
1406
+ return std::make_pair ( PredOpcode, Pred) ;
1392
1407
1393
1408
// For PTEST(PTRUE_ALL, PTEST_LIKE), the PTEST is redundant if the
1394
1409
// the element size matches and either the PTEST_LIKE instruction uses
@@ -1398,7 +1413,7 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1398
1413
getElementSizeForOpcode (PredOpcode)) {
1399
1414
auto PTestLikeMask = MRI->getUniqueVRegDef (Pred->getOperand (1 ).getReg ());
1400
1415
if (Mask == PTestLikeMask || PTest->getOpcode () == AArch64::PTEST_PP_ANY)
1401
- return PredOpcode;
1416
+ return std::make_pair ( PredOpcode, Pred) ;
1402
1417
}
1403
1418
1404
1419
// For PTEST(PG, PTEST_LIKE(PG, ...)), the PTEST is redundant since the
@@ -1427,7 +1442,7 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1427
1442
uint64_t PredElementSize = getElementSizeForOpcode (PredOpcode);
1428
1443
if (Mask == PTestLikeMask && (PredElementSize == AArch64::ElementSizeB ||
1429
1444
PTest->getOpcode () == AArch64::PTEST_PP_ANY))
1430
- return PredOpcode;
1445
+ return std::make_pair ( PredOpcode, Pred) ;
1431
1446
1432
1447
return {};
1433
1448
}
@@ -1471,7 +1486,7 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1471
1486
return {};
1472
1487
}
1473
1488
1474
- return convertToFlagSettingOpc (PredOpcode);
1489
+ return std::make_pair ( convertToFlagSettingOpc (PredOpcode), Pred );
1475
1490
}
1476
1491
1477
1492
// / optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
@@ -1481,10 +1496,12 @@ bool AArch64InstrInfo::optimizePTestInstr(
1481
1496
const MachineRegisterInfo *MRI) const {
1482
1497
auto *Mask = MRI->getUniqueVRegDef (MaskReg);
1483
1498
auto *Pred = MRI->getUniqueVRegDef (PredReg);
1499
+ unsigned NewOp;
1484
1500
unsigned PredOpcode = Pred->getOpcode ();
1485
- auto NewOp = canRemovePTestInstr (PTest, Mask, Pred, MRI);
1486
- if (!NewOp )
1501
+ auto canRemove = canRemovePTestInstr (PTest, Mask, Pred, MRI);
1502
+ if (!canRemove )
1487
1503
return false ;
1504
+ std::tie (NewOp, Pred) = *canRemove;
1488
1505
1489
1506
const TargetRegisterInfo *TRI = &getRegisterInfo ();
1490
1507
@@ -1498,8 +1515,8 @@ bool AArch64InstrInfo::optimizePTestInstr(
1498
1515
// operand to be replaced with an equivalent instruction that also sets the
1499
1516
// flags.
1500
1517
PTest->eraseFromParent ();
1501
- if (* NewOp != PredOpcode) {
1502
- Pred->setDesc (get (* NewOp));
1518
+ if (NewOp != PredOpcode) {
1519
+ Pred->setDesc (get (NewOp));
1503
1520
bool succeeded = UpdateOperandRegClass (*Pred);
1504
1521
(void )succeeded;
1505
1522
assert (succeeded && " Operands have incompatible register classes!" );
@@ -1560,7 +1577,8 @@ bool AArch64InstrInfo::optimizeCompareInstr(
1560
1577
}
1561
1578
1562
1579
if (CmpInstr.getOpcode () == AArch64::PTEST_PP ||
1563
- CmpInstr.getOpcode () == AArch64::PTEST_PP_ANY)
1580
+ CmpInstr.getOpcode () == AArch64::PTEST_PP_ANY ||
1581
+ CmpInstr.getOpcode () == AArch64::PTEST_PP_FIRST)
1564
1582
return optimizePTestInstr (&CmpInstr, SrcReg, SrcReg2, MRI);
1565
1583
1566
1584
if (SrcReg2 != 0 )
0 commit comments