-
Notifications
You must be signed in to change notification settings - Fork 29
[AIEX] Refactor Set/GetControlRegister and UPS instruction selection to share common code #712
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: aie-public
Are you sure you want to change the base?
Changes from all commits
e337104
da7c5c5
c83d8e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps we can generalize this using getRegSizeInBits(Reg, MRI)
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm. It looks as if their size is 32 bit...
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you're right |
||
| default: | ||
| llvm_unreachable("Unknown control register."); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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."); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. getIConstantVRegValWithLookThroughOrFail() could encapsulate the llvm_unreachable. |
||
|
|
||
| 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<unsigned> 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); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CHECK: this is mimicking the hardware when it would move it from a register source. To be frank, I would prefer a frontend error on writing an out of bound constant value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where should the valid range constraints for control registers be enforced, at the intrinsic definition in headers?