Index: llvm/lib/Target/SystemZ/SystemZHazardRecognizer.h =================================================================== --- llvm/lib/Target/SystemZ/SystemZHazardRecognizer.h +++ llvm/lib/Target/SystemZ/SystemZHazardRecognizer.h @@ -45,6 +45,8 @@ class SystemZHazardRecognizer : public ScheduleHazardRecognizer { const SystemZInstrInfo *TII; + std::string getSideSteerResourceName(unsigned ID) const; + const TargetRegisterInfo *TRI; const TargetSchedModel *SchedModel; /// Keep track of the number of decoder slots used in the current @@ -88,6 +90,69 @@ /// when a stalling operation is scheduled (which uses the FPd resource). unsigned LastFPdOpCycleIdx; + // There is no enum list generated for the processor resources by tablegen, + // so make one here for the needed ones. + enum ProcRes { B2BRW = 1, B2BRn = 2, B2BnW = 3, LSU = 6 }; + bool usesProcRes(SUnit *SU, ProcRes ProcResIdx) const; + bool readsB2BVector(SUnit *SU) const { + return usesProcRes(SU, ProcRes::B2BRW) || usesProcRes(SU, ProcRes::B2BRn); + } + bool writesB2BVector(SUnit *SU) const { + return usesProcRes(SU, ProcRes::B2BRW) || usesProcRes(SU, ProcRes::B2BnW); + } + bool isB2BOpIdx(SUnit *SU, unsigned Idx) const; + bool isB2BOpIdx(SUnit *SU, unsigned Idx, bool Def) const; + bool isB2BOpReg(SUnit *SU, Register Reg, bool Def) const; + bool isB2BEdge(SUnit *SU, SUnit *SuccSU, Register Reg) const; + bool isCountedProcResource(unsigned PIdx) const { + return !(PIdx == ProcRes::B2BRW || PIdx == ProcRes::B2BRn || + PIdx == ProcRes::B2BnW); + } + + std::map B2BWSides; + bool willGoLeft(SUnit *SU) const { return getCurrCycleIdx(SU) < 3; } + bool wasScheduledLeft(SUnit *SU) const { + std::map::const_iterator I = B2BWSides.find(SU); + assert(I != B2BWSides.end() && "SU not scheduled?"); + return I->second; + } + bool isWaitingFor(SUnit *SU, SUnit *SuccSU, SUnit *SUPred = nullptr) const; + bool isAvailable(SUnit *SU) const; + + SUnit *findOtherPred(SUnit *User, SUnit *Candidate) const; + enum UserType { Waiting, WaitingPlus1Avail, WaitingPlus1Same, + WaitingPlus1Other, Other }; + UserType checkB2BUser(SUnit *User, SUnit *Candidate, Register Reg) const; + int B2BWriteCost(SUnit *SU, bool More = true) const; + + struct LookAhead_GroupMetrics { + int B2BReads; + int B2BReadersOutside; + unsigned NumDecoderSlots; + LookAhead_GroupMetrics() : B2BReads(0), B2BReadersOutside(0), + NumDecoderSlots(0) {} + int worth() const { return B2BReads; } // - B2BReadersOutside; } + bool betterThan(LookAhead_GroupMetrics &Other) const { + return worth() > Other.worth(); + } + void reset() { + B2BReads = 0; + B2BReadersOutside = 0; + } + }; + std::vector LA_Scheduled; + unsigned LA_GroupSize; + LookAhead_GroupMetrics CurrBest; + LookAhead_GroupMetrics NextBest; + void flipLADefs(); + unsigned LookAhead_getFirstIdx(); + void LookAhead_evalSU(SUnit *SU, bool FlipSide, LookAhead_GroupMetrics &C); + void LookAhead_eval(); + void LookAhead_scheduleSU(SUnit *SU); + bool LookAhead_trySchedule(SUnit *SU); + void LookAhead_tryScheduleSuccessors(SUnit *SU); + void LookAhead_unScheduleTo(SUnit *SU); + /// A counter of decoder groups scheduled. unsigned GrpCount; @@ -108,9 +173,25 @@ public: SystemZHazardRecognizer(const SystemZInstrInfo *tii, + const TargetRegisterInfo *tri, const TargetSchedModel *SM) - : TII(tii), SchedModel(SM) { + : TII(tii), TRI(tri), SchedModel(SM) { Reset(); + +#ifndef NDEBUG + const MCProcResourceDesc *PRD = SchedModel->getProcResource(ProcRes::B2BRW); + assert(std::string(PRD->Name).find("B2BRW") != std::string::npos && + "Bad ProcRes enum mapping"); + PRD = SchedModel->getProcResource(ProcRes::B2BRn); + assert(std::string(PRD->Name).find("B2BRn") != std::string::npos && + "Bad ProcRes enum mapping"); + PRD = SchedModel->getProcResource(ProcRes::B2BnW); + assert(std::string(PRD->Name).find("B2BnW") != std::string::npos && + "Bad ProcRes enum mapping"); + PRD = SchedModel->getProcResource(ProcRes::LSU); + assert(std::string(PRD->Name).find("LSU") != std::string::npos && + "Bad ProcRes enum mapping"); +#endif } HazardType getHazardType(SUnit *SU, int Stalls = 0) override; @@ -141,6 +222,61 @@ /// a negative value means it would be good to schedule SU next. int resourcesCost(SUnit *SU); + struct B2B_Cost { + bool Heuristical; + int HeuristicVal; + LookAhead_GroupMetrics CurrBest; + LookAhead_GroupMetrics NextBest; + bool HasB2BEdge; + bool OnFirstSlot; + bool OnLastSlot; + B2B_Cost() : Heuristical(true), HeuristicVal(0) {} + B2B_Cost(int HV) : Heuristical(true), HeuristicVal(HV) {} + B2B_Cost(LookAhead_GroupMetrics CB, LookAhead_GroupMetrics NB, bool HBE, + bool OFS, bool OLS) : Heuristical(false), HeuristicVal(0), + CurrBest(CB), NextBest(NB), HasB2BEdge(HBE), + OnFirstSlot(OFS), OnLastSlot(OLS) {} + bool isNoCost() const { + if (Heuristical) + return HeuristicVal == -3; + return false; + } + int getSidePref() const { + int C = -CurrBest.worth() + NextBest.worth(); + return HasB2BEdge ? C : (C < 0 ? C : 0); + } + bool isOnFirstCase() const { + return OnFirstSlot && CurrBest.NumDecoderSlots >= 3 && + getSidePref() <= 0 && CurrBest.worth() > 0; + } + bool betterThan(const B2B_Cost &Other) const; + +#ifndef NDEBUG + void dump() { + if (Heuristical && HeuristicVal != 0) + dbgs() << " B2BCost:" << HeuristicVal; + if (!Heuristical) { + int SidePref = getSidePref(); + bool OnFirstCase = isOnFirstCase(); + int W = CurrBest.worth(); + if (SidePref || OnFirstCase || W) + dbgs() << " B2B"; + if (W) + dbgs() << " -" << W; + if (SidePref != 0) + dbgs() << " SidePref:" << SidePref; + if (OnFirstCase) + dbgs() << " Slot0"; + } + } +#endif + }; + + B2B_Cost B2BCost(SUnit *SU); + void B2BReadCost(SUnit *SU, unsigned &NumGood, unsigned &NumBad, + bool FlipSide = false) const; + void clearSUMappings() { B2BWSides.clear(); } + #ifndef NDEBUG // Debug dumping. std::string CurGroupDbg; // current group as text Index: llvm/lib/Target/SystemZ/SystemZHazardRecognizer.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZHazardRecognizer.cpp +++ llvm/lib/Target/SystemZ/SystemZHazardRecognizer.cpp @@ -42,6 +42,13 @@ "resources during scheduling."), cl::init(8)); +// EXPERIMENTAL +#include "llvm/Support/CommandLine.h" +static cl::opt SIDESTEERING_LASTSLOT("sidesteer-lastslot", cl::init(false)); +static cl::opt SIDESTEERING_TRIANG("sidesteer-triang", cl::init(false)); +static cl::opt SIDESTEERING_LOOKAHEAD("sidesteer-lookahead", cl::init(false)); +static cl::opt DUMP_LA("dump-la", cl::init(false)); + unsigned SystemZHazardRecognizer:: getNumDecoderSlots(SUnit *SU) const { const MCSchedClassDesc *SC = getSchedClass(SU); @@ -73,6 +80,358 @@ return Idx; } +static bool isFXUReg(Register Reg) { + return (SystemZ::GRX32BitRegClass.contains(Reg) || + SystemZ::GR64BitRegClass.contains(Reg) || + SystemZ::GR128BitRegClass.contains(Reg)); +} + +static bool isFXUReg(const MachineOperand &MO) { return isFXUReg(MO.getReg()); } + +bool SystemZHazardRecognizer::usesProcRes(SUnit *SU, ProcRes ProcResIdx) const { + const MCSchedClassDesc *SC = getSchedClass(SU); + if (!SC->isValid()) + return false; + for (TargetSchedModel::ProcResIter + PI = SchedModel->getWriteProcResBegin(SC), + PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) + if (PI->ProcResourceIdx == ProcResIdx) + return true; + return false; +} + +bool SystemZHazardRecognizer::isB2BOpIdx(SUnit *SU, unsigned Idx) const { + MachineInstr *MI = SU->getInstr(); + return MI->getOperand(Idx).isReg() && + isB2BOpIdx(SU, Idx, MI->getOperand(Idx).isDef()); +} + +bool SystemZHazardRecognizer:: +isB2BOpIdx(SUnit *SU, unsigned Idx, bool Def) const { + MachineInstr *MI = SU->getInstr(); + // A memory operand handled by the LSU is not back-to-back. + const MCInstrDesc &MCID = MI->getDesc(); + if (Idx >= MCID.getNumOperands()) + return false; + if (MCID.OpInfo[Idx].OperandType == MCOI::OPERAND_MEMORY && + usesProcRes(SU, ProcRes::LSU)) + return false; + + const MachineOperand &MO = MI->getOperand(Idx); + if (!MO.isReg() || !MO.getReg() || MO.isImplicit() || Def != MO.isDef() || + !isFXUReg(MO)) + return false; + return ((!Def && readsB2BVector(SU)) || (Def && writesB2BVector(SU))); +} + +bool SystemZHazardRecognizer:: +isB2BOpReg(SUnit *SU, Register Reg, bool Def) const { + MachineInstr *MI = SU->getInstr(); + for (unsigned Idx = 0; Idx < MI->getNumExplicitOperands(); ++Idx) { + MachineOperand &MO = MI->getOperand(Idx); + if (MO.isReg() && + ((Def && TRI->regsOverlap(MO.getReg(), Reg)) || + (!Def && MO.getReg() == Reg)) && + isB2BOpIdx(SU, Idx, Def)) + return true; + } + return false; +} + +bool SystemZHazardRecognizer:: +isB2BEdge(SUnit *SU, SUnit *SuccSU, Register Reg) const { + // Check the difference in height in order to ignore cases which are not on the CP. + // TODO: Try to check reachablility instead? Then a slightly lower but + // independent user could also perhaps be B2B...? + unsigned HeightDiff = SU->getHeight() - SuccSU->getHeight(); + return (HeightDiff <= SU->Latency && // Might be less due to read-advance. + isB2BOpReg(SU, Reg, true/*Def*/) && + isB2BOpReg(SuccSU, Reg, false/*Def*/)); +} + +bool SystemZHazardRecognizer:: +isWaitingFor(SUnit *SU, SUnit *SuccSU, SUnit *SUPred) const { + assert(SuccSU->isPred(SU)); + assert(SUPred == nullptr || SU->isPred(SUPred)); + for (SDep &Pred : SuccSU->Preds) { + SUnit *P = Pred.getSUnit(); + if (!P->isBoundaryNode() && P != SU && !P->isScheduled && P != SUPred) + return false; + } + return true; +} + +bool SystemZHazardRecognizer::isAvailable(SUnit *SU) const { + for (SDep &Pred : SU->Preds) { + SUnit *P = Pred.getSUnit(); + if (!P->isBoundaryNode() && !P->isScheduled) + return false; + } + return true; +} + +SUnit *SystemZHazardRecognizer:: +findOtherPred(SUnit *User, SUnit *Candidate) const { + assert(User->isPred(Candidate)); + SUnit *OtherPred = nullptr; + for (SDep &Pred : User->Preds) { + SUnit *P = Pred.getSUnit(); + if (P->isBoundaryNode() || P == Candidate) + continue; + if (OtherPred) { + if (P != OtherPred) + return nullptr; + continue; + } + if (getNumDecoderSlots(P) > 1 || !isAvailable(P)) + return nullptr; + OtherPred = P; + } + if (!SIDESTEERING_TRIANG && OtherPred && OtherPred->isPred(Candidate)) + return nullptr; + return OtherPred; +} + +SystemZHazardRecognizer::UserType SystemZHazardRecognizer:: +checkB2BUser(SUnit *User, SUnit *Candidate, Register Reg) const { + if (getSchedClass(User)->BeginGroup) + return UserType::Other; + + bool HasScheduledSameSide = false; + bool HasScheduledOtherSide = false; + SUnit *OtherPred = nullptr; + for (SDep &Pred : User->Preds) { + SUnit *P = Pred.getSUnit(); + if (P->isBoundaryNode() || P == Candidate) + continue; + + // User could have a scheduled B2BW predecessor. + if (P->isScheduled) { + if (Pred.getKind() == SDep::Data && isB2BEdge(P, User, Pred.getReg())) { + if (B2BWSides.count(P)) { + if (wasScheduledLeft(P) == willGoLeft(Candidate)) + HasScheduledSameSide = true; + else + HasScheduledOtherSide = true; + } + } + continue; + } + + // B2BW Candidate + // /\ /\ P2 + // \ \ + // \ OtherPred Scheduled Pred + // P \ /\ P .....: P + // \ / .......: + // B2BR User...: + // + // => [Candidate (OtherPred) User] (decoder group) + // Allow one other unscheduled predecessor than Candidate if it is + // available or only waiting for Candidate. + if (OtherPred) { + if (P != OtherPred) + return UserType::Other; + continue; + } + for (SDep &Pred2 : P->Preds) { + SUnit *P2 = Pred2.getSUnit(); + if (!P2->isBoundaryNode() && !P2->isScheduled) { + if (SIDESTEERING_TRIANG && P2 == Candidate) + continue; + return UserType::Other; + } + } + if (getSchedClass(P)->NumMicroOps > 1) + return UserType::Other; + OtherPred = P; + } + + if (OtherPred) + return UserType::WaitingPlus1Avail; + return (HasScheduledSameSide ? UserType::WaitingPlus1Same : + (HasScheduledOtherSide ? UserType::WaitingPlus1Other + : UserType::Waiting)); +} + +int SystemZHazardRecognizer::B2BWriteCost(SUnit *SU, bool More) const { + unsigned CurrIdx = getCurrCycleIdx(SU); + bool OnLastSlot = (CurrIdx == 2 || CurrIdx == 5); + bool OnFirstSlot = (CurrIdx == 0 || CurrIdx == 3); + + // Give an immediate user a chance into the same decoder group. + int MaxCost = 0; + int MinCost = 0; + for (SDep &SuccDep : SU->Succs) { + SUnit *SuccSU = SuccDep.getSUnit(); + if (!SuccSU->isBoundaryNode() && SuccDep.getKind() == SDep::Data && + isB2BEdge(SU, SuccSU, SuccDep.getReg())) { + UserType UserTy = checkB2BUser(SuccSU, SU, SuccDep.getReg()); + // Give negative cost if user could be put in same group. The value + // reflects the relative order between the types (e.g. better take + // WaitingPlus1 before Waiting on first slot). + int CurrCost = 0; + switch (UserTy) { + case UserType::Waiting: // Only waiting for SU + CurrCost = OnLastSlot ? 2 : -1; + break; + case UserType::WaitingPlus1Same: // Has op scheduled on same side. + if (More) + CurrCost = OnLastSlot ? 2 : -1; + break; + case UserType::WaitingPlus1Avail: // Waiting for SU and one available. + if (More) + CurrCost = OnFirstSlot ? -2 : 2; + break; + case UserType::WaitingPlus1Other: // Has op scheduled on other side. + if (More) + CurrCost = 2; + break; + case UserType::Other: break; + } + MaxCost = CurrCost > MaxCost ? CurrCost : MaxCost; + MinCost = CurrCost < MinCost ? CurrCost : MinCost; + } + } + // If there is a benefit, take it, or reject if better to wait. + return MinCost < 0 ? MinCost : MaxCost; +} + +void SystemZHazardRecognizer::flipLADefs() { + for (auto *SU : LA_Scheduled) { + std::map::iterator I = B2BWSides.find(SU); + if (I != B2BWSides.end()) + I->second ^= true; + } +} + +unsigned SystemZHazardRecognizer::LookAhead_getFirstIdx() { + unsigned Idx = 0; // Skip leading pseudo (e.g. KILL) instruction. + while (Idx < LA_Scheduled.size() && !getNumDecoderSlots(LA_Scheduled[Idx])) + Idx++; + return Idx; +} + +void SystemZHazardRecognizer:: +LookAhead_evalSU(SUnit *SU, bool FlipSide, LookAhead_GroupMetrics &C) { + unsigned NumGood = 0; + unsigned NumBad = 0; + B2BReadCost(SU, NumGood, NumBad, FlipSide); + if (!NumBad && NumGood) + C.B2BReads++; + else if (!NumGood && NumBad) + C.B2BReads--; + + if (isB2BOpIdx(SU, 0, true/*Def*/)) + for (SDep &SuccDep : SU->Succs) { + SUnit *SuccSU = SuccDep.getSUnit(); + if (!SuccSU->isBoundaryNode() && SuccDep.getKind() == SDep::Data && + isB2BEdge(SU, SuccSU, SuccDep.getReg())) { + if (!SuccSU->isScheduled && isAvailable(SuccSU)) + C.B2BReadersOutside++; // XXX B2BWriteOpsMixed + } + } +} + +void SystemZHazardRecognizer::LookAhead_eval() { + if (!LA_GroupSize) + return; + + // Current group + LookAhead_GroupMetrics CurrC; + unsigned FirstIdx = LookAhead_getFirstIdx(); + bool FlipCurr = + CurrGroupSize != 0 && getSchedClass(LA_Scheduled[FirstIdx])->BeginGroup; + if (FlipCurr) + flipLADefs(); + unsigned First = FlipCurr ? 0 : CurrGroupSize; + unsigned Size = First; + for (unsigned I = FirstIdx; I < LA_Scheduled.size(); I++) { + Size += getNumDecoderSlots(LA_Scheduled[I]); + LookAhead_evalSU(LA_Scheduled[I], FlipCurr, CurrC); + if (Size >= 3) + break; + } + if (CurrC.betterThan(CurrBest)) { + CurrBest = CurrC; + CurrBest.NumDecoderSlots = Size - First; + } + + // Next group + flipLADefs(); + bool FlipNext = !FlipCurr; + LookAhead_GroupMetrics NextC; + for (auto *SU : LA_Scheduled) + LookAhead_evalSU(SU, FlipNext, NextC); + if (NextC.betterThan(NextBest)) { + NextBest = NextC; + NextBest.NumDecoderSlots = LA_GroupSize; + } + if (!FlipCurr) + flipLADefs(); + + if (DUMP_LA) { + dbgs() << "++ B2B LookAhead (Current/Next): " << CurrBest.worth() + << "/" << NextBest.worth() << " [ "; + for (auto *SU : LA_Scheduled) + dbgs() << TII->getName(SU->getInstr()->getOpcode()) << "(" << SU->NodeNum << ") "; + dbgs() << "]\n"; + } +} + +void SystemZHazardRecognizer::LookAhead_scheduleSU(SUnit *SU) { + LA_GroupSize += getNumDecoderSlots(SU); + B2BWSides[SU] = willGoLeft(SU); + LA_Scheduled.push_back(SU); + SU->isScheduled = true; +} + +bool SystemZHazardRecognizer::LookAhead_trySchedule(SUnit *SU) { + if (SU->isBoundaryNode() || LA_GroupSize >= 3 || + (LA_GroupSize != 0 && getSchedClass(SU)->BeginGroup)) + return false; + if (!isAvailable(SU) && LA_GroupSize == 1 && + LookAhead_getFirstIdx() == LA_Scheduled.size() - 1) { + if (SUnit *OtherPred = findOtherPred(SU, LA_Scheduled.back())) { + LookAhead_scheduleSU(OtherPred); + assert(isAvailable(SU)); + } + } + if (!isAvailable(SU)) + return false; + LookAhead_scheduleSU(SU); + LookAhead_eval(); + return true; +} + +void SystemZHazardRecognizer::LookAhead_tryScheduleSuccessors(SUnit *SU) { + // Using a recursive function since KILL instruction might be present... + SmallPtrSet Seen; + for (SDep &SuccDep : SU->Succs) { + SUnit *S = SuccDep.getSUnit(); + if (Seen.insert(SU).second && LookAhead_trySchedule(S)) { + LookAhead_tryScheduleSuccessors(S); + LookAhead_unScheduleTo(SU); + } + } +} + +void SystemZHazardRecognizer::LookAhead_unScheduleTo(SUnit *SU) { + assert(!LA_Scheduled.empty()); + SUnit *B = LA_Scheduled.back(); + LA_Scheduled.pop_back(); + unsigned NumSlots = getNumDecoderSlots(B); + assert(LA_GroupSize >= NumSlots); + LA_GroupSize -= NumSlots; + B2BWSides.erase(B); + B->isScheduled = false; + assert((!SU || !LA_Scheduled.empty()) && "No scheduled SU left to match."); + if (SU && SU != LA_Scheduled.back()) + LookAhead_unScheduleTo(SU); + assert(((!SU && LA_Scheduled.empty()) || SU == LA_Scheduled.back()) && + "Bad unscheduling."); +} + ScheduleHazardRecognizer::HazardType SystemZHazardRecognizer:: getHazardType(SUnit *SU, int Stalls) { return (fitsIntoCurrentGroup(SU) ? NoHazard : Hazard); @@ -85,6 +444,7 @@ GrpCount = 0; LastFPdOpCycleIdx = UINT_MAX; LastEmittedMI = nullptr; + B2BWSides.clear(); LLVM_DEBUG(CurGroupDbg = "";); } @@ -165,8 +525,9 @@ #ifndef NDEBUG // Debug output void SystemZHazardRecognizer::dumpSU(SUnit *SU, raw_ostream &OS) const { + const MachineInstr *MI = SU->getInstr(); OS << "SU(" << SU->NodeNum << "):"; - OS << TII->getName(SU->getInstr()->getOpcode()); + OS << TII->getName(MI->getOpcode()); const MCSchedClassDesc *SC = getSchedClass(SU); if (!SC->isValid()) @@ -175,8 +536,10 @@ for (TargetSchedModel::ProcResIter PI = SchedModel->getWriteProcResBegin(SC), PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) { - const MCProcResourceDesc &PRD = - *SchedModel->getProcResource(PI->ProcResourceIdx); + unsigned PIdx = PI->ProcResourceIdx; + if (!isCountedProcResource(PIdx)) + continue; + const MCProcResourceDesc &PRD = *SchedModel->getProcResource(PIdx); std::string FU(PRD.Name); // trim e.g. Z13_FXaUnit -> FXa FU = FU.substr(FU.find('_') + 1); @@ -201,8 +564,14 @@ OS << "/EndsGroup"; if (SU->isUnbuffered) OS << "/Unbuffered"; - if (has4RegOps(SU->getInstr())) + if (has4RegOps(MI)) OS << "/4RegOps"; + + if (isB2BOpIdx(SU, 0, true/*Def*/)) + OS << "/" << TRI->getName(MI->getOperand(0).getReg()) << ":B2BW"; + for (unsigned Idx = 0; Idx < MI->getNumOperands(); ++Idx) + if (isB2BOpIdx(SU, Idx, false/*Def*/)) + OS << "/" << TRI->getName(MI->getOperand(Idx).getReg()) << ":B2BR"; } void SystemZHazardRecognizer::dumpCurrGroup(std::string Msg) const { @@ -247,8 +616,8 @@ void SystemZHazardRecognizer::dumpState() const { dumpCurrGroup("| Current decoder group"); - dbgs() << "++ | Current cycle index: " - << getCurrCycleIdx() << "\n"; + dbgs() << "++ | Current side: " << (getCurrCycleIdx() < 3 ? "Left" : "Right") + << "\n"; dumpProcResourceCounters(); if (LastFPdOpCycleIdx != UINT_MAX) dbgs() << "++ | Last FPd cycle index: " << LastFPdOpCycleIdx << "\n"; @@ -299,6 +668,8 @@ // Don't handle FPd together with the other resources. if (SchedModel->getProcResource(PI->ProcResourceIdx)->BufferSize == 1) continue; + if (!isCountedProcResource(PI->ProcResourceIdx)) + continue; int &CurrCounter = ProcResourceCounters[PI->ProcResourceIdx]; CurrCounter += PI->Cycles; @@ -323,6 +694,9 @@ << "\n";); } + if (isB2BOpIdx(SU, 0, true/*Def*/)) + B2BWSides[SU] = willGoLeft(SU); + // Insert SU into current group by increasing number of slots used // in current group. CurrGroupSize += getNumDecoderSlots(SU); @@ -407,6 +781,123 @@ return Cost; } +void SystemZHazardRecognizer::B2BReadCost(SUnit *SU, unsigned &NumGood, + unsigned &NumBad, bool FlipSide) const { + int RegsSameSide = 0; + int RegsOppositeSide = 0; + for (SDep &Pred : SU->Preds) { + SUnit *P = Pred.getSUnit(); + if (Pred.getKind() == SDep::Data && isB2BEdge(P, SU, Pred.getReg())) { + if (B2BWSides.count(P)) { + if (wasScheduledLeft(P) == (willGoLeft(SU) ^ FlipSide)) + RegsSameSide++; + else + RegsOppositeSide++; + } + } + } + NumGood = RegsSameSide; + NumBad = RegsOppositeSide; +} + +bool SystemZHazardRecognizer::B2B_Cost::betterThan(const B2B_Cost &Other) const { + if (Heuristical) + return HeuristicVal < Other.HeuristicVal; + + // Check if makes sense to take one before the other. + int SidePref = getSidePref(); + int SidePref_Other = Other.getSidePref(); + if (SidePref < SidePref_Other) + return true; + if ( SidePref > SidePref_Other) + return false; + + int Worth = CurrBest.worth(); + int Worth_Other = Other.CurrBest.worth(); + // if (Worth > Worth_Other) + // return true; + // if (Worth < Worth_Other) + // return false; + if (Worth > 0 && Worth_Other == 0) + return true; + if (Worth == 0 && Worth_Other > 0) + return false; + + // This needs the first slot while the other does not. + if (isOnFirstCase() && Other.CurrBest.NumDecoderSlots < 3) + return true; + + return false; +} + +SystemZHazardRecognizer::B2B_Cost SystemZHazardRecognizer::B2BCost(SUnit *SU) { + unsigned CurrIdx = getCurrCycleIdx(SU); + bool OnLastSlot = (CurrIdx == 2 || CurrIdx == 5); + bool OnFirstSlot = (CurrIdx == 0 || CurrIdx == 3); + + if (SIDESTEERING_LOOKAHEAD) { + LA_Scheduled.clear(); + LA_GroupSize = 0; + CurrBest.reset(); + NextBest.reset(); + + if (LookAhead_trySchedule(SU)) { + LookAhead_tryScheduleSuccessors(SU); + LookAhead_unScheduleTo(nullptr); + } + assert(LA_Scheduled.empty() && "Bad state after lookahead."); + assert(LA_GroupSize == 0 && "Bad state after lookahead."); + bool HasB2BEdge = false; + for (unsigned Idx = 0; Idx < SU->getInstr()->getNumExplicitOperands(); ++Idx) + if (isB2BOpIdx(SU, Idx)) { + HasB2BEdge = true; + break; + } + return B2B_Cost(CurrBest, NextBest, HasB2BEdge, OnFirstSlot, OnLastSlot); + } + + // Put B2BR register use on same side as previous def(s). + unsigned NumGood = 0; + unsigned NumBad = 0; + B2BReadCost(SU, NumGood, NumBad); + if (!NumBad && NumGood) + return B2B_Cost(-3); + if (!NumGood && NumBad) + return B2B_Cost(3); + + if (!SIDESTEERING_LASTSLOT) + return B2B_Cost(0); + + int WriteCost = B2BWriteCost(SU); + if (WriteCost != 0) + return B2B_Cost(WriteCost); + + // If SU would make a successor B2B read available in same group, schedule it. + for (SDep &SuccDep : SU->Succs) { + SUnit *SuccSU = SuccDep.getSUnit(); + if (!OnLastSlot && !SuccSU->isBoundaryNode() && + !getSchedClass(SuccSU)->BeginGroup && isWaitingFor(SU, SuccSU)) { + B2BReadCost(SuccSU, NumGood, NumBad); + if (!NumBad && NumGood) + return B2B_Cost(-1); + if (OnFirstSlot && B2BWriteCost(SuccSU, false) == -1) + return B2B_Cost(-1); + if (OnFirstSlot) + for (SDep &S2Dep : SuccSU->Succs) { + SUnit *S2SU = S2Dep.getSUnit(); + if (!S2SU->isBoundaryNode() && + !getSchedClass(S2SU)->BeginGroup && isWaitingFor(SuccSU, S2SU, SU)) { + B2BReadCost(S2SU, NumGood, NumBad); + if (!NumBad && NumGood) + return B2B_Cost(-1); + } + } + } + } + + return B2B_Cost(0); +} + void SystemZHazardRecognizer::emitInstruction(MachineInstr *MI, bool TakenBranch) { // Make a temporary SUnit. Index: llvm/lib/Target/SystemZ/SystemZMachineScheduler.h =================================================================== --- llvm/lib/Target/SystemZ/SystemZMachineScheduler.h +++ llvm/lib/Target/SystemZ/SystemZMachineScheduler.h @@ -31,6 +31,7 @@ const MachineLoopInfo *MLI; const SystemZInstrInfo *TII; + const TargetRegisterInfo *TRI; // A SchedModel is needed before any DAG is built while advancing past // non-scheduled instructions, so it would not always be possible to call @@ -47,6 +48,9 @@ /// The processor resources cost. int ResourcesCost = 0; + /// The (negative) B2B cost of FXU registers. + SystemZHazardRecognizer::B2B_Cost B2BCost; + Candidate() = default; Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec); @@ -54,8 +58,14 @@ bool operator<(const Candidate &other); // Check if this node is free of cost ("as good as any"). - bool noCost() const { - return (GroupingCost <= 0 && !ResourcesCost); + bool noCost(unsigned &NumTried) const { + if (GroupingCost <= 0 && !ResourcesCost) { + if (B2BCost.isNoCost() || NumTried >= 6) + return true; + else + NumTried++; + } + return false; } #ifndef NDEBUG @@ -64,6 +74,7 @@ dbgs() << " Grouping cost:" << GroupingCost; if (ResourcesCost != 0) dbgs() << " Resource cost:" << ResourcesCost; + B2BCost.dump(); } #endif }; Index: llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp +++ llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp @@ -16,6 +16,7 @@ #include "SystemZMachineScheduler.h" #include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" using namespace llvm; @@ -73,6 +74,7 @@ void SystemZPostRASchedStrategy::initialize(ScheduleDAGMI *dag) { Available.clear(); // -misched-cutoff. + HazardRec->clearSUMappings(); LLVM_DEBUG(HazardRec->dumpState();); } @@ -82,18 +84,19 @@ LLVM_DEBUG(dbgs() << "** Entering " << printMBBReference(*NextMBB)); MBB = NextMBB; + const MachineLoop *Loop = MLI->getLoopFor(MBB); /// Create a HazardRec for MBB, save it in SchedStates and set HazardRec to /// point to it. - HazardRec = SchedStates[MBB] = new SystemZHazardRecognizer(TII, &SchedModel); - LLVM_DEBUG(const MachineLoop *Loop = MLI->getLoopFor(MBB); - if (Loop && Loop->getHeader() == MBB) dbgs() << " (Loop header)"; - dbgs() << ":\n";); + HazardRec = SchedStates[MBB] = new SystemZHazardRecognizer(TII, TRI, + &SchedModel); + LLVM_DEBUG(if(Loop && Loop->getHeader() == MBB) + dbgs() << " (Loop header)"; + dbgs() << ":\n";); // Try to take over the state from a single predecessor, if it has been // scheduled. If this is not possible, we are done. - MachineBasicBlock *SinglePredMBB = - getSingleSchedPred(MBB, MLI->getLoopFor(MBB)); + MachineBasicBlock *SinglePredMBB = getSingleSchedPred(MBB, Loop); if (SinglePredMBB == nullptr || SchedStates.find(SinglePredMBB) == SchedStates.end()) return; @@ -131,6 +134,7 @@ : MLI(C->MLI), TII(static_cast (C->MF->getSubtarget().getInstrInfo())), + TRI(C->MF->getRegInfo().getTargetRegisterInfo()), MBB(nullptr), HazardRec(nullptr) { const TargetSubtargetInfo *ST = &C->MF->getSubtarget(); SchedModel.init(ST); @@ -174,6 +178,7 @@ LLVM_DEBUG(dbgs() << "** Available: "; Available.dump(*HazardRec);); Candidate Best; + unsigned NumTried = 0; for (auto *SU : Available) { // SU is the next candidate to be compared against current Best. @@ -190,7 +195,7 @@ // Once we know we have seen all SUs that affect grouping or use unbuffered // resources, we can stop iterating if Best looks good. - if (!SU->isScheduleHigh && Best.noCost()) + if (!SU->isScheduleHigh && Best.noCost(NumTried)) break; } @@ -198,6 +203,10 @@ return Best.SU; } +// EXPERIMENTAL +#include "llvm/Support/CommandLine.h" +static cl::opt SIDESTEERING_FXU("sidesteer-fxu", cl::init(false)); + SystemZPostRASchedStrategy::Candidate:: Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec) : Candidate() { SU = SU_; @@ -209,6 +218,10 @@ // Check the resources cost for this SU. ResourcesCost = HazardRec.resourcesCost(SU); + + // Side steering + if (SIDESTEERING_FXU) + B2BCost = HazardRec.B2BCost(SU); } bool SystemZPostRASchedStrategy::Candidate:: @@ -226,6 +239,14 @@ if (ResourcesCost > other.ResourcesCost) return false; + // Try to help FXU bypassing. + if (true /*heightdiff / cutoff ??*/) { + if (B2BCost.betterThan(other.B2BCost)) + return true; + if (other.B2BCost.betterThan(B2BCost)) + return false; + } + // Higher SU is otherwise generally better. if (SU->getHeight() > other.SU->getHeight()) return true; @@ -242,7 +263,8 @@ void SystemZPostRASchedStrategy::schedNode(SUnit *SU, bool IsTopNode) { LLVM_DEBUG(dbgs() << "** Scheduling SU(" << SU->NodeNum << ") "; if (Available.size() == 1) dbgs() << "(only one) "; - Candidate c(SU, *HazardRec); c.dumpCosts(); dbgs() << "\n";); + // Candidate c(SU, *HazardRec); c.dumpCosts(); + dbgs() << "\n";); // Remove SU from Available set and update HazardRec. Available.erase(SU); Index: llvm/lib/Target/SystemZ/SystemZSchedule.td =================================================================== --- llvm/lib/Target/SystemZ/SystemZSchedule.td +++ llvm/lib/Target/SystemZ/SystemZSchedule.td @@ -59,6 +59,10 @@ def MCD : SchedWrite; // Millicode +def B2BRW : SchedWrite; // Reads and Writes the back-to-back vector. +def B2BRn : SchedWrite; // Reads the back-to-back vector. +def B2BnW : SchedWrite; // Writes the back-to-back vector. + include "SystemZScheduleZ15.td" include "SystemZScheduleZ14.td" include "SystemZScheduleZ13.td" Index: llvm/lib/Target/SystemZ/SystemZScheduleZ14.td =================================================================== --- llvm/lib/Target/SystemZ/SystemZScheduleZ14.td +++ llvm/lib/Target/SystemZ/SystemZScheduleZ14.td @@ -80,6 +80,9 @@ def Z14_VecFPdUnit : ProcResource<2> { let BufferSize = 1; /* blocking */ } def Z14_VBUnit : ProcResource<2>; def Z14_MCD : ProcResource<1>; +def Z14_B2BRW : ProcResource<6>; // Avoid becoming the critical resource +def Z14_B2BRn : ProcResource<6>; +def Z14_B2BnW : ProcResource<6>; // Subtarget specific definitions of scheduling resources. let NumMicroOps = 0 in { @@ -113,6 +116,12 @@ let BeginGroup = 1; let EndGroup = 1; } +let NumMicroOps = 0 in { + def : WriteRes {} + def : WriteRes {} + def : WriteRes {} +} + // -------------------------- INSTRUCTIONS ---------------------------------- // // InstRW constructs have been used in order to preserve the @@ -126,7 +135,7 @@ //===----------------------------------------------------------------------===// // Pseudo -> LA / LAY -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ADJDYNALLOC$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ADJDYNALLOC$")>; //===----------------------------------------------------------------------===// // Branch instructions @@ -138,7 +147,7 @@ def : InstRW<[WLat1, FXb, NormalGr], (instregex "(Call)?BC(R)?(Asm.*)?$")>; def : InstRW<[WLat1, FXb, NormalGr], (instregex "(Call)?B(R)?(Asm.*)?$")>; def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "BI(C)?(Asm.*)?$")>; -def : InstRW<[WLat1, FXa, EndGroup], (instregex "BRCT(G)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, EndGroup], (instregex "BRCT(G)?$")>; def : InstRW<[WLat1, FXa, FXb, GroupAlone], (instregex "BRCTH$")>; def : InstRW<[WLat1, FXa, FXb, GroupAlone], (instregex "BCT(G)?(R)?$")>; def : InstRW<[WLat1, FXa2, FXb2, GroupAlone2], @@ -167,10 +176,12 @@ //===----------------------------------------------------------------------===// // Call -def : InstRW<[WLat1, VBU, FXa2, GroupAlone], (instregex "(Call)?BRAS$")>; -def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL$")>; -def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?$")>; -def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "TLS_(G|L)DCALL$")>; +def : InstRW<[WLat1, VBU, FXa2, B2BRW, GroupAlone], (instregex "(Call)?BRAS$")>; +def : InstRW<[WLat1, FXa2, FXb, B2BRW, GroupAlone], (instregex "(Call)?BRASL$")>; +def : InstRW<[WLat1, FXa2, FXb, B2BRW, GroupAlone], + (instregex "(Call)?BAS(R)?$")>; +def : InstRW<[WLat1, FXa2, FXb, B2BRW, GroupAlone], + (instregex "TLS_(G|L)DCALL$")>; // Return def : InstRW<[WLat1, FXb, EndGroup], (instregex "Return$")>; @@ -189,10 +200,10 @@ def : InstRW<[WLat30, WLat30, WLat30, MCD], (instregex "MVCL(E|U)?$")>; // Pseudo -> reg move -def : InstRW<[WLat1, FXa, NormalGr], (instregex "COPY(_TO_REGCLASS)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "EXTRACT_SUBREG$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "INSERT_SUBREG$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "REG_SEQUENCE$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "COPY(_TO_REGCLASS)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "EXTRACT_SUBREG$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "INSERT_SUBREG$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "REG_SEQUENCE$")>; // Loads def : InstRW<[LSULatency, LSU, NormalGr], (instregex "L(Y|FH|RL|Mux)?$")>; @@ -200,12 +211,13 @@ def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LG(RL)?$")>; def : InstRW<[LSULatency, LSU, NormalGr], (instregex "L128$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LLIH(F|H|L)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LLIL(F|H|L)$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "LLI(H|L)F$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LLI(H|L)(H|L)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LG(F|H)I$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LHI(Mux)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LR$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "LGFI$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LGHI$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LHI(Mux)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LR$")>; // Load and zero rightmost byte def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LZR(F|G)$")>; @@ -214,8 +226,9 @@ def : InstRW<[WLat1LSU, FXb, LSU, NormalGr], (instregex "L(FH|G)?AT$")>; // Load and test -def : InstRW<[WLat1LSU, WLat1LSU, LSU, FXa, NormalGr], (instregex "LT(G)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LT(G)?R$")>; +def : InstRW<[WLat1LSU, WLat1LSU, LSU, FXa, B2BRW, NormalGr], + (instregex "LT(G)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LT(G)?R$")>; // Stores def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "STG(RL)?$")>; @@ -229,10 +242,11 @@ // Conditional move instructions //===----------------------------------------------------------------------===// -def : InstRW<[WLat2, FXa, NormalGr], (instregex "LOCRMux$")>; -def : InstRW<[WLat2, FXa, NormalGr], (instregex "LOC(G|FH)?R(Asm.*)?$")>; -def : InstRW<[WLat2, FXa, NormalGr], (instregex "LOC(G|H)?HI(Mux|(Asm.*))?$")>; -def : InstRW<[WLat2LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat2, FXa, B2BnW, NormalGr], (instregex "LOCRMux$")>; +def : InstRW<[WLat2, FXa, B2BnW, NormalGr], (instregex "LOC(G|FH)?R(Asm.*)?$")>; +def : InstRW<[WLat2, FXa, B2BnW, NormalGr], + (instregex "LOC(G|H)?HI(Mux|(Asm.*))?$")>; +def : InstRW<[WLat2LSU, RegReadAdv, FXa, LSU, B2BnW, NormalGr], (instregex "LOC(G|FH|Mux)?(Asm.*)?$")>; def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "STOC(G|FH|Mux)?(Asm.*)?$")>; @@ -241,28 +255,30 @@ // Sign extensions //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, FXa, NormalGr], (instregex "L(B|H|G)R$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LG(B|H|F)R$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "L(B|H|G)R$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LG(B|H|F)R$")>; -def : InstRW<[WLat1LSU, WLat1LSU, FXa, LSU, NormalGr], (instregex "LTGF$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LTGFR$")>; +def : InstRW<[WLat1LSU, WLat1LSU, FXa, LSU, B2BnW, NormalGr], + (instregex "LTGF$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LTGFR$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LB(H|Mux)?$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LH(Y)?$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LH(H|Mux|RL)$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LG(B|H|F)$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LG(H|F)RL$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LB(H|Mux)?$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LH(Y)?$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LH(H|Mux|RL)$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LGB$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BRW, NormalGr], (instregex "LG(H|F)$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LG(H|F)RL$")>; //===----------------------------------------------------------------------===// // Zero extensions //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LLCR(Mux)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LLHR(Mux)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LLG(C|H|F|T)R$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LLCR(Mux)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LLHR(Mux)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LLG(C|H|F|T)R$")>; def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LLC(Mux)?$")>; def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LLH(Mux)?$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LL(C|H)H$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LL(C|H)H$")>; def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LLHRL$")>; def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LLG(C|H|F|T|HRL|FRL)$")>; @@ -297,8 +313,8 @@ // Byte swaps //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LRV(G)?R$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LRV(G|H)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LRV(G)?R$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BRW, NormalGr], (instregex "LRV(G|H)?$")>; def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "STRV(G|H)?$")>; def : InstRW<[WLat30, MCD], (instregex "MVCIN$")>; @@ -306,223 +322,231 @@ // Load address instructions //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LA(Y|RL)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LA(Y)?$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "LARL?$")>; // Load the Global Offset Table address ( -> larl ) -def : InstRW<[WLat1, FXa, NormalGr], (instregex "GOT$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "GOT$")>; //===----------------------------------------------------------------------===// // Absolute and Negation //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, WLat1, FXa, NormalGr], (instregex "LP(G)?R$")>; -def : InstRW<[WLat2, WLat2, FXa2, Cracked], (instregex "L(N|P)GFR$")>; -def : InstRW<[WLat1, WLat1, FXa, NormalGr], (instregex "LN(R|GR)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LC(R|GR)$")>; -def : InstRW<[WLat2, WLat2, FXa2, Cracked], (instregex "LCGFR$")>; +def : InstRW<[WLat1, WLat1, FXa, B2BRW, NormalGr], (instregex "LP(G)?R$")>; +def : InstRW<[WLat2, WLat2, FXa2, B2BRW, Cracked], (instregex "L(N|P)GFR$")>; +def : InstRW<[WLat1, WLat1, FXa, B2BRW, NormalGr], (instregex "LN(R|GR)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LC(R|GR)$")>; +def : InstRW<[WLat2, WLat2, FXa2, B2BRW, Cracked], (instregex "LCGFR$")>; //===----------------------------------------------------------------------===// // Insertion //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], (instregex "IC(Y)?$")>; -def : InstRW<[WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], + (instregex "IC(Y)?$")>; +def : InstRW<[WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "IC32(Y)?$")>; -def : InstRW<[WLat1LSU, RegReadAdv, WLat1LSU, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, RegReadAdv, WLat1LSU, FXa, LSU, B2BRW, NormalGr], (instregex "ICM(H|Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "II(F|H|L)Mux$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IIHF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IIHH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IIHL(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IILF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IILH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IILL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "IIFMux$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "II(H|L)Mux$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "IIHF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "IIHH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "IIHL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "IILF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "IILH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "IILL(64)?$")>; //===----------------------------------------------------------------------===// // Addition //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "A(Y)?$")>; -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "AH(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AIH$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AFI(Mux)?$")>; -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AIH$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AFI(Mux)?$")>; +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "AG$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AGFI$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AGHI(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AHI(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AHIMux(K)?$")>; -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AGFI$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AGHI(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AHI(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AHIMux(K)?$")>; +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "AL(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AL(FI|HSIK)$")>; -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AL(FI|HSIK)$")>; +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "ALG(F)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ALGHSIK$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ALGF(I|R)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ALGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ALR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "A(L)?HHHR$")>; -def : InstRW<[WLat2, WLat2, FXa, NormalGr], (instregex "A(L)?HHLR$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ALSIH(N)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ALGHSIK$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ALGF(I|R)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ALGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ALR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "A(L)?HHHR$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BRW, NormalGr], (instregex "A(L)?HHLR$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ALSIH(N)?$")>; def : InstRW<[WLat2LSU, FXb, LSU, NormalGr], (instregex "A(L)?(G)?SI$")>; // Logical addition with carry -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, GroupAlone], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BnW, GroupAlone], (instregex "ALC(G)?$")>; -def : InstRW<[WLat2, WLat2, FXa, GroupAlone], (instregex "ALC(G)?R$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BnW, GroupAlone], (instregex "ALC(G)?R$")>; // Add with sign extension (16/32 -> 64) -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "AG(F|H)$")>; -def : InstRW<[WLat2, WLat2, FXa, NormalGr], (instregex "AGFR$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BRW, NormalGr], (instregex "AGFR$")>; //===----------------------------------------------------------------------===// // Subtraction //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "S(G|Y)?$")>; -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "SH(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLFI$")>; -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLFI$")>; +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "SL(G|GF|Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLGF(I|R)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "S(L)?HHHR$")>; -def : InstRW<[WLat2, WLat2, FXa, NormalGr], (instregex "S(L)?HHLR$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLGF(I|R)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "S(L)?HHHR$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BRW, NormalGr], (instregex "S(L)?HHLR$")>; // Subtraction with borrow -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, GroupAlone], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BnW, GroupAlone], (instregex "SLB(G)?$")>; -def : InstRW<[WLat2, WLat2, FXa, GroupAlone], (instregex "SLB(G)?R$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BnW, GroupAlone], (instregex "SLB(G)?R$")>; // Subtraction with sign extension (16/32 -> 64) -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "SG(F|H)$")>; -def : InstRW<[WLat2, WLat2, FXa, NormalGr], (instregex "SGFR$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BRW, NormalGr], (instregex "SGFR$")>; //===----------------------------------------------------------------------===// // AND //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "N(G|Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NI(FMux|HMux|LMux)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NI(FMux|HMux|LMux)$")>; def : InstRW<[WLat2LSU, FXb, LSU, NormalGr], (instregex "NI(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NIHF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NIHH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NIHL(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NILF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NILH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NILL(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NIHF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NIHH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NIHL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NILF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NILH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NILL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NR(K)?$")>; def : InstRW<[WLat3LSU, LSU2, FXb, Cracked], (instregex "NC$")>; //===----------------------------------------------------------------------===// // OR //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "O(G|Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OGR(K)?$")>; def : InstRW<[WLat2LSU, FXb, LSU, NormalGr], (instregex "OI(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OI(FMux|HMux|LMux)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OIHF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OIHH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OIHL(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OILF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OILH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OILL(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OI(FMux|HMux|LMux)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OIHF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OIHH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OIHL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OILF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OILH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OILL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OR(K)?$")>; def : InstRW<[WLat3LSU, LSU2, FXb, Cracked], (instregex "OC$")>; //===----------------------------------------------------------------------===// // XOR //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "X(G|Y)?$")>; def : InstRW<[WLat2LSU, FXb, LSU, NormalGr], (instregex "XI(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "XIFMux$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "XGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "XIHF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "XILF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "XR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "XIFMux$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "XGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "XIHF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "XILF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "XR(K)?$")>; def : InstRW<[WLat3LSU, LSU2, FXb, Cracked], (instregex "XC$")>; //===----------------------------------------------------------------------===// // Multiplication //===----------------------------------------------------------------------===// -def : InstRW<[WLat5LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat5LSU, RegReadAdv, FXa, LSU, B2BRn, NormalGr], (instregex "MS(GF|Y)?$")>; -def : InstRW<[WLat5, FXa, NormalGr], (instregex "MS(R|FI)$")>; -def : InstRW<[WLat7LSU, RegReadAdv, FXa, LSU, NormalGr], (instregex "MSG$")>; -def : InstRW<[WLat7, FXa, NormalGr], (instregex "MSGR$")>; -def : InstRW<[WLat5, FXa, NormalGr], (instregex "MSGF(I|R)$")>; -def : InstRW<[WLat8LSU, RegReadAdv, FXa2, LSU, GroupAlone], (instregex "MLG$")>; -def : InstRW<[WLat8, FXa2, GroupAlone], (instregex "MLGR$")>; -def : InstRW<[WLat4, FXa, NormalGr], (instregex "MGHI$")>; -def : InstRW<[WLat4, FXa, NormalGr], (instregex "MHI$")>; -def : InstRW<[WLat4LSU, RegReadAdv, FXa, LSU, NormalGr], (instregex "MH(Y)?$")>; -def : InstRW<[WLat6, FXa2, GroupAlone], (instregex "M(L)?R$")>; -def : InstRW<[WLat6LSU, RegReadAdv, FXa2, LSU, GroupAlone], +def : InstRW<[WLat5, FXa, B2BRn, NormalGr], (instregex "MS(R|FI)$")>; +def : InstRW<[WLat7LSU, RegReadAdv, FXa, LSU, B2BRn, NormalGr], + (instregex "MSG$")>; +def : InstRW<[WLat7, FXa, B2BRn, NormalGr], (instregex "MSGR$")>; +def : InstRW<[WLat5, FXa, B2BRn, NormalGr], (instregex "MSGF(I|R)$")>; +def : InstRW<[WLat8LSU, RegReadAdv, FXa2, LSU, B2BRn, GroupAlone], + (instregex "MLG$")>; +def : InstRW<[WLat8, FXa2, B2BRn, GroupAlone], (instregex "MLGR$")>; +def : InstRW<[WLat4, FXa, B2BRW, NormalGr], (instregex "MGHI$")>; +def : InstRW<[WLat4, FXa, B2BRW, NormalGr], (instregex "MHI$")>; +def : InstRW<[WLat4LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], + (instregex "MH(Y)?$")>; +def : InstRW<[WLat6, FXa2, B2BRn, GroupAlone], (instregex "M(L)?R$")>; +def : InstRW<[WLat6LSU, RegReadAdv, FXa2, LSU, B2BRn, GroupAlone], (instregex "M(FY|L)?$")>; -def : InstRW<[WLat8, RegReadAdv, FXa, LSU, NormalGr], (instregex "MGH$")>; -def : InstRW<[WLat12, RegReadAdv, FXa2, LSU, GroupAlone], (instregex "MG$")>; -def : InstRW<[WLat8, FXa2, GroupAlone], (instregex "MGRK$")>; -def : InstRW<[WLat6LSU, WLat6LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat8, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "MGH$")>; +def : InstRW<[WLat12, RegReadAdv, FXa2, LSU, B2BRn, GroupAlone], + (instregex "MG$")>; +def : InstRW<[WLat8, FXa2, B2BRn, GroupAlone], (instregex "MGRK$")>; +def : InstRW<[WLat6LSU, WLat6LSU, RegReadAdv, FXa, LSU, B2BRn, NormalGr], (instregex "MSC$")>; -def : InstRW<[WLat8LSU, WLat8LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat8LSU, WLat8LSU, RegReadAdv, FXa, LSU, B2BRn, NormalGr], (instregex "MSGC$")>; -def : InstRW<[WLat6, WLat6, FXa, NormalGr], (instregex "MSRKC$")>; -def : InstRW<[WLat8, WLat8, FXa, NormalGr], (instregex "MSGRKC$")>; +def : InstRW<[WLat6, WLat6, FXa, B2BRn, NormalGr], (instregex "MSRKC$")>; +def : InstRW<[WLat8, WLat8, FXa, B2BRn, NormalGr], (instregex "MSGRKC$")>; //===----------------------------------------------------------------------===// // Division and remainder //===----------------------------------------------------------------------===// -def : InstRW<[WLat20, FXa4, GroupAlone], (instregex "DR$")>; -def : InstRW<[WLat30, RegReadAdv, FXa4, LSU, GroupAlone2], (instregex "D$")>; -def : InstRW<[WLat30, FXa2, GroupAlone], (instregex "DSG(F)?R$")>; -def : InstRW<[WLat30, RegReadAdv, FXa2, LSU, GroupAlone2], +def : InstRW<[WLat20, FXa4, B2BRn, GroupAlone], (instregex "DR$")>; +def : InstRW<[WLat30, RegReadAdv, FXa4, LSU, B2BRn, GroupAlone2], + (instregex "D$")>; +def : InstRW<[WLat30, FXa2, B2BRn, GroupAlone], (instregex "DSG(F)?R$")>; +def : InstRW<[WLat30, RegReadAdv, FXa2, LSU, B2BRn, GroupAlone2], (instregex "DSG(F)?$")>; -def : InstRW<[WLat20, FXa4, GroupAlone], (instregex "DLR$")>; -def : InstRW<[WLat30, FXa4, GroupAlone], (instregex "DLGR$")>; -def : InstRW<[WLat30, RegReadAdv, FXa4, LSU, GroupAlone2], +def : InstRW<[WLat20, FXa4, B2BRn, GroupAlone], (instregex "DLR$")>; +def : InstRW<[WLat30, FXa4, B2BRn, GroupAlone], (instregex "DLGR$")>; +def : InstRW<[WLat30, RegReadAdv, FXa4, LSU, B2BRn, GroupAlone2], (instregex "DL(G)?$")>; //===----------------------------------------------------------------------===// // Shifts //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLL(G|K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SRL(G|K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SRA(G|K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLA(G|K)?$")>; -def : InstRW<[WLat5LSU, WLat5LSU, FXa4, LSU, GroupAlone2], +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLL(G|K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SRL(G|K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SRA(G|K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLA(G|K)?$")>; +def : InstRW<[WLat5LSU, WLat5LSU, FXa4, LSU, B2BRW, GroupAlone2], (instregex "S(L|R)D(A|L)$")>; // Rotate -def : InstRW<[WLat2LSU, FXa, LSU, NormalGr], (instregex "RLL(G)?$")>; +def : InstRW<[WLat2LSU, FXa, LSU, B2BRW, NormalGr], (instregex "RLL(G)?$")>; // Rotate and insert -def : InstRW<[WLat1, FXa, NormalGr], (instregex "RISBG(N|32)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "RISBH(G|H|L)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "RISBL(G|H|L)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "RISBMux$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "RISBG(N|32)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "RISBH(G|H|L)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "RISBL(G|H|L)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "RISBMux$")>; // Rotate and Select -def : InstRW<[WLat2, WLat2, FXa2, Cracked], (instregex "R(N|O|X)SBG$")>; +def : InstRW<[WLat2, WLat2, FXa2, B2BRW, Cracked], (instregex "R(N|O|X)SBG$")>; //===----------------------------------------------------------------------===// // Comparison @@ -616,7 +640,7 @@ (instregex "CS(G|Y)?$")>; // Compare double and swap -def : InstRW<[WLat6LSU, WLat6LSU, FXa3, FXb2, LSU, GroupAlone2], +def : InstRW<[WLat6LSU, WLat6LSU, FXa3, FXb2, LSU, B2BnW, GroupAlone2], (instregex "CDS(Y)?$")>; def : InstRW<[WLat15, WLat15, FXa2, FXb4, LSU3, GroupAlone3], (instregex "CDSG$")>; @@ -710,13 +734,13 @@ //===----------------------------------------------------------------------===// // Insert Program Mask -def : InstRW<[WLat3, FXa, EndGroup], (instregex "IPM$")>; +def : InstRW<[WLat3, FXa, B2BnW, EndGroup], (instregex "IPM$")>; // Set Program Mask def : InstRW<[WLat3, LSU, EndGroup], (instregex "SPM$")>; // Branch and link -def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "BAL(R)?$")>; +def : InstRW<[WLat1, FXa2, FXb, B2BnW, GroupAlone], (instregex "BAL(R)?$")>; // Test addressing mode def : InstRW<[WLat1, FXb, NormalGr], (instregex "TAM$")>; @@ -725,8 +749,8 @@ def : InstRW<[WLat1, FXb, EndGroup], (instregex "SAM(24|31|64)$")>; // Branch (and save) and set mode. -def : InstRW<[WLat1, FXa, FXb, GroupAlone], (instregex "BSM$")>; -def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "BASSM$")>; +def : InstRW<[WLat1, FXa, FXb, B2BRW, GroupAlone], (instregex "BSM$")>; +def : InstRW<[WLat1, FXa2, FXb, B2BRW, GroupAlone], (instregex "BASSM$")>; //===----------------------------------------------------------------------===// // Transactional execution @@ -758,10 +782,10 @@ //===----------------------------------------------------------------------===// // Find leftmost one -def : InstRW<[WLat5, WLat5, FXa2, GroupAlone], (instregex "FLOGR$")>; +def : InstRW<[WLat5, WLat5, FXa2, B2BRn, GroupAlone], (instregex "FLOGR$")>; // Population count -def : InstRW<[WLat3, WLat3, FXa, NormalGr], (instregex "POPCNT$")>; +def : InstRW<[WLat3, WLat3, FXa, B2BRW, NormalGr], (instregex "POPCNT$")>; // String instructions def : InstRW<[WLat30, WLat30, WLat30, MCD], (instregex "SRST(U)?$")>; @@ -1501,11 +1525,11 @@ def : InstRW<[WLat30, WLat30, MCD], (instregex "EPSW$")>; def : InstRW<[WLat20, GroupAlone3], (instregex "LPSW(E)?$")>; -def : InstRW<[WLat3, FXa, GroupAlone], (instregex "IPK$")>; +def : InstRW<[WLat3, FXa, B2BRW, GroupAlone], (instregex "IPK$")>; def : InstRW<[WLat1, LSU, EndGroup], (instregex "SPKA$")>; def : InstRW<[WLat1, LSU, EndGroup], (instregex "SSM$")>; def : InstRW<[WLat1, FXb, LSU, GroupAlone], (instregex "ST(N|O)SM$")>; -def : InstRW<[WLat3, FXa, NormalGr], (instregex "IAC$")>; +def : InstRW<[WLat3, FXa, B2BRW, NormalGr], (instregex "IAC$")>; def : InstRW<[WLat1, LSU, EndGroup], (instregex "SAC(F)?$")>; //===----------------------------------------------------------------------===// Index: llvm/lib/Target/SystemZ/SystemZScheduleZ15.td =================================================================== --- llvm/lib/Target/SystemZ/SystemZScheduleZ15.td +++ llvm/lib/Target/SystemZ/SystemZScheduleZ15.td @@ -80,6 +80,9 @@ def Z15_VecFPdUnit : ProcResource<2> { let BufferSize = 1; /* blocking */ } def Z15_VBUnit : ProcResource<2>; def Z15_MCD : ProcResource<1>; +def Z15_B2BRW : ProcResource<6>; // Avoid becoming the critical resource +def Z15_B2BRn : ProcResource<6>; +def Z15_B2BnW : ProcResource<6>; // Subtarget specific definitions of scheduling resources. let NumMicroOps = 0 in { @@ -113,6 +116,12 @@ let BeginGroup = 1; let EndGroup = 1; } +let NumMicroOps = 0 in { + def : WriteRes {} + def : WriteRes {} + def : WriteRes {} +} + // -------------------------- INSTRUCTIONS ---------------------------------- // // InstRW constructs have been used in order to preserve the @@ -126,7 +135,7 @@ //===----------------------------------------------------------------------===// // Pseudo -> LA / LAY -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ADJDYNALLOC$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ADJDYNALLOC$")>; //===----------------------------------------------------------------------===// // Branch instructions @@ -138,7 +147,7 @@ def : InstRW<[WLat1, FXb, NormalGr], (instregex "(Call)?BC(R)?(Asm.*)?$")>; def : InstRW<[WLat1, FXb, NormalGr], (instregex "(Call)?B(R)?(Asm.*)?$")>; def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "BI(C)?(Asm.*)?$")>; -def : InstRW<[WLat1, FXa, EndGroup], (instregex "BRCT(G)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, EndGroup], (instregex "BRCT(G)?$")>; def : InstRW<[WLat1, FXa, FXb, GroupAlone], (instregex "BRCTH$")>; def : InstRW<[WLat1, FXa, FXb, GroupAlone], (instregex "BCT(G)?(R)?$")>; def : InstRW<[WLat1, FXa2, FXb2, GroupAlone2], @@ -167,10 +176,12 @@ //===----------------------------------------------------------------------===// // Call -def : InstRW<[WLat1, VBU, FXa2, GroupAlone], (instregex "(Call)?BRAS$")>; -def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BRASL$")>; -def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "(Call)?BAS(R)?$")>; -def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "TLS_(G|L)DCALL$")>; +def : InstRW<[WLat1, VBU, FXa2, B2BRW, GroupAlone], (instregex "(Call)?BRAS$")>; +def : InstRW<[WLat1, FXa2, FXb, B2BRW, GroupAlone], (instregex "(Call)?BRASL$")>; +def : InstRW<[WLat1, FXa2, FXb, B2BRW, GroupAlone], + (instregex "(Call)?BAS(R)?$")>; +def : InstRW<[WLat1, FXa2, FXb, B2BRW, GroupAlone], + (instregex "TLS_(G|L)DCALL$")>; // Return def : InstRW<[WLat1, FXb, EndGroup], (instregex "Return$")>; @@ -190,10 +201,10 @@ def : InstRW<[WLat1, LSU2, GroupAlone], (instregex "MVCRL$")>; // Pseudo -> reg move -def : InstRW<[WLat1, FXa, NormalGr], (instregex "COPY(_TO_REGCLASS)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "EXTRACT_SUBREG$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "INSERT_SUBREG$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "REG_SEQUENCE$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "COPY(_TO_REGCLASS)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "EXTRACT_SUBREG$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "INSERT_SUBREG$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "REG_SEQUENCE$")>; // Loads def : InstRW<[LSULatency, LSU, NormalGr], (instregex "L(Y|FH|RL|Mux)?$")>; @@ -201,12 +212,13 @@ def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LG(RL)?$")>; def : InstRW<[LSULatency, LSU, NormalGr], (instregex "L128$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LLIH(F|H|L)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LLIL(F|H|L)$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "LLI(H|L)F$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LLI(H|L)(H|L)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LG(F|H)I$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LHI(Mux)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LR$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "LGFI$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LGHI$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LHI(Mux)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LR$")>; // Load and zero rightmost byte def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LZR(F|G)$")>; @@ -215,8 +227,9 @@ def : InstRW<[WLat1LSU, FXb, LSU, NormalGr], (instregex "L(FH|G)?AT$")>; // Load and test -def : InstRW<[WLat1LSU, WLat1LSU, LSU, FXa, NormalGr], (instregex "LT(G)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LT(G)?R$")>; +def : InstRW<[WLat1LSU, WLat1LSU, LSU, FXa, B2BRW, NormalGr], + (instregex "LT(G)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LT(G)?R$")>; // Stores def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "STG(RL)?$")>; @@ -230,43 +243,46 @@ // Conditional move instructions //===----------------------------------------------------------------------===// -def : InstRW<[WLat2, FXa, NormalGr], (instregex "LOCRMux$")>; -def : InstRW<[WLat2, FXa, NormalGr], (instregex "LOC(G|FH)?R(Asm.*)?$")>; -def : InstRW<[WLat2, FXa, NormalGr], (instregex "LOC(G|H)?HI(Mux|(Asm.*))?$")>; -def : InstRW<[WLat2LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat2, FXa, B2BnW, NormalGr], (instregex "LOCRMux$")>; +def : InstRW<[WLat2, FXa, B2BnW, NormalGr], (instregex "LOC(G|FH)?R(Asm.*)?$")>; +def : InstRW<[WLat2, FXa, B2BnW, NormalGr], + (instregex "LOC(G|H)?HI(Mux|(Asm.*))?$")>; +def : InstRW<[WLat2LSU, RegReadAdv, FXa, LSU, B2BnW, NormalGr], (instregex "LOC(G|FH|Mux)?(Asm.*)?$")>; def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "STOC(G|FH|Mux)?(Asm.*)?$")>; -def : InstRW<[WLat2, FXa, NormalGr], (instregex "SELRMux$")>; -def : InstRW<[WLat2, FXa, NormalGr], (instregex "SEL(G|FH)?R(Asm.*)?$")>; +def : InstRW<[WLat2, FXa, B2BnW, NormalGr], (instregex "SELRMux$")>; +def : InstRW<[WLat2, FXa, B2BnW, NormalGr], (instregex "SEL(G|FH)?R(Asm.*)?$")>; //===----------------------------------------------------------------------===// // Sign extensions //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, FXa, NormalGr], (instregex "L(B|H|G)R$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LG(B|H|F)R$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "L(B|H|G)R$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LG(B|H|F)R$")>; -def : InstRW<[WLat1LSU, WLat1LSU, FXa, LSU, NormalGr], (instregex "LTGF$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LTGFR$")>; +def : InstRW<[WLat1LSU, WLat1LSU, FXa, LSU, B2BnW, NormalGr], + (instregex "LTGF$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LTGFR$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LB(H|Mux)?$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LH(Y)?$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LH(H|Mux|RL)$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LG(B|H|F)$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LG(H|F)RL$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LB(H|Mux)?$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LH(Y)?$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LH(H|Mux|RL)$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LGB$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BRW, NormalGr], (instregex "LG(H|F)$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LG(H|F)RL$")>; //===----------------------------------------------------------------------===// // Zero extensions //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LLCR(Mux)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LLHR(Mux)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LLG(C|H|F|T)R$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LLCR(Mux)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LLHR(Mux)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LLG(C|H|F|T)R$")>; def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LLC(Mux)?$")>; def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LLH(Mux)?$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LL(C|H)H$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BnW, NormalGr], (instregex "LL(C|H)H$")>; def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LLHRL$")>; def : InstRW<[LSULatency, LSU, NormalGr], (instregex "LLG(C|H|F|T|HRL|FRL)$")>; @@ -301,8 +317,8 @@ // Byte swaps //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LRV(G)?R$")>; -def : InstRW<[WLat1LSU, FXa, LSU, NormalGr], (instregex "LRV(G|H)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LRV(G)?R$")>; +def : InstRW<[WLat1LSU, FXa, LSU, B2BRW, NormalGr], (instregex "LRV(G|H)?$")>; def : InstRW<[WLat1, FXb, LSU, NormalGr], (instregex "STRV(G|H)?$")>; def : InstRW<[WLat30, MCD], (instregex "MVCIN$")>; @@ -310,233 +326,241 @@ // Load address instructions //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LA(Y|RL)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LA(Y)?$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "LARL?$")>; // Load the Global Offset Table address ( -> larl ) -def : InstRW<[WLat1, FXa, NormalGr], (instregex "GOT$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "GOT$")>; //===----------------------------------------------------------------------===// // Absolute and Negation //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, WLat1, FXa, NormalGr], (instregex "LP(G)?R$")>; -def : InstRW<[WLat2, WLat2, FXa2, Cracked], (instregex "L(N|P)GFR$")>; -def : InstRW<[WLat1, WLat1, FXa, NormalGr], (instregex "LN(R|GR)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "LC(R|GR)$")>; -def : InstRW<[WLat2, WLat2, FXa2, Cracked], (instregex "LCGFR$")>; +def : InstRW<[WLat1, WLat1, FXa, B2BRW, NormalGr], (instregex "LP(G)?R$")>; +def : InstRW<[WLat2, WLat2, FXa2, B2BRW, Cracked], (instregex "L(N|P)GFR$")>; +def : InstRW<[WLat1, WLat1, FXa, B2BRW, NormalGr], (instregex "LN(R|GR)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "LC(R|GR)$")>; +def : InstRW<[WLat2, WLat2, FXa2, B2BRW, Cracked], (instregex "LCGFR$")>; //===----------------------------------------------------------------------===// // Insertion //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], (instregex "IC(Y)?$")>; -def : InstRW<[WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], + (instregex "IC(Y)?$")>; +def : InstRW<[WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "IC32(Y)?$")>; -def : InstRW<[WLat1LSU, RegReadAdv, WLat1LSU, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, RegReadAdv, WLat1LSU, FXa, LSU, B2BRW, NormalGr], (instregex "ICM(H|Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "II(F|H|L)Mux$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IIHF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IIHH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IIHL(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IILF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IILH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "IILL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "IIFMux$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "II(H|L)Mux$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "IIHF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "IIHH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "IIHL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BnW, NormalGr], (instregex "IILF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "IILH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "IILL(64)?$")>; //===----------------------------------------------------------------------===// // Addition //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "A(Y)?$")>; -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "AH(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AIH$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AFI(Mux)?$")>; -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AIH$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AFI(Mux)?$")>; +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "AG$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AGFI$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AGHI(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AHI(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AHIMux(K)?$")>; -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AGFI$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AGHI(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AHI(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AHIMux(K)?$")>; +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "AL(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AL(FI|HSIK)$")>; -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AL(FI|HSIK)$")>; +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "ALG(F)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ALGHSIK$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ALGF(I|R)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ALGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ALR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "AR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "A(L)?HHHR$")>; -def : InstRW<[WLat2, WLat2, FXa, NormalGr], (instregex "A(L)?HHLR$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "ALSIH(N)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ALGHSIK$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ALGF(I|R)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ALGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ALR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "AR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "A(L)?HHHR$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BRW, NormalGr], (instregex "A(L)?HHLR$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "ALSIH(N)?$")>; def : InstRW<[WLat2LSU, FXb, LSU, NormalGr], (instregex "A(L)?(G)?SI$")>; // Logical addition with carry -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, GroupAlone], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BnW, GroupAlone], (instregex "ALC(G)?$")>; -def : InstRW<[WLat2, WLat2, FXa, GroupAlone], (instregex "ALC(G)?R$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BnW, GroupAlone], (instregex "ALC(G)?R$")>; // Add with sign extension (16/32 -> 64) -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "AG(F|H)$")>; -def : InstRW<[WLat2, WLat2, FXa, NormalGr], (instregex "AGFR$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BRW, NormalGr], (instregex "AGFR$")>; //===----------------------------------------------------------------------===// // Subtraction //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "S(G|Y)?$")>; -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "SH(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLFI$")>; -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLFI$")>; +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "SL(G|GF|Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLGF(I|R)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "S(L)?HHHR$")>; -def : InstRW<[WLat2, WLat2, FXa, NormalGr], (instregex "S(L)?HHLR$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLGF(I|R)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "S(L)?HHHR$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BRW, NormalGr], (instregex "S(L)?HHLR$")>; // Subtraction with borrow -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, GroupAlone], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BnW, GroupAlone], (instregex "SLB(G)?$")>; -def : InstRW<[WLat2, WLat2, FXa, GroupAlone], (instregex "SLB(G)?R$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BnW, GroupAlone], (instregex "SLB(G)?R$")>; // Subtraction with sign extension (16/32 -> 64) -def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat2LSU, WLat2LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "SG(F|H)$")>; -def : InstRW<[WLat2, WLat2, FXa, NormalGr], (instregex "SGFR$")>; +def : InstRW<[WLat2, WLat2, FXa, B2BRW, NormalGr], (instregex "SGFR$")>; //===----------------------------------------------------------------------===// // AND //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "N(G|Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NI(FMux|HMux|LMux)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NI(FMux|HMux|LMux)$")>; def : InstRW<[WLat2LSU, FXb, LSU, NormalGr], (instregex "NI(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NIHF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NIHH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NIHL(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NILF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NILH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NILL(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NIHF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NIHH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NIHL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NILF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NILH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NILL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NR(K)?$")>; def : InstRW<[WLat3LSU, LSU2, FXb, Cracked], (instregex "NC$")>; //===----------------------------------------------------------------------===// // OR //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "O(G|Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OGR(K)?$")>; def : InstRW<[WLat2LSU, FXb, LSU, NormalGr], (instregex "OI(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OI(FMux|HMux|LMux)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OIHF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OIHH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OIHL(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OILF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OILH(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OILL(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OI(FMux|HMux|LMux)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OIHF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OIHH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OIHL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OILF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OILH(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OILL(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OR(K)?$")>; def : InstRW<[WLat3LSU, LSU2, FXb, Cracked], (instregex "OC$")>; //===----------------------------------------------------------------------===// // XOR //===----------------------------------------------------------------------===// -def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat1LSU, WLat1LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "X(G|Y)?$")>; def : InstRW<[WLat2LSU, FXb, LSU, NormalGr], (instregex "XI(Y)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "XIFMux$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "XGR(K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "XIHF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "XILF(64)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "XR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "XIFMux$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "XGR(K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "XIHF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "XILF(64)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "XR(K)?$")>; def : InstRW<[WLat3LSU, LSU2, FXb, Cracked], (instregex "XC$")>; //===----------------------------------------------------------------------===// // Combined logical operations //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NC(G)?RK$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "OC(G)?RK$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NN(G)?RK$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NO(G)?RK$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "NX(G)?RK$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NC(G)?RK$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "OC(G)?RK$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NN(G)?RK$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NO(G)?RK$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "NX(G)?RK$")>; //===----------------------------------------------------------------------===// // Multiplication //===----------------------------------------------------------------------===// -def : InstRW<[WLat5LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat5LSU, RegReadAdv, FXa, LSU, B2BRn, NormalGr], (instregex "MS(GF|Y)?$")>; -def : InstRW<[WLat5, FXa, NormalGr], (instregex "MS(R|FI)$")>; -def : InstRW<[WLat7LSU, RegReadAdv, FXa, LSU, NormalGr], (instregex "MSG$")>; -def : InstRW<[WLat7, FXa, NormalGr], (instregex "MSGR$")>; -def : InstRW<[WLat5, FXa, NormalGr], (instregex "MSGF(I|R)$")>; -def : InstRW<[WLat8LSU, RegReadAdv, FXa2, LSU, GroupAlone], (instregex "MLG$")>; -def : InstRW<[WLat8, FXa2, GroupAlone], (instregex "MLGR$")>; -def : InstRW<[WLat4, FXa, NormalGr], (instregex "MGHI$")>; -def : InstRW<[WLat4, FXa, NormalGr], (instregex "MHI$")>; -def : InstRW<[WLat4LSU, RegReadAdv, FXa, LSU, NormalGr], (instregex "MH(Y)?$")>; -def : InstRW<[WLat6, FXa2, GroupAlone], (instregex "M(L)?R$")>; -def : InstRW<[WLat6LSU, RegReadAdv, FXa2, LSU, GroupAlone], +def : InstRW<[WLat5, FXa, B2BRn, NormalGr], (instregex "MS(R|FI)$")>; +def : InstRW<[WLat7LSU, RegReadAdv, FXa, LSU, B2BRn, NormalGr], + (instregex "MSG$")>; +def : InstRW<[WLat7, FXa, B2BRn, NormalGr], (instregex "MSGR$")>; +def : InstRW<[WLat5, FXa, B2BRn, NormalGr], (instregex "MSGF(I|R)$")>; +def : InstRW<[WLat8LSU, RegReadAdv, FXa2, LSU, B2BRn, GroupAlone], + (instregex "MLG$")>; +def : InstRW<[WLat8, FXa2, B2BRn, GroupAlone], (instregex "MLGR$")>; +def : InstRW<[WLat4, FXa, B2BRW, NormalGr], (instregex "MGHI$")>; +def : InstRW<[WLat4, FXa, B2BRW, NormalGr], (instregex "MHI$")>; +def : InstRW<[WLat4LSU, RegReadAdv, FXa, LSU, B2BRW, NormalGr], + (instregex "MH(Y)?$")>; +def : InstRW<[WLat6, FXa2, B2BRn, GroupAlone], (instregex "M(L)?R$")>; +def : InstRW<[WLat6LSU, RegReadAdv, FXa2, LSU, B2BRn, GroupAlone], (instregex "M(FY|L)?$")>; -def : InstRW<[WLat8, RegReadAdv, FXa, LSU, NormalGr], (instregex "MGH$")>; -def : InstRW<[WLat12, RegReadAdv, FXa2, LSU, GroupAlone], (instregex "MG$")>; -def : InstRW<[WLat8, FXa2, GroupAlone], (instregex "MGRK$")>; -def : InstRW<[WLat6LSU, WLat6LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat8, RegReadAdv, FXa, LSU, B2BRW, NormalGr], (instregex "MGH$")>; +def : InstRW<[WLat12, RegReadAdv, FXa2, LSU, B2BRn, GroupAlone], + (instregex "MG$")>; +def : InstRW<[WLat8, FXa2, B2BRn, GroupAlone], (instregex "MGRK$")>; +def : InstRW<[WLat6LSU, WLat6LSU, RegReadAdv, FXa, LSU, B2BRn, NormalGr], (instregex "MSC$")>; -def : InstRW<[WLat8LSU, WLat8LSU, RegReadAdv, FXa, LSU, NormalGr], +def : InstRW<[WLat8LSU, WLat8LSU, RegReadAdv, FXa, LSU, B2BRn, NormalGr], (instregex "MSGC$")>; -def : InstRW<[WLat6, WLat6, FXa, NormalGr], (instregex "MSRKC$")>; -def : InstRW<[WLat8, WLat8, FXa, NormalGr], (instregex "MSGRKC$")>; +def : InstRW<[WLat6, WLat6, FXa, B2BRn, NormalGr], (instregex "MSRKC$")>; +def : InstRW<[WLat8, WLat8, FXa, B2BRn, NormalGr], (instregex "MSGRKC$")>; //===----------------------------------------------------------------------===// // Division and remainder //===----------------------------------------------------------------------===// -def : InstRW<[WLat20, FXa4, GroupAlone], (instregex "DR$")>; -def : InstRW<[WLat30, RegReadAdv, FXa4, LSU, GroupAlone2], (instregex "D$")>; -def : InstRW<[WLat30, FXa2, GroupAlone], (instregex "DSG(F)?R$")>; -def : InstRW<[WLat30, RegReadAdv, FXa2, LSU, GroupAlone2], +def : InstRW<[WLat20, FXa4, B2BRn, GroupAlone], (instregex "DR$")>; +def : InstRW<[WLat30, RegReadAdv, FXa4, LSU, B2BRn, GroupAlone2], + (instregex "D$")>; +def : InstRW<[WLat30, FXa2, B2BRn, GroupAlone], (instregex "DSG(F)?R$")>; +def : InstRW<[WLat30, RegReadAdv, FXa2, LSU, B2BRn, GroupAlone2], (instregex "DSG(F)?$")>; -def : InstRW<[WLat20, FXa4, GroupAlone], (instregex "DLR$")>; -def : InstRW<[WLat30, FXa4, GroupAlone], (instregex "DLGR$")>; -def : InstRW<[WLat30, RegReadAdv, FXa4, LSU, GroupAlone2], +def : InstRW<[WLat20, FXa4, B2BRn, GroupAlone], (instregex "DLR$")>; +def : InstRW<[WLat30, FXa4, B2BRn, GroupAlone], (instregex "DLGR$")>; +def : InstRW<[WLat30, RegReadAdv, FXa4, LSU, B2BRn, GroupAlone2], (instregex "DL(G)?$")>; //===----------------------------------------------------------------------===// // Shifts //===----------------------------------------------------------------------===// -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLL(G|K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SRL(G|K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SRA(G|K)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "SLA(G|K)?$")>; -def : InstRW<[WLat5LSU, WLat5LSU, FXa4, LSU, GroupAlone2], +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLL(G|K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SRL(G|K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SRA(G|K)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "SLA(G|K)?$")>; +def : InstRW<[WLat5LSU, WLat5LSU, FXa4, LSU, B2BRW, GroupAlone2], (instregex "S(L|R)D(A|L)$")>; // Rotate -def : InstRW<[WLat2LSU, FXa, LSU, NormalGr], (instregex "RLL(G)?$")>; +def : InstRW<[WLat2LSU, FXa, LSU, B2BRW, NormalGr], (instregex "RLL(G)?$")>; // Rotate and insert -def : InstRW<[WLat1, FXa, NormalGr], (instregex "RISBG(N|32)?$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "RISBH(G|H|L)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "RISBL(G|H|L)$")>; -def : InstRW<[WLat1, FXa, NormalGr], (instregex "RISBMux$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "RISBG(N|32)?$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "RISBH(G|H|L)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "RISBL(G|H|L)$")>; +def : InstRW<[WLat1, FXa, B2BRW, NormalGr], (instregex "RISBMux$")>; // Rotate and Select -def : InstRW<[WLat2, WLat2, FXa2, Cracked], (instregex "R(N|O|X)SBG$")>; +def : InstRW<[WLat2, WLat2, FXa2, B2BRW, Cracked], (instregex "R(N|O|X)SBG$")>; //===----------------------------------------------------------------------===// // Comparison @@ -630,7 +654,7 @@ (instregex "CS(G|Y)?$")>; // Compare double and swap -def : InstRW<[WLat6LSU, WLat6LSU, FXa3, FXb2, LSU, GroupAlone2], +def : InstRW<[WLat6LSU, WLat6LSU, FXa3, FXb2, LSU, B2BnW, GroupAlone2], (instregex "CDS(Y)?$")>; def : InstRW<[WLat15, WLat15, FXa2, FXb4, LSU3, GroupAlone3], (instregex "CDSG$")>; @@ -725,13 +749,13 @@ //===----------------------------------------------------------------------===// // Insert Program Mask -def : InstRW<[WLat3, FXa, EndGroup], (instregex "IPM$")>; +def : InstRW<[WLat3, FXa, B2BnW, EndGroup], (instregex "IPM$")>; // Set Program Mask def : InstRW<[WLat3, LSU, EndGroup], (instregex "SPM$")>; // Branch and link -def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "BAL(R)?$")>; +def : InstRW<[WLat1, FXa2, FXb, B2BnW, GroupAlone], (instregex "BAL(R)?$")>; // Test addressing mode def : InstRW<[WLat1, FXb, NormalGr], (instregex "TAM$")>; @@ -740,8 +764,8 @@ def : InstRW<[WLat1, FXb, EndGroup], (instregex "SAM(24|31|64)$")>; // Branch (and save) and set mode. -def : InstRW<[WLat1, FXa, FXb, GroupAlone], (instregex "BSM$")>; -def : InstRW<[WLat1, FXa2, FXb, GroupAlone], (instregex "BASSM$")>; +def : InstRW<[WLat1, FXa, FXb, B2BRW, GroupAlone], (instregex "BSM$")>; +def : InstRW<[WLat1, FXa2, FXb, B2BRW, GroupAlone], (instregex "BASSM$")>; //===----------------------------------------------------------------------===// // Transactional execution @@ -773,10 +797,10 @@ //===----------------------------------------------------------------------===// // Find leftmost one -def : InstRW<[WLat5, WLat5, FXa2, GroupAlone], (instregex "FLOGR$")>; +def : InstRW<[WLat5, WLat5, FXa2, B2BRn, GroupAlone], (instregex "FLOGR$")>; // Population count -def : InstRW<[WLat3, WLat3, FXa, NormalGr], (instregex "POPCNT(Opt)?$")>; +def : InstRW<[WLat3, WLat3, FXa, B2BRW, NormalGr], (instregex "POPCNT(Opt)?$")>; // String instructions def : InstRW<[WLat30, WLat30, WLat30, MCD], (instregex "SRST(U)?$")>; @@ -1547,11 +1571,11 @@ def : InstRW<[WLat30, WLat30, MCD], (instregex "EPSW$")>; def : InstRW<[WLat20, GroupAlone3], (instregex "LPSW(E)?$")>; -def : InstRW<[WLat3, FXa, GroupAlone], (instregex "IPK$")>; +def : InstRW<[WLat3, FXa, B2BRW, GroupAlone], (instregex "IPK$")>; def : InstRW<[WLat1, LSU, EndGroup], (instregex "SPKA$")>; def : InstRW<[WLat1, LSU, EndGroup], (instregex "SSM$")>; def : InstRW<[WLat1, FXb, LSU, GroupAlone], (instregex "ST(N|O)SM$")>; -def : InstRW<[WLat3, FXa, NormalGr], (instregex "IAC$")>; +def : InstRW<[WLat3, FXa, B2BRW, NormalGr], (instregex "IAC$")>; def : InstRW<[WLat1, LSU, EndGroup], (instregex "SAC(F)?$")>; //===----------------------------------------------------------------------===// Index: llvm/test/CodeGen/SystemZ/postra-sched-sidesteer.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/SystemZ/postra-sched-sidesteer.mir @@ -0,0 +1,109 @@ +# RUN_: llc -mtriple=s390x-linux-gnu -mcpu=z14 -run-pass=postmisched \ +# RUN_: -sidesteer-fxu -sidesteer-lastslot %s -o - 2>&1 | FileCheck %s + +# Alternate method: +# RUN: llc -mtriple=s390x-linux-gnu -mcpu=z14 -run-pass=postmisched \ +# RUN: -sidesteer-fxu -sidesteer-lastslot -sidesteer-lookahead %s -o - 2>&1 | FileCheck %s + +# Test that the last use of r2 ends up on same side as the the def. +--- +# CHECK: name: fun0 +# CHECK-LABEL: bb.0: +# CHECK: $r2d = LGR killed $r0d +# CHECK: $r3d = LGR $r2d +# CHECK: $r4d = LGR $r2d +# CHECK: $r6d = LGR $r5d +# CHECK: $r7d = LGR $r5d +# CHECK: $r8d = LGR killed $r5d +# CHECK: $r0d = LGR $r2d +# CHECK: Return implicit killed $r2d +name: fun0 +machineFunctionInfo: {} +body: | + bb.0: + $r2d = LGR $r0d + $r3d = LGR $r2d + $r4d = LGR $r2d + $r0d = LGR $r2d + $r6d = LGR $r5d + $r7d = LGR $r5d + $r8d = LGR $r5d + Return implicit $r2d +... + + +# Test that the r7 def is not put in the last slot of the decoder group given +# the immediate user of it. +--- +# CHECK: name: fun1 +# CHECK-LABEL: bb.0: +# CHECK: $r2d = LGR killed $r0d +# CHECK: $r2d = LGR killed $r2d +# CHECK: $r4d = LGR killed $r3d +# CHECK: $r7d = LGR killed $r1d +# CHECK: $r8d = LGR killed $r7d +# CHECK: $r6d = LGR killed $r5d +# CHECK: Return implicit killed $r2d + +name: fun1 +machineFunctionInfo: {} +body: | + bb.0: + $r2d = LGR $r0d + $r2d = LGR $r2d + $r4d = LGR $r3d + $r6d = LGR $r5d + $r7d = LGR $r1d + $r8d = LGR $r7d + Return implicit $r2d +... + + +# Test that r4d is put early into decoder group given the immediate user. +--- +# CHECK: name: fun2 +# CHECK-LABEL: bb.0: +# CHECK: $r6d = LGR killed $r7d +# CHECK: $r8d = LGR killed $r6d +# CHECK: $r10d = MSGRKC killed $r8d, $r8d, implicit-def $cc +# CHECK: $r4d = LGR killed $r3d +# CHECK: $r5d = LGR killed $r4d +# CHECK: $r2d = LGR killed $r10d +# CHECK: Return implicit killed $r2d + + name: fun2 + machineFunctionInfo: {} + body: | + bb.0: + $r6d = LGR $r7d + $r4d = LGR $r3d + $r5d = LGR $r4d + $r8d = LGR $r6d + $r10d = MSGRKC $r8d, $r8d, implicit-def $cc + $r2d = LGR $r10d + Return implicit $r2d +... + + +# Test that r6 and r8 are put early into same decoder group as MSGRKC (MSGRKC has other predecessor). +--- +# CHECK: name: fun3 +# CHECK-LABEL: bb.0: +# CHECK: $r6d = LGR killed $r7d +# CHECK: $r8d = LGR killed $r9d +# CHECK: $r10d = MSGRKC killed $r6d, killed $r8d, implicit-def $cc +# CHECK: $r4d = LGR killed $r3d +# CHECK: $r5d = LGR killed $r4d +# CHECK: Return implicit killed $r2d + +name: fun3 +machineFunctionInfo: {} +body: | + bb.0: + $r4d = LGR $r3d + $r6d = LGR $r7d + $r8d = LGR $r9d + $r5d = LGR $r4d + $r10d = MSGRKC $r6d, $r8d, implicit-def $cc + Return implicit $r2d +...