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:
parent
ab5dc34351
commit
b93331f3be
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 //
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 //
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.";
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue