Skip to content

Commit c6967ef

Browse files
authored
[Xtensa] Implement Code Density Option. (#119639)
The Code Density option adds 16-bit encoding for frequently used instructions.
1 parent bf62ea4 commit c6967ef

16 files changed

+471
-25
lines changed

llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ struct XtensaOperand : public MCParsedAsmOperand {
193193

194194
bool isImm1_16() const { return isImm(1, 16); }
195195

196+
// Check that value is either equals (-1) or from [1,15] range.
197+
bool isImm1n_15() const { return isImm(1, 15) || isImm(-1, -1); }
198+
199+
bool isImm32n_95() const { return isImm(-32, 95); }
200+
196201
bool isB4const() const {
197202
if (Kind != Immediate)
198203
return false;
@@ -480,6 +485,12 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
480485
case Match_InvalidImm1_16:
481486
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
482487
"expected immediate in range [1, 16]");
488+
case Match_InvalidImm1n_15:
489+
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
490+
"expected immediate in range [-1, 15] except 0");
491+
case Match_InvalidImm32n_95:
492+
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
493+
"expected immediate in range [-32, 95]");
483494
case Match_InvalidShimm1_31:
484495
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
485496
"expected immediate in range [1, 31]");

llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp

+73-8
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@ class XtensaDisassembler : public MCDisassembler {
3838
XtensaDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool isLE)
3939
: MCDisassembler(STI, Ctx), IsLittleEndian(isLE) {}
4040

41-
bool hasDensity() const {
42-
return STI.hasFeature(Xtensa::FeatureDensity);
43-
}
41+
bool hasDensity() const { return STI.hasFeature(Xtensa::FeatureDensity); }
4442

4543
DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
4644
ArrayRef<uint8_t> Bytes, uint64_t Address,
@@ -99,8 +97,8 @@ static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
9997
uint64_t InstSize, MCInst &MI,
10098
const void *Decoder) {
10199
const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
102-
return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset, /*OpSize=*/0,
103-
InstSize);
100+
return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset,
101+
/*OpSize=*/0, InstSize);
104102
}
105103

106104
static DecodeStatus decodeCallOperand(MCInst &Inst, uint64_t Imm,
@@ -190,6 +188,28 @@ static DecodeStatus decodeImm1_16Operand(MCInst &Inst, uint64_t Imm,
190188
return MCDisassembler::Success;
191189
}
192190

191+
static DecodeStatus decodeImm1n_15Operand(MCInst &Inst, uint64_t Imm,
192+
int64_t Address,
193+
const void *Decoder) {
194+
assert(isUInt<4>(Imm) && "Invalid immediate");
195+
if (!Imm)
196+
Inst.addOperand(MCOperand::createImm(-1));
197+
else
198+
Inst.addOperand(MCOperand::createImm(Imm));
199+
return MCDisassembler::Success;
200+
}
201+
202+
static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm,
203+
int64_t Address,
204+
const void *Decoder) {
205+
assert(isUInt<7>(Imm) && "Invalid immediate");
206+
if ((Imm & 0x60) == 0x60)
207+
Inst.addOperand(MCOperand::createImm((~0x1f) | Imm));
208+
else
209+
Inst.addOperand(MCOperand::createImm(Imm));
210+
return MCDisassembler::Success;
211+
}
212+
193213
static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm,
194214
int64_t Address,
195215
const void *Decoder) {
@@ -243,9 +263,37 @@ static DecodeStatus decodeMem32Operand(MCInst &Inst, uint64_t Imm,
243263
return MCDisassembler::Success;
244264
}
245265

266+
static DecodeStatus decodeMem32nOperand(MCInst &Inst, uint64_t Imm,
267+
int64_t Address, const void *Decoder) {
268+
assert(isUInt<8>(Imm) && "Invalid immediate");
269+
DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
270+
Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3c));
271+
return MCDisassembler::Success;
272+
}
273+
274+
/// Read two bytes from the ArrayRef and return 16 bit data sorted
275+
/// according to the given endianness.
276+
static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
277+
uint64_t &Size, uint64_t &Insn,
278+
bool IsLittleEndian) {
279+
// We want to read exactly 2 Bytes of data.
280+
if (Bytes.size() < 2) {
281+
Size = 0;
282+
return MCDisassembler::Fail;
283+
}
284+
285+
if (!IsLittleEndian) {
286+
report_fatal_error("Big-endian mode currently is not supported!");
287+
} else {
288+
Insn = (Bytes[1] << 8) | Bytes[0];
289+
}
290+
291+
return MCDisassembler::Success;
292+
}
293+
246294
/// Read three bytes from the ArrayRef and return 24 bit data
247295
static DecodeStatus readInstruction24(ArrayRef<uint8_t> Bytes, uint64_t Address,
248-
uint64_t &Size, uint32_t &Insn,
296+
uint64_t &Size, uint64_t &Insn,
249297
bool IsLittleEndian) {
250298
// We want to read exactly 3 Bytes of data.
251299
if (Bytes.size() < 3) {
@@ -259,7 +307,6 @@ static DecodeStatus readInstruction24(ArrayRef<uint8_t> Bytes, uint64_t Address,
259307
Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);
260308
}
261309

262-
Size = 3;
263310
return MCDisassembler::Success;
264311
}
265312

