Preface
My question is similar to this one, but it is also different.
2022: [GISel/InstructionSelect] Assertion: Register class not set, wrong accessor?
A brief introduction to my compiler backend information
Before I describe my problem, please allow me to describe the hardware situation of the compiler backend I have implemented.
There are two register classes in the hardware, SGPR and SRAR. SGPR includes registers: R1, R2, R3. The SRAR register class includes AR1, AR2, and AR3, as well as OR1, OR2, and OR3. SGPR registers are used for storing integers and floating-point numbers. SRAR is used for storing addresses, where AR stores the base address and OR stores the offset.
If there is a need to transfer data between registers of the SGPR and SAR, the SMVA instruction needs to be used.
For example:
...
// SVMI: immediate move instruction
// SMVA: address move instruction
// SST: scalar store instruction
SMVI 100, R3; // R3 = 100;
SMVI 1, R1; // R1 is assigned the value 1
SMVA R1, AR1; // Give the value of R1 to AR1 as the base address
SMVI 8, R2;
SMVA R2, OR1;
SST R3, AR1, OR1; // Save the value of the R3 register at the address of AR1+OR1
...
I now have the following tablegen definition:
def SGP32Regs : RegisterClass<"Matrix", [i32], 32, (add (sequence "R%u", 0, 63))>;
def SGP64Regs : RegisterClass<"Matrix", [i64], 64, (add (sequence "R%u", 0, 63))>;
...
/// Scalar General Purpose Registers:
def SGPRRegBank : RegisterBank<"SGPR",
[SGP32Regs, SGP64Regs, SGPv2i32Regs, SGPv4i16Regs]>;
def ARegs : RegisterClass<"Matrix", [i64], 64, (add (sequence "AR%u", 0, 15))>;
...
/// Scalar Address Base Address Registers:
def SARRegBank : RegisterBank<"SAR",
[SARegs]>;
Problems encountered in global instruction selection
gMIR
...
%15:sgpr(s64) = G_LOAD %27:sgpr(p0) :: (dereferenceable load (s64) from %ir.i)
%25:sgpr(s64) = G_CONSTANT i64 3
%16:sgpr(s64) = G_SHL %15:sgpr, %25:sgpr(s64)
%29:sgpr(p0) = G_FRAME_INDEX %stack.1.b
%17:sgpr(p0) = G_PTR_ADD %29:sgpr, %16:sgpr(s64)
G_STORE %14:sgpr(s64), %17:sgpr(p0) :: (store (s64) into %ir.arrayidx1)
...
Global Instruction Selection procedure:
Selecting:
G_STORE %14:sgpr(s64), %17:sgpr(p0) :: (store (s64) into %ir.arrayidx1)
5: GIM_SwitchOpcode(MIs[0], [45, 201), Default=14437, JumpTable...) // Got=84
2936: Begin try-block
2941: GIM_CheckType(MIs[0]->getOperand(0), TypeID=1)
2942: Begin try-block
2947: GIM_CheckMemorySizeEqual(MIs[0]->memoperands() + 0, Size=8)
8 bytes vs 8 bytes
2950: GIM_CheckAtomicOrderingWeakerThan(MIs[0], 5)
2953: GIM_CheckAtomicOrderingOrStrongerThan(MIs[0], 1)
2953: Rejected
2990: Resume at 2990 (2 try-blocks remain)
2991: Begin try-block
2996: GIM_CheckMemorySizeEqualToLLT(MIs[0]->memoperands() + 0, OpIdx=0)
2999: GIM_CheckAtomicOrdering(MIs[0], 0)
3003: GIM_CheckRegBankForClass(MIs[0]->getOperand(0), RCEnum=5)
3007: GIM_CheckPointerToAny(MIs[0]->getOperand(1), SizeInBits=0)
3008: Begin try-block
3014: State.Renderers[0] = GIM_CheckComplexPattern(MIs[0]->getOperand(1), ComplexPredicateID=5)
3017: GIR_BuildMI(OutMIs[0], 494)
3021: GIR_Copy(OutMIs[0], MIs[0], 0)
3025: GIR_ComplexSubOperandRenderer(OutMIs[0], 0, 0)
3029: GIR_ComplexSubOperandRenderer(OutMIs[0], 0, 1)
3031: GIR_MergeMemOperands(OutMIs[0], MIs[0])
3035: GIR_EraseFromParent(MIs[0])
Converting operand: %14:sgpr
Converting operand: %29:sgpr
Converting operand: %16:sgpr
3037: GIR_ConstrainSelectedInstOperands(OutMIs[0])
3038: GIR_Done
Into:
%35:saregs = COPY %29:sgpr(p0)
%36:soregs = COPY %16:sgpr(s64)
SSTW %14:sgpregs(s64), %35:saregs, %36:soregs :: (store (s64) into %ir.arrayidx1)
The problem arises
The COPY instruction was added automatically, which would have been fine.However, during the verification process after instruction selection, there are issues that arise.
Function call stack
The problems that arise are:
llc: /root/project/llvm-15.0.1-for-matrix/llvm/include/llvm/CodeGen/MachineRegisterInfo.h:644: const llvm::TargetRegisterClass *llvm::MachineRegisterInfo::getRegClass(llvm::Register) const: Assertion `VRegInfo[Reg.id()].first.is<const TargetRegisterClass *>() && "Register class not set, wrong accessor"' failed.
In other words, the RegClass of the variable %29 in the instruction %35:saregs = COPY %29:sgpr(p0)
has not been set correctly.
I’m confused and puzzled, I need help!
%35:saregs = COPY %29:sgpr(p0)
This instruction is automatically generated during the instruction selection process, and I am not sure why a COPY instruction is being generated, and why the register class for the variable %29 is not set correctly.
gMIR at the time of the error occurrence.
...
%16:sgpregs(s64) = SSHFLLrr %25:sgpregs(s64), %15:sgpregs(s64), 0
%37:sraregs = SADDAri %stack.1.b, 0
%29:sgpr(p0) = COPY %37:sraregs
%35:saregs = COPY %29:sgpr(p0)
%36:soregs = COPY %16:sgpregs(s64)
SSTW %14:sgpregs(s64), %35:saregs, %36:soregs :: (store (s64) into %ir.arrayidx1)
...
error info:
llc: /root/project/llvm-15.0.1-for-matrix/llvm/include/llvm/CodeGen/MachineRegisterInfo.h:644: const llvm::TargetRegisterClass *llvm::MachineRegisterInfo::getRegClass(llvm::Register) const: Assertion `VRegInfo[Reg.id()].first.is<const TargetRegisterClass *>() && “Register class not set, wrong accessor”’ failed.
I would like to know how to avoid this error. I am currently clueless and would greatly appreciate it if you could provide me with some ideas, suggestions, advice, guidance, or relevant resources.