From 67a418b5657de6712502cd50c4a12118debce25e Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Tue, 30 Aug 2022 09:34:43 -0400 Subject: [m88k] Implement add/sub with carry. --- .../Target/M88k/GISel/M88kGenRegisterBankInfo.def | 16 ++++++--- .../Target/M88k/GISel/M88kInstructionSelector.cpp | 40 ++++++++++++++++++++++ llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp | 4 +++ .../M88k/GISel/M88kPostLegalizerLowering.cpp | 13 ++++--- .../lib/Target/M88k/GISel/M88kRegisterBankInfo.cpp | 15 ++++++++ llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.h | 5 +-- llvm/lib/Target/M88k/GISel/M88kRegisterBanks.td | 1 + 7 files changed, 83 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Target/M88k/GISel/M88kGenRegisterBankInfo.def b/llvm/lib/Target/M88k/GISel/M88kGenRegisterBankInfo.def index bf8a220..8cd362a 100644 --- a/llvm/lib/Target/M88k/GISel/M88kGenRegisterBankInfo.def +++ b/llvm/lib/Target/M88k/GISel/M88kGenRegisterBankInfo.def @@ -23,6 +23,8 @@ RegisterBankInfo::PartialMapping M88kGenRegisterBankInfo::PartMappings[]{ {0, 32, M88k::GRRegBank}, // 4: GPR 64-bit value. {0, 64, M88k::GRRegBank}, + // 5: CR 32-bit value. + {0, 32, M88k::CRRegBank}, }; // ValueMappings. @@ -48,20 +50,24 @@ RegisterBankInfo::ValueMapping M88kGenRegisterBankInfo::ValMappings[]{ {&M88kGenRegisterBankInfo::PartMappings[PMI_GR32 - PMI_Min], 1}, {&M88kGenRegisterBankInfo::PartMappings[PMI_GR32 - PMI_Min], 1}, {&M88kGenRegisterBankInfo::PartMappings[PMI_GR32 - PMI_Min], 1}, - // 13: 2x GR 32-bit value. <-- This must match Last3OpsIdx. + // 13: 2x GR 32-bit value. {&M88kGenRegisterBankInfo::PartMappings[PMI_GR64 - PMI_Min], 1}, {&M88kGenRegisterBankInfo::PartMappings[PMI_GR64 - PMI_Min], 1}, {&M88kGenRegisterBankInfo::PartMappings[PMI_GR64 - PMI_Min], 1}, - // 16: GR 32-bit <- XR 32-bit copy. <-- This must match FirstCrossRegCpyIdx. + // 16: CR 32-bit value. <-- This must match Last3OpsIdx. + {&M88kGenRegisterBankInfo::PartMappings[PMI_CR - PMI_Min], 1}, + {&M88kGenRegisterBankInfo::PartMappings[PMI_CR - PMI_Min], 1}, + {&M88kGenRegisterBankInfo::PartMappings[PMI_CR - PMI_Min], 1}, + // 19: GR 32-bit <- XR 32-bit copy. <-- This must match FirstCrossRegCpyIdx. {&M88kGenRegisterBankInfo::PartMappings[PMI_GR32 - PMI_Min], 1}, {&M88kGenRegisterBankInfo::PartMappings[PMI_XR32 - PMI_Min], 1}, - // 18: XR 32-bit <- GR 32-bit copy. + // 21: XR 32-bit <- GR 32-bit copy. {&M88kGenRegisterBankInfo::PartMappings[PMI_XR32 - PMI_Min], 1}, {&M88kGenRegisterBankInfo::PartMappings[PMI_GR32 - PMI_Min], 1}, - // 20: 2x GR 32-bit <- XR 64-bit copy. + // 23: 2x GR 32-bit <- XR 64-bit copy. {&M88kGenRegisterBankInfo::PartMappings[PMI_GR64 - PMI_Min], 1}, {&M88kGenRegisterBankInfo::PartMappings[PMI_XR64 - PMI_Min], 1}, - // 22: XR 64-bit <- 2x GR 32-bit copy. <-- This must match + // 25: XR 64-bit <- 2x GR 32-bit copy. <-- This must match // LastCrossRegCpyIdx. {&M88kGenRegisterBankInfo::PartMappings[PMI_XR64 - PMI_Min], 1}, {&M88kGenRegisterBankInfo::PartMappings[PMI_GR64 - PMI_Min], 1}, diff --git a/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp b/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp index 175769c..dba84c0 100644 --- a/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp +++ b/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp @@ -82,6 +82,8 @@ private: MachineRegisterInfo &MRI) const; bool selectPtrAdd(MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const; + bool selectAddSubWithCarry(MachineInstr &I, MachineBasicBlock &MBB, + MachineRegisterInfo &MRI) const; bool selectMul(MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const; bool selectUDiv(MachineInstr &I, MachineBasicBlock &MBB, @@ -608,6 +610,39 @@ bool M88kInstructionSelector::selectPtrAdd(MachineInstr &I, return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); } +bool M88kInstructionSelector::selectAddSubWithCarry( + MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const { + assert(I.getOpcode() == TargetOpcode::G_UADDO || + I.getOpcode() == TargetOpcode::G_USUBO || + I.getOpcode() == TargetOpcode::G_UADDE || + I.getOpcode() == TargetOpcode::G_USUBE && "Unexpected G code"); + + static unsigned TargetOpc[] = { + M88k::ADDUrrco, M88k::ADDUrrci, M88k::ADDUrrcio, // Add + M88k::SUBUrrco, M88k::SUBUrrci, M88k::SUBUrrcio, // Sub + }; + unsigned Opc = I.getOpcode(); + bool HasCarryInOut = + Opc == TargetOpcode::G_UADDE || Opc == TargetOpcode::G_USUBE; + bool IsCarryOutUsed = + HasCarryInOut && MRI.use_begin(I.getOperand(1).getReg()) != MRI.use_end(); + bool IsSub = Opc == TargetOpcode::G_USUBO || Opc == TargetOpcode::G_USUBE; + unsigned NewOpc = + TargetOpc[3 * IsSub + HasCarryInOut + IsCarryOutUsed]; + + MachineInstr *MI = nullptr; + Register DstReg = I.getOperand(0).getReg(); + Register Src1Reg = I.getOperand(2).getReg(); + Register Src2Reg = I.getOperand(3).getReg(); + + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc), DstReg) + .addReg(Src1Reg) + .addReg(Src2Reg); + + I.eraseFromParent(); + return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); +} + bool M88kInstructionSelector::selectMul(MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const { assert(I.getOpcode() == TargetOpcode::G_MUL && "Unexpected G code"); @@ -1131,6 +1166,11 @@ bool M88kInstructionSelector::select(MachineInstr &I) { return selectBrJT(I, MBB, MRI); case TargetOpcode::G_BRINDIRECT: return selectBrIndirect(I, MBB, MRI); + case TargetOpcode::G_UADDO: + case TargetOpcode::G_USUBO: + case TargetOpcode::G_UADDE: + case TargetOpcode::G_USUBE: + return selectAddSubWithCarry(I, MBB, MRI); case TargetOpcode::G_MUL: return selectMul(I, MBB, MRI); case TargetOpcode::G_UDIV: diff --git a/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp b/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp index ea865ca..8533953 100644 --- a/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp +++ b/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp @@ -86,6 +86,10 @@ M88kLegalizerInfo::M88kLegalizerInfo(const M88kSubtarget &ST) { .legalIf( all(typeInSet(0, {V8S8, V4S16, V2S32}), LegalityPredicate(IsMC88110))) .clampScalar(0, S32, S32); + getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_USUBO, G_USUBE}) + .legalFor({S32, S32}) + .clampScalar(0, S32, S32) + .clampScalar(1, S32, S32); getActionDefinitionsBuilder({G_MUL, G_UDIV}) .legalFor({S32}) .customIf(all(typeInSet(0, {S64}), LegalityPredicate(IsMC88110))) diff --git a/llvm/lib/Target/M88k/GISel/M88kPostLegalizerLowering.cpp b/llvm/lib/Target/M88k/GISel/M88kPostLegalizerLowering.cpp index aa29756..be20a0e 100644 --- a/llvm/lib/Target/M88k/GISel/M88kPostLegalizerLowering.cpp +++ b/llvm/lib/Target/M88k/GISel/M88kPostLegalizerLowering.cpp @@ -398,15 +398,20 @@ bool M88kPostLegalizerLoweringInfo::combine(GISelChangeObserver &Observer, // swap the operands. The matcher generated from the SDAG patterns expects the // constant always as the second operand, otherwise operand is not matched as // immediate. - if (MI.isCommutable()) { - assert(MI.getNumExplicitOperands() == 3 && "Not a binary operation"); + if (MI.isCommutable() && isPreISelGenericOpcode(MI.getOpcode())) { + assert(MI.getNumExplicitOperands() >= 3 && "Not a binary operation"); + unsigned Opc = MI.getOpcode(); + bool HasCarry = + Opc == TargetOpcode::G_UADDO || Opc == TargetOpcode::G_USUBO || + Opc == TargetOpcode::G_UADDE || Opc == TargetOpcode::G_USUBE; + unsigned SrcIdx = HasCarry ? 2 : 1; unsigned SrcOpc = - getDefIgnoringCopies(MI.getOperand(1).getReg(), *B.getMRI()) + getDefIgnoringCopies(MI.getOperand(SrcIdx).getReg(), *B.getMRI()) ->getOpcode(); if (SrcOpc == TargetOpcode::G_CONSTANT || SrcOpc == TargetOpcode::G_FCONSTANT) { Observer.changingInstr(MI); - B.getTII().commuteInstruction(MI, false, 1, 2); + B.getTII().commuteInstruction(MI, false, SrcIdx, SrcIdx + 1); Observer.changedInstr(MI); } } diff --git a/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.cpp b/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.cpp index 60cbfe7..c607087 100644 --- a/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.cpp +++ b/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.cpp @@ -169,6 +169,21 @@ M88kRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { OperandsMapping = getValueMapping(RBIdx); break; } + // Integer arithmetic producing a carry. + case TargetOpcode::G_UADDO: + case TargetOpcode::G_USUBO: + OperandsMapping = getOperandsMapping( + {getValueMapping(PMI_GR32), getValueMapping(PMI_CR), + getValueMapping(PMI_GR32), getValueMapping(PMI_GR32)}); + break; + // Integer arithmetic producing and consuming a carry. + case TargetOpcode::G_UADDE: + case TargetOpcode::G_USUBE: + OperandsMapping = getOperandsMapping( + {getValueMapping(PMI_GR32), getValueMapping(PMI_CR), + getValueMapping(PMI_GR32), getValueMapping(PMI_GR32), + getValueMapping(PMI_CR)}); + break; // Floating point ops. case TargetOpcode::G_FADD: case TargetOpcode::G_FSUB: diff --git a/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.h b/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.h index ccba9aa..bf0ada2 100644 --- a/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.h +++ b/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.h @@ -31,6 +31,7 @@ protected: PMI_XR80, PMI_GR32, PMI_GR64, + PMI_CR, PMI_Min = PMI_XR32, }; @@ -41,9 +42,9 @@ protected: enum ValueMappingIdx { InvalidIdx = 0, First3OpsIdx = 1, - Last3OpsIdx = 13, + Last3OpsIdx = 16, DistanceBetweenRegBanks = 3, - FirstCrossRegCpyIdx = 16, + FirstCrossRegCpyIdx = 19, LastCrossRegCpyIdx = 22, DistanceBetweenCrossRegCpy = 2, }; diff --git a/llvm/lib/Target/M88k/GISel/M88kRegisterBanks.td b/llvm/lib/Target/M88k/GISel/M88kRegisterBanks.td index 391cc74..ef0a55e 100644 --- a/llvm/lib/Target/M88k/GISel/M88kRegisterBanks.td +++ b/llvm/lib/Target/M88k/GISel/M88kRegisterBanks.td @@ -14,3 +14,4 @@ /// Register banks. def GRRegBank : RegisterBank<"GR", [GPRRC, GPR64RC]>; def XRRegBank : RegisterBank<"XR", [XRRC]>; +def CRRegBank : RegisterBank<"CR", [CRRC]>; -- cgit v1.1