@@ -269,13 +316,31 @@ DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
269316
ArrayRef<uint8_t> Bytes,
270317
uint64_t Address,
271318
raw_ostream &CS) const {
272-
uint32_t Insn;
319+
uint64_t Insn;
273320
DecodeStatus Result;
274321

322+
// Parse 16-bit instructions
323+
if (hasDensity()) {
324+
Result = readInstruction16(Bytes, Address, Size, Insn, IsLittleEndian);
325+
if (Result == MCDisassembler::Fail)
326+
return MCDisassembler::Fail;
327+
LLVM_DEBUG(dbgs() << "Trying Xtensa 16-bit instruction table :\n");
328+
Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI);
329+
if (Result != MCDisassembler::Fail) {
330+
Size = 2;
331+
return Result;
332+
}
333+
}
334+
335+
// Parse Core 24-bit instructions
275336
Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian);
276337
if (Result == MCDisassembler::Fail)
277338
return MCDisassembler::Fail;
278339
LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n");
279340
Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI);
341+
if (Result != MCDisassembler::Fail) {
342+
Size = 3;
343+
return Result;
344+
}
280345
return Result;
281346
}

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,10 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
8888
case FK_Data_8:
8989
return Value;
9090
case Xtensa::fixup_xtensa_branch_6: {
91+
if (!Value)
92+
return 0;
9193
Value -= 4;
92-
if (!isInt<6>(Value))
94+
if (!isUInt<6>(Value))
9395
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
9496
unsigned Hi2 = (Value >> 4) & 0x3;
9597
unsigned Lo4 = Value & 0xf;

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,28 @@ void XtensaInstPrinter::printImm1_16_AsmOperand(const MCInst *MI, int OpNum,
242242
printOperand(MI, OpNum, O);
243243
}
244244

245+
void XtensaInstPrinter::printImm1n_15_AsmOperand(const MCInst *MI, int OpNum,
246+
raw_ostream &O) {
247+
if (MI->getOperand(OpNum).isImm()) {
248+
int64_t Value = MI->getOperand(OpNum).getImm();
249+
assert((Value >= -1 && (Value != 0) && Value <= 15) &&
250+
"Invalid argument, value must be in ranges <-1,-1> or <1,15>");
251+
O << Value;
252+
} else
253+
printOperand(MI, OpNum, O);
254+
}
255+
256+
void XtensaInstPrinter::printImm32n_95_AsmOperand(const MCInst *MI, int OpNum,
257+
raw_ostream &O) {
258+
if (MI->getOperand(OpNum).isImm()) {
259+
int64_t Value = MI->getOperand(OpNum).getImm();
260+
assert((Value >= -32 && Value <= 95) &&
261+
"Invalid argument, value must be in ranges <-32,95>");
262+
O << Value;
263+
} else
264+
printOperand(MI, OpNum, O);
265+
}
266+
245267
void XtensaInstPrinter::printOffset8m8_AsmOperand(const MCInst *MI, int OpNum,
246268
raw_ostream &O) {
247269
if (MI->getOperand(OpNum).isImm()) {

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ class XtensaInstPrinter : public MCInstPrinter {
5858
void printUimm5_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
5959
void printShimm1_31_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6060
void printImm1_16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
61+
void printImm1n_15_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
62+
void printImm32n_95_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6163
void printOffset8m8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6264
void printOffset8m16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
6365
void printOffset8m32_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp

+53-2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ class XtensaMCCodeEmitter : public MCCodeEmitter {
103103
SmallVectorImpl<MCFixup> &Fixups,
104104
const MCSubtargetInfo &STI) const;
105105

106+
uint32_t getImm1n_15OpValue(const MCInst &MI, unsigned OpNo,
107+
SmallVectorImpl<MCFixup> &Fixups,
108+
const MCSubtargetInfo &STI) const;
109+
110+
uint32_t getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
111+
SmallVectorImpl<MCFixup> &Fixups,
112+
const MCSubtargetInfo &STI) const;
113+
106114
uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
107115
SmallVectorImpl<MCFixup> &Fixups,
108116
const MCSubtargetInfo &STI) const;
@@ -188,6 +196,11 @@ uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding(
188196
Fixups.push_back(MCFixup::create(
189197
0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_12), MI.getLoc()));
190198
return 0;
199+
case Xtensa::BEQZ_N:
200+
case Xtensa::BNEZ_N:
201+
Fixups.push_back(MCFixup::create(
202+
0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_6), MI.getLoc()));
203+
return 0;
191204
default:
192205
Fixups.push_back(MCFixup::create(
193206
0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_8), MI.getLoc()));
@@ -255,14 +268,24 @@ XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
255268
break;
256269
case Xtensa::S32I:
257270
case Xtensa::L32I:
271+
case Xtensa::S32I_N:
272+
case Xtensa::L32I_N:
258273
if (Res & 0x3) {
259274
report_fatal_error("Unexpected operand value!");
260275
}
261276
Res >>= 2;
262277
break;
263278
}
264-
265-
assert((isUInt<8>(Res)) && "Unexpected operand value!");
279+
280+
switch (MI.getOpcode()) {
281+
case Xtensa::S32I_N:
282+
case Xtensa::L32I_N:
283+
assert((isUInt<4>(Res)) && "Unexpected operand value!");
284+
break;
285+
default:
286+
assert((isUInt<8>(Res)) && "Unexpected operand value!");
287+
break;
288+
}
266289

