diff options
-rw-r--r-- | llvm/include/llvm/Target/TargetInstrDesc.h | 24 | ||||
-rw-r--r-- | llvm/utils/TableGen/InstrInfoEmitter.cpp | 56 | ||||
-rw-r--r-- | llvm/utils/TableGen/InstrInfoEmitter.h | 5 |
3 files changed, 79 insertions, 6 deletions
diff --git a/llvm/include/llvm/Target/TargetInstrDesc.h b/llvm/include/llvm/Target/TargetInstrDesc.h index c83f8e21fb9..6d9a9bca28b 100644 --- a/llvm/include/llvm/Target/TargetInstrDesc.h +++ b/llvm/include/llvm/Target/TargetInstrDesc.h @@ -19,6 +19,8 @@ namespace llvm { +class TargetRegisterClass; + //===----------------------------------------------------------------------===// // Machine Operand Flags and Description //===----------------------------------------------------------------------===// @@ -107,16 +109,17 @@ namespace TID { /// points to this struct directly to describe itself. class TargetInstrDesc { public: - unsigned short Opcode; // The opcode number. + unsigned short Opcode; // The opcode number unsigned short NumOperands; // Num of args (may be more if variable_ops) - unsigned short NumDefs; // Num of args that are definitions. + unsigned short NumDefs; // Num of args that are definitions unsigned short SchedClass; // enum identifying instr sched class - const char * Name; // Name of the instruction record in td file. - unsigned Flags; // flags identifying machine instr class + const char * Name; // Name of the instruction record in td file + unsigned Flags; // Flags identifying machine instr class unsigned TSFlags; // Target Specific Flag values const unsigned *ImplicitUses; // Registers implicitly read by this instr const unsigned *ImplicitDefs; // Registers implicitly defined by this instr - const TargetOperandInfo *OpInfo; // 'NumOperands' entries about operands. + const TargetRegisterClass **RCBarriers; // Reg classes completely "clobbered" + const TargetOperandInfo *OpInfo; // 'NumOperands' entries about operands /// getOperandConstraint - Returns the value of the specific constraint if /// it is set. Returns -1 if it is not set. @@ -202,6 +205,17 @@ public: return ImplicitDefs; } + /// getRegClassBarriers - Return a list of register classes that are + /// completely clobbered by this machine instruction. For example, on X86 + /// the call instructions will completely clobber all the registers in the + /// fp stack and XMM classes. + /// + /// This method returns null if the instruction doesn't completely clobber + /// any register class. + const TargetRegisterClass **getRegClassBarriers() const { + return RCBarriers; + } + /// getSchedClass - Return the scheduling class for this instruction. The /// scheduling class is an index into the InstrItineraryData table. This /// returns zero if there is no known scheduling information for the diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp index c29f5c48bfa..705901f91df 100644 --- a/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -27,6 +27,14 @@ static void PrintDefList(const std::vector<Record*> &Uses, OS << "0 };\n"; } +static void PrintBarriers(std::vector<Record*> &Barriers, + unsigned Num, std::ostream &OS) { + OS << "static const TargetRegisterClass* Barriers" << Num << "[] = { "; + for (unsigned i = 0, e = Barriers.size(); i != e; ++i) + OS << "&" << getQualifiedName(Barriers[i]) << "RegClass, "; + OS << "NULL };\n"; +} + //===----------------------------------------------------------------------===// // Instruction Itinerary Information. //===----------------------------------------------------------------------===// @@ -137,6 +145,33 @@ void InstrInfoEmitter::EmitOperandInfo(std::ostream &OS, } } +void InstrInfoEmitter::DetectRegisterClassBarriers(std::vector<Record*> &Defs, + const std::vector<CodeGenRegisterClass> &RCs, + std::vector<Record*> &Barriers) { + std::set<Record*> DefSet; + unsigned NumDefs = Defs.size(); + for (unsigned i = 0; i < NumDefs; ++i) + DefSet.insert(Defs[i]); + + for (unsigned i = 0, e = RCs.size(); i != e; ++i) { + const CodeGenRegisterClass &RC = RCs[i]; + unsigned NumRegs = RC.Elements.size(); + if (NumRegs > NumDefs) + continue; // Can't possibly clobber this RC. + + bool Clobber = true; + for (unsigned j = 0; j < NumRegs; ++j) { + Record *Reg = RC.Elements[j]; + if (!DefSet.count(Reg)) { + Clobber = false; + break; + } + } + if (Clobber) + Barriers.push_back(RC.TheDef); + } +} + //===----------------------------------------------------------------------===// // Main Output. //===----------------------------------------------------------------------===// @@ -151,10 +186,14 @@ void InstrInfoEmitter::run(std::ostream &OS) { CodeGenTarget &Target = CDP.getTargetInfo(); const std::string &TargetName = Target.getName(); Record *InstrInfo = Target.getInstructionSet(); + const std::vector<CodeGenRegisterClass> &RCs = Target.getRegisterClasses(); // Keep track of all of the def lists we have emitted already. std::map<std::vector<Record*>, unsigned> EmittedLists; unsigned ListNumber = 0; + std::map<std::vector<Record*>, unsigned> EmittedBarriers; + unsigned BarrierNumber = 0; + std::map<Record*, unsigned> BarriersMap; // Emit all of the instruction's implicit uses and defs. for (CodeGenTarget::inst_iterator II = Target.inst_begin(), @@ -167,6 +206,14 @@ void InstrInfoEmitter::run(std::ostream &OS) { } std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs"); if (!Defs.empty()) { + std::vector<Record*> RCBarriers; + DetectRegisterClassBarriers(Defs, RCs, RCBarriers); + if (!RCBarriers.empty()) { + unsigned &IB = EmittedBarriers[RCBarriers]; + if (!IB) PrintBarriers(RCBarriers, IB = ++BarrierNumber, OS); + BarriersMap.insert(std::make_pair(Inst, IB)); + } + unsigned &IL = EmittedLists[Defs]; if (!IL) PrintDefList(Defs, IL = ++ListNumber, OS); } @@ -186,7 +233,7 @@ void InstrInfoEmitter::run(std::ostream &OS) { for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists, - OperandInfoIDs, OS); + BarriersMap, OperandInfoIDs, OS); OS << "};\n"; OS << "} // End llvm namespace \n"; } @@ -194,6 +241,7 @@ void InstrInfoEmitter::run(std::ostream &OS) { void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map<std::vector<Record*>, unsigned> &EmittedLists, + std::map<Record*, unsigned> &BarriersMap, const OperandInfoMapTy &OpInfo, std::ostream &OS) { int MinOperands = 0; @@ -257,6 +305,12 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, else OS << "ImplicitList" << EmittedLists[DefList] << ", "; + std::map<Record*, unsigned>::iterator BI = BarriersMap.find(Inst.TheDef); + if (BI == BarriersMap.end()) + OS << "NULL, "; + else + OS << "Barriers" << BI->second << ", "; + // Emit the operand info. std::vector<std::string> OperandInfo = GetOperandInfo(Inst); if (OperandInfo.empty()) diff --git a/llvm/utils/TableGen/InstrInfoEmitter.h b/llvm/utils/TableGen/InstrInfoEmitter.h index 2dd3a0f44fc..870ea0c5878 100644 --- a/llvm/utils/TableGen/InstrInfoEmitter.h +++ b/llvm/utils/TableGen/InstrInfoEmitter.h @@ -44,6 +44,7 @@ private: void emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map<std::vector<Record*>, unsigned> &EL, + std::map<Record*, unsigned> &BM, const OperandInfoMapTy &OpInfo, std::ostream &OS); void emitShiftedValue(Record *R, StringInit *Val, IntInit *Shift, @@ -56,6 +57,10 @@ private: // Operand information. void EmitOperandInfo(std::ostream &OS, OperandInfoMapTy &OperandInfoIDs); std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst); + + void DetectRegisterClassBarriers(std::vector<Record*> &Defs, + const std::vector<CodeGenRegisterClass> &RCs, + std::vector<Record*> &Barriers); }; } // End llvm namespace |