Skip to content

Commit 983d8be

Browse files
committed
[TableGen][DecoderEmitter] Calculate encoding bits once (NFC)
`insnWithID` is called multiple times for the same encoding ID. Call it once and store the result in `NumberedEncodings`. Also, give the method a more meaningful name.
1 parent c74afaa commit 983d8be

File tree

1 file changed

+104
-70
lines changed

1 file changed

+104
-70
lines changed

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 104 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,13 @@ class InstructionEncoding {
157157
/// The name of this encoding (for debugging purposes).
158158
std::string Name;
159159

160-
/// The size of this encoding, in bits.
161-
unsigned BitWidth;
160+
/// Known bits of this encoding. This is the value of the `Inst` field
161+
/// with any variable references replaced with '?'.
162+
KnownBits InstBits;
163+
164+
/// Mask of bits that should be considered unknown during decoding.
165+
/// This is the value of the `SoftFail` field.
166+
APInt SoftFailBits;
162167

163168
/// The name of the function to use for decoding. May be an empty string,
164169
/// meaning the decoder is generated.
@@ -186,7 +191,13 @@ class InstructionEncoding {
186191
StringRef getName() const { return Name; }
187192

188193
/// Returns the size of this encoding, in bits.
189-
unsigned getBitWidth() const { return BitWidth; }
194+
unsigned getBitWidth() const { return InstBits.getBitWidth(); }
195+
196+
/// Returns the known bits of this encoding.
197+
const KnownBits &getInstBits() const { return InstBits; }
198+
199+
/// Returns a mask of bits that should be considered unknown during decoding.
200+
const APInt &getSoftFailBits() const { return SoftFailBits; }
190201

191202
/// Returns the name of the function to use for decoding, or an empty string
192203
/// if the decoder is generated.
@@ -200,6 +211,9 @@ class InstructionEncoding {
200211
ArrayRef<OperandInfo> getOperands() const { return Operands; }
201212

202213
private:
214+
void parseVarLenEncoding(const VarLenInst &VLI);
215+
void parseFixedLenEncoding(const BitsInit &Bits);
216+
203217
void parseVarLenOperands(const VarLenInst &VLI);
204218
void parseFixedLenOperands(const BitsInit &Bits);
205219
};
@@ -331,27 +345,6 @@ class DecoderEmitter {
331345

332346
} // end anonymous namespace
333347

334-
static const BitsInit &getBitsField(const Record &Def, StringRef FieldName) {
335-
const RecordVal *RV = Def.getValue(FieldName);
336-
if (const BitsInit *Bits = dyn_cast<BitsInit>(RV->getValue()))
337-
return *Bits;
338-
339-
// Handle variable length instructions.
340-
VarLenInst VLI(cast<DagInit>(RV->getValue()), RV);
341-
SmallVector<const Init *, 16> Bits;
342-
343-
for (const auto &SI : VLI) {
344-
if (const BitsInit *BI = dyn_cast<BitsInit>(SI.Value))
345-
llvm::append_range(Bits, BI->getBits());
346-
else if (const BitInit *BI = dyn_cast<BitInit>(SI.Value))
347-
Bits.push_back(BI);
348-
else
349-
Bits.append(SI.BitWidth, UnsetInit::get(Def.getRecords()));
350-
}
351-
352-
return *BitsInit::get(Def.getRecords(), Bits);
353-
}
354-
355348
namespace {
356349

357350
class FilterChooser;
@@ -534,30 +527,14 @@ class FilterChooser {
534527

535528
protected:
536529
KnownBits getMandatoryEncodingBits(unsigned EncodingID) const {
537-
const Record *EncodingDef = Encodings[EncodingID].getRecord();
538-
const BitsInit &Bits = getBitsField(*EncodingDef, "Inst");
539-
KnownBits Insn(std::max(BitWidth, Bits.getNumBits()));
540-
// We may have a SoftFail bitmask, which specifies a mask where an encoding
541-
// may differ from the value in "Inst" and yet still be valid, but the
542-
// disassembler should return SoftFail instead of Success.
543-
//
544-
// This is used for marking UNPREDICTABLE instructions in the ARM world.
545-
const RecordVal *RV = EncodingDef->getValue("SoftFail");
546-
const BitsInit *SFBits = RV ? dyn_cast<BitsInit>(RV->getValue()) : nullptr;
547-
for (unsigned i = 0; i < Bits.getNumBits(); ++i) {
548-
if (SFBits) {
549-
const auto *B = dyn_cast<BitInit>(SFBits->getBit(i));
550-
if (B && B->getValue())
551-
continue;
552-
}
553-
if (const auto *B = dyn_cast<BitInit>(Bits.getBit(i))) {
554-
if (B->getValue())
555-
Insn.One.setBit(i);
556-
else
557-
Insn.Zero.setBit(i);
558-
}
559-
}
560-
return Insn;
530+
const InstructionEncoding &Encoding = Encodings[EncodingID];
531+
KnownBits EncodingBits = Encoding.getInstBits();
532+
// Clear all bits that are allowed to change according to SoftFail mask.
533+
EncodingBits.Zero &= ~Encoding.getSoftFailBits();
534+
EncodingBits.One &= ~Encoding.getSoftFailBits();
535+
// Truncate or extend with unknown bits according to the filter bit width.
536+
// FIXME: We should stop doing this.
537+
return EncodingBits.anyextOrTrunc(BitWidth);
561538
}
562539

563540
/// dumpStack - dumpStack traverses the filter chooser chain and calls
@@ -1336,36 +1313,23 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo,
13361313

13371314
void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
13381315
unsigned EncodingID) const {
1339-
const Record *EncodingDef = Encodings[EncodingID].getRecord();
1340-
const RecordVal *RV = EncodingDef->getValue("SoftFail");
1341-
const BitsInit *SFBits = RV ? dyn_cast<BitsInit>(RV->getValue()) : nullptr;
1316+
const InstructionEncoding &Encoding = Encodings[EncodingID];
1317+
const KnownBits &InstBits = Encoding.getInstBits();
1318+
const APInt &SFBits = Encoding.getSoftFailBits();
13421319

1343-
if (!SFBits)
1320+
if (SFBits.isZero())
13441321
return;
1345-
const BitsInit *InstBits = EncodingDef->getValueAsBitsInit("Inst");
13461322

13471323
APInt PositiveMask(BitWidth, 0ULL);
13481324
APInt NegativeMask(BitWidth, 0ULL);
13491325
for (unsigned i = 0; i < BitWidth; ++i) {
1350-
if (!isa<BitInit>(SFBits->getBit(i)) ||
1351-
!cast<BitInit>(SFBits->getBit(i))->getValue())
1326+
if (!SFBits[i])
13521327
continue;
13531328

1354-
if (!isa<BitInit>(InstBits->getBit(i))) {
1355-
// The bit is not set; this must be an error!
1356-
errs() << "SoftFail Conflict: bit SoftFail{" << i << "} in "
1357-
<< Encodings[EncodingID].getName() << " is set but Inst{" << i
1358-
<< "} is unset!\n"
1359-
<< " - You can only mark a bit as SoftFail if it is fully defined"
1360-
<< " (1/0 - not '?') in Inst\n";
1361-
return;
1362-
}
1363-
1364-
bool IB = cast<BitInit>(InstBits->getBit(i))->getValue();
1365-
if (!IB) {
1329+
if (InstBits.Zero[i]) {
13661330
// The bit is meant to be false, so emit a check to see if it is true.
13671331
PositiveMask.setBit(i);
1368-
} else {
1332+
} else if (InstBits.One[i]) {
13691333
// The bit is meant to be true, so emit a check to see if it is false.
13701334
NegativeMask.setBit(i);
13711335
}
@@ -1797,6 +1761,75 @@ OperandInfo getOpInfo(const Record *TypeRecord) {
17971761
return OperandInfo(findOperandDecoderMethod(TypeRecord), HasCompleteDecoder);
17981762
}
17991763

1764+
void InstructionEncoding::parseVarLenEncoding(const VarLenInst &VLI) {
1765+
InstBits = KnownBits(VLI.size());
1766+
SoftFailBits = APInt(VLI.size(), 0);
1767+
1768+
// Parse Inst field.
1769+
unsigned I = 0;
1770+
for (const EncodingSegment &S : VLI) {
1771+
if (const auto *SegmentBits = dyn_cast<BitsInit>(S.Value)) {
1772+
for (const Init *V : SegmentBits->getBits()) {
1773+
if (const auto *B = dyn_cast<BitInit>(V)) {
1774+
if (B->getValue())
1775+
InstBits.One.setBit(I);
1776+
else
1777+
InstBits.Zero.setBit(I);
1778+
}
1779+
++I;
1780+
}
1781+
} else if (const auto *B = dyn_cast<BitInit>(S.Value)) {
1782+
if (B->getValue())
1783+
InstBits.One.setBit(I);
1784+
else
1785+
InstBits.Zero.setBit(I);
1786+
++I;
1787+
} else {
1788+
I += S.BitWidth;
1789+
}
1790+
}
1791+
assert(I == VLI.size());
1792+
}
1793+
1794+
void InstructionEncoding::parseFixedLenEncoding(const BitsInit &Bits) {
1795+
InstBits = KnownBits(Bits.getNumBits());
1796+
SoftFailBits = APInt(Bits.getNumBits(), 0);
1797+
1798+
// Parse Inst field.
1799+
for (auto [I, V] : enumerate(Bits.getBits())) {
1800+
if (const auto *B = dyn_cast<BitInit>(V)) {
1801+
if (B->getValue())
1802+
InstBits.One.setBit(I);
1803+
else
1804+
InstBits.Zero.setBit(I);
1805+
}
1806+
}
1807+
1808+
// Parse SoftFail field.
1809+
if (const RecordVal *SoftFailField = EncodingDef->getValue("SoftFail")) {
1810+
const auto *SFBits = dyn_cast<BitsInit>(SoftFailField->getValue());
1811+
if (!SFBits || SFBits->getNumBits() != Bits.getNumBits()) {
1812+
PrintNote(EncodingDef->getLoc(), "in record");
1813+
PrintFatalError(SoftFailField,
1814+
formatv("SoftFail field, if defined, must be "
1815+
"of the same type as Inst, which is bits<{}>",
1816+
Bits.getNumBits()));
1817+
}
1818+
for (auto [I, V] : enumerate(SFBits->getBits())) {
1819+
if (const auto *B = dyn_cast<BitInit>(V); B && B->getValue()) {
1820+
if (!InstBits.Zero[I] && !InstBits.One[I]) {
1821+
PrintNote(EncodingDef->getLoc(), "in record");
1822+
PrintError(SoftFailField,
1823+
formatv("SoftFail{{{0}} = 1 requires Inst{{{0}} "
1824+
"to be fully defined (0 or 1, not '?')",
1825+
I));
1826+
}
1827+
SoftFailBits.setBit(I);
1828+
}
1829+
}
1830+
}
1831+
}
1832+
18001833
void InstructionEncoding::parseVarLenOperands(const VarLenInst &VLI) {
18011834
SmallVector<int> TiedTo;
18021835

@@ -2025,13 +2058,13 @@ InstructionEncoding::InstructionEncoding(const Record *EncodingDef,
20252058
const RecordVal *InstField = EncodingDef->getValue("Inst");
20262059
if (const auto *DI = dyn_cast<DagInit>(InstField->getValue())) {
20272060
VarLenInst VLI(DI, InstField);
2028-
BitWidth = VLI.size();
2061+
parseVarLenEncoding(VLI);
20292062
// If the encoding has a custom decoder, don't bother parsing the operands.
20302063
if (DecoderMethod.empty())
20312064
parseVarLenOperands(VLI);
20322065
} else {
20332066
const auto *BI = cast<BitsInit>(InstField->getValue());
2034-
BitWidth = BI->getNumBits();
2067+
parseFixedLenEncoding(*BI);
20352068
// If the encoding has a custom decoder, don't bother parsing the operands.
20362069
if (DecoderMethod.empty())
20372070
parseFixedLenOperands(*BI);
@@ -2346,6 +2379,7 @@ static bool isValidEncoding(const Record *EncodingDef) {
23462379
return false;
23472380

23482381
// At least one of the encoding bits must be complete (not '?').
2382+
// FIXME: This should take SoftFail field into account.
23492383
return !InstInit->allInComplete();
23502384
}
23512385

0 commit comments

Comments
 (0)