Skip to content

Commit ebe1ece

Browse files
authored
[TableGen][RISCV] Support sub-operands in CompressInstEmitter.cpp. (#133039)
I'm looking into using sub-operands for memory operands. This would use MIOperandInfo to create a single operand that contains a register and immediate as sub-operands. We can treat this as a single operand for parsing and matching in the assembler. I believe this will provide some simplifications like removing the InstAliases we need to support "(rs1)" without an immediate. Doing this requires making CompressInstEmitter aware of sub-operands. I've chosen to use a flat list of operands in the CompressPats so each sub-operand is represented individually.
1 parent 89cfeeb commit ebe1ece

File tree

2 files changed

+468
-174
lines changed

2 files changed

+468
-174
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
// RUN: llvm-tblgen -gen-compress-inst-emitter -I %p/../../../include %s 2>&1 | FileCheck %s
2+
3+
include "llvm/Target/Target.td"
4+
5+
def ArchInstrInfo : InstrInfo { }
6+
def ArchAsmWriter : AsmWriter {
7+
int PassSubtarget = 1;
8+
}
9+
10+
def Arch : Target {
11+
let InstructionSet = ArchInstrInfo;
12+
let AssemblyWriters = [ArchAsmWriter];
13+
}
14+
15+
def Reg0 : Register<"reg0"> {
16+
let HWEncoding{4-0} = 0;
17+
}
18+
def Reg1 : Register<"reg1"> {
19+
let HWEncoding{4-0} = 1;
20+
}
21+
22+
def Regs : RegisterClass<"Arch", [i32], 32, (add Reg0, Reg1)>;
23+
def RegsC : RegisterClass<"Arch", [i32], 32, (sub Regs, Reg0)>;
24+
25+
def simm6 : Operand<i32>, ImmLeaf<i32, [{return isInt<6>(Imm);}]> {
26+
let MCOperandPredicate = [{
27+
int64_t Imm;
28+
if (!MCOp.evaluateAsConstantImm(Imm))
29+
return false;
30+
return isInt<6>(Imm);
31+
}];
32+
}
33+
34+
def simm12 : Operand<i32>, ImmLeaf<i32, [{return isInt<12>(Imm);}]> {
35+
let MCOperandPredicate = [{
36+
int64_t Imm;
37+
if (!MCOp.evaluateAsConstantImm(Imm))
38+
return false;
39+
return isInt<12>(Imm);
40+
}];
41+
}
42+
43+
def MemOpnd : Operand<iPTR> {
44+
let MIOperandInfo = (ops Regs, simm12);
45+
}
46+
47+
def MemOpndC : Operand<iPTR> {
48+
let MIOperandInfo = (ops RegsC, simm6);
49+
}
50+
51+
def BigInst : Instruction {
52+
let Namespace = "MyNS";
53+
let OutOperandList = (outs Regs:$dst);
54+
let InOperandList = (ins MemOpnd:$addr);
55+
let Size = 4;
56+
let AsmString = "big $dst, $addr";
57+
}
58+
59+
def SmallInst : Instruction {
60+
let Namespace = "MyNS";
61+
let OutOperandList = (outs RegsC:$dst);
62+
let InOperandList = (ins MemOpndC:$addr);
63+
let Size = 2;
64+
let AsmString = "small $dst, $addr";
65+
}
66+
67+
def : CompressPat<(BigInst RegsC:$dst, RegsC:$src, simm6:$imm),
68+
(SmallInst RegsC:$dst, RegsC:$src, simm6:$imm)>;
69+
70+
def BigInst2 : Instruction {
71+
let Namespace = "MyNS";
72+
let OutOperandList = (outs Regs:$dst);
73+
let InOperandList = (ins MemOpnd:$addr);
74+
let Size = 4;
75+
let AsmString = "big $dst, $addr";
76+
}
77+
78+
def SmallInst2 : Instruction {
79+
let Namespace = "MyNS";
80+
let OutOperandList = (outs RegsC:$dst);
81+
let InOperandList = (ins RegsC:$src, simm6:$imm);
82+
let Size = 2;
83+
let AsmString = "small $dst, $src, $imm";
84+
}
85+
86+
def : CompressPat<(BigInst2 RegsC:$dst, RegsC:$src, simm6:$imm),
87+
(SmallInst2 RegsC:$dst, RegsC:$src, simm6:$imm)>;
88+
89+
def BigInst3 : Instruction {
90+
let Namespace = "MyNS";
91+
let OutOperandList = (outs Regs:$dst);
92+
let InOperandList = (ins Regs:$src, simm12:$imm);
93+
let Size = 4;
94+
let AsmString = "big $dst, $src, $imm";
95+
}
96+
97+
def SmallInst3 : Instruction {
98+
let Namespace = "MyNS";
99+
let OutOperandList = (outs RegsC:$dst);
100+
let InOperandList = (ins MemOpndC:$addr);
101+
let Size = 2;
102+
let AsmString = "small $dst, $addr";
103+
}
104+
105+
def : CompressPat<(BigInst3 RegsC:$dst, RegsC:$src, simm6:$imm),
106+
(SmallInst3 RegsC:$dst, RegsC:$src, simm6:$imm)>;
107+
108+
// CHECK-LABEL: ArchValidateMCOperandForCompress
109+
// CHECK: // simm6
110+
// CHECK: return isInt<6>(Imm);
111+
112+
// CHECK-LABEL: compressInst
113+
// CHECK: case Arch::BigInst
114+
// CHECK-NEXT: if (MI.getOperand(0).isReg() &&
115+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) &&
116+
// CHECK-NEXT: MI.getOperand(1).isReg() &&
117+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) &&
118+
// CHECK-NEXT: ArchValidateMCOperandForCompress(MI.getOperand(2), STI, 1)) {
119+
// CHECK-NEXT: // small $dst, $addr
120+
// CHECK-NEXT: OutInst.setOpcode(Arch::SmallInst);
121+
// CHECK-NEXT: // Operand: dst
122+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0));
123+
// CHECK-NEXT: // Operand: addr
124+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1));
125+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(2));
126+
// CHECK-NEXT: OutInst.setLoc(MI.getLoc());
127+
// CHECK-NEXT: return true;
128+
// CHECK-NEXT: } // if
129+
// CHECK: case Arch::BigInst2
130+
// CHECK-NEXT: if (MI.getOperand(0).isReg() &&
131+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) &&
132+
// CHECK-NEXT: MI.getOperand(1).isReg() &&
133+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) &&
134+
// CHECK-NEXT: ArchValidateMCOperandForCompress(MI.getOperand(2), STI, 1)) {
135+
// CHECK-NEXT: // small $dst, $src, $imm
136+
// CHECK-NEXT: OutInst.setOpcode(Arch::SmallInst2);
137+
// CHECK-NEXT: // Operand: dst
138+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0));
139+
// CHECK-NEXT: // Operand: src
140+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1));
141+
// CHECK-NEXT: // Operand: imm
142+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(2));
143+
// CHECK-NEXT: OutInst.setLoc(MI.getLoc());
144+
// CHECK-NEXT: return true;
145+
// CHECK-NEXT: } // if
146+
// CHECK: case Arch::BigInst3
147+
// CHECK-NEXT: if (MI.getOperand(0).isReg() &&
148+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) &&
149+
// CHECK-NEXT: MI.getOperand(1).isReg() &&
150+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) &&
151+
// CHECK-NEXT: ArchValidateMCOperandForCompress(MI.getOperand(2), STI, 1)) {
152+
// CHECK-NEXT: // small $dst, $addr
153+
// CHECK-NEXT: OutInst.setOpcode(Arch::SmallInst3);
154+
// CHECK-NEXT: // Operand: dst
155+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0));
156+
// CHECK-NEXT: // Operand: addr
157+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1));
158+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(2));
159+
// CHECK-NEXT: OutInst.setLoc(MI.getLoc());
160+
// CHECK-NEXT: return true;
161+
// CHECK-NEXT: } // if
162+
163+
// CHECK-LABEL: ArchValidateMCOperandForUncompress
164+
// CHECK: // simm12
165+
// CHECK: return isInt<12>(Imm);
166+
167+
// CHECK-LABEL: uncompressInst
168+
// CHECK: case Arch::SmallInst:
169+
// CHECK-NEXT: if (MI.getOperand(0).isReg() &&
170+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsRegClassID].contains(MI.getOperand(0).getReg()) &&
171+
// CHECK-NEXT: MI.getOperand(1).isReg() &&
172+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsRegClassID].contains(MI.getOperand(1).getReg()) &&
173+
// CHECK-NEXT: ArchValidateMCOperandForUncompress(MI.getOperand(2), STI, 1)) {
174+
// CHECK-NEXT: // big $dst, $addr
175+
// CHECK-NEXT: OutInst.setOpcode(Arch::BigInst);
176+
// CHECK-NEXT: // Operand: dst
177+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0));
178+
// CHECK-NEXT: // Operand: addr
179+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1));
180+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(2));
181+
// CHECK-NEXT: OutInst.setLoc(MI.getLoc());
182+
// CHECK-NEXT: return true;
183+
// CHECK-NEXT: } // if
184+
// CHECK: case Arch::SmallInst2:
185+
// CHECK-NEXT: if (MI.getOperand(0).isReg() &&
186+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsRegClassID].contains(MI.getOperand(0).getReg()) &&
187+
// CHECK-NEXT: MI.getOperand(1).isReg() &&
188+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsRegClassID].contains(MI.getOperand(1).getReg()) &&
189+
// CHECK-NEXT: ArchValidateMCOperandForUncompress(MI.getOperand(2), STI, 1)) {
190+
// CHECK-NEXT: // big $dst, $addr
191+
// CHECK-NEXT: OutInst.setOpcode(Arch::BigInst2);
192+
// CHECK-NEXT: // Operand: dst
193+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0));
194+
// CHECK-NEXT: // Operand: addr
195+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1));
196+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(2));
197+
// CHECK-NEXT: OutInst.setLoc(MI.getLoc());
198+
// CHECK-NEXT: return true;
199+
// CHECK-NEXT: } // if
200+
// CHECK: case Arch::SmallInst3:
201+
// CHECK-NEXT: if (MI.getOperand(0).isReg() &&
202+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsRegClassID].contains(MI.getOperand(0).getReg()) &&
203+
// CHECK-NEXT: MI.getOperand(1).isReg() &&
204+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsRegClassID].contains(MI.getOperand(1).getReg()) &&
205+
// CHECK-NEXT: ArchValidateMCOperandForUncompress(MI.getOperand(2), STI, 1)) {
206+
// CHECK-NEXT: // big $dst, $src, $imm
207+
// CHECK-NEXT: OutInst.setOpcode(Arch::BigInst3);
208+
// CHECK-NEXT: // Operand: dst
209+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0));
210+
// CHECK-NEXT: // Operand: src
211+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1));
212+
// CHECK-NEXT: // Operand: imm
213+
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(2));
214+
// CHECK-NEXT: OutInst.setLoc(MI.getLoc());
215+
// CHECK-NEXT: return true;
216+
// CHECK-NEXT: } // if
217+
218+
// CHECK-LABEL: ArchValidateMachineOperand
219+
// CHECK: // simm6
220+
// CHECK: return isInt<6>(Imm);
221+
222+
// CHECK-LABEL: isCompressibleInst
223+
// CHECK: case Arch::BigInst: {
224+
// CHECK-NEXT: if (MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() &&
225+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) &&
226+
// CHECK-NEXT: MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isPhysical() &&
227+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) &&
228+
// CHECK-NEXT: MI.getOperand(2).isImm() &&
229+
// CHECK-NEXT: ArchValidateMachineOperand(MI.getOperand(2), &STI, 1)) {
230+
// CHECK-NEXT: // small $dst, $addr
231+
// CHECK-NEXT: // Operand: dst
232+
// CHECK-NEXT: // Operand: addr
233+
// CHECK-NEXT: return true;
234+
// CHECK-NEXT: } // if
235+
// CHECK: case Arch::BigInst2: {
236+
// CHECK-NEXT: if (MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() &&
237+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) &&
238+
// CHECK-NEXT: MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isPhysical() &&
239+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) &&
240+
// CHECK-NEXT: MI.getOperand(2).isImm() &&
241+
// CHECK-NEXT: ArchValidateMachineOperand(MI.getOperand(2), &STI, 1)) {
242+
// CHECK-NEXT: // small $dst, $src, $imm
243+
// CHECK-NEXT: // Operand: dst
244+
// CHECK-NEXT: // Operand: src
245+
// CHECK-NEXT: // Operand: imm
246+
// CHECK-NEXT: return true;
247+
// CHECK-NEXT: } // if
248+
// CHECK: case Arch::BigInst3: {
249+
// CHECK-NEXT: if (MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() &&
250+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(0).getReg()) &&
251+
// CHECK-NEXT: MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isPhysical() &&
252+
// CHECK-NEXT: ArchMCRegisterClasses[Arch::RegsCRegClassID].contains(MI.getOperand(1).getReg()) &&
253+
// CHECK-NEXT: MI.getOperand(2).isImm() &&
254+
// CHECK-NEXT: ArchValidateMachineOperand(MI.getOperand(2), &STI, 1)) {
255+
// CHECK-NEXT: // small $dst, $addr
256+
// CHECK-NEXT: // Operand: dst
257+
// CHECK-NEXT: // Operand: addr
258+
// CHECK-NEXT: return true;
259+
// CHECK-NEXT: } // if

0 commit comments

Comments
 (0)