267290
uint32_t OffBits = Res << 4;
268291
uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
@@ -354,6 +377,34 @@ XtensaMCCodeEmitter::getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
354377
return (Res - 1);
355378
}
356379

380+
uint32_t
381+
XtensaMCCodeEmitter::getImm1n_15OpValue(const MCInst &MI, unsigned OpNo,
382+
SmallVectorImpl<MCFixup> &Fixups,
383+
const MCSubtargetInfo &STI) const {
384+
const MCOperand &MO = MI.getOperand(OpNo);
385+
int32_t Res = static_cast<int32_t>(MO.getImm());
386+
387+
assert(((Res >= -1) && (Res <= 15) && (Res != 0)) &&
388+
"Unexpected operand value!");
389+
390+
if (Res < 0)
391+
Res = 0;
392+
393+
return Res;
394+
}
395+
396+
uint32_t
397+
XtensaMCCodeEmitter::getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
398+
SmallVectorImpl<MCFixup> &Fixups,
399+
const MCSubtargetInfo &STI) const {
400+
const MCOperand &MO = MI.getOperand(OpNo);
401+
int32_t Res = static_cast<int32_t>(MO.getImm());
402+
403+
assert(((Res >= -32) && (Res <= 95)) && "Unexpected operand value!");
404+
405+
return Res;
406+
}
407+
357408
uint32_t
358409
XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
359410
SmallVectorImpl<MCFixup> &Fixups,

llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,17 @@ using namespace llvm;
2727
namespace {
2828

2929
class XtensaDAGToDAGISel : public SelectionDAGISel {
30+
const XtensaSubtarget *Subtarget = nullptr;
31+
3032
public:
31-
XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
33+
explicit XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
3234
: SelectionDAGISel(TM, OptLevel) {}
3335

36+
bool runOnMachineFunction(MachineFunction &MF) override {
37+
Subtarget = &MF.getSubtarget<XtensaSubtarget>();
38+
return SelectionDAGISel::runOnMachineFunction(MF);
39+
}
40+
3441
void Select(SDNode *Node) override;
3542

3643
bool SelectInlineAsmMemoryOperand(const SDValue &Op,

llvm/lib/Target/Xtensa/XtensaISelLowering.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,8 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
506506
SDValue Memcpy = DAG.getMemcpy(
507507
Chain, DL, Address, ArgValue, SizeNode, Flags.getNonZeroByValAlign(),
508508
/*isVolatile=*/false, /*AlwaysInline=*/false,
509-
/*CI=*/nullptr, std::nullopt, MachinePointerInfo(), MachinePointerInfo());
509+
/*CI=*/nullptr, std::nullopt, MachinePointerInfo(),
510+
MachinePointerInfo());
510511
MemOpChains.push_back(Memcpy);
511512
} else {
512513
assert(VA.isMemLoc() && "Argument not register or memory");
@@ -1319,10 +1320,12 @@ MachineBasicBlock *XtensaTargetLowering::EmitInstrWithCustomInserter(
13191320
case Xtensa::S8I:
13201321
case Xtensa::S16I:
13211322
case Xtensa::S32I:
1323+
case Xtensa::S32I_N:
13221324
case Xtensa::L8UI:
13231325
case Xtensa::L16SI:
13241326
case Xtensa::L16UI:
1325-
case Xtensa::L32I: {
1327+
case Xtensa::L32I:
1328+
case Xtensa::L32I_N: {
13261329
// Insert memory wait instruction "memw" before volatile load/store as it is
13271330
// implemented in gcc. If memoperands is empty then assume that it aslo
13281331
// maybe volatile load/store and insert "memw".

0 commit comments

Comments
 (0)