
TableGen builds up a map of "SubRegIdx -> Subclass" where Subclass is the largest class where all registers have SubRegIdx as a sub-register. When SubRegIdx (vis-a-vis the sub-register) is artificial it should still include it in the map. This map is used in various places, including in the calculation of the Lanemask of a register class, which otherwise calculates an incorrect lanemask.
220 lines
7.0 KiB
TableGen
220 lines
7.0 KiB
TableGen
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK
|
|
include "llvm/Target/Target.td"
|
|
|
|
// This file tests that when using `isArtificial` for subregisters in
|
|
// combination with `CoveredBySubRegs`, that TableGen infers the
|
|
// correct register classes, subregisters and lane masks, especially
|
|
// when the registers (that consist partially from artificial subregs)
|
|
// are used in tuples.
|
|
//
|
|
// The register hierarchy that this test implements is:
|
|
//
|
|
// ssub_hi ssub
|
|
// \ /
|
|
// dsub
|
|
// dsub_hi /
|
|
// \ /
|
|
// qsub
|
|
//
|
|
// Where the _hi parts are artificial and where subregs ssub, dsub and qsub
|
|
// are all addressable as real registers.
|
|
//
|
|
// These are then used in {S0, S1, S2}, {D0, D1, D2} and {Q0, Q1, Q2},
|
|
// from which tuples are created.
|
|
|
|
class MyReg<string n, list<Register> subregs = []>
|
|
: Register<n> {
|
|
let Namespace = "Test";
|
|
let SubRegs = subregs;
|
|
}
|
|
|
|
class MyClass<int size, list<ValueType> types, dag registers>
|
|
: RegisterClass<"Test", types, size, registers> {
|
|
let Size = size;
|
|
}
|
|
|
|
def ssub : SubRegIndex< 32, 0>;
|
|
def ssub_hi : SubRegIndex< 32, 32>;
|
|
def dsub : SubRegIndex< 64, 0>;
|
|
def dsub_hi : SubRegIndex< 64, 64>;
|
|
def qsub : SubRegIndex<128, 0>;
|
|
|
|
def S0 : MyReg<"s0">;
|
|
def S1 : MyReg<"s1">;
|
|
def S2 : MyReg<"s2">;
|
|
|
|
let isArtificial = 1 in {
|
|
def S0_HI : MyReg<"s0_hi">;
|
|
def S1_HI : MyReg<"s1_hi">;
|
|
def S2_HI : MyReg<"s2_hi">;
|
|
|
|
def D0_HI : MyReg<"D0_hi">;
|
|
def D1_HI : MyReg<"D1_hi">;
|
|
def D2_HI : MyReg<"D2_hi">;
|
|
}
|
|
|
|
let SubRegIndices = [ssub, ssub_hi], CoveredBySubRegs = 1 in {
|
|
def D0 : MyReg<"d0", [S0, S0_HI]>;
|
|
def D1 : MyReg<"d1", [S1, S1_HI]>;
|
|
def D2 : MyReg<"d2", [S2, S2_HI]>;
|
|
}
|
|
|
|
let SubRegIndices = [dsub, dsub_hi], CoveredBySubRegs = 1 in {
|
|
def Q0 : MyReg<"q0", [D0, D0_HI]>;
|
|
def Q1 : MyReg<"q1", [D1, D1_HI]>;
|
|
def Q2 : MyReg<"q2", [D2, D2_HI]>;
|
|
}
|
|
|
|
def SRegs : MyClass<32, [i32], (sequence "S%u", 0, 2)>;
|
|
def DRegs : MyClass<64, [i64], (sequence "D%u", 0, 2)>;
|
|
def QRegs : MyClass<128, [i128], (sequence "Q%u", 0, 2)>;
|
|
|
|
def dsub0 : SubRegIndex<64>;
|
|
def dsub1 : SubRegIndex<64>;
|
|
def dsub2 : SubRegIndex<64>;
|
|
|
|
def ssub0 : SubRegIndex<32>;
|
|
def ssub1 : ComposedSubRegIndex<dsub1, ssub>;
|
|
def ssub2 : ComposedSubRegIndex<dsub2, ssub>;
|
|
|
|
def STuples2 : RegisterTuples<[ssub0, ssub1],
|
|
[(shl SRegs, 0), (shl SRegs, 1)]>;
|
|
def STuplesRC2 : MyClass<64, [untyped], (add STuples2)>;
|
|
|
|
def DTuples2 : RegisterTuples<[dsub0, dsub1],
|
|
[(shl DRegs, 0), (shl DRegs, 1)]>;
|
|
def DTuplesRC2 : MyClass<128, [untyped], (add DTuples2)>;
|
|
|
|
def STuples3 : RegisterTuples<[ssub0, ssub1, ssub2],
|
|
[(shl SRegs, 0), (shl SRegs, 1), (shl SRegs, 2)]>;
|
|
def STuplesRC3 : MyClass<96, [untyped], (add STuples3)>;
|
|
|
|
def DTuples3 : RegisterTuples<[dsub0, dsub1, dsub2],
|
|
[(shl DRegs, 0), (shl DRegs, 1), (shl DRegs, 2)]>;
|
|
def DTuplesRC3 : MyClass<192, [untyped], (add DTuples3)>;
|
|
|
|
def TestTarget : Target;
|
|
|
|
// CHECK: RegisterClass SRegs:
|
|
// CHECK: LaneMask: 0000000000000001
|
|
// CHECK: HasDisjunctSubRegs: 0
|
|
// CHECK: CoveredBySubRegs: 0
|
|
// CHECK: Regs: S0 S1 S2
|
|
// CHECK: SubClasses: SRegs
|
|
// CHECK: SuperClasses:
|
|
//
|
|
// CHECK: RegisterClass DRegs:
|
|
// CHECK: LaneMask: 0000000000000044
|
|
// CHECK: HasDisjunctSubRegs: 1
|
|
// CHECK: CoveredBySubRegs: 1
|
|
// CHECK: Regs: D0 D1 D2
|
|
// CHECK: SubClasses: DRegs
|
|
// CHECK: SuperClasses:
|
|
//
|
|
// CHECK: RegisterClass QRegs:
|
|
// CHECK: LaneMask: 0000000000000045
|
|
// CHECK: HasDisjunctSubRegs: 1
|
|
// CHECK: CoveredBySubRegs: 1
|
|
// CHECK: Regs: Q0 Q1 Q2
|
|
// CHECK: SubClasses: QRegs
|
|
// CHECK: SuperClasses:
|
|
//
|
|
// CHECK: SubRegIndex dsub:
|
|
// CHECK-NEXT: LaneMask: 0000000000000044
|
|
// CHECK: SubRegIndex dsub0:
|
|
// CHECK-NEXT: LaneMask: 0000000000000044
|
|
// CHECK: SubRegIndex dsub1:
|
|
// CHECK-NEXT: LaneMask: 0000000000000090
|
|
// CHECK: SubRegIndex dsub2:
|
|
// CHECK-NEXT: LaneMask: 0000000000000120
|
|
// CHECK: SubRegIndex dsub_hi:
|
|
// CHECK-NEXT: LaneMask: 0000000000000001
|
|
// CHECK: SubRegIndex ssub:
|
|
// CHECK-NEXT: LaneMask: 0000000000000004
|
|
// CHECK: SubRegIndex ssub0:
|
|
// CHECK-NEXT: LaneMask: 0000000000000008
|
|
// CHECK: SubRegIndex ssub1:
|
|
// CHECK-NEXT: LaneMask: 0000000000000010
|
|
// CHECK: SubRegIndex ssub2:
|
|
// CHECK-NEXT: LaneMask: 0000000000000020
|
|
// CHECK: SubRegIndex ssub_hi:
|
|
// CHECK-NEXT: LaneMask: 0000000000000040
|
|
// CHECK: SubRegIndex dsub1_then_ssub_hi:
|
|
// CHECK-NEXT: LaneMask: 0000000000000080
|
|
// CHECK: SubRegIndex dsub2_then_ssub_hi:
|
|
// CHECK-NEXT: LaneMask: 0000000000000100
|
|
// CHECK: SubRegIndex ssub_ssub1:
|
|
// CHECK-NEXT: LaneMask: 0000000000000014
|
|
// CHECK: SubRegIndex dsub0_dsub1:
|
|
// CHECK-NEXT: LaneMask: 00000000000000D4
|
|
// CHECK: SubRegIndex dsub1_dsub2:
|
|
// CHECK-NEXT: LaneMask: 00000000000001B0
|
|
// CHECK: SubRegIndex ssub_ssub1_ssub2:
|
|
// CHECK-NEXT: LaneMask: 0000000000000034
|
|
// CHECK: SubRegIndex ssub1_ssub2:
|
|
// CHECK-NEXT: LaneMask: 0000000000000030
|
|
// CHECK: SubRegIndex ssub0_ssub1:
|
|
// CHECK-NEXT: LaneMask: 0000000000000018
|
|
|
|
// CHECK: Register D0:
|
|
// CHECK: CoveredBySubregs: 1
|
|
// CHECK: HasDisjunctSubRegs: 1
|
|
// CHECK: SubReg ssub = S0
|
|
// CHECK: SubReg ssub_hi = S0_HI
|
|
//
|
|
// CHECK: Register Q0:
|
|
// CHECK: CoveredBySubregs: 1
|
|
// CHECK: HasDisjunctSubRegs: 1
|
|
// CHECK: SubReg dsub = D0
|
|
// CHECK: SubReg dsub_hi = D0_HI
|
|
// CHECK: SubReg ssub = S0
|
|
// CHECK: SubReg ssub_hi = S0_HI
|
|
//
|
|
// CHECK: Register S0:
|
|
// CHECK: CoveredBySubregs: 0
|
|
// CHECK: HasDisjunctSubRegs: 0
|
|
//
|
|
// CHECK: Register D0_D1:
|
|
// CHECK: CoveredBySubregs: 1
|
|
// CHECK: HasDisjunctSubRegs: 1
|
|
// CHECK: SubReg dsub0 = D0
|
|
// CHECK: SubReg dsub1 = D1
|
|
// CHECK: SubReg ssub = S0
|
|
// CHECK: SubReg ssub1 = S1
|
|
// CHECK: SubReg ssub_hi = S0_HI
|
|
// CHECK: SubReg dsub1_then_ssub_hi = S1_HI
|
|
// CHECK: SubReg ssub_ssub1 = S0_S1
|
|
//
|
|
// CHECK: Register D0_D1_D2:
|
|
// CHECK: CoveredBySubregs: 1
|
|
// CHECK: HasDisjunctSubRegs: 1
|
|
// CHECK: SubReg dsub0 = D0
|
|
// CHECK: SubReg dsub1 = D1
|
|
// CHECK: SubReg dsub2 = D2
|
|
// CHECK: SubReg ssub = S0
|
|
// CHECK: SubReg ssub1 = S1
|
|
// CHECK: SubReg ssub2 = S2
|
|
// CHECK: SubReg ssub_hi = S0_HI
|
|
// CHECK: SubReg dsub1_then_ssub_hi = S1_HI
|
|
// CHECK: SubReg dsub2_then_ssub_hi = S2_HI
|
|
// CHECK: SubReg ssub_ssub1 = S0_S1
|
|
// CHECK: SubReg dsub0_dsub1 = D0_D1
|
|
// CHECK: SubReg dsub1_dsub2 = D1_D2
|
|
// CHECK: SubReg ssub_ssub1_ssub2 = S0_S1_S2
|
|
// CHECK: SubReg ssub1_ssub2 = S1_S2
|
|
//
|
|
// CHECK: Register S0_S1:
|
|
// CHECK: CoveredBySubregs: 1
|
|
// CHECK: HasDisjunctSubRegs: 1
|
|
// CHECK: SubReg ssub0 = S0
|
|
// CHECK: SubReg ssub1 = S1
|
|
//
|
|
// CHECK: Register S0_S1_S2:
|
|
// CHECK: CoveredBySubregs: 1
|
|
// CHECK: HasDisjunctSubRegs: 1
|
|
// CHECK: SubReg ssub0 = S0
|
|
// CHECK: SubReg ssub1 = S1
|
|
// CHECK: SubReg ssub2 = S2
|
|
// CHECK: SubReg ssub1_ssub2 = S1_S2
|
|
// CHECK: SubReg ssub0_ssub1 = S0_S1
|