Skip to content

Commit f8325f1

Browse files
authored
[Tablegen] Bugfix and refactor VarLenCodeEmitter HwModes. (llvm#68795)
VarLenCodeEmitterGen produced code that did not compile if using alternative encoding in different HwModes. It's not possbile to assign unsigned **Index = Index_<mode>[][2] = { ... }; As a fix, Index and InstBits where removed in favor of mode specific getInstBits_<mode> functions since this is the only place the arrays are accessed. Handling of HwModes is now concentrated to the VarLenCodeEmitterGen::run method reducing the overall amount of code and enabling other types of alternative encodings not related to HwModes. Added a test for VarLenCodeEmitterGen HwModes. Make sure that HwModes are supported in the same way they are supported for the standard CodeEmitter. It should be possible to define instructions with universal encoding across modes, distinct encodings for each mode or only define encodings for some modes. Fixed indentation in generated code.
1 parent 833a8db commit f8325f1

File tree

2 files changed

+206
-93
lines changed

2 files changed

+206
-93
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// RUN: llvm-tblgen -gen-emitter -I %p/../../include %s | FileCheck %s
2+
3+
// Verify VarLenCodeEmitterGen using EncodingInfos with different HwModes.
4+
5+
include "llvm/Target/Target.td"
6+
7+
def ArchInstrInfo : InstrInfo { }
8+
9+
def Arch : Target {
10+
let InstructionSet = ArchInstrInfo;
11+
}
12+
13+
def Reg : Register<"reg">;
14+
15+
def RegClass : RegisterClass<"foo", [i64], 0, (add Reg)>;
16+
17+
def GR64 : RegisterOperand<RegClass>;
18+
19+
def HasA : Predicate<"Subtarget->hasA()">;
20+
def HasB : Predicate<"Subtarget->hasB()">;
21+
22+
def ModeA : HwMode<"+a", [HasA]>;
23+
def ModeB : HwMode<"+b", [HasB]>;
24+
25+
def fooTypeEncA : InstructionEncoding {
26+
dag Inst = (descend
27+
(operand "$src", 4),
28+
(operand "$dst", 4),
29+
0b00000001
30+
);
31+
}
32+
33+
def fooTypeEncB : InstructionEncoding {
34+
dag Inst = (descend
35+
(operand "$dst", 4),
36+
(operand "$src", 4),
37+
0b00000010
38+
);
39+
}
40+
41+
def fooTypeEncC : InstructionEncoding {
42+
dag Inst = (descend
43+
(operand "$dst", 4),
44+
(operand "$src", 4),
45+
0b00000100
46+
);
47+
}
48+
49+
class VarLenInst : Instruction {
50+
let AsmString = "foo $src, $dst";
51+
let OutOperandList = (outs GR64:$dst);
52+
let InOperandList = (ins GR64:$src);
53+
}
54+
55+
// Defined in both HwModes
56+
def foo : VarLenInst {
57+
let EncodingInfos = EncodingByHwMode<
58+
[ModeA, ModeB],
59+
[fooTypeEncA, fooTypeEncB]
60+
>;
61+
}
62+
63+
// Same encoding in any HwMode
64+
def bar : VarLenInst {
65+
dag Inst = (descend
66+
(operand "$dst", 4),
67+
(operand "$src", 4),
68+
0b00000011
69+
);
70+
}
71+
72+
// Only defined in HwMode B.
73+
def baz : VarLenInst {
74+
let EncodingInfos = EncodingByHwMode<
75+
[ModeB],
76+
[fooTypeEncC]
77+
>;
78+
}
79+
80+
// CHECK: static const uint64_t InstBits_ModeA[] = {
81+
// CHECK: UINT64_C(3), // bar
82+
// CHECK: UINT64_C(1), // foo
83+
84+
// CHECK: static const uint64_t InstBits_ModeB[] = {
85+
// CHECK: UINT64_C(3), // bar
86+
// CHECK: UINT64_C(4), // baz
87+
// CHECK: UINT64_C(2), // foo
88+
89+
// CHECK: auto getInstBits_ModeA =
90+
// CHECK: Idx = Index_ModeA
91+
92+
// CHECK: auto getInstBits_ModeB =
93+
// CHECK: Idx = Index_ModeB
94+
95+
// CHECK: case ::bar: {
96+
// CHECK-NOT: switch (Mode) {
97+
// CHECK: Inst = getInstBits_ModeA
98+
99+
// CHECK: case ::foo: {
100+
// CHECK: switch (Mode) {
101+
// CHECK: case 1: {
102+
// CHECK: Inst = getInstBits_ModeA
103+
// CHECK: case 2: {
104+
// CHECK: Inst = getInstBits_ModeB
105+
106+
// CHECK: case ::baz: {
107+
// CHECK: case 1: {
108+
// CHECK: llvm_unreachable("Undefined encoding in this mode");
109+
// CHECK: case 2: {
110+
// CHECK: Inst = getInstBits_ModeB

0 commit comments

Comments
 (0)