Replace TSFlagsFields and TSFlagsShifts with a simpler TSFlags field.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Mon, 5 Apr 2010 03:10:20 +0000 (03:10 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Mon, 5 Apr 2010 03:10:20 +0000 (03:10 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100384 91177308-0d34-0410-b5e6-96231b3b80d8

18 files changed:
include/llvm/Target/Target.td
lib/Target/ARM/ARM.td
lib/Target/ARM/ARMInstrFormats.td
lib/Target/Alpha/Alpha.td
lib/Target/MBlaze/MBlaze.td
lib/Target/MSP430/MSP430.td
lib/Target/MSP430/MSP430InstrFormats.td
lib/Target/Mips/Mips.td
lib/Target/PowerPC/PPC.td
lib/Target/PowerPC/PPCInstrFormats.td
lib/Target/Sparc/Sparc.td
lib/Target/X86/X86.td
lib/Target/X86/X86InstrFormats.td
lib/Target/XCore/XCore.td
utils/TableGen/InstrInfoEmitter.cpp
utils/TableGen/InstrInfoEmitter.h
utils/TableGen/Record.cpp
utils/TableGen/Record.h

index 0a7f54937705a6174afaaf2a63dc2dc25b70be51..5612f97acf41e62f8c14870266db8b223b0a9ace 100644 (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
index 6486a608e46d5585a2cc86c839c7dd9ca0d60220..8d9c62253cdd1d65373724bd41d996c2c07c84c7 100644 (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
index 4427e50bbdb19a62ff2db2c07cd700b6be3660b9..b466d0dd994e0b853a7503688b118d860ac073b2 100644 (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,
index 6efdf554e1760f63ab480037c6ce5893b2350771..4508eda897d2b98aacbcd419ab00ce53754d8869 100644 (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
index 16797529cb2800ee0035f23d432dd04ae3f2da5c..482ddd3963fbaaa9ca43ee7be788f001f156258b 100644 (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                                              //
index fe533d3d2e5c84eb7594eaba89d436b9e6720711..0f08e3d8ca0f597b5e7da34d4c7d51a695a02a74 100644 (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";
index 4ccc7df57664f1e87bbb1b38c0ec220c1b8a4aad..73aef1facc0f9fa98535f07b3d4e50ecf988bddc 100644 (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;
 }
index 79a78d86aef7893e8a1a47195c7718d78f3b2faf..aa036aef83d0b81f340df923526b8ed9857db76a 100644 (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                                                    //
index 08f5bb43087f611bda0f965248541746113b6cf9..27644b2daca872fbee099808ed1fdccda28407ba 100644 (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;
 }
 
index 54cebcdecd61a35b3f5bf23871ea04baff34a5d4..4357bdccec7bde7f633bb82296e5a0f683a2ed74 100644 (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;  }
index 53ea8f4a35f0fd295ea62855363b820174d5bbfd..925d782d988be8a56f810bb452de486fc5027eb3 100644 (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.
index 89cc84ffb3c6b48d75a0a5dba5afb518d5ab378e..ec86fc248e3d444fd47bb5c26d8c10ff0dd0fbb1 100644 (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
index cbe4c825629918ec20ad0ca1e3b1f76ccd269e03..42414337934667bf3cefba71c88180b08a386f2c 100644 (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,
index b07445dd386f297cccc58c9224db75422f4e1c5d..38401895e6345f22b55e99a9b9d843552c678da9 100644 (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.
index 9bc545928d9b57e3aa4d3979941d8a8a61de1925..006a2a1b09335922158274b11c8ed83eb77bf2c4 100644 (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.";
+  OS << " },  // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
 }
-
index 657939e46388508edf81c59af42161b4f0bddc8d..abb1c6bc188cbd94e9ee7c15cb9ec6153dcdb0ea 100644 (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();
index 55c998926c0ae0400f5556dd6b1d7e0c50fac96f..4f9f6045c14c9ea35c7c7f685237b8f1341cb418 100644 (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) {
index 41373c799a0dc67b0caf0ef92e5fba5aba80c738..55c1a80f9b6a048d3297f6044d3235b9191e0f7c 100644 (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);