Jyotsna Verma
2012-Aug-16 20:39 UTC
[LLVMdev] TableGen related question for the Hexagon backend
Hi Everyone, After some more thoughts to the Jacob's suggestion of using multiclasses for Opcode mapping, this is what I have come up with. Please take a look at the design below and let me know if you have any suggestions/questions. I have tried to keep the design target independent so that other targets could benefit from it. 1) The idea is to add 3 new classes into include/llvm/Target/Target.td which provide the basic infrastructure for relating instructions with each other. Class Relations {} // any target interested in mapping relations, need to define a // class of its own as a subclass of 'Relations'. class IFormat<bits<4> value> { // Used to define basic instruction formats, Ex: register-register, register-immediate bits<4> Value = value; } // class RelationMap is actually used to related instructions with each other. class RelationMap<IFormat pFormat, IFormat iFormat, list<string> ancestors [] > { IFormat ParentFormat = pFormat; IFormat InstrFormat = iFormat; list <string> Ancestors = ancestors; } 2) Include some basic setup in the InstrInfo.td file. Any target interested in mapping relation needs to define a class as a subclass of 'Relations'. This class is primarily used for the recordkeeping and has one string variable for each basic format required for relation modeling. All instructions that want to define relationship mapping, should inherit from this class in addition to RelationMap class. This is explained below using a prototype model for Hexagon. Example from Hexagon backend: class RelHexagon : Relations { string InstFormat0; //prev form string InstFormat1; //rr (register register) string InstFormat2; //ri (register immediate) string InstFormat3; //pred true string InstFormat4; //pred false } Define Instruction formats which are IFormat objects and have a unique integer value associated with them. It is used to access appropriate field within RelHexagon Class. def Format_prev : IFormat<0>; // previous form def Format_rr : IFormat<1>; // register register def Format_ri : IFormat<2>; // register immediate def Format_predt : IFormat<3>; // pred true def Format_predf : IFormat<4>; // pred false 4) Prototype relationship model for a simple 'add' instruction with 6 variants: /---- if (p0) R1 = add(R2, R3) / (Predicate true) Add register register - R1 = add(R2, R3) -- \ \---- if (!p0) R1 = add(R2, R3) (predicate false) /---- if (p0) R1 = add(R2, #12) / (Predicate true) Add register immediate - R1 = add(R2, #12) -- \ \---- if (!p0) R1 = add(R2, #12) (predicate false) multiclass Add_rr < IFormat TransformsFrom> { def #NAME# : V2_A2_add, RelationMap < TransformsFrom, Format_rr>; defm _pt : V2_A2_padd, RelationMap < Format_rr, Format_predt, ["rr"]>; defm _pf : V2_A2_padd, RelationMap < Format_rr, Format_predf, ["rr"] >; } multiclass Add_ri < IFormat TransformsFrom> { def #NAME# : V2_A2_addi, RelationMap < TransformsFrom, Format_ri >; defm _pt : V2_A2_paddi, RelationMap < Format_ri, Format_predt, ["ri"] >; defm _pf : V2_A2_paddi, RelationMap < Format_ri, Format_predf, ["ri"] >; } multiclass Add_base { defm rr : Add_rr < Format_rr>; defm ri : Add_ri < Format_rr>; } defm ADD : Add_base, RelHexagon; <- defm needs to inherit from RelHexagon Class here 5) We need some changes in the TGParser.cpp so that it can use the information specified through the RelationMap and populate relevant fields in the RelHexagon class. This eventually becomes part of the instruction definition (record). bool TGParser::ParseDefm(MultiClass *CurMultiClass) { ... if (InheritFromClass) { // Process all the classes to inherit as if they were part of a // regular 'def' and inherit all record values. SubClassReference SubClass = ParseSubClassReference(0, false); while (1) { // Check for error. if (SubClass.Rec == 0) return true; // Get the expanded definition prototypes and teach them about // the record values the current class to inherit has for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) { Record *CurRec = NewRecDefs[i]; **** proposed changes -begin ***** if (SubClass.Rec->isSubClassOf("Relations")) { std::vector<Init*> InstrFormats(SubClass.Rec->getValues().size()); 1) Traverse thru all the records to see if CurRec's InstrFormat is same as the ParentFormat for any of the records and they both share same ancestors. If so, insert that record at the appropriate place in the vector using the integer value of the InstrFormat of the children instructions. 2) Use Vector to populate fields of the SubClass.Rec (RelHexagon in our case) Class. } **** proposed changes -end ***** // All the fields from a subclass are eventually added into the instruction record -- existing functionality 6) Add a new command line option into TableGen that will emit this information as a table in a .inc file. 7) Target is required to add its own API to read the table and extract relevant information. Thanks, Jyotsna -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum. -----Original Message----- From: Jakob Stoklund Olesen [mailto:stoklund at 2pi.dk] Sent: Thursday, August 02, 2012 5:24 PM To: Jyotsna Verma Cc: 'Tony Linthicum'; llvmdev at cs.uiuc.edu Subject: Re: TableGen related question for the Hexagon backend On Aug 1, 2012, at 1:53 PM, Jyotsna Verma <jverma at codeaurora.org> wrote:> > Currently, we rely on switch tables to transform between formats. > However, we would like to have a different mechanism to represent > these relationships instead of switch tables. I am thinking of > modeling these relations in HexagonInstrInfo.td file and use TableGen > to generate a table with the information.That would be a good idea. X86 could also use some help with opcode mapping tables.> Idea is to have a new class, say Relations, with some members of type > 'Instruction' each representing a specific relation between itself and > 'ThisInstr'. > > For example: > class Relations { > Instruction ThisInstr; > Instruction BaseForm; > Instruction TruePred; > Instruction FalsePred; > } > > def Rel_ADDrr : Relations<ADDrr, ADDrr, ADDrr_p, ADDrr_np>; def > Rel_ADDrr_p: Relations<ADDrr_p, ADDrr, , >; def Rel_ADDrr_np : > Relations<ADDrr_np,ADDrr, , >;The problem is, this isn't really any better than having a large switch statement. You just moved the table into the .td file. You should be taking advantage of the instruction multiclasses so you don't have to maintain a full table of opcodes. /jakob
Jakob Stoklund Olesen
2012-Aug-17 00:21 UTC
[LLVMdev] TableGen related question for the Hexagon backend
On Aug 16, 2012, at 1:39 PM, Jyotsna Verma <jverma at codeaurora.org> wrote:> Hi Everyone, > > After some more thoughts to the Jacob's suggestion of using multiclasses for > Opcode mapping, this is what I have come up with. Please take a look at the > design below and let me know if you have any suggestions/questions.Hi Jyotsna, You are on to something here, but you don't need to define a 'Relations' class on top of the tablegen records. They are already relations, you just need the proper query language to match the instructions you want. You simply use the existing fields in your instructions, or add new ones as needed. You don't want to be limited to a single 'IFormat' as a column identifier, there can be many different types of relationships between instructions. Do something like this: def getPredicatedOpcode : InstrMapping { // Only include instructions form the PredRel class. let FilterClass = "PredRel"; // Instructions with the same BaseOpcode field form a row. let RowFields = ["BaseOpcode"]; // Instructions with the same predicate sense form a column. let ColFields = ["PredSense"]; // The key column is the unpredicated instructions. let KeyCol = ["nopred"]; // Value columns are predicate=true and predicate=false let ValueCols = [["true"], ["false"]]; }; That should be enough to generate a table: // key , PredSense=true, PredSense=false { ADD , ADDtrue, ADDfalse, // BaseOpcode="ADD" { SUB , SUBtrue, SUBfalse, // BaseOpcode="SUB" …> 5) We need some changes in the TGParser.cpp so that it can use the > information specified > through the RelationMap and populate relevant fields in the RelHexagon > class.The tablegen parser is definitely not the right place to implement this. /jakob
Jyotsna Verma
2012-Aug-17 17:02 UTC
[LLVMdev] TableGen related question for the Hexagon backend
Hi Jacob, Thanks for the suggestions. I have a few questions here.> You are on to something here, but you don't need to define a 'Relations'class> on top of the tablegen records. They are already relations, you just needthe> proper query language to match the instructions you want.Are you saying that the mechanism is already present which allows us to relate instructions with each other? What do you mean by a proper query language?> You don't want to be limited to a single 'IFormat' as a column > identifier, there can be many different types of relationships between > instructions.We do have different type of relationships between instructions. I define multiple IFormat objects one per relationship which finally translates into a unique column into the mapping table. def Format_rr : IFormat<1>; def Format_ri : IFormat<2>; def Format_predt : IFormat<3>; def Format_predf : IFormat<4>; Addrr : { Addrr, Addri, Addrr_pt, Addrr_pf, .. , ..} Addri : { Addrr, Addri, Addri_pt, Addri_pf,..> Do something like this: > > def getPredicatedOpcode : InstrMapping { > // Only include instructions form the PredRel class. > let FilterClass = "PredRel"; > > // Instructions with the same BaseOpcode field form a row. > let RowFields = ["BaseOpcode"]; > > // Instructions with the same predicate sense form a column. > let ColFields = ["PredSense"]; > > // The key column is the unpredicated instructions. > let KeyCol = ["nopred"]; > > // Value columns are predicate=true and predicate=false > let ValueCols = [["true"], ["false"]]; };Can you please elaborate it more? It seems interesting but I coundn't understand it completely. Also, how do I get the table from the definition above? For the table, I need to know the name of the predicated-true and false instructions.> That should be enough to generate a table: > > // key , PredSense=true, PredSense=false > { ADD , ADDtrue, ADDfalse, // BaseOpcode="ADD" > { SUB , SUBtrue, SUBfalse, // BaseOpcode="SUB"> > > 5) We need some changes in the TGParser.cpp so that it can use the > > information specified through the RelationMap and populate relevant > > fields in the RelHexagon class. > > The tablegen parser is definitely not the right place to implement this.I didn't want to modify the tablegen parser either. But, I couldn't think of a way around it. Once instructions are expended by the TableGen parser, there is no way to relate them. Since I wanted to encode this formation within the instruction itself while they are being expanded, parser appeared to be the only place to do it. Thanks, Jyotsna
Possibly Parallel Threads
- [LLVMdev] TableGen related question for the Hexagon backend
- [LLVMdev] TableGen related question for the Hexagon backend
- [LLVMdev] TableGen related question for the Hexagon backend
- [LLVMdev] TableGen related question for the Hexagon backend
- [LLVMdev] TableGen backend support to express relations between instruction