Index: llvm/trunk/include/llvm/TableGen/Record.h =================================================================== --- llvm/trunk/include/llvm/TableGen/Record.h +++ llvm/trunk/include/llvm/TableGen/Record.h @@ -391,14 +391,6 @@ /// This method is used to return the initializer for the specified /// bit. 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(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) { @@ -954,8 +946,8 @@ Init *convertInitializerTo(RecTy *Ty) const override; - Init *getBitVar() const override { return TI; } - unsigned getBitNum() const override { return Bit; } + Init *getBitVar() const { return TI; } + unsigned getBitNum() const { return Bit; } std::string getAsString() const override; Init *resolveReferences(Resolver &R) const override; Index: llvm/trunk/lib/TableGen/Record.cpp =================================================================== --- llvm/trunk/lib/TableGen/Record.cpp +++ llvm/trunk/lib/TableGen/Record.cpp @@ -393,54 +393,35 @@ 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(After) || !R.keepUnsetBits()) - return After; - return Before; -} - // resolveReferences - If there are any field references that refer to fields // that have been filled in, we can propagate the values now. Init *BitsInit::resolveReferences(Resolver &R) const { bool Changed = false; SmallVector NewBits(getNumBits()); - Init *CachedInit = nullptr; - Init *CachedBitVar = nullptr; - bool CachedBitVarChanged = false; + Init *CachedBitVarRef = nullptr; + Init *CachedBitVarResolved = nullptr; for (unsigned i = 0, e = getNumBits(); i != e; ++i) { Init *CurBit = getBit(i); - Init *CurBitVar = CurBit->getBitVar(); + Init *NewBit = CurBit; - NewBits[i] = CurBit; - - if (CurBitVar == CachedBitVar) { - if (CachedBitVarChanged) { - Init *Bit = CachedInit->getBit(CurBit->getBitNum()); - NewBits[i] = fixBitInit(R, CurBit, Bit); + if (VarBitInit *CurBitVar = dyn_cast(CurBit)) { + if (CurBitVar->getBitVar() != CachedBitVarRef) { + CachedBitVarRef = CurBitVar->getBitVar(); + CachedBitVarResolved = CachedBitVarRef->resolveReferences(R); } - continue; - } - CachedBitVar = CurBitVar; - CachedBitVarChanged = false; - Init *B; - do { - B = CurBitVar; - CurBitVar = CurBitVar->resolveReferences(R); - 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); + NewBit = CachedBitVarResolved->getBit(CurBitVar->getBitNum()); + } else { + // getBit(0) implicitly converts int and bits<1> values to bit. + NewBit = CurBit->resolveReferences(R)->getBit(0); } + + if (isa(NewBit) && R.keepUnsetBits()) + NewBit = CurBit; + NewBits[i] = NewBit; + Changed |= CurBit != NewBit; } if (Changed) Index: llvm/trunk/test/TableGen/UnsetBitInit.td =================================================================== --- llvm/trunk/test/TableGen/UnsetBitInit.td +++ llvm/trunk/test/TableGen/UnsetBitInit.td @@ -1,5 +1,34 @@ -// RUN: llvm-tblgen %s +// RUN: llvm-tblgen %s | FileCheck %s // 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 { field bits<32> A; }