TargetRegisterInfo::getCommonSubClass bug, perhaps.

Hi,

ABCRegister.td :
def SGPR32 : RegisterClass<"ABC", [i32], 16, (add
    S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11,
    S12, S13, S14, S15
  )>;

def SFGPR32 : RegisterClass<"ABC", [f32], 16, (add
    S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11,
    S12, S13, S14, S15
  )>;

===== Instruction selection ends:
...
            t8: i32 = ADDrr t37, t32
...
Instruction Selection correct : i32 = ADDrr i32, i32

*** MachineFunction at end of ISel ***
# Machine code for function _Z11scalar_loopPsS_ss: IsSSA, TracksLiveness
...
  %31:sfgpr32 = ADDrr killed %32:sgpr32, %27:sgpr32
...

Here should not select f32 sfgpr32 register, debugger point to
TargetRegisterInfo:: getCommonSubClass(const TargetRegisterClass *A,
                    const TargetRegisterClass *B,
                    const MVT::SimpleValueType SVT =
                    MVT::SimpleValueType::Any)
This function has been called 10+ in LLVM, only one place give
specific SVT parameter. Most of those places are hard to get the
MVT::SimpleValueType infos and use the default value. That's why
sfgpr32 comes out. LLVM defect?

Hi,

ABCRegister.td :
def SGPR32 : RegisterClass<"ABC", [i32], 16, (add
   S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11,
   S12, S13, S14, S15
)>;

def SFGPR32 : RegisterClass<"ABC", [f32], 16, (add
   S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11,
   S12, S13, S14, S15
)>;

===== Instruction selection ends:
...
           t8: i32 = ADDrr t37, t32
...
Instruction Selection correct : i32 = ADDrr i32, i32

*** MachineFunction at end of ISel ***
# Machine code for function _Z11scalar_loopPsS_ss: IsSSA, TracksLiveness
...
%31:sfgpr32 = ADDrr killed %32:sgpr32, %27:sgpr32
...

Here should not select f32 sfgpr32 register, debugger point to
TargetRegisterInfo:: getCommonSubClass(const TargetRegisterClass *A,
                   const TargetRegisterClass *B,
                   const MVT::SimpleValueType SVT =
                   MVT::SimpleValueType::Any)
This function has been called 10+ in LLVM, only one place give
specific SVT parameter. Most of those places are hard to get the
MVT::SimpleValueType infos and use the default value. That's why
sfgpr32 comes out. LLVM defect?

That doesn’t sound problematic. getCommonSubClass should have enough information to get the right register class from A and B.
What is your description of ADDrr. It sounds to me that you allowed ADDrr destination to use SFGPR32 and that would be your problem.

Cheers,
-Quentin

That doesn’t sound problematic. getCommonSubClass should have enough information to get the right register class from A and B.
What is your description of ADDrr. It sounds to me that you allowed ADDrr destination to use SFGPR32 and that would be your problem.

Cheers,
-Quentin

I only allowed ADDrr use SGPR32 register class. Here's fragment of
llvm-tblgen -print-records infos.

def ADDrr { // Instruction ABCInst ABCInstPErr
....
  string Namespace = "ABC";
  dag OutOperandList = (outs SGPR32:$vx);
  dag InOperandList = (ins SGPR32:$rs1, SGPR32:$rs2);
  string AsmString = "ADD.U32 $rs1, $rs2, $vx";
....

I was going to say that you should check what arguments you get from getCommonSubClass and where it comes from for the faulty call, because per the instruction description, ISel is supposed to constrain your destination to SGPR32, but actually, you’re problem is much simpler.

Looking back at your register classes descriptions, both SGPR32 and SFGPR32 contains the exact same set of registers. Thus, for the purpose of constraining the arguments it does not matter which one is being used.
You should make them truly disjoint if you don’t want them to be used interchangeably.