Replace TSFlagsFields and TSFlagsShifts with a simpler TSFlags field.

When a target instruction wants to set target-specific flags, it should simply
set bits in the TSFlags bit vector defined in the Instruction TableGen class.

This works well because TableGen resolves member references late:

class I : Instruction {
  AddrMode AM = AddrModeNone;
  let TSFlags{3-0} = AM.Value;
}

let AM = AddrMode4 in
def ADD : I;

TSFlags gets the expected bits from AddrMode4 in this example.

llvm-svn: 100384
This commit is contained in:
Jakob Stoklund Olesen 2010-04-05 03:10:20 +00:00
parent ab5dc34351
commit b93331f3be
18 changed files with 61 additions and 199 deletions

View File

@ -224,10 +224,13 @@ class Instruction {
InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling.
string Constraints = ""; // OperandConstraint, e.g. $src = $dst.
/// DisableEncoding - List of operand names (e.g. "$op1,$op2") that should not
/// be encoded into the output machineinstr.
string DisableEncoding = "";
/// Target-specific flags. This becomes the TSFlags field in TargetInstrDesc.
bits<32> TSFlags = 0;
}
/// Predicates - These are extra conditionals which are turned into instruction
@ -372,13 +375,6 @@ class OptionalDefOperand<ValueType ty, dag OpTypes, dag defaultops>
// which are global to the target machine.
//
class InstrInfo {
// If the target wants to associate some target-specific information with each
// instruction, it should provide these two lists to indicate how to assemble
// the target specific information into the 32 bits available.
//
list<string> TSFlagsFields = [];
list<int> TSFlagsShifts = [];
// Target can specify its instructions in either big or little-endian formats.
// For instance, while both Sparc and PowerPC are big-endian platforms, the
// Sparc manual specifies its instructions in the format [31..0] (big), while

View File

@ -140,23 +140,7 @@ include "ARMCallingConv.td"
include "ARMInstrInfo.td"
def ARMInstrInfo : InstrInfo {
// Define how we want to layout our target-specific information field.
let TSFlagsFields = ["AddrModeBits",
"SizeFlag",
"IndexModeBits",
"Form",
"isUnaryDataProc",
"canXformTo16Bit",
"Dom"];
let TSFlagsShifts = [0,
4,
7,
9,
15,
16,
17];
}
def ARMInstrInfo : InstrInfo;
//===----------------------------------------------------------------------===//
// Declare the target which we are implementing

View File

@ -185,28 +185,25 @@ class InstTemplate<AddrMode am, SizeFlagVal sz, IndexMode im,
: Instruction {
let Namespace = "ARM";
// TSFlagsFields
AddrMode AM = am;
bits<4> AddrModeBits = AM.Value;
SizeFlagVal SZ = sz;
bits<3> SizeFlag = SZ.Value;
IndexMode IM = im;
bits<2> IndexModeBits = IM.Value;
Format F = f;
bits<6> Form = F.Value;
Domain D = d;
bits<2> Dom = D.Value;
//
// Attributes specific to ARM instructions...
//
bit isUnaryDataProc = 0;
bit canXformTo16Bit = 0;
// The layout of TSFlags should be kept in sync with ARMBaseInstrInfo.h.
let TSFlags{3-0} = AM.Value;
let TSFlags{6-4} = SZ.Value;
let TSFlags{8-7} = IndexModeBits;
let TSFlags{14-9} = Form;
let TSFlags{15} = isUnaryDataProc;
let TSFlags{16} = canXformTo16Bit;
let TSFlags{18-17} = D.Value;
let Constraints = cstr;
let Itinerary = itin;
}
@ -1317,7 +1314,7 @@ class ADI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
let Inst{11-8} = 0b1011;
// 64-bit loads & stores operate on both NEON and VFP pipelines.
let Dom = VFPNeonDomain.Value;
let D = VFPNeonDomain;
}
class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
@ -1341,7 +1338,7 @@ class AXDI5<dag oops, dag iops, IndexMode im, InstrItinClass itin,
let Inst{11-8} = 0b1011;
// 64-bit loads & stores operate on both NEON and VFP pipelines.
let Dom = VFPNeonDomain.Value;
let D = VFPNeonDomain;
}
class AXSI5<dag oops, dag iops, IndexMode im, InstrItinClass itin,

View File

@ -47,11 +47,7 @@ include "AlphaSchedule.td"
include "AlphaInstrInfo.td"
def AlphaInstrInfo : InstrInfo {
// Define how we want to layout our target-specific information field.
// let TSFlagsFields = [];
// let TSFlagsShifts = [];
}
def AlphaInstrInfo : InstrInfo;
//===----------------------------------------------------------------------===//
// Alpha Processor Definitions

View File

@ -25,11 +25,7 @@ include "MBlazeIntrinsics.td"
include "MBlazeInstrInfo.td"
include "MBlazeCallingConv.td"
def MBlazeInstrInfo : InstrInfo {
let TSFlagsFields = [];
let TSFlagsShifts = [];
}
def MBlazeInstrInfo : InstrInfo;
//===----------------------------------------------------------------------===//
// Microblaze Subtarget features //

