[llvm-commits] [llvm] r118352 - in /llvm/trunk: docs/CodeGenerator.html lib/Target/X86/AsmParser/X86AsmParser.cpp lib/Target/X86/X86InstrInfo.td utils/TableGen/AsmMatcherEmitter.cpp utils/TableGen/CodeGenInstruction.cpp utils/TableGen/CodeGenInstruction.h utils/TableGen/CodeGenRegisters.h
Chris Lattner
sabre at nondot.org
Sat Nov 6 12:57:21 PDT 2010
Author: lattner
Date: Sat Nov 6 14:57:21 2010
New Revision: 118352
URL: http://llvm.org/viewvc/llvm-project?rev=118352&view=rev
Log:
add (and document) the ability for alias results to have
fixed physical registers. Start moving fp comparison
aliases to the .td file (which default to using %st1 if
nothing is specified).
Modified:
llvm/trunk/docs/CodeGenerator.html
llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp
llvm/trunk/lib/Target/X86/X86InstrInfo.td
llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp
llvm/trunk/utils/TableGen/CodeGenInstruction.cpp
llvm/trunk/utils/TableGen/CodeGenInstruction.h
llvm/trunk/utils/TableGen/CodeGenRegisters.h
Modified: llvm/trunk/docs/CodeGenerator.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CodeGenerator.html?rev=118352&r1=118351&r2=118352&view=diff
==============================================================================
--- llvm/trunk/docs/CodeGenerator.html (original)
+++ llvm/trunk/docs/CodeGenerator.html Sat Nov 6 14:57:21 2010
@@ -1998,12 +1998,20 @@
<p>This example also shows that tied operands are only listed once. In the X86
backend, XOR8rr has two input GR8's and one output GR8 (where an input is tied
to the output). InstAliases take a flattened operand list without duplicates
-for tied operands. The result of an instruction alias can also use immediates,
-which are added as simple immediate operands in the result, for example:</p>
+for tied operands. The result of an instruction alias can also use immediates
+and fixed physical registers which are added as simple immediate operands in the
+result, for example:</p>
<div class="doc_code">
<pre>
+// Fixed Immediate operand.
def : InstAlias<"aad", (AAD8i8 10)>;
+
+// Fixed register operand.
+def : InstAlias<"fcomi", (COM_FIr ST1)>;
+
+// Simple alias.
+def : InstAlias<"fcomi $reg", (COM_FIr RST:$reg)>;
</pre>
</div>
Modified: llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp?rev=118352&r1=118351&r2=118352&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp Sat Nov 6 14:57:21 2010
@@ -821,7 +821,7 @@
// The assembler accepts these instructions with no operand as a synonym for
// an instruction acting on st(1). e.g. "fxch" -> "fxch %st(1)".
- if ((Name == "fxch" || Name == "fucom" || Name == "fucomp" ||
+ if ((Name == "fxch" ||
Name == "faddp" || Name == "fsubp" || Name == "fsubrp" ||
Name == "fmulp" || Name == "fdivp" || Name == "fdivrp") &&
Operands.size() == 1) {
@@ -829,18 +829,6 @@
NameLoc, NameLoc));
}
- // The assembler accepts these instructions with two few operands as a synonym
- // for taking %st(1),%st(0) or X, %st(0).
- if ((Name == "fcomi" || Name == "fucomi" || Name == "fucompi" ||
- Name == "fcompi" ) &&
- Operands.size() < 3) {
- if (Operands.size() == 1)
- Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(1)"),
- NameLoc, NameLoc));
- Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(0)"),
- NameLoc, NameLoc));
- }
-
return false;
}
@@ -854,6 +842,8 @@
// First, handle aliases that expand to multiple instructions.
// FIXME: This should be replaced with a real .td file alias mechanism.
+ // Also, MatchInstructionImpl should do actually *do* the EmitInstruction
+ // call.
if (Op->getToken() == "fstsw" || Op->getToken() == "fstcw" ||
Op->getToken() == "fstsww" || Op->getToken() == "fstcww" ||
Op->getToken() == "finit" || Op->getToken() == "fsave" ||
Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=118352&r1=118351&r2=118352&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Sat Nov 6 14:57:21 2010
@@ -1377,6 +1377,19 @@
def : InstAlias<"clrl $reg", (XOR32rr GR32:$reg, GR32:$reg)>;
def : InstAlias<"clrq $reg", (XOR64rr GR64:$reg, GR64:$reg)>;
+// Default arguments for various fp stack instructions.
+def : InstAlias<"fucom", (UCOM_Fr ST1)>;
+def : InstAlias<"fucomp", (UCOM_FPr ST1)>;
+def : InstAlias<"fcomi", (COM_FIr ST1)>;
+def : InstAlias<"fcomi $reg", (COM_FIr RST:$reg)>;
+def : InstAlias<"fcomip", (COM_FIPr ST1)>;
+def : InstAlias<"fcomip $reg", (COM_FIPr RST:$reg)>;
+def : InstAlias<"fucomi", (UCOM_FIr ST1)>;
+def : InstAlias<"fucomi $reg", (UCOM_FIr RST:$reg)>;
+def : InstAlias<"fucomip", (UCOM_FIPr ST1)>;
+def : InstAlias<"fucomip $reg", (UCOM_FIPr RST:$reg)>;
+
+
// We accepts "fnstsw %eax" even though it only writes %ax.
def : InstAlias<"fnstsw %eax", (FNSTSW8r)>;
def : InstAlias<"fnstsw %al" , (FNSTSW8r)>;
Modified: llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp?rev=118352&r1=118351&r2=118352&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp Sat Nov 6 14:57:21 2010
@@ -274,7 +274,10 @@
/// ImmOperand - This represents an immediate value that is dumped into
/// the operand.
- ImmOperand
+ ImmOperand,
+
+ /// RegOperand - This represents a fixed register that is dumped in.
+ RegOperand
} Kind;
union {
@@ -288,6 +291,9 @@
/// ImmVal - This is the immediate value added to the instruction.
int64_t ImmVal;
+
+ /// Register - This is the register record.
+ Record *Register;
};
/// OpInfo - This is the information about the instruction operand that is
@@ -320,6 +326,16 @@
X.OpInfo = Op;
return X;
}
+
+ static ResOperand getRegOp(Record *Reg,
+ const CGIOperandList::OperandInfo *Op) {
+ ResOperand X;
+ X.Kind = RegOperand;
+ X.Register = Reg;
+ X.OpInfo = Op;
+ return X;
+ }
+
};
/// TheDef - This is the definition of the instruction or InstAlias that this
@@ -1243,7 +1259,8 @@
// Find out what operand from the asmparser that this MCInst operand comes
// from.
- if (CGA.ResultOperands[AliasOpNo].isRecord()) {
+ switch (CGA.ResultOperands[AliasOpNo].Kind) {
+ case CodeGenInstAlias::ResultOperand::K_Record: {
StringRef Name = CGA.ResultOperands[AliasOpNo++].getName();
int SrcOperand = FindAsmOperandNamed(Name);
if (SrcOperand != -1) {
@@ -1255,10 +1272,18 @@
TheDef->getName() + "' has operand '" + OpInfo.Name +
"' that doesn't appear in asm string!");
}
-
- int64_t ImmVal = CGA.ResultOperands[AliasOpNo++].getImm();
- ResOperands.push_back(ResOperand::getImmOp(ImmVal, &OpInfo));
- continue;
+ case CodeGenInstAlias::ResultOperand::K_Imm: {
+ int64_t ImmVal = CGA.ResultOperands[AliasOpNo++].getImm();
+ ResOperands.push_back(ResOperand::getImmOp(ImmVal, &OpInfo));
+ continue;
+ }
+
+ case CodeGenInstAlias::ResultOperand::K_Reg: {
+ Record *Reg = CGA.ResultOperands[AliasOpNo++].getRegister();
+ ResOperands.push_back(ResOperand::getRegOp(Reg, &OpInfo));
+ continue;
+ }
+ }
}
}
@@ -1341,6 +1366,11 @@
Signature += "__imm" + itostr(Val);
break;
}
+ case MatchableInfo::ResOperand::RegOperand: {
+ std::string N = getQualifiedName(OpInfo.Register);
+ CaseOS << " Inst.addOperand(MCOperand::CreateReg(" << N << "));\n";
+ Signature += "__reg" + OpInfo.Register->getName();
+ }
}
}
Modified: llvm/trunk/utils/TableGen/CodeGenInstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenInstruction.cpp?rev=118352&r1=118351&r2=118352&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenInstruction.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenInstruction.cpp Sat Nov 6 14:57:21 2010
@@ -419,6 +419,30 @@
Init *Arg = Result->getArg(AliasOpNo);
+ Record *ResultOpRec = ResultInst->Operands[i].Rec;
+
+ // Handle explicit registers.
+ if (DefInit *ADI = dynamic_cast<DefInit*>(Arg)) {
+ if (ADI->getDef()->isSubClassOf("Register")) {
+ if (!Result->getArgName(AliasOpNo).empty())
+ throw TGError(R->getLoc(), "result fixed register argument must "
+ "not have a name!");
+
+ if (!ResultOpRec->isSubClassOf("RegisterClass"))
+ throw TGError(R->getLoc(), "result fixed register argument is not "
+ "passed to a RegisterClass operand!");
+
+ if (!T.getRegisterClass(ResultOpRec).containsRegister(ADI->getDef()))
+ throw TGError(R->getLoc(), "fixed register " +ADI->getDef()->getName()
+ + " is not a member of the " + ResultOpRec->getName() +
+ " register class!");
+
+ // Now that it is validated, add it.
+ ResultOperands.push_back(ResultOperand(ADI->getDef()));
+ ++AliasOpNo;
+ continue;
+ }
+ }
// If the operand is a record, it must have a name, and the record type must
// match up with the instruction's argument type.
@@ -427,11 +451,11 @@
throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
" must have a name!");
- if (ADI->getDef() != ResultInst->Operands[i].Rec)
+ if (ADI->getDef() != ResultOpRec)
throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
" declared with class " + ADI->getDef()->getName() +
", instruction operand is class " +
- ResultInst->Operands[i].Rec->getName());
+ ResultOpRec->getName());
// Verify we don't have something like: (someinst GR16:$foo, GR32:$foo)
// $foo can exist multiple times in the result list, but it must have the
@@ -456,9 +480,9 @@
throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
" must not have a name!");
if (ResultInst->Operands[i].MINumOperands != 1 ||
- !ResultInst->Operands[i].Rec->isSubClassOf("Operand"))
+ !ResultOpRec->isSubClassOf("Operand"))
throw TGError(R->getLoc(), "invalid argument class " +
- ResultInst->Operands[i].Rec->getName() +
+ ResultOpRec->getName() +
" for integer result operand!");
ResultOperands.push_back(ResultOperand(II->getValue()));
++AliasOpNo;
Modified: llvm/trunk/utils/TableGen/CodeGenInstruction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenInstruction.h?rev=118352&r1=118351&r2=118352&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenInstruction.h (original)
+++ llvm/trunk/utils/TableGen/CodeGenInstruction.h Sat Nov 6 14:57:21 2010
@@ -275,18 +275,22 @@
public:
enum {
K_Record,
- K_Imm
+ K_Imm,
+ K_Reg
} Kind;
ResultOperand(StringRef N, Record *r) : Name(N), R(r), Kind(K_Record) {}
ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {}
+ ResultOperand(Record *r) : R(r), Kind(K_Reg) {}
bool isRecord() const { return Kind == K_Record; }
bool isImm() const { return Kind == K_Imm; }
+ bool isReg() const { return Kind == K_Reg; }
StringRef getName() const { assert(isRecord()); return Name; }
Record *getRecord() const { assert(isRecord()); return R; }
int64_t getImm() const { assert(isImm()); return Imm; }
+ Record *getRegister() const { assert(isReg()); return R; }
};
/// ResultOperands - The decoded operands for the result instruction.
Modified: llvm/trunk/utils/TableGen/CodeGenRegisters.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenRegisters.h?rev=118352&r1=118351&r2=118352&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenRegisters.h (original)
+++ llvm/trunk/utils/TableGen/CodeGenRegisters.h Sat Nov 6 14:57:21 2010
@@ -57,6 +57,12 @@
abort();
}
+ bool containsRegister(Record *R) const {
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i)
+ if (Elements[i] == R) return true;
+ return false;
+ }
+
// Returns true if RC is a strict subclass.
// RC is a sub-class of this class if it is a valid replacement for any
// instruction operand where a register of this classis required. It must
More information about the llvm-commits
mailing list