TableGen: Simplify BitsInit::resolveReferences

Summary:
No functional change intended. The removed code has a loop for
recursive resolving, which is superseded by the recursive
resolving done by the Resolver implementations.

Add a test case which was broken by an earlier version of this
change.

Change-Id: Ib208d037b77a8bbb725977f1388601fc984723d8

Reviewers: arsenm, craig.topper, tra, MartinO

Subscribers: wdng, llvm-commits

Differential Revision: https://reviews.llvm.org/D43655

llvm-svn: 326784
This commit is contained in:
Nicolai Haehnle 2018-03-06 13:48:30 +00:00
parent 13080fd14e
commit 9a84a50913
3 changed files with 48 additions and 46 deletions

View File

@ -391,14 +391,6 @@ public:
/// This method is used to return the initializer for the specified /// This method is used to return the initializer for the specified
/// bit. /// bit.
virtual Init *getBit(unsigned Bit) const = 0; virtual Init *getBit(unsigned Bit) const = 0;
/// This method is used to retrieve the initializer for bit
/// reference. For non-VarBitInit, it simply returns itself.
virtual Init *getBitVar() const { return const_cast<Init*>(this); }
/// This method is used to retrieve the bit number of a bit
/// reference. For non-VarBitInit, it simply returns 0.
virtual unsigned getBitNum() const { return 0; }
}; };
inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) { inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
@ -954,8 +946,8 @@ public:
Init *convertInitializerTo(RecTy *Ty) const override; Init *convertInitializerTo(RecTy *Ty) const override;
Init *getBitVar() const override { return TI; } Init *getBitVar() const { return TI; }
unsigned getBitNum() const override { return Bit; } unsigned getBitNum() const { return Bit; }
std::string getAsString() const override; std::string getAsString() const override;
Init *resolveReferences(Resolver &R) const override; Init *resolveReferences(Resolver &R) const override;

View File

@ -393,54 +393,35 @@ std::string BitsInit::getAsString() const {
return Result + " }"; return Result + " }";
} }
// Fix bit initializer to preserve the behavior that bit reference from a unset
// bits initializer will resolve into VarBitInit to keep the field name and bit
// number used in targets with fixed insn length.
static Init *fixBitInit(const Resolver &R, Init *Before, Init *After) {
if (!isa<UnsetInit>(After) || !R.keepUnsetBits())
return After;
return Before;
}
// resolveReferences - If there are any field references that refer to fields // resolveReferences - If there are any field references that refer to fields
// that have been filled in, we can propagate the values now. // that have been filled in, we can propagate the values now.
Init *BitsInit::resolveReferences(Resolver &R) const { Init *BitsInit::resolveReferences(Resolver &R) const {
bool Changed = false; bool Changed = false;
SmallVector<Init *, 16> NewBits(getNumBits()); SmallVector<Init *, 16> NewBits(getNumBits());
Init *CachedInit = nullptr; Init *CachedBitVarRef = nullptr;
Init *CachedBitVar = nullptr; Init *CachedBitVarResolved = nullptr;
bool CachedBitVarChanged = false;
for (unsigned i = 0, e = getNumBits(); i != e; ++i) { for (unsigned i = 0, e = getNumBits(); i != e; ++i) {
Init *CurBit = getBit(i); Init *CurBit = getBit(i);
Init *CurBitVar = CurBit->getBitVar(); Init *NewBit = CurBit;
NewBits[i] = CurBit; if (VarBitInit *CurBitVar = dyn_cast<VarBitInit>(CurBit)) {
if (CurBitVar->getBitVar() != CachedBitVarRef) {
if (CurBitVar == CachedBitVar) { CachedBitVarRef = CurBitVar->getBitVar();
if (CachedBitVarChanged) { CachedBitVarResolved = CachedBitVarRef->resolveReferences(R);
Init *Bit = CachedInit->getBit(CurBit->getBitNum());
NewBits[i] = fixBitInit(R, CurBit, Bit);
} }
continue;
}
CachedBitVar = CurBitVar;
CachedBitVarChanged = false;
Init *B; NewBit = CachedBitVarResolved->getBit(CurBitVar->getBitNum());
do { } else {
B = CurBitVar; // getBit(0) implicitly converts int and bits<1> values to bit.
CurBitVar = CurBitVar->resolveReferences(R); NewBit = CurBit->resolveReferences(R)->getBit(0);
CachedBitVarChanged |= B != CurBitVar;
Changed |= B != CurBitVar;
} while (B != CurBitVar);
CachedInit = CurBitVar;
if (CachedBitVarChanged) {
Init *Bit = CurBitVar->getBit(CurBit->getBitNum());
NewBits[i] = fixBitInit(R, CurBit, Bit);
} }
if (isa<UnsetInit>(NewBit) && R.keepUnsetBits())
NewBit = CurBit;
NewBits[i] = NewBit;
Changed |= CurBit != NewBit;
} }
if (Changed) if (Changed)

View File

@ -1,5 +1,34 @@
// RUN: llvm-tblgen %s // RUN: llvm-tblgen %s | FileCheck %s
// XFAIL: vg_leak // XFAIL: vg_leak
// CHECK: --- Defs ---
// Test that P and Q are not replaced by ?. TableGen's codegen emitter backend
// relies on keeping variable references like this around to describe the
// structure of instruction encodings.
//
// CHECK: def A {
// CHECK: bits<8> Inst = { 1, 1, 1, 1, 1, 1, P, Q };
// CHECK: bits<2> src = { ?, ? };
// CHECK: bit P = ?;
// CHECK: bit Q = ?;
// CHECK: }
def A {
bits<8> Inst;
bits<2> src;
bit P;
bit Q;
let Inst{7-2} = 0x3f;
let Inst{1} = P;
let Inst{0} = Q;
let P = src{1};
let Q = src{0};
}
class x { class x {
field bits<32> A; field bits<32> A;
} }