View File

@ -48,14 +48,7 @@ include "MSP430CallingConv.td"
include "MSP430InstrInfo.td"
def MSP430InstrInfo : InstrInfo {
// Define how we want to layout our TargetSpecific information field... This
// should be kept up-to-date with the fields in the MSP430InstrInfo.h file.
let TSFlagsFields = ["FormBits",
"Size"];
let TSFlagsShifts = [0,
2];
}
def MSP430InstrInfo : InstrInfo;
def MSP430InstPrinter : AsmWriter {
string AsmWriterClassName = "InstPrinter";

View File

@ -61,10 +61,12 @@ class MSP430Inst<dag outs, dag ins, SizeVal sz, Format f,
dag InOperandList = ins;
Format Form = f;
bits<2> FormBits = Form.Value;
SizeVal Sz = sz;
bits<3> Size = Sz.Value;
// Define how we want to layout our TargetSpecific information field... This
// should be kept up-to-date with the fields in the MSP430InstrInfo.h file.
let TSFlags{1-0} = Form.Value;
let TSFlags{4-2} = Sz.Value;
let AsmString = asmstr;
}

View File

@ -24,10 +24,7 @@ include "MipsSchedule.td"
include "MipsInstrInfo.td"
include "MipsCallingConv.td"
def MipsInstrInfo : InstrInfo {
let TSFlagsFields = [];
let TSFlagsShifts = [];
}
def MipsInstrInfo : InstrInfo;
//===----------------------------------------------------------------------===//
// Mips Subtarget features //

View File

@ -96,14 +96,6 @@ def : Processor<"ppc64", G5Itineraries,
include "PPCCallingConv.td"
def PPCInstrInfo : InstrInfo {
// Define how we want to layout our TargetSpecific information field... This
// should be kept up-to-date with the fields in the PPCInstrInfo.h file.
let TSFlagsFields = ["PPC970_First",
"PPC970_Single",
"PPC970_Cracked",
"PPC970_Unit"];
let TSFlagsShifts = [0, 1, 2, 3];
let isLittleEndianEncoding = 1;
}

View File

@ -23,13 +23,18 @@ class I<bits<6> opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin>
let InOperandList = IOL;
let AsmString = asmstr;
let Itinerary = itin;
/// These fields correspond to the fields in PPCInstrInfo.h. Any changes to
/// these must be reflected there! See comments there for what these are.
bits<1> PPC970_First = 0;
bits<1> PPC970_Single = 0;
bits<1> PPC970_Cracked = 0;
bits<3> PPC970_Unit = 0;
/// These fields correspond to the fields in PPCInstrInfo.h. Any changes to
/// these must be reflected there! See comments there for what these are.
let TSFlags{0} = PPC970_First;
let TSFlags{1} = PPC970_Single;
let TSFlags{2} = PPC970_Cracked;
let TSFlags{5-3} = PPC970_Unit;
}
class PPC970_DGroup_First { bits<1> PPC970_First = 1; }

View File

@ -38,11 +38,7 @@ include "SparcRegisterInfo.td"
include "SparcCallingConv.td"
include "SparcInstrInfo.td"
def SparcInstrInfo : InstrInfo {
// Define how we want to layout our target-specific information field.
let TSFlagsFields = [];
let TSFlagsShifts = [];
}
def SparcInstrInfo : InstrInfo;
//===----------------------------------------------------------------------===//
// SPARC processors supported.

View File

@ -164,33 +164,7 @@ include "X86RegisterInfo.td"
include "X86InstrInfo.td"
def X86InstrInfo : InstrInfo {
// Define how we want to layout our TargetSpecific information field... This
// should be kept up-to-date with the fields in the X86InstrInfo.h file.
let TSFlagsFields = ["FormBits",
"hasOpSizePrefix",
"hasAdSizePrefix",
"Prefix",
"hasREX_WPrefix",
"ImmT.Value",
"FPForm.Value",
"hasLockPrefix",
"SegOvrBits",
"ExeDomain.Value",
"Opcode"];
let TSFlagsShifts = [0,
6,
7,
8,
12,
13,
16,
19,
20,
22,
24];
}
def X86InstrInfo : InstrInfo;
//===----------------------------------------------------------------------===//
// Calling Conventions

View File

@ -128,6 +128,19 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
bit hasLockPrefix = 0; // Does this inst have a 0xF0 prefix?
bits<2> SegOvrBits = 0; // Segment override prefix.
Domain ExeDomain = d;
// TSFlags layout should be kept in sync with X86InstrInfo.h.
let TSFlags{5-0} = FormBits;
let TSFlags{6} = hasOpSizePrefix;
let TSFlags{7} = hasAdSizePrefix;
let TSFlags{11-8} = Prefix;
let TSFlags{12} = hasREX_WPrefix;
let TSFlags{15-13} = ImmT.Value;
let TSFlags{18-16} = FPForm.Value;
let TSFlags{19} = hasLockPrefix;
let TSFlags{21-20} = SegOvrBits;
let TSFlags{23-22} = ExeDomain.Value;
let TSFlags{31-24} = Opcode;
}
class I<bits<8> o, Format f, dag outs, dag ins, string asm,

