@@ -1183,6 +1183,7 @@ bool AArch64InstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
1183
1183
break ;
1184
1184
case AArch64::PTEST_PP:
1185
1185
case AArch64::PTEST_PP_ANY:
1186
+ case AArch64::PTEST_PP_FIRST:
1186
1187
SrcReg = MI.getOperand (0 ).getReg ();
1187
1188
SrcReg2 = MI.getOperand (1 ).getReg ();
1188
1189
// Not sure about the mask and value for now...
@@ -1354,12 +1355,25 @@ static bool areCFlagsAccessedBetweenInstrs(
1354
1355
return false ;
1355
1356
}
1356
1357
1357
- std::pair <bool , unsigned >
1358
+ std::tuple <bool , unsigned , MachineInstr * >
1358
1359
AArch64InstrInfo::canRemovePTestInstr (MachineInstr *PTest, MachineInstr *Mask,
1359
1360
MachineInstr *Pred,
1360
1361
const MachineRegisterInfo *MRI) const {
1361
1362
unsigned MaskOpcode = Mask->getOpcode ();
1362
1363
unsigned PredOpcode = Pred->getOpcode ();
1364
+
1365
+ // Handle a COPY from the LSB of the results of paired WHILEcc instruction.
1366
+ if ((PredOpcode == TargetOpcode::COPY &&
1367
+ Pred->getOperand (1 ).getSubReg () == AArch64::psub0) ||
1368
+ // Handle unpack of the LSB of the result of a WHILEcc instruction.
1369
+ PredOpcode == AArch64::PUNPKLO_PP) {
1370
+ MachineInstr *MI = MRI->getUniqueVRegDef (Pred->getOperand (1 ).getReg ());
1371
+ if (MI && isWhileOpcode (MI->getOpcode ())) {
1372
+ Pred = MI;
1373
+ PredOpcode = MI->getOpcode ();
1374
+ }
1375
+ }
1376
+
1363
1377
bool PredIsPTestLike = isPTestLikeOpcode (PredOpcode);
1364
1378
bool PredIsWhileLike = isWhileOpcode (PredOpcode);
1365
1379
@@ -1368,17 +1382,18 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1368
1382
// instruction and the condition is "any" since WHILcc does an implicit
1369
1383
// PTEST(ALL, PG) check and PG is always a subset of ALL.
1370
1384
if ((Mask == Pred) && PTest->getOpcode () == AArch64::PTEST_PP_ANY)
1371
- return {true , 0 };
1385
+ return {true , 0 , Pred };
1372
1386
1373
- // For PTEST(PTRUE_ALL, WHILE), if the element size matches, the PTEST is
1374
- // redundant since WHILE performs an implicit PTEST with an all active
1375
- // mask .
1387
+ // For PTEST(PTRUE_ALL, WHILE), since WHILE performs an implicit PTEST
1388
+ // with an all active mask, the PTEST is redundant if ether the element
1389
+ // size matches or the PTEST condition is "first" .
1376
1390
if (isPTrueOpcode (MaskOpcode) && Mask->getOperand (1 ).getImm () == 31 &&
1377
- getElementSizeForOpcode (MaskOpcode) ==
1378
- getElementSizeForOpcode (PredOpcode))
1379
- return {true , 0 };
1391
+ (PTest->getOpcode () == AArch64::PTEST_PP_FIRST ||
1392
+ getElementSizeForOpcode (MaskOpcode) ==
1393
+ getElementSizeForOpcode (PredOpcode)))
1394
+ return {true , 0 , Pred};
1380
1395
1381
- return {false , 0 };
1396
+ return {false , 0 , nullptr };
1382
1397
}
1383
1398
1384
1399
if (PredIsPTestLike) {
@@ -1387,7 +1402,7 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1387
1402
// "any" since PG is always a subset of the governing predicate of the
1388
1403
// ptest-like instruction.
1389
1404
if ((Mask == Pred) && PTest->getOpcode () == AArch64::PTEST_PP_ANY)
1390
- return {true , 0 };
1405
+ return {true , 0 , Pred };
1391
1406
1392
1407
// For PTEST(PTRUE_ALL, PTEST_LIKE), the PTEST is redundant if the
1393
1408
// the element size matches and either the PTEST_LIKE instruction uses
@@ -1397,7 +1412,7 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1397
1412
getElementSizeForOpcode (PredOpcode)) {
1398
1413
auto PTestLikeMask = MRI->getUniqueVRegDef (Pred->getOperand (1 ).getReg ());
1399
1414
if (Mask == PTestLikeMask || PTest->getOpcode () == AArch64::PTEST_PP_ANY)
1400
- return {true , 0 };
1415
+ return {true , 0 , Pred };
1401
1416
}
1402
1417
1403
1418
// For PTEST(PG, PTEST_LIKE(PG, ...)), the PTEST is redundant since the
@@ -1426,9 +1441,9 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1426
1441
uint64_t PredElementSize = getElementSizeForOpcode (PredOpcode);
1427
1442
if (Mask == PTestLikeMask && (PredElementSize == AArch64::ElementSizeB ||
1428
1443
PTest->getOpcode () == AArch64::PTEST_PP_ANY))
1429
- return {true , 0 };
1444
+ return {true , 0 , Pred };
1430
1445
1431
- return {false , 0 };
1446
+ return {false , 0 , nullptr };
1432
1447
}
1433
1448
1434
1449
// If OP in PTEST(PG, OP(PG, ...)) has a flag-setting variant change the
@@ -1450,7 +1465,7 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1450
1465
// may be different and we can't remove the ptest.
1451
1466
auto *PredMask = MRI->getUniqueVRegDef (Pred->getOperand (1 ).getReg ());
1452
1467
if (Mask != PredMask)
1453
- return {false , 0 };
1468
+ return {false , 0 , nullptr };
1454
1469
break ;
1455
1470
}
1456
1471
case AArch64::BRKN_PPzP: {
@@ -1459,18 +1474,18 @@ AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1459
1474
// PTEST(PTRUE_B(31), BRKN(PG, A, B)) -> BRKNS(PG, A, B).
1460
1475
if ((MaskOpcode != AArch64::PTRUE_B) ||
1461
1476
(Mask->getOperand (1 ).getImm () != 31 ))
1462
- return {false , 0 };
1477
+ return {false , 0 , nullptr };
1463
1478
break ;
1464
1479
}
1465
1480
case AArch64::PTRUE_B:
1466
1481
// PTEST(OP=PTRUE_B(A), OP) -> PTRUES_B(A)
1467
1482
break ;
1468
1483
default :
1469
1484
// Bail out if we don't recognize the input
1470
- return {false , 0 };
1485
+ return {false , 0 , nullptr };
1471
1486
}
1472
1487
1473
- return {true , convertToFlagSettingOpc (PredOpcode)};
1488
+ return {true , convertToFlagSettingOpc (PredOpcode), Pred };
1474
1489
}
1475
1490
1476
1491
// / optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
@@ -1480,7 +1495,10 @@ bool AArch64InstrInfo::optimizePTestInstr(
1480
1495
const MachineRegisterInfo *MRI) const {
1481
1496
auto *Mask = MRI->getUniqueVRegDef (MaskReg);
1482
1497
auto *Pred = MRI->getUniqueVRegDef (PredReg);
1483
- auto [canRemove, NewOp] = canRemovePTestInstr (PTest, Mask, Pred, MRI);
1498
+ bool canRemove;
1499
+ unsigned NewOp;
1500
+ std::tie (canRemove, NewOp, Pred) =
1501
+ canRemovePTestInstr (PTest, Mask, Pred, MRI);
1484
1502
if (!canRemove)
1485
1503
return false ;
1486
1504
@@ -1558,7 +1576,8 @@ bool AArch64InstrInfo::optimizeCompareInstr(
1558
1576
}
1559
1577
1560
1578
if (CmpInstr.getOpcode () == AArch64::PTEST_PP ||
1561
- CmpInstr.getOpcode () == AArch64::PTEST_PP_ANY)
1579
+ CmpInstr.getOpcode () == AArch64::PTEST_PP_ANY ||
1580
+ CmpInstr.getOpcode () == AArch64::PTEST_PP_FIRST)
1562
1581
return optimizePTestInstr (&CmpInstr, SrcReg, SrcReg2, MRI);
1563
1582
1564
1583
if (SrcReg2 != 0 )
0 commit comments