llvm.org GIT mirror llvm / 86f9adb
TableGen'erated MC lowering for simple pseudo-instructions. This allows the (many) pseudo-instructions we have that map onto a single real instruction to have their expansion during MC lowering handled automatically instead of the current cumbersome manual expansion required. These sorts of pseudos are common when an instruction is used in situations that require different MachineInstr flags (isTerminator, isBranch, et. al.) than the generic instruction description has. For example, using a move to the PC to implement a branch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134704 91177308-0d34-0410-b5e6-96231b3b80d8 Jim Grosbach 8 years ago
6 changed file(s) with 329 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
17481748 $(ObjDir)/%GenMCCodeEmitter.inc.tmp: %.td $(ObjDir)/.dir
17491749 $(Echo) "Building $(
17501750 $(Verb) $(TableGen) -gen-emitter -mc-emitter -o $(call SYSPATH, $@) $<
1751
1752 $(TARGET:%=$(ObjDir)/%GenMCPseudoLowering.inc.tmp): \
1753 $(ObjDir)/%GenMCPseudoLowering.inc.tmp: %.td $(ObjDir)/.dir
1754 $(Echo) "Building $(
1755 $(Verb) $(TableGen) -gen-pseudo-lowering -o $(call SYSPATH, $@) $<
17511756
17521757 $(TARGET:%=$(ObjDir)/%GenCodeEmitter.inc.tmp): \
17531758 $(ObjDir)/%GenCodeEmitter.inc.tmp: %.td $(ObjDir)/.dir
372372 ///@}
373373 }
374374
375 /// PseudoInstExpansion - Expansion information for a pseudo-instruction.
376 /// Which instruction it expands to and how the operands map from the
377 /// pseudo.
378 class PseudoInstExpansion {
379 dag ResultInst = Result; // The instruction to generate.
380 bit isPseudo = 1;
381 }
382
375383 /// Predicates - These are extra conditionals which are turned into instruction
376384 /// selector matching code. Currently each predicate is just a string.
377385 class Predicate {
3333 LLVMCConfigurationEmitter.cpp
3434 NeonEmitter.cpp
3535 OptParserEmitter.cpp
36 PseudoLoweringEmitter.cpp
3637 Record.cpp
3738 RegisterInfoEmitter.cpp
3839 SetTheory.cpp
0 //===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #define DEBUG_TYPE "pseudo-lowering"
10 #include "Error.h"
11 #include "CodeGenInstruction.h"
12 #include "PseudoLoweringEmitter.h"
13 #include "Record.h"
14 #include "llvm/ADT/IndexedMap.h"
15 #include "llvm/ADT/StringMap.h"
16 #include "llvm/Support/ErrorHandling.h"
17 #include "llvm/Support/Debug.h"
18 #include
19 using namespace llvm;
20
21 // FIXME: This pass currently can only expand a pseudo to a single instruction.
22 // The pseudo expansion really should take a list of dags, not just
23 // a single dag, so we can do fancier things.
24
25 unsigned PseudoLoweringEmitter::
26 addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
27 IndexedMap &OperandMap, unsigned BaseIdx) {
28 unsigned OpsAdded = 0;
29 for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
30 if (DefInit *DI = dynamic_cast(Dag->getArg(i))) {
31 // Physical register reference. Explicit check for the special case
32 // "zero_reg" definition.
33 if (DI->getDef()->isSubClassOf("Register") ||
34 DI->getDef()->getName() == "zero_reg") {
35 OperandMap[BaseIdx + i].Kind = OpData::Reg;
36 OperandMap[BaseIdx + i].Data.Reg = DI->getDef();
37 ++OpsAdded;
38 continue;
39 }
40
41 // Normal operands should always have the same type, or we have a
42 // problem.
43 // FIXME: We probably shouldn't ever get a non-zero BaseIdx here.
44 assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!");
45 if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec)
46 throw TGError(Rec->getLoc(),
47 "Pseudo operand type '" + DI->getDef()->getName() +
48 "' does not match expansion operand type '" +
49 Insn.Operands[BaseIdx + i].Rec->getName() + "'");
50 // Source operand maps to destination operand. The Data element
51 // will be filled in later, just set the Kind for now. Do it
52 // for each corresponding MachineInstr operand, not just the first.
53 for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
54 OperandMap[BaseIdx + i + I].Kind = OpData::Operand;
55 OpsAdded += Insn.Operands[i].MINumOperands;
56 } else if (IntInit *II = dynamic_cast(Dag->getArg(i))) {
57 OperandMap[BaseIdx + i].Kind = OpData::Imm;
58 OperandMap[BaseIdx + i].Data.Imm = II->getValue();
59 ++OpsAdded;
60 } else if (DagInit *SubDag = dynamic_cast(Dag->getArg(i))) {
61 // Just add the operands recursively. This is almost certainly
62 // a constant value for a complex operand (> 1 MI operand).
63 unsigned NewOps =
64 addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i);
65 OpsAdded += NewOps;
66 // Since we added more than one, we also need to adjust the base.
67 BaseIdx += NewOps - 1;
68 } else
69 assert(0 && "Unhandled pseudo-expansion argument type!");
70 }
71 return OpsAdded;
72 }
73
74 void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
75 DEBUG(dbgs() << "Pseudo definition: " << Rec->getName() << "\n");
76
77 // Validate that the result pattern has the corrent number and types
78 // of arguments for the instruction it references.
79 DagInit *Dag = Rec->getValueAsDag("ResultInst");
80 assert(Dag && "Missing result instruction in pseudo expansion!");
81 DEBUG(dbgs() << " Result: " << *Dag << "\n");
82
83 DefInit *OpDef = dynamic_cast(Dag->getOperator());
84 if (!OpDef)
85 throw TGError(Rec->getLoc(), Rec->getName() +
86 " has unexpected operator type!");
87 Record *Operator = OpDef->getDef();
88 if (!Operator->isSubClassOf("Instruction"))
89 throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
90 "' is not an instruction!");
91
92 CodeGenInstruction Insn(Operator);
93
94 if (Insn.isCodeGenOnly || Insn.isPseudo)
95 throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
96 "' cannot be another pseudo instruction!");
97
98 if (Insn.Operands.size() != Dag->getNumArgs())
99 throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
100 "' operand count mismatch");
101
102 IndexedMap OperandMap;
103 OperandMap.grow(Insn.Operands.size());
104
105 addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0);
106
107 // If there are more operands that weren't in the DAG, they have to
108 // be operands that have default values, or we have an error. Currently,
109 // PredicateOperand and OptionalDefOperand both have default values.
110
111
112 // Validate that each result pattern argument has a matching (by name)
113 // argument in the source instruction, in either the (outs) or (ins) list.
114 // Also check that the type of the arguments match.
115 //
116 // Record the mapping of the source to result arguments for use by
117 // the lowering emitter.
118 CodeGenInstruction SourceInsn(Rec);
119 StringMap SourceOperands;
120 for (unsigned i = 0, e = SourceInsn.Operands.size(); i != e; ++i)
121 SourceOperands[SourceInsn.Operands[i].Name] = i;
122
123 DEBUG(dbgs() << " Operand mapping:\n");
124 for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) {
125 // We've already handled constant values. Just map instruction operands
126 // here.
127 if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand)
128 continue;
129 StringMap::iterator SourceOp =
130 SourceOperands.find(Dag->getArgName(i));
131 if (SourceOp == SourceOperands.end())
132 throw TGError(Rec->getLoc(),
133 "Pseudo output operand '" + Dag->getArgName(i) +
134 "' has no matching source operand.");
135 // Map the source operand to the destination operand index for each
136 // MachineInstr operand.
137 for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
138 OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand =
139 SourceOp->getValue();
140
141 DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << i << "\n");
142 }
143
144 Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap));
145 }
146
147 void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
148 // Emit file header.
149 EmitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o);
150
151 o << "bool " << Target.getName() + "AsmPrinter" << "::\n"
152 << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n"
153 << " const MachineInstr *MI) {\n"
154 << " switch (MI->getOpcode()) {\n"
155 << " default: return false;\n";
156 for (unsigned i = 0, e = Expansions.size(); i != e; ++i) {
157 PseudoExpansion &Expansion = Expansions[i];
158 CodeGenInstruction &Source = Expansion.Source;
159 CodeGenInstruction &Dest = Expansion.Dest;
160 o << " case " << Source.Namespace << "::"
161 << Source.TheDef->getName() << ": {\n"
162 << " MCInst TmpInst;\n"
163 << " MCOperand MCOp;\n"
164 << " TmpInst.setOpcode(" << Dest.Namespace << "::"
165 << Dest.TheDef->getName() << ");\n";
166
167 // Copy the operands from the source instruction.
168 // FIXME: Instruction operands with defaults values (predicates and cc_out
169 // in ARM, for example shouldn't need explicit values in the
170 // expansion DAG.
171 unsigned MIOpNo = 0;
172 for (unsigned OpNo = 0, E = Dest.Operands.size(); OpNo != E;
173 ++OpNo) {
174 o << " // Operand: " << Dest.Operands[OpNo].Name << "\n";
175 for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands;
176 i != e; ++i) {
177 switch (Expansion.OperandMap[MIOpNo + i].Kind) {
178 default:
179 llvm_unreachable("Unknown operand type?!");
180 case OpData::Operand:
181 o << " lowerOperand(MI->getOperand("
182 << Source.Operands[Expansion.OperandMap[MIOpNo].Data
183 .Operand].MIOperandNo + i
184 << "), MCOp);\n"
185 << " TmpInst.addOperand(MCOp);\n";
186 break;
187 case OpData::Imm:
188 o << " TmpInst.addOperand(MCOperand::CreateImm("
189 << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n";
190 break;
191 case OpData::Reg: {
192 Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg;
193 o << " TmpInst.addOperand(MCOperand::CreateReg(";
194 // "zero_reg" is special.
195 if (Reg->getName() == "zero_reg")
196 o << "0";
197 else
198 o << Reg->getValueAsString("Namespace") << "::" << Reg->getName();
199 o << "));\n";
200 break;
201 }
202 }
203 }
204 MIOpNo += Dest.Operands[OpNo].MINumOperands;
205 }
206 if (Dest.Operands.isVariadic) {
207 o << " // variable_ops\n";
208 o << " for (unsigned i = " << MIOpNo
209 << ", e = MI->getNumOperands(); i != e; ++i)\n"
210 << " if (lowerOperand(MI->getOperand(i), MCOp))\n"
211 << " TmpInst.addOperand(MCOp);\n";
212 }
213 o << " OutStreamer.EmitInstruction(TmpInst);\n"
214 << " break;\n"
215 << " }\n";
216 }
217 o << " }\n return true;\n}\n\n";
218 }
219
220 void PseudoLoweringEmitter::run(raw_ostream &o) {
221 Record *ExpansionClass = Records.getClass("PseudoInstExpansion");
222 Record *InstructionClass = Records.getClass("PseudoInstExpansion");
223 assert(ExpansionClass && "PseudoInstExpansion class definition missing!");
224 assert(InstructionClass && "Instruction class definition missing!");
225
226 std::vector Insts;
227 for (std::map::const_iterator I =
228 Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) {
229 if (I->second->isSubClassOf(ExpansionClass) &&
230 I->second->isSubClassOf(InstructionClass))
231 Insts.push_back(I->second);
232 }
233
234 // Process the pseudo expansion definitions, validating them as we do so.
235 for (unsigned i = 0, e = Insts.size(); i != e; ++i)
236 evaluateExpansion(Insts[i]);
237
238 // Generate expansion code to lower the pseudo to an MCInst of the real
239 // instruction.
240 emitLoweringEmitter(o);
241 }
242
0 //===- PseudoLoweringEmitter.h - PseudoLowering Generator -------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef PSEUDOLOWERINGEMITTER_H
10 #define PSEUDOLOWERINGEMITTER_H
11
12 #include "CodeGenInstruction.h"
13 #include "CodeGenTarget.h"
14 #include "TableGenBackend.h"
15 #include "llvm/ADT/IndexedMap.h"
16 #include "llvm/ADT/SmallVector.h"
17
18 namespace llvm {
19
20 class PseudoLoweringEmitter : public TableGenBackend {
21 struct OpData {
22 enum MapKind { Operand, Imm, Reg };
23 MapKind Kind;
24 union {
25 unsigned Operand; // Operand number mapped to.
26 uint64_t Imm; // Integer immedate value.
27 Record *Reg; // Physical register.
28 } Data;
29 };
30 struct PseudoExpansion {
31 CodeGenInstruction Source; // The source pseudo instruction definition.
32 CodeGenInstruction Dest; // The destination instruction to lower to.
33 IndexedMap OperandMap;
34
35 PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d,
36 IndexedMap &m) :
37 Source(s), Dest(d), OperandMap(m) {}
38 };
39
40 RecordKeeper &Records;
41
42 // It's overkill to have an instance of the full CodeGenTarget object,
43 // but it loads everything on demand, not in the constructor, so it's
44 // lightweight in performance, so it works out OK.
45 CodeGenTarget Target;
46
47 SmallVector Expansions;
48
49 unsigned addDagOperandMapping(Record *Rec, DagInit *Dag,
50 CodeGenInstruction &Insn,
51 IndexedMap &OperandMap,
52 unsigned BaseIdx);
53 void evaluateExpansion(Record *Pseudo);
54 void emitLoweringEmitter(raw_ostream &o);
55 public:
56 PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {}
57
58 /// run - Output the pseudo-lowerings.
59 void run(raw_ostream &o);
60 };
61
62 } // end llvm namespace
63
64 #endif
3232 #include "LLVMCConfigurationEmitter.h"
3333 #include "NeonEmitter.h"
3434 #include "OptParserEmitter.h"
35 #include "PseudoLoweringEmitter.h"
3536 #include "Record.h"
3637 #include "RegisterInfoEmitter.h"
3738 #include "ARMDecoderEmitter.h"
5859 GenAsmMatcher,
5960 GenARMDecoder,
6061 GenDisassembler,
62 GenPseudoLowering,
6163 GenCallingConv,
6264 GenClangAttrClasses,
6365 GenClangAttrImpl,
105107 "Generate decoders for ARM/Thumb"),
106108 clEnumValN(GenDisassembler, "gen-disassembler",
107109 "Generate disassembler"),
110 clEnumValN(GenPseudoLowering, "gen-pseudo-lowering",
111 "Generate pseudo instruction lowering"),
108112 clEnumValN(GenAsmMatcher, "gen-asm-matcher",
109113 "Generate assembly instruction matcher"),
110114 clEnumValN(GenDAGISel, "gen-dag-isel",
313317 case GenDisassembler:
314318 DisassemblerEmitter(Records).run(Out.os());
315319 break;
320 case GenPseudoLowering:
321 PseudoLoweringEmitter(Records).run(Out.os());
322 break;
316323 case GenOptParserDefs:
317324 OptParserEmitter(Records, true).run(Out.os());
318325 break;