How to specify the RegisterClass of an IMPLICIT_DEF?


I’m implementing the built_vector as an IMPLICIT_DEF followed by INSERT_SUBREGs. This approach is the one of the SPARC architecture.

def : Pat<(build_vector (f32 fpimm:$a1), (f32 fpimm:$a2)),


(i32 (COPY_TO_REGCLASS (MOVSUTO_A_iSLo (bitcast_fpimm_to_i32 f32:$a1)), FPUaOffsetClass)), A_UNIT_PART),

(i32 (COPY_TO_REGCLASS (MOVSUTO_A_iSLo (bitcast_fpimm_to_i32 f32:$a2)), FPUaOffsetClass)), B_UNIT_PART)>;

This work quite well: an IMPLICIT_DEF:v2f32 is generated.

Selected selection DAG: BB#0 ‘vector2floatMulSum:entry’

SelectionDAG has 19 nodes:

t0: ch = EntryToken

t2: v2f32,ch = CopyFromReg t0, Register:v2f32 %vreg0

t4: v2f32,ch = CopyFromReg t2:1, Register:v2f32 %vreg1

t14: i16 = MOVSUTO_A_iSLo Constant:i32<1084227584>

t16: i32 = COPY_TO_REGCLASS t14, TargetConstant:i32<8>

t18: v2f32 = INSERT_SUBREG IMPLICIT_DEF:v2f32, t16, TargetConstant:i32<1>

t6: v2f32 = INSERT_SUBREG t18, t16, TargetConstant:i32<2>

t7: v2f32 = FMUL_AB_oo t2, t6

But there is one small issue in the inference of RegisterClass of the implicitly defined register.

As shown below, the %vreg6 is implicitly defined as FPUabRegisterClass.

This register class accepts the v2f32 type, but for others addressing mode context this register should be FPUabOffsetClass.

Is there a mechanism, an option to inforce/control the RegisterClass of registers defined by IMPLICIT_DEF ?

Machine code for function vector2floatMulSum: SSA

Function Live Ins: %FA_ROFF1 in %vreg0, %FA_ROFF2 in %vreg1

BB#0: derived from LLVM BB %entry

Live Ins: %FA_ROFF1 %FA_ROFF2

%vreg1 = COPY %FA_ROFF2; FPUabOffsetClass:%vreg1

%vreg0 = COPY %FA_ROFF1; FPUabOffsetClass:%vreg0

%vreg3 = MOVSUTO_A_iSLo 1084227584, %RSPA; FPUaOffsetClass:%vreg3

%vreg4 = COPY %vreg3; FPUaOffsetClass:%vreg4,%vreg3

→ %vreg6 = IMPLICIT_DEF; FPUabRegisterClass:%vreg6

%vreg5<def,tied1> = INSERT_SUBREG %vreg6, %vreg4, A_UNIT_PART; FPUabRegisterClass:%vreg5,%vreg6 FPUaOffsetClass:%vreg4

%vreg7<def,tied1> = INSERT_SUBREG %vreg5, %vreg4, B_UNIT_PART; FPUabRegisterClass:%vreg7,%vreg5 FPUaOffsetClass:%vreg4

%vreg9 = COPY %vreg7; FPUabOffsetClass:%vreg9 FPUabRegisterClass:%vreg7

%vreg8 = FMUL_AB_oo %vreg0, %vreg9, %RFLAGA<imp-def,dead>, %RFLAGB<imp-def,dead>, %RSPA, %RSPB; FPUabROUTMULRegisterClass:%vreg8 FPUabOffsetClass:%vreg0,%vreg9

A virtual register has a specific register class assigned to it, and is implicitly a member of any superclass of that class. If you want to use the register in a place that requires another class, you will need to create a new virtual register for the new class and copy the value into it.

In instruction selection, it's usually the type of the value that determines the register class of the register holding it. Also, the register classes of instruction operands can restrict it further. If you want to put a certain value into a register from a specific class, you can use COPY_TO_REGCLASS (just like the code you quoted does):
   Dst = COPY_TO_REGCLASS Src, RegClass


After further investigation of the TargetLoweringBase class, the register is allocated from RegisterClass defined by the RegClassForVT table.
This table is defined by the addRegisterClass() sequence. Only the last RegisterClass for a given type is kept.
So by ordering the addRegisterClass() sequence, you can enforce the allocated RegisterClass.
I my case, this lead to a more optimized generated code.

Thanks for your general advice. Regards, Dominique Torette.