View File

@ -24,10 +24,7 @@ include "XCoreRegisterInfo.td"
include "XCoreInstrInfo.td"
include "XCoreCallingConv.td"
def XCoreInstrInfo : InstrInfo {
let TSFlagsFields = [];
let TSFlagsShifts = [];
}
def XCoreInstrInfo : InstrInfo;
//===----------------------------------------------------------------------===//
// XCore processors supported.

View File

@ -288,19 +288,19 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
if (Inst.isAsCheapAsAMove) OS << "|(1<<TID::CheapAsAMove)";
if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<TID::ExtraSrcRegAllocReq)";
if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<TID::ExtraDefRegAllocReq)";
OS << ", 0";
// Emit all of the target-specific flags...
ListInit *LI = InstrInfo->getValueAsListInit("TSFlagsFields");
ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts");
if (LI->getSize() != Shift->getSize())
throw "Lengths of " + InstrInfo->getName() +
":(TargetInfoFields, TargetInfoPositions) must be equal!";
for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
emitShiftedValue(Inst.TheDef, dynamic_cast<StringInit*>(LI->getElement(i)),
dynamic_cast<IntInit*>(Shift->getElement(i)), OS);
BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
if (!TSF) throw "no TSFlags?";
uint64_t Value = 0;
for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) {
if (BitInit *Bit = dynamic_cast<BitInit*>(TSF->getBit(i)))
Value |= uint64_t(Bit->getValue()) << i;
else
throw "Invalid TSFlags bit in " + Inst.TheDef->getName();
}
OS << ", 0x";
OS.write_hex(Value);
OS << ", ";
// Emit the implicit uses and defs lists...
@ -328,66 +328,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
OS << "0";
else
OS << "OperandInfo" << OpInfo.find(OperandInfo)->second;
OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
}
void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
IntInit *ShiftInt, raw_ostream &OS) {
if (Val == 0 || ShiftInt == 0)
throw std::string("Illegal value or shift amount in TargetInfo*!");
RecordVal *RV = R->getDottedValue(Val->getValue());
int Shift = ShiftInt->getValue();
if (RV == 0 || RV->getValue() == 0) {
// This isn't an error if this is a builtin instruction.
if (R->getName() != "PHI" &&
R->getName() != "INLINEASM" &&
R->getName() != "DBG_LABEL" &&
R->getName() != "EH_LABEL" &&
R->getName() != "GC_LABEL" &&
R->getName() != "KILL" &&
R->getName() != "EXTRACT_SUBREG" &&
R->getName() != "INSERT_SUBREG" &&
R->getName() != "IMPLICIT_DEF" &&
R->getName() != "SUBREG_TO_REG" &&
R->getName() != "COPY_TO_REGCLASS" &&
R->getName() != "DBG_VALUE")
throw R->getName() + " doesn't have a field named '" +
Val->getValue() + "'!";
return;
}
Init *Value = RV->getValue();
if (BitInit *BI = dynamic_cast<BitInit*>(Value)) {
if (BI->getValue()) OS << "|(1<<" << Shift << ")";
return;
} else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) {
// Convert the Bits to an integer to print...
Init *I = BI->convertInitializerTo(new IntRecTy());
if (I)
if (IntInit *II = dynamic_cast<IntInit*>(I)) {
if (II->getValue()) {
if (Shift)
OS << "|(" << II->getValue() << "<<" << Shift << ")";
else
OS << "|" << II->getValue();
}
return;
}
} else if (IntInit *II = dynamic_cast<IntInit*>(Value)) {
if (II->getValue()) {
if (Shift)
OS << "|(" << II->getValue() << "<<" << Shift << ")";
else
OS << II->getValue();
}
return;
}
errs() << "Unhandled initializer: " << *Val << "\n";
throw "In record '" + R->getName() + "' for TSFlag emission.";
}

View File

@ -47,8 +47,6 @@ private:
std::map<Record*, unsigned> &BM,
const OperandInfoMapTy &OpInfo,
raw_ostream &OS);
void emitShiftedValue(Record *R, StringInit *Val, IntInit *Shift,
raw_ostream &OS);
// Itinerary information.
void GatherItinClasses();

View File

@ -1307,17 +1307,6 @@ void Record::resolveReferencesTo(const RecordVal *RV) {
}
}
RecordVal *Record::getDottedValue(StringRef Name) {
size_t pos = Name.find('.');
if (pos == StringRef::npos)
return getValue(Name);
RecordVal *RV = getValue(Name.substr(0, pos));
if (!RV) return 0;
DefInit *DI = dynamic_cast<DefInit*>(RV->getValue());
if (!DI) return 0;
return DI->getDef()->getDottedValue(Name.substr(pos+1));
}
void Record::dump() const { errs() << *this; }
raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) {

View File

@ -1262,9 +1262,6 @@ public:
return 0;
}
// Like getValue, but allow dotting into members: X.Y
RecordVal *getDottedValue(StringRef Name);
void addTemplateArg(StringRef Name) {
assert(!isTemplateArg(Name) && "Template arg already defined!");
TemplateArgs.push_back(Name);