diff --git a/llvm/lib/Target/AIE/AIE2InstrInfo.cpp b/llvm/lib/Target/AIE/AIE2InstrInfo.cpp index ff3e72e3d26d..eae13da9a5f1 100644 --- a/llvm/lib/Target/AIE/AIE2InstrInfo.cpp +++ b/llvm/lib/Target/AIE/AIE2InstrInfo.cpp @@ -479,6 +479,9 @@ unsigned AIE2InstrInfo::getOpCode(MachineInstr &I) const { Register AIE2InstrInfo::getVaddSignControlRegister() const { return AIE2::crVaddSign; } +Register AIE2InstrInfo::getUPSSignControlRegister() const { + return AIE2::crUPSSign; +} // Implement CopyToReg/CopyFromReg void AIE2InstrInfo::copyPhysReg(MachineBasicBlock &MBB, diff --git a/llvm/lib/Target/AIE/AIE2InstrInfo.h b/llvm/lib/Target/AIE/AIE2InstrInfo.h index 9b13f01e1230..d9c4e537cdf9 100644 --- a/llvm/lib/Target/AIE/AIE2InstrInfo.h +++ b/llvm/lib/Target/AIE/AIE2InstrInfo.h @@ -99,6 +99,7 @@ class AIE2InstrInfo : public AIE2GenInstrInfo { TypeSize Size) const override; unsigned getOpCode(MachineInstr &MI) const override; Register getVaddSignControlRegister() const override; + Register getUPSSignControlRegister() const override; virtual std::optional getZOLSupport() const override; virtual std::optional getJNZDSupport() const override; diff --git a/llvm/lib/Target/AIE/AIE2InstructionSelector.cpp b/llvm/lib/Target/AIE/AIE2InstructionSelector.cpp index 7e0f47815596..d85f65f295a1 100644 --- a/llvm/lib/Target/AIE/AIE2InstructionSelector.cpp +++ b/llvm/lib/Target/AIE/AIE2InstructionSelector.cpp @@ -61,9 +61,7 @@ class AIE2InstructionSelector : public AIEBaseInstructionSelector { bool selectG_GLOBAL_VALUE(MachineInstr &I, MachineRegisterInfo &MRI); bool selectG_LOAD(MachineInstr &I, MachineRegisterInfo &MRI); bool selectG_STORE(MachineInstr &I, MachineRegisterInfo &MRI); - bool selectGetControlRegister(MachineInstr &I, MachineRegisterInfo &MRI); bool selectReadTM(MachineInstr &I, MachineRegisterInfo &MRI); - bool selectSetControlRegister(MachineInstr &I, MachineRegisterInfo &MRI); bool selectVEXTRACT(MachineInstr &I, MachineRegisterInfo &MRI); bool selectVSRS(MachineInstr &I, MachineRegisterInfo &MRI); bool selectVUNPACK(MachineInstr &I, MachineRegisterInfo &MRI); @@ -72,12 +70,12 @@ class AIE2InstructionSelector : public AIEBaseInstructionSelector { getOrDefineAddressingRegister(MachineInstr &MemI, MachineRegisterInfo &MRI) final; bool selectG_AIE_LOAD_UNPACK(MachineInstr &StoreI, MachineRegisterInfo &MRI); - bool selectG_AIE_LOAD_UPS(MachineInstr &StoreI, MachineRegisterInfo &MRI); + bool selectG_AIE_LOAD_UPS(MachineInstr &StoreI, MachineRegisterInfo &MRI, + std::optional crUPSModeVal) override; bool select512BitG_AIE_LOAD_UPS(MachineInstr &UPSI, LoadStoreOpcodes &LSO, AddressingModeInfo &AMI, Register DstReg, Register ShftReg, Register SignReg, bool ConstantSign, MachineRegisterInfo &MRI); - bool selectVUPS(MachineInstr &I, MachineRegisterInfo &MRI); bool selectWriteTM(MachineInstr &I, MachineRegisterInfo &MRI); LoadStoreOpcodes getLoadStoreOpcode(const MachineInstr &I, const MachineRegisterInfo &MRI, @@ -1835,8 +1833,9 @@ bool AIE2InstructionSelector::select512BitG_AIE_LOAD_UPS( } } -bool AIE2InstructionSelector::selectG_AIE_LOAD_UPS(MachineInstr &UPSI, - MachineRegisterInfo &MRI) { +bool AIE2InstructionSelector::selectG_AIE_LOAD_UPS( + MachineInstr &UPSI, MachineRegisterInfo &MRI, + std::optional crUPSModeVal) { // First use is the G_INTRINSIC_W_SIDE_EFFECTS ID Register LoadResult = (std::next(UPSI.uses().begin()))->getReg(); @@ -1905,33 +1904,6 @@ bool AIE2InstructionSelector::selectG_AIE_LOAD_UPS(MachineInstr &UPSI, return constrainSelectedInstRegOperands(*NewInstr.getInstr(), TII, TRI, RBI); } -bool AIE2InstructionSelector::selectVUPS(MachineInstr &I, - MachineRegisterInfo &MRI) { - // First try to match UPS combine - if (selectG_AIE_LOAD_UPS(I, MRI)) - return true; - - Register DstReg = I.getOperand(0).getReg(); - // In this case of G_INTRINSIC_W_SIDE_EFFECTS operand 1 is target intrinsic - Register SrcReg = I.getOperand(2).getReg(); - Register ShftReg = I.getOperand(3).getReg(); - Register SignReg = I.getOperand(4).getReg(); - - if (auto SignVal = getIConstantVRegValWithLookThrough(SignReg, MRI)) { - // Handle constant sign through instruction patterns - return selectImpl(I, *CoverageInfo); - } - - unsigned OpCode = TII.getOpCode(I); - MachineInstrBuilder MI = - MIB.buildInstr(OpCode, {DstReg}, {}).addReg(SrcReg).addReg(ShftReg); - - setUnsetCtrlRegister(MIB, *MI, MRI, AIE2::crUPSSign, SignReg); - - I.eraseFromParent(); - return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); -} - bool AIE2InstructionSelector::selectVSRS(MachineInstr &I, MachineRegisterInfo &MRI) { @@ -2090,84 +2062,6 @@ Register AIE2InstructionSelector::createDSRegSequence( return MI.getReg(0); } -// Build Instruction to get control register -bool AIE2InstructionSelector::selectGetControlRegister( - MachineInstr &I, MachineRegisterInfo &MRI) { - - Register DstReg = I.getOperand(0).getReg(); - // In this case of G_INTRINSIC operand 1 is target intrinsic - Register IdxReg = I.getOperand(2).getReg(); - Register CtrlReg; - - // Check if the argument is constant for register map index. - if (auto Idx = getIConstantVRegValWithLookThrough(IdxReg, MRI)) - CtrlReg = TRI.getControlRegister(Idx->Value.getZExtValue()); - else - llvm_unreachable("Expected const value for control register map index."); - - if (!RBI.constrainGenericRegister(DstReg, AIE2::eRRegClass, MRI)) - return false; - - auto CopyInstr = - MIB.buildInstr(TargetOpcode::COPY, {DstReg}, {}).addReg(CtrlReg); - if (!selectCopy(*CopyInstr, MRI)) { - return false; - } - I.eraseFromParent(); - return true; -} - -// Build Instruction to set control register -bool AIE2InstructionSelector::selectSetControlRegister( - MachineInstr &I, MachineRegisterInfo &MRI) { - - Register IdxReg = I.getOperand(1).getReg(); - Register SrcReg = I.getOperand(2).getReg(); - Register CtrlReg; - - // Check if the argument is constant for register map index. - if (auto Idx = getIConstantVRegValWithLookThrough(IdxReg, MRI)) - CtrlReg = TRI.getControlRegister(Idx->Value.getZExtValue()); - else - llvm_unreachable("Expected const value for control register map index."); - - // Handle const input val for control regs. - if (auto Src = getIConstantVRegValWithLookThrough(SrcReg, MRI)) { - unsigned SrcConstVal = Src->Value.getZExtValue(); - /* Modulo by width of control regs. - To constrain the max possible value in the register - according to register width. - */ - switch (CtrlReg) { - case AIE2::crSat: - SrcConstVal = SrcConstVal % (1 << 2); - break; - case AIE2::crRnd: - SrcConstVal = SrcConstVal % (1 << 4); - break; - case AIE2::crF2FMask: - case AIE2::crF2IMask: - case AIE2::crFPMask: - SrcConstVal = SrcConstVal % (1 << 5); - break; - default: - break; - } - - MachineInstrBuilder MI = setCtrlRegister(MIB, CtrlReg, SrcConstVal); - I.eraseFromParent(); - return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); - } - - auto CopyInstr = - MIB.buildInstr(TargetOpcode::COPY, {CtrlReg}, {}).addReg(SrcReg); - if (!selectCopy(*CopyInstr, MRI)) - return false; - - I.eraseFromParent(); - return true; -} - bool AIE2InstructionSelector::selectWriteTM(MachineInstr &I, MachineRegisterInfo &MRI) { Register Value = I.getOperand(1).getReg(); diff --git a/llvm/lib/Target/AIE/AIE2RegisterInfo.cpp b/llvm/lib/Target/AIE/AIE2RegisterInfo.cpp index d5014d98be43..02256b1ea3dc 100644 --- a/llvm/lib/Target/AIE/AIE2RegisterInfo.cpp +++ b/llvm/lib/Target/AIE/AIE2RegisterInfo.cpp @@ -539,3 +539,22 @@ bool AIE2RegisterInfo::isVecOrAccRegClass(const TargetRegisterClass &RC) const { return false; } + +unsigned +AIE2RegisterInfo::matchControlRegisterBitwidth(Register CtrlReg, + unsigned SrcConstVal) const { + // Modulo by width of control regs. To constrain the max possible value in + // the register according to register width. + switch (CtrlReg) { + case AIE2::crSat: + return SrcConstVal % (1 << 2); + case AIE2::crRnd: + return SrcConstVal % (1 << 4); + case AIE2::crF2FMask: + case AIE2::crF2IMask: + case AIE2::crFPMask: + return SrcConstVal % (1 << 5); + default: + llvm_unreachable("Unknown control register."); + } +} diff --git a/llvm/lib/Target/AIE/AIE2RegisterInfo.h b/llvm/lib/Target/AIE/AIE2RegisterInfo.h index 61ac4b978cf6..4a29b2d6a9b9 100644 --- a/llvm/lib/Target/AIE/AIE2RegisterInfo.h +++ b/llvm/lib/Target/AIE/AIE2RegisterInfo.h @@ -70,7 +70,7 @@ struct AIE2RegisterInfo : public AIE2GenRegisterInfo { const MachineOperand &MO, const MachineRegisterInfo &MRI) const override; Register getStackPointerRegister() const override; - Register getControlRegister(unsigned Idx) const; + Register getControlRegister(unsigned Idx) const override; const TargetRegisterClass * getLargestLegalSuperClass(const TargetRegisterClass *RC, @@ -101,6 +101,8 @@ struct AIE2RegisterInfo : public AIE2GenRegisterInfo { const TargetRegisterClass *getAddrCountRegClass() const override { return &AIE2::eDCRegClass; } + unsigned matchControlRegisterBitwidth(Register CtrlReg, + unsigned SrcConstVal) const override; }; } // namespace llvm diff --git a/llvm/lib/Target/AIE/AIEBaseInstrInfo.h b/llvm/lib/Target/AIE/AIEBaseInstrInfo.h index eab759ef75fa..f43791daf94e 100644 --- a/llvm/lib/Target/AIE/AIEBaseInstrInfo.h +++ b/llvm/lib/Target/AIE/AIEBaseInstrInfo.h @@ -375,6 +375,12 @@ struct AIEBaseInstrInfo : public TargetInstrInfo { virtual Register getVaddSignControlRegister() const { llvm_unreachable("Target didn't implement vaddSign control register"); } + virtual Register getUPSModeControlRegister() const { + llvm_unreachable("Target didn't implement UPSMode control register"); + } + virtual Register getUPSSignControlRegister() const { + llvm_unreachable("Target didn't implement UPSSign control register"); + } // Opcodes related to hardware loop handling virtual bool isHardwareLoopDec(unsigned Opcode) const; virtual bool isHardwareLoopJNZ(unsigned Opcode) const; diff --git a/llvm/lib/Target/AIE/AIEBaseInstructionSelector.cpp b/llvm/lib/Target/AIE/AIEBaseInstructionSelector.cpp index 112ef713da3f..f1ff9e0abf60 100644 --- a/llvm/lib/Target/AIE/AIEBaseInstructionSelector.cpp +++ b/llvm/lib/Target/AIE/AIEBaseInstructionSelector.cpp @@ -1046,3 +1046,101 @@ bool AIEBaseInstructionSelector::selectWriteTM(MachineInstr &I, I.eraseFromParent(); return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); } + +// Build Instruction to set control register +bool AIEBaseInstructionSelector::selectSetControlRegister( + MachineInstr &I, MachineRegisterInfo &MRI) { + + const Register IdxReg = I.getOperand(1).getReg(); + const Register SrcReg = I.getOperand(2).getReg(); + + // Check if the argument is constant for register map index. + const auto Idx = getIConstantVRegValWithLookThrough(IdxReg, MRI); + if (!Idx) + llvm_unreachable("Expected const value for control register map index."); + + const Register CtrlReg = TRI.getControlRegister(Idx->Value.getZExtValue()); + + // Handle const input val for control regs. + if (const auto Src = getIConstantVRegValWithLookThrough(SrcReg, MRI)) { + const unsigned SrcConstVal = + TRI.matchControlRegisterBitwidth(CtrlReg, Src->Value.getZExtValue()); + + MachineInstrBuilder MI = setCtrlRegister(MIB, CtrlReg, SrcConstVal); + I.eraseFromParent(); + return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); + } + + auto CopyInstr = + MIB.buildInstr(TargetOpcode::COPY, {CtrlReg}, {}).addReg(SrcReg); + if (!selectCopy(*CopyInstr, MRI)) + return false; + + I.eraseFromParent(); + return true; +} + +// Build Instruction to get control register +bool AIEBaseInstructionSelector::selectGetControlRegister( + MachineInstr &I, MachineRegisterInfo &MRI) { + + const Register DstReg = I.getOperand(0).getReg(); + // In this case of G_INTRINSIC operand 1 is target intrinsic + const Register IdxReg = I.getOperand(2).getReg(); + + // Check if the argument is constant for register map index. + const auto Idx = getIConstantVRegValWithLookThrough(IdxReg, MRI); + if (!Idx) + llvm_unreachable("Expected const value for control register map index."); + + const Register CtrlReg = TRI.getControlRegister(Idx->Value.getZExtValue()); + const MachineFunction &MF = *I.getParent()->getParent(); + + if (!RBI.constrainGenericRegister(DstReg, *TRI.getGPRRegClass(MF), MRI)) + return false; + + auto CopyInstr = + MIB.buildInstr(TargetOpcode::COPY, {DstReg}, {}).addReg(CtrlReg); + if (!selectCopy(*CopyInstr, MRI)) + return false; + + I.eraseFromParent(); + return true; +} + +bool AIEBaseInstructionSelector::selectVUPS( + MachineInstr &I, MachineRegisterInfo &MRI, + std::optional crUPSModeVal) { + // First try to match UPS combine + if (selectG_AIE_LOAD_UPS(I, MRI, crUPSModeVal)) + return true; + + // TODO Match UPS combine + const Register DstReg = I.getOperand(0).getReg(); + // In this case of G_INTRINSIC_W_SIDE_EFFECTS operand 1 is target intrinsic + const Register SrcReg = I.getOperand(2).getReg(); + const Register ShftReg = I.getOperand(3).getReg(); + const Register SignReg = I.getOperand(4).getReg(); + + if (crUPSModeVal.has_value()) { + // Selects the mode of the accumulator for UPS instructions + // 0 – 32-bit accumulator lane + // 1 – 64-bit accumulator lane + MIB.setInstr(I); + setCtrlRegister(MIB, TII.getUPSModeControlRegister(), *crUPSModeVal); + } + + if (const auto SignVal = getIConstantVRegValWithLookThrough(SignReg, MRI)) { + // Handle constant sign through instruction patterns + return selectImpl(I, *CoverageInfo); + } + + const unsigned OpCode = TII.getOpCode(I); + MachineInstrBuilder MI = + MIB.buildInstr(OpCode, {DstReg}, {}).addReg(SrcReg).addReg(ShftReg); + + setUnsetCtrlRegister(MIB, *MI, MRI, TII.getUPSSignControlRegister(), SignReg); + + I.eraseFromParent(); + return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); +} diff --git a/llvm/lib/Target/AIE/AIEBaseInstructionSelector.h b/llvm/lib/Target/AIE/AIEBaseInstructionSelector.h index 017abd90544e..b80ae3843e98 100644 --- a/llvm/lib/Target/AIE/AIEBaseInstructionSelector.h +++ b/llvm/lib/Target/AIE/AIEBaseInstructionSelector.h @@ -191,6 +191,15 @@ class AIEBaseInstructionSelector : public InstructionSelector { bool selectG_AIE_LOAD_CONV(MachineInstr &CONVI, MachineRegisterInfo &MRI); bool selectVCONV(MachineInstr &I, MachineRegisterInfo &MRI); bool selectStartLoop(MachineInstr &I, MachineRegisterInfo &MRI); + bool selectSetControlRegister(MachineInstr &I, MachineRegisterInfo &MRI); + bool selectGetControlRegister(MachineInstr &I, MachineRegisterInfo &MRI); + bool selectVUPS(MachineInstr &I, MachineRegisterInfo &MRI, + std::optional crUPSModeVal = std::nullopt); + virtual bool selectG_AIE_LOAD_UPS(MachineInstr &StoreI, + MachineRegisterInfo &MRI, + std::optional crUPSModeVal) { + return false; + } protected: MachineIRBuilder MIB; diff --git a/llvm/lib/Target/AIE/AIEBaseRegisterInfo.h b/llvm/lib/Target/AIE/AIEBaseRegisterInfo.h index c23b8417f003..a47fd64e6368 100644 --- a/llvm/lib/Target/AIE/AIEBaseRegisterInfo.h +++ b/llvm/lib/Target/AIE/AIEBaseRegisterInfo.h @@ -110,6 +110,14 @@ struct AIEBaseRegisterInfo : public TargetRegisterInfo { unsigned SubReg, const TargetRegisterClass *DstRC, unsigned DstSubReg, const TargetRegisterClass *NewRC, LiveIntervals &LIS) const override; + + virtual unsigned matchControlRegisterBitwidth(Register CtrlReg, + unsigned SrcConstVal) const { + llvm_unreachable("Target didn't implement matchControlRegisterBitwidth!"); + } + virtual Register getControlRegister(unsigned Idx) const { + llvm_unreachable("Target didn't implement getControlRegister!"); + } }; template bool isEncodableAsNegativeInt(int Value) { diff --git a/llvm/lib/Target/AIE/aie2p/AIE2PInstrInfo.cpp b/llvm/lib/Target/AIE/aie2p/AIE2PInstrInfo.cpp index c6fe181621dc..58e4d47d2465 100644 --- a/llvm/lib/Target/AIE/aie2p/AIE2PInstrInfo.cpp +++ b/llvm/lib/Target/AIE/aie2p/AIE2PInstrInfo.cpp @@ -574,6 +574,12 @@ unsigned AIE2PInstrInfo::getOpCode(MachineInstr &I) const { Register AIE2PInstrInfo::getVaddSignControlRegister() const { return AIE2P::vaddSign0; } +Register AIE2PInstrInfo::getUPSModeControlRegister() const { + return AIE2P::crUPSMode; +} +Register AIE2PInstrInfo::getUPSSignControlRegister() const { + return AIE2P::upsSign0; +} // Implement CopyToReg/CopyFromReg void AIE2PInstrInfo::copyPhysReg(MachineBasicBlock &MBB, diff --git a/llvm/lib/Target/AIE/aie2p/AIE2PInstrInfo.h b/llvm/lib/Target/AIE/aie2p/AIE2PInstrInfo.h index 7b69a16bda09..025edb8fc30f 100644 --- a/llvm/lib/Target/AIE/aie2p/AIE2PInstrInfo.h +++ b/llvm/lib/Target/AIE/aie2p/AIE2PInstrInfo.h @@ -105,6 +105,8 @@ class AIE2PInstrInfo : public AIE2PGenInstrInfo { getStoreFlushConvOpcode(unsigned StoreFlushOpcode) const override; unsigned getOpCode(MachineInstr &MI) const override; Register getVaddSignControlRegister() const override; + Register getUPSModeControlRegister() const override; + Register getUPSSignControlRegister() const override; virtual std::optional getZOLSupport() const override; virtual std::optional getJNZDSupport() const override; diff --git a/llvm/lib/Target/AIE/aie2p/AIE2PInstructionSelector.cpp b/llvm/lib/Target/AIE/aie2p/AIE2PInstructionSelector.cpp index e9ed7720ec21..7f985928cd5a 100644 --- a/llvm/lib/Target/AIE/aie2p/AIE2PInstructionSelector.cpp +++ b/llvm/lib/Target/AIE/aie2p/AIE2PInstructionSelector.cpp @@ -45,14 +45,10 @@ class AIE2PInstructionSelector : public AIEBaseInstructionSelector { bool select(MachineInstr &I) override; bool selectG_GLOBAL_VALUE(MachineInstr &I, MachineRegisterInfo &MRI); - bool selectSetControlRegister(MachineInstr &I, MachineRegisterInfo &MRI); - bool selectGetControlRegister(MachineInstr &I, MachineRegisterInfo &MRI); bool selectVSRS(MachineInstr &I, MachineRegisterInfo &MRI, unsigned crSRSModeVal); - bool selectVUPS(MachineInstr &I, MachineRegisterInfo &MRI, - unsigned crUPSModeVal); bool selectG_AIE_LOAD_UPS(MachineInstr &StoreI, MachineRegisterInfo &MRI, - unsigned crUPSModeVal); + std::optional crUPSModeVal) override; bool selectVCONVbfp16(MachineInstr &I, MachineRegisterInfo &MRI); bool selectG_AIE_PAD_VECTOR_UNDEF(MachineInstr &I, MachineOperand &DstReg, MachineOperand &SrcReg, @@ -316,8 +312,10 @@ bool AIE2PInstructionSelector::select(MachineInstr &I) { case G_INTRINSIC_W_SIDE_EFFECTS: switch (cast(I).getIntrinsicID()) { case Intrinsic::aie2p_set_ctrl_reg: + case Intrinsic::aie2p_set_status_reg: return selectSetControlRegister(I, MRI); case Intrinsic::aie2p_get_ctrl_reg: + case Intrinsic::aie2p_get_status_reg: return selectGetControlRegister(I, MRI); case Intrinsic::aie2p_I256_v16_acc32_srs: case Intrinsic::aie2p_I256_v32_acc32_srs: @@ -575,90 +573,6 @@ bool AIE2PInstructionSelector::selectG_GLOBAL_VALUE(MachineInstr &I, return constrainSelectedInstRegOperands(I, TII, TRI, RBI); } -// Build Instruction to get control register -bool AIE2PInstructionSelector::selectGetControlRegister( - MachineInstr &I, MachineRegisterInfo &MRI) { - - Register DstReg = I.getOperand(0).getReg(); - // In this case of G_INTRINSIC operand 1 is target intrinsic - Register IdxReg = I.getOperand(2).getReg(); - Register CtrlReg; - - // Check if the argument is constant for register map index. - if (auto Idx = getIConstantVRegValWithLookThrough(IdxReg, MRI)) - CtrlReg = TRI.getControlRegister(Idx->Value.getZExtValue()); - else - llvm_unreachable("Expected const value for control register map index."); - - if (!RBI.constrainGenericRegister(DstReg, AIE2P::eRRegClass, MRI)) - return false; - - auto CopyInstr = - MIB.buildInstr(TargetOpcode::COPY, {DstReg}, {}).addReg(CtrlReg); - if (!selectCopy(*CopyInstr, MRI)) { - return false; - } - I.eraseFromParent(); - return true; -} - -// Build Instruction to set control register -bool AIE2PInstructionSelector::selectSetControlRegister( - MachineInstr &I, MachineRegisterInfo &MRI) { - - Register IdxReg = I.getOperand(1).getReg(); - Register SrcReg = I.getOperand(2).getReg(); - Register CtrlReg; - - // Check if the argument is constant for register map index. - if (auto Idx = getIConstantVRegValWithLookThrough(IdxReg, MRI)) - CtrlReg = TRI.getControlRegister(Idx->Value.getZExtValue()); - else - llvm_unreachable("Expected const value for control register map index."); - - // Handle const input val for control regs. - if (auto Src = getIConstantVRegValWithLookThrough(SrcReg, MRI)) { - unsigned SrcConstVal = Src->Value.getZExtValue(); - /* Modulo by width of control regs. - To constrain the max possible value in the register - according to register width. - */ - switch (CtrlReg) { - case AIE2P::crSat: - SrcConstVal = SrcConstVal % (1 << 2); - break; - case AIE2P::crRnd: - SrcConstVal = SrcConstVal % (1 << 4); - break; - case AIE2P::crF2FMask: - case AIE2P::crF2IMask: - case AIE2P::crFPMask: - case AIE2P::crF2BMask: - SrcConstVal = SrcConstVal % (1 << 5); - break; - case AIE2P::crFPNlfMask: - case AIE2P::crFPCnvFx2FlMask: - case AIE2P::crFPCnvFl2FxMask: - SrcConstVal = SrcConstVal % (1 << 8); - break; - default: - break; - } - - MachineInstrBuilder MI = setCtrlRegister(MIB, CtrlReg, SrcConstVal); - I.eraseFromParent(); - return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); - } - - auto CopyInstr = - MIB.buildInstr(TargetOpcode::COPY, {CtrlReg}, {}).addReg(SrcReg); - if (!selectCopy(*CopyInstr, MRI)) - return false; - - I.eraseFromParent(); - return true; -} - bool AIE2PInstructionSelector::selectVSRS(MachineInstr &I, MachineRegisterInfo &MRI, unsigned crSRSModeVal) { @@ -687,9 +601,9 @@ bool AIE2PInstructionSelector::selectVSRS(MachineInstr &I, return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); } -bool AIE2PInstructionSelector::selectG_AIE_LOAD_UPS(MachineInstr &UPSI, - MachineRegisterInfo &MRI, - unsigned crUPSModeVal) { +bool AIE2PInstructionSelector::selectG_AIE_LOAD_UPS( + MachineInstr &UPSI, MachineRegisterInfo &MRI, + std::optional crUPSModeVal) { // First use is the G_INTRINSIC_W_SIDE_EFFECTS ID Register LoadResult = (std::next(UPSI.uses().begin()))->getReg(); @@ -736,11 +650,13 @@ bool AIE2PInstructionSelector::selectG_AIE_LOAD_UPS(MachineInstr &UPSI, (DstRegSize != 1024 || DstRegSize != 2048))) && "Unexpected VLDA.UPS size"); + if (!crUPSModeVal.has_value()) + return false; // Selects the mode of the accumulator for UPS instructions // 0 – 32-bit accumulator lane // 1 – 64-bit accumulator lane MIB.setInstr(UPSI); - setCtrlRegister(MIB, AIE2P::crUPSMode, crUPSModeVal); + setCtrlRegister(MIB, AIE2P::crUPSMode, *crUPSModeVal); auto NewInstr = MIB.buildInstr(LSO->ISelOpcode); @@ -764,40 +680,6 @@ bool AIE2PInstructionSelector::selectG_AIE_LOAD_UPS(MachineInstr &UPSI, return constrainSelectedInstRegOperands(*NewInstr.getInstr(), TII, TRI, RBI); } -bool AIE2PInstructionSelector::selectVUPS(MachineInstr &I, - MachineRegisterInfo &MRI, - unsigned crUPSModeVal) { - // First try to match UPS combine - if (selectG_AIE_LOAD_UPS(I, MRI, crUPSModeVal)) - return true; - - // TODO Match UPS combine - Register DstReg = I.getOperand(0).getReg(); - // In this case of G_INTRINSIC_W_SIDE_EFFECTS operand 1 is target intrinsic - Register SrcReg = I.getOperand(2).getReg(); - Register ShftReg = I.getOperand(3).getReg(); - Register SignReg = I.getOperand(4).getReg(); - // Selects the mode of the accumulator for UPS instructions - // 0 – 32-bit accumulator lane - // 1 – 64-bit accumulator lane - MIB.setInstr(I); - setCtrlRegister(MIB, AIE2P::crUPSMode, crUPSModeVal); - - if (auto SignVal = getIConstantVRegValWithLookThrough(SignReg, MRI)) { - // Handle constant sign through instruction patterns - return selectImpl(I, *CoverageInfo); - } - - unsigned OpCode = TII.getOpCode(I); - MachineInstrBuilder MI = - MIB.buildInstr(OpCode, {DstReg}, {}).addReg(SrcReg).addReg(ShftReg); - - setUnsetCtrlRegister(MIB, *MI, MRI, AIE2P::upsSign0, SignReg); - - I.eraseFromParent(); - return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); -} - bool AIE2PInstructionSelector::selectVCONVbfp16(MachineInstr &I, MachineRegisterInfo &MRI) { auto IntrinsicID = cast(I).getIntrinsicID(); diff --git a/llvm/lib/Target/AIE/aie2p/AIE2PRegisterInfo.cpp b/llvm/lib/Target/AIE/aie2p/AIE2PRegisterInfo.cpp index 622e3ae8e79a..2930ede76d4e 100644 --- a/llvm/lib/Target/AIE/aie2p/AIE2PRegisterInfo.cpp +++ b/llvm/lib/Target/AIE/aie2p/AIE2PRegisterInfo.cpp @@ -649,3 +649,66 @@ bool AIE2PRegisterInfo::shouldCoalesce( return TargetRegisterInfo::shouldCoalesce(MI, SrcRC, SubReg, DstRC, DstSubReg, NewRC, LIS); } + +unsigned +AIE2PRegisterInfo::matchControlRegisterBitwidth(Register CtrlReg, + unsigned SrcConstVal) const { + // Modulo by width of control regs. To constrain the max possible value in + // the register according to register width. + switch (CtrlReg) { + // 1-bit registers (status and control) + case AIE2P::srCarry: + case AIE2P::srSRS_of: + case AIE2P::srUPS_of: + case AIE2P::srSparse_of: + case AIE2P::srFifo_of: + case AIE2P::srFifo_uf: + case AIE2P::crSRSMode: + case AIE2P::crUPSMode: + case AIE2P::crUnpackSize: + case AIE2P::crPackSize: + case AIE2P::srsSign0: + case AIE2P::srsSign1: + case AIE2P::upsSign0: + case AIE2P::upsSign1: + case AIE2P::packSign0: + case AIE2P::packSign1: + case AIE2P::unpackSign0: + case AIE2P::unpackSign1: + case AIE2P::vaddSign0: + case AIE2P::vaddSign1: + case AIE2P::crSCDEn: + case AIE2P::crMCDEn: + return SrcConstVal % (1 << 1); + // 2-bit registers + case AIE2P::crSat: + return SrcConstVal % (1 << 2); + // 4-bit registers + case AIE2P::crRnd: + return SrcConstVal % (1 << 4); + // 5-bit registers (status and control) + case AIE2P::srFPFlags: + case AIE2P::srF2IFlags: + case AIE2P::srF2FFlags: + case AIE2P::srF2BFlags: + case AIE2P::crF2FMask: + case AIE2P::crF2IMask: + case AIE2P::crFPMask: + case AIE2P::crF2BMask: + return SrcConstVal % (1 << 5); + // 8-bit registers (status and control) + case AIE2P::srFPNlf: + case AIE2P::srFPCnvFx2Fl: + case AIE2P::srFPCnvFl2Fx: + case AIE2P::crFPNlfMask: + case AIE2P::crFPCnvFx2FlMask: + case AIE2P::crFPCnvFl2FxMask: + return SrcConstVal % (1 << 8); + // Stream switch status registers (variable width, no masking needed) + case AIE2P::srSS0: + case AIE2P::srMS0: + return SrcConstVal; // These are full-width, no masking + default: + llvm_unreachable("Unknown control or status register."); + } +} diff --git a/llvm/lib/Target/AIE/aie2p/AIE2PRegisterInfo.h b/llvm/lib/Target/AIE/aie2p/AIE2PRegisterInfo.h index 27e2540c1fbe..efbbfff203a6 100644 --- a/llvm/lib/Target/AIE/aie2p/AIE2PRegisterInfo.h +++ b/llvm/lib/Target/AIE/aie2p/AIE2PRegisterInfo.h @@ -71,7 +71,7 @@ struct AIE2PRegisterInfo : public AIE2PGenRegisterInfo { const MachineOperand &MO, const MachineRegisterInfo &MRI) const override; Register getStackPointerRegister() const override; - Register getControlRegister(unsigned Idx) const; + Register getControlRegister(unsigned Idx) const override; const TargetRegisterClass * getLargestLegalSuperClass(const TargetRegisterClass *RC, @@ -110,6 +110,9 @@ struct AIE2PRegisterInfo : public AIE2PGenRegisterInfo { unsigned SubReg, const TargetRegisterClass *DstRC, unsigned DstSubReg, const TargetRegisterClass *NewRC, LiveIntervals &LIS) const override; + + unsigned matchControlRegisterBitwidth(Register CtrlReg, + unsigned SrcConstVal) const override; }; } // namespace llvm diff --git a/llvm/test/CodeGen/AIE/aie2p/GlobalIsel/inst-select-set-mode.mir b/llvm/test/CodeGen/AIE/aie2p/GlobalIsel/inst-select-set-mode.mir index 9cc3c2da64fc..e9e110015ed6 100644 --- a/llvm/test/CodeGen/AIE/aie2p/GlobalIsel/inst-select-set-mode.mir +++ b/llvm/test/CodeGen/AIE/aie2p/GlobalIsel/inst-select-set-mode.mir @@ -4,7 +4,7 @@ # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # -# (c) Copyright 2024 Advanced Micro Devices, Inc. or its affiliates +# (c) Copyright 2024-2025 Advanced Micro Devices, Inc. or its affiliates # RUN: llc -mtriple aie2p -run-pass=instruction-select %s -verify-machineinstrs -o - | FileCheck %s --- @@ -329,3 +329,247 @@ body: | $r0 = COPY %0:gprregbank(s32) PseudoRET implicit $lr, implicit $r0 ... + +--- +name: set_srcarry +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + liveins: $r0 + ; CHECK-LABEL: name: set_srcarry + ; CHECK: liveins: $r0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:er = COPY $r0 + ; CHECK-NEXT: $srcarry = COPY [[COPY]] + ; CHECK-NEXT: PseudoRET implicit $lr + %0:gprregbank(s32) = COPY $r0 + %1:gprregbank(s32) = G_CONSTANT i32 25 + G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.set.status.reg), %1:gprregbank(s32), %0:gprregbank(s32) + PseudoRET implicit $lr +... + +--- +name: set_srss0 +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: set_srss0 + ; CHECK: $srss0 = MOV_scalar_imm11_pseudo 1 + ; CHECK-NEXT: PseudoRET implicit $lr + %0:gprregbank(s32) = G_CONSTANT i32 26 + %1:gprregbank(s32) = G_CONSTANT i32 1 + G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.set.status.reg), %0:gprregbank(s32), %1:gprregbank(s32) + PseudoRET implicit $lr +... + +--- +name: set_srms0 +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: set_srms0 + ; CHECK: $srms0 = MOV_scalar_imm11_pseudo 0 + ; CHECK-NEXT: PseudoRET implicit $lr + %0:gprregbank(s32) = G_CONSTANT i32 27 + %1:gprregbank(s32) = G_CONSTANT i32 0 + G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.set.status.reg), %0:gprregbank(s32), %1:gprregbank(s32) + PseudoRET implicit $lr +... + +--- +name: set_srsrs_of +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + liveins: $r0 + ; CHECK-LABEL: name: set_srsrs_of + ; CHECK: liveins: $r0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:er = COPY $r0 + ; CHECK-NEXT: $srsrs_of = COPY [[COPY]] + ; CHECK-NEXT: PseudoRET implicit $lr + %0:gprregbank(s32) = COPY $r0 + %1:gprregbank(s32) = G_CONSTANT i32 28 + G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.set.status.reg), %1:gprregbank(s32), %0:gprregbank(s32) + PseudoRET implicit $lr +... + +--- +name: set_srups_of +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: set_srups_of + ; CHECK: $srups_of = MOV_scalar_imm11_pseudo 0 + ; CHECK-NEXT: PseudoRET implicit $lr + %0:gprregbank(s32) = G_CONSTANT i32 8 + %1:gprregbank(s32) = G_CONSTANT i32 29 + G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.set.status.reg), %1:gprregbank(s32), %0:gprregbank(s32) + PseudoRET implicit $lr +... + +--- +name: set_srfpflags +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + liveins: $r0 + ; CHECK-LABEL: name: set_srfpflags + ; CHECK: liveins: $r0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:er = COPY $r0 + ; CHECK-NEXT: $srfpflags = COPY [[COPY]] + ; CHECK-NEXT: PseudoRET implicit $lr + %0:gprregbank(s32) = COPY $r0 + %1:gprregbank(s32) = G_CONSTANT i32 33 + G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.set.status.reg), %1:gprregbank(s32), %0:gprregbank(s32) + PseudoRET implicit $lr +... + +--- +name: get_srcarry +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: get_srcarry + ; CHECK: [[COPY:%[0-9]+]]:er = COPY $srcarry + ; CHECK-NEXT: $r0 = COPY [[COPY]] + ; CHECK-NEXT: PseudoRET implicit $lr, implicit $r0 + %1:gprregbank(s32) = G_CONSTANT i32 25 + %0:gprregbank(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.get.status.reg), %1:gprregbank(s32) + $r0 = COPY %0:gprregbank(s32) + PseudoRET implicit $lr, implicit $r0 +... + +--- +name: get_srss0 +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: get_srss0 + ; CHECK: [[COPY:%[0-9]+]]:er = COPY $srss0 + ; CHECK-NEXT: $r0 = COPY [[COPY]] + ; CHECK-NEXT: PseudoRET implicit $lr, implicit $r0 + %1:gprregbank(s32) = G_CONSTANT i32 26 + %0:gprregbank(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.get.status.reg), %1:gprregbank(s32) + $r0 = COPY %0:gprregbank(s32) + PseudoRET implicit $lr, implicit $r0 +... + +--- +name: get_srms0 +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: get_srms0 + ; CHECK: [[COPY:%[0-9]+]]:er = COPY $srms0 + ; CHECK-NEXT: $r0 = COPY [[COPY]] + ; CHECK-NEXT: PseudoRET implicit $lr, implicit $r0 + %1:gprregbank(s32) = G_CONSTANT i32 27 + %0:gprregbank(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.get.status.reg), %1:gprregbank(s32) + $r0 = COPY %0:gprregbank(s32) + PseudoRET implicit $lr, implicit $r0 +... + +--- +name: get_srsrs_of +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: get_srsrs_of + ; CHECK: [[COPY:%[0-9]+]]:er = COPY $srsrs_of + ; CHECK-NEXT: $r0 = COPY [[COPY]] + ; CHECK-NEXT: PseudoRET implicit $lr, implicit $r0 + %1:gprregbank(s32) = G_CONSTANT i32 28 + %0:gprregbank(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.get.status.reg), %1:gprregbank(s32) + $r0 = COPY %0:gprregbank(s32) + PseudoRET implicit $lr, implicit $r0 +... + +--- +name: get_srups_of +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: get_srups_of + ; CHECK: [[COPY:%[0-9]+]]:er = COPY $srups_of + ; CHECK-NEXT: $r0 = COPY [[COPY]] + ; CHECK-NEXT: PseudoRET implicit $lr, implicit $r0 + %1:gprregbank(s32) = G_CONSTANT i32 29 + %0:gprregbank(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.get.status.reg), %1:gprregbank(s32) + $r0 = COPY %0:gprregbank(s32) + PseudoRET implicit $lr, implicit $r0 +... + +--- +name: get_srfpflags +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: get_srfpflags + ; CHECK: [[COPY:%[0-9]+]]:er = COPY $srfpflags + ; CHECK-NEXT: $r0 = COPY [[COPY]] + ; CHECK-NEXT: PseudoRET implicit $lr, implicit $r0 + %1:gprregbank(s32) = G_CONSTANT i32 33 + %0:gprregbank(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.get.status.reg), %1:gprregbank(s32) + $r0 = COPY %0:gprregbank(s32) + PseudoRET implicit $lr, implicit $r0 +... + +--- +name: get_srf2iflags +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: get_srf2iflags + ; CHECK: [[COPY:%[0-9]+]]:er = COPY $srf2iflags + ; CHECK-NEXT: $r0 = COPY [[COPY]] + ; CHECK-NEXT: PseudoRET implicit $lr, implicit $r0 + %1:gprregbank(s32) = G_CONSTANT i32 34 + %0:gprregbank(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.get.status.reg), %1:gprregbank(s32) + $r0 = COPY %0:gprregbank(s32) + PseudoRET implicit $lr, implicit $r0 +... + +--- +name: get_srfpnlf +alignment: 16 +legalized: true +regBankSelected: true +body: | + bb.1.entry: + ; CHECK-LABEL: name: get_srfpnlf + ; CHECK: [[COPY:%[0-9]+]]:er = COPY $srfpnlf + ; CHECK-NEXT: $r0 = COPY [[COPY]] + ; CHECK-NEXT: PseudoRET implicit $lr, implicit $r0 + %1:gprregbank(s32) = G_CONSTANT i32 37 + %0:gprregbank(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aie2p.get.status.reg), %1:gprregbank(s32) + $r0 = COPY %0:gprregbank(s32) + PseudoRET implicit $lr, implicit $r0 +...