@@ -610,6 +610,32 @@ void SystemZInstrInfo::insertSelect(MachineBasicBlock &MBB,
610610 .addImm (CCValid).addImm (CCMask);
611611}
612612
613+ MachineInstr *SystemZInstrInfo::optimizeLoadInstr (MachineInstr &MI,
614+ const MachineRegisterInfo *MRI,
615+ Register &FoldAsLoadDefReg,
616+ MachineInstr *&DefMI) const {
617+ // Check whether we can move the DefMI load, and that it only has one use.
618+ DefMI = MRI->getVRegDef (FoldAsLoadDefReg);
619+ assert (DefMI);
620+ bool SawStore = false ;
621+ if (!DefMI->isSafeToMove (nullptr , SawStore) ||
622+ !MRI->hasOneNonDBGUse (FoldAsLoadDefReg))
623+ return nullptr ;
624+
625+ int UseOpIdx =
626+ MI.findRegisterUseOperandIdx (FoldAsLoadDefReg, /* TRI=*/ nullptr );
627+ assert (UseOpIdx != -1 && " Expected FoldAsLoadDefReg to be used by MI." );
628+
629+ // Check whether we can fold the load.
630+ if (MachineInstr *FoldMI =
631+ foldMemoryOperand (MI, {((unsigned )UseOpIdx)}, *DefMI)) {
632+ FoldAsLoadDefReg = 0 ;
633+ return FoldMI;
634+ }
635+
636+ return nullptr ;
637+ }
638+
613639bool SystemZInstrInfo::foldImmediate (MachineInstr &UseMI, MachineInstr &DefMI,
614640 Register Reg,
615641 MachineRegisterInfo *MRI) const {
@@ -1004,6 +1030,67 @@ SystemZInstrInfo::convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,
10041030 return nullptr ;
10051031}
10061032
1033+ bool SystemZInstrInfo::isAssociativeAndCommutative (const MachineInstr &Inst,
1034+ bool Invert) const {
1035+ unsigned Opc = Inst.getOpcode ();
1036+ if (Invert) {
1037+ auto InverseOpcode = getInverseOpcode (Opc);
1038+ if (!InverseOpcode)
1039+ return false ;
1040+ Opc = *InverseOpcode;
1041+ }
1042+
1043+ switch (Opc) {
1044+ default :
1045+ break ;
1046+ // Adds and multiplications.
1047+ case SystemZ::WFADB:
1048+ case SystemZ::WFASB:
1049+ case SystemZ::WFAXB:
1050+ case SystemZ::VFADB:
1051+ case SystemZ::VFASB:
1052+ case SystemZ::WFMDB:
1053+ case SystemZ::WFMSB:
1054+ case SystemZ::WFMXB:
1055+ case SystemZ::VFMDB:
1056+ case SystemZ::VFMSB:
1057+ return (Inst.getFlag (MachineInstr::MIFlag::FmReassoc) &&
1058+ Inst.getFlag (MachineInstr::MIFlag::FmNsz));
1059+ }
1060+
1061+ return false ;
1062+ }
1063+
1064+ std::optional<unsigned >
1065+ SystemZInstrInfo::getInverseOpcode (unsigned Opcode) const {
1066+ // fadd => fsub
1067+ switch (Opcode) {
1068+ case SystemZ::WFADB:
1069+ return SystemZ::WFSDB;
1070+ case SystemZ::WFASB:
1071+ return SystemZ::WFSSB;
1072+ case SystemZ::WFAXB:
1073+ return SystemZ::WFSXB;
1074+ case SystemZ::VFADB:
1075+ return SystemZ::VFSDB;
1076+ case SystemZ::VFASB:
1077+ return SystemZ::VFSSB;
1078+ // fsub => fadd
1079+ case SystemZ::WFSDB:
1080+ return SystemZ::WFADB;
1081+ case SystemZ::WFSSB:
1082+ return SystemZ::WFASB;
1083+ case SystemZ::WFSXB:
1084+ return SystemZ::WFAXB;
1085+ case SystemZ::VFSDB:
1086+ return SystemZ::VFADB;
1087+ case SystemZ::VFSSB:
1088+ return SystemZ::VFASB;
1089+ default :
1090+ return std::nullopt ;
1091+ }
1092+ }
1093+
10071094MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl (
10081095 MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned > Ops,
10091096 MachineBasicBlock::iterator InsertPt, int FrameIndex,
@@ -1338,7 +1425,83 @@ MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl(
13381425 MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned > Ops,
13391426 MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI,
13401427 LiveIntervals *LIS) const {
1341- return nullptr ;
1428+ MachineRegisterInfo *MRI = &MF.getRegInfo ();
1429+ MachineBasicBlock *MBB = MI.getParent ();
1430+
1431+ // For reassociable FP operations, any loads have been purposefully left
1432+ // unfolded so that MachineCombiner can do its work on reg/reg
1433+ // opcodes. After that, as many loads as possible are now folded.
1434+ // TODO: This may be beneficial with other opcodes as well as machine-sink
1435+ // can move loads close to their user in a different MBB, which the isel
1436+ // matcher did not see.
1437+ unsigned LoadOpc = 0 ;
1438+ unsigned RegMemOpcode = 0 ;
1439+ const TargetRegisterClass *FPRC = nullptr ;
1440+ RegMemOpcode = MI.getOpcode () == SystemZ::WFADB ? SystemZ::ADB
1441+ : MI.getOpcode () == SystemZ::WFSDB ? SystemZ::SDB
1442+ : MI.getOpcode () == SystemZ::WFMDB ? SystemZ::MDB
1443+ : 0 ;
1444+ if (RegMemOpcode) {
1445+ LoadOpc = SystemZ::VL64;
1446+ FPRC = &SystemZ::FP64BitRegClass;
1447+ } else {
1448+ RegMemOpcode = MI.getOpcode () == SystemZ::WFASB ? SystemZ::AEB
1449+ : MI.getOpcode () == SystemZ::WFSSB ? SystemZ::SEB
1450+ : MI.getOpcode () == SystemZ::WFMSB ? SystemZ::MEEB
1451+ : 0 ;
1452+ if (RegMemOpcode) {
1453+ LoadOpc = SystemZ::VL32;
1454+ FPRC = &SystemZ::FP32BitRegClass;
1455+ }
1456+ }
1457+ if (!RegMemOpcode || LoadMI.getOpcode () != LoadOpc)
1458+ return nullptr ;
1459+
1460+ // If RegMemOpcode clobbers CC, first make sure CC is not live at this point.
1461+ if (get (RegMemOpcode).hasImplicitDefOfPhysReg (SystemZ::CC)) {
1462+ assert (LoadMI.getParent () == MI.getParent () && " Assuming a local fold." );
1463+ assert (LoadMI != InsertPt && " Assuming InsertPt not to be first in MBB." );
1464+ for (MachineBasicBlock::iterator MII = std::prev (InsertPt);;
1465+ --MII) {
1466+ if (MII->definesRegister (SystemZ::CC, /* TRI=*/ nullptr )) {
1467+ if (!MII->registerDefIsDead (SystemZ::CC, /* TRI=*/ nullptr ))
1468+ return nullptr ;
1469+ break ;
1470+ }
1471+ if (MII == MBB->begin ()) {
1472+ if (MBB->isLiveIn (SystemZ::CC))
1473+ return nullptr ;
1474+ break ;
1475+ }
1476+ }
1477+ }
1478+
1479+ Register FoldAsLoadDefReg = LoadMI.getOperand (0 ).getReg ();
1480+ if (Ops.size () != 1 || FoldAsLoadDefReg != MI.getOperand (Ops[0 ]).getReg ())
1481+ return nullptr ;
1482+ Register DstReg = MI.getOperand (0 ).getReg ();
1483+ MachineOperand LHS = MI.getOperand (1 );
1484+ MachineOperand RHS = MI.getOperand (2 );
1485+ MachineOperand &RegMO = RHS.getReg () == FoldAsLoadDefReg ? LHS : RHS;
1486+ if ((RegMemOpcode == SystemZ::SDB || RegMemOpcode == SystemZ::SEB) &&
1487+ FoldAsLoadDefReg != RHS.getReg ())
1488+ return nullptr ;
1489+
1490+ MachineOperand &Base = LoadMI.getOperand (1 );
1491+ MachineOperand &Disp = LoadMI.getOperand (2 );
1492+ MachineOperand &Indx = LoadMI.getOperand (3 );
1493+ MachineInstrBuilder MIB =
1494+ BuildMI (*MI.getParent (), InsertPt, MI.getDebugLoc (), get (RegMemOpcode), DstReg)
1495+ .add (RegMO)
1496+ .add (Base)
1497+ .add (Disp)
1498+ .add (Indx);
1499+ MIB->addRegisterDead (SystemZ::CC, &RI);
1500+ MRI->setRegClass (DstReg, FPRC);
1501+ MRI->setRegClass (RegMO.getReg (), FPRC);
1502+ transferMIFlag (&MI, MIB, MachineInstr::NoFPExcept);
1503+
1504+ return MIB;
13421505}
13431506
13441507bool SystemZInstrInfo::expandPostRAPseudo (MachineInstr &MI) const {
0 commit comments