From: Chris Lattner
Date: Sat, 6 Nov 2010 19:25:43 +0000 (+0000)
Subject: generalize alias support to allow the result of an alias to
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=98c870f87b7f0c996a9ba67003d88d434d6dbcd0;p=oota-llvm.git
generalize alias support to allow the result of an alias to
add fixed immediate values. Move the aad and aam aliases to
use this, and document it.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118350 91177308-0d34-0410-b5e6-96231b3b80d8
---
diff --git a/docs/CodeGenerator.html b/docs/CodeGenerator.html
index d4e932a969f..376b91c8f1a 100644
--- a/docs/CodeGenerator.html
+++ b/docs/CodeGenerator.html
@@ -1998,7 +1998,15 @@ def : InstAlias<"clrq $reg", (XOR64rr GR64:$reg, GR64:$reg)>;
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.
+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:
+
+
+
+def : InstAlias<"aad", (AAD8i8 10)>;
+
+
+
Instruction aliases can also have a Requires clause to make them
subtarget specific.
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 4ab25cf4bf8..9ab6b56c8f0 100644
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -752,6 +752,22 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
if (getLexer().is(AsmToken::EndOfStatement))
Parser.Lex(); // Consume the EndOfStatement
+ // This is a terrible hack to handle "out[bwl]? %al, (%dx)" ->
+ // "outb %al, %dx". Out doesn't take a memory form, but this is a widely
+ // documented form in various unofficial manuals, so a lot of code uses it.
+ if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") &&
+ Operands.size() == 3) {
+ X86Operand &Op = *(X86Operand*)Operands.back();
+ if (Op.isMem() && Op.Mem.SegReg == 0 &&
+ isa(Op.Mem.Disp) &&
+ cast(Op.Mem.Disp)->getValue() == 0 &&
+ Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
+ SMLoc Loc = Op.getEndLoc();
+ Operands.back() = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
+ delete &Op;
+ }
+ }
+
// FIXME: Hack to handle recognize s{hr,ar,hl} $1, . Canonicalize to
// "shift ".
if ((Name.startswith("shr") || Name.startswith("sar") ||
@@ -781,20 +797,6 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
X86Operand::CreateImm(One, NameLoc, NameLoc));
}
- // FIXME: Hack to handle "out[bwl]? %al, (%dx)" -> "outb %al, %dx".
- if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") &&
- Operands.size() == 3) {
- X86Operand &Op = *(X86Operand*)Operands.back();
- if (Op.isMem() && Op.Mem.SegReg == 0 &&
- isa(Op.Mem.Disp) &&
- cast(Op.Mem.Disp)->getValue() == 0 &&
- Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
- SMLoc Loc = Op.getEndLoc();
- Operands.back() = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
- delete &Op;
- }
- }
-
// FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
// "f{mul*,add*,sub*,div*} $op"
if ((Name.startswith("fmul") || Name.startswith("fadd") ||
@@ -839,13 +841,6 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
NameLoc, NameLoc));
}
- // FIXME: Hack to handle recognize "aa[dm]" -> "aa[dm] $0xA".
- if ((Name.startswith("aad") || Name.startswith("aam")) &&
- Operands.size() == 1) {
- const MCExpr *A = MCConstantExpr::Create(0xA, getParser().getContext());
- Operands.push_back(X86Operand::CreateImm(A, NameLoc, NameLoc));
- }
-
return false;
}
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 125da18600e..7fec0141ce4 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -1367,6 +1367,10 @@ defm : IntegerCondCodeMnemonicAlias<"cmov", "q">;
// Assembler Instruction Aliases
//===----------------------------------------------------------------------===//
+// aad/aam default to base 10 if no operand is specified.
+def : InstAlias<"aad", (AAD8i8 10)>;
+def : InstAlias<"aam", (AAM8i8 10)>;
+
// clr aliases.
def : InstAlias<"clrb $reg", (XOR8rr GR8 :$reg, GR8 :$reg)>;
def : InstAlias<"clrw $reg", (XOR16rr GR16:$reg, GR16:$reg)>;
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 23d370c506e..46866140eb4 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -270,7 +270,11 @@ struct MatchableInfo {
/// TiedOperand - This represents a result operand that is a duplicate of
/// a previous result operand.
- TiedOperand
+ TiedOperand,
+
+ /// ImmOperand - This represents an immediate value that is dumped into
+ /// the operand.
+ ImmOperand
} Kind;
union {
@@ -281,6 +285,9 @@ struct MatchableInfo {
/// TiedOperandNum - This is the (earlier) result operand that should be
/// copied from.
unsigned TiedOperandNum;
+
+ /// ImmVal - This is the immediate value added to the instruction.
+ int64_t ImmVal;
};
/// OpInfo - This is the information about the instruction operand that is
@@ -304,6 +311,15 @@ struct MatchableInfo {
X.OpInfo = Op;
return X;
}
+
+ static ResOperand getImmOp(int64_t Val,
+ const CGIOperandList::OperandInfo *Op) {
+ ResOperand X;
+ X.Kind = ImmOperand;
+ X.ImmVal = Val;
+ X.OpInfo = Op;
+ return X;
+ }
};
/// TheDef - This is the definition of the instruction or InstAlias that this
@@ -538,16 +554,6 @@ void MatchableInfo::dump() {
AsmOperand &Op = AsmOperands[i];
errs() << " op[" << i << "] = " << Op.Class->ClassName << " - ";
errs() << '\"' << Op.Token << "\"\n";
-#if 0
- if (!Op.OperandInfo) {
- errs() << "(singleton register)\n";
- continue;
- }
-
- const CGIOperandList::OperandInfo &OI = *Op.OperandInfo;
- errs() << OI.Name << " " << OI.Rec->getName()
- << " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n";
-#endif
}
}
@@ -1174,7 +1180,8 @@ void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II,
// Set up the operand class.
for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i)
- if (CGA.ResultOperands[i].Name == OperandName) {
+ if (CGA.ResultOperands[i].isRecord() &&
+ CGA.ResultOperands[i].getName() == OperandName) {
// It's safe to go with the first one we find, because CodeGenInstAlias
// validates that all operands with the same name have the same record.
unsigned ResultIdx =CGA.getResultInstOperandIndexForResultOperandIndex(i);
@@ -1236,15 +1243,22 @@ void MatchableInfo::BuildAliasResultOperands() {
// Find out what operand from the asmparser that this MCInst operand comes
// from.
- int SrcOperand = FindAsmOperandNamed(CGA.ResultOperands[AliasOpNo++].Name);
- if (SrcOperand != -1) {
- ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
- continue;
+ if (CGA.ResultOperands[AliasOpNo].isRecord()) {
+ StringRef Name = CGA.ResultOperands[AliasOpNo++].getName();
+ int SrcOperand = FindAsmOperandNamed(Name);
+ if (SrcOperand != -1) {
+ ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
+ continue;
+ }
+
+ throw TGError(TheDef->getLoc(), "Instruction '" +
+ TheDef->getName() + "' has operand '" + OpInfo.Name +
+ "' that doesn't appear in asm string!");
}
- throw TGError(TheDef->getLoc(), "Instruction '" +
- 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;
}
}
@@ -1291,7 +1305,6 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
// Generate code to populate each result operand.
switch (OpInfo.Kind) {
- default: assert(0 && "Unknown result operand kind");
case MatchableInfo::ResOperand::RenderAsmOperand: {
// This comes from something we parsed.
MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum];
@@ -1322,6 +1335,12 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
Signature += "__Tie" + utostr(TiedOp);
break;
}
+ case MatchableInfo::ResOperand::ImmOperand: {
+ int64_t Val = OpInfo.ImmVal;
+ CaseOS << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n";
+ Signature += "__imm" + itostr(Val);
+ break;
+ }
}
}
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 40d4206b30e..924608cbf0f 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -449,6 +449,21 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
++AliasOpNo;
continue;
}
+
+ if (IntInit *II = dynamic_cast(Arg)) {
+ // Integer arguments can't have names.
+ if (!Result->getArgName(AliasOpNo).empty())
+ 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"))
+ throw TGError(R->getLoc(), "invalid argument class " +
+ ResultInst->Operands[i].Rec->getName() +
+ " for integer result operand!");
+ ResultOperands.push_back(ResultOperand(II->getValue()));
+ ++AliasOpNo;
+ continue;
+ }
throw TGError(R->getLoc(), "result of inst alias has unknown operand type");
}
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index f5b22396360..ac593dfb17d 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -267,10 +267,26 @@ namespace llvm {
struct ResultOperand {
+ private:
StringRef Name;
Record *R;
- ResultOperand(StringRef N, Record *r) : Name(N), R(r) {}
+ int64_t Imm;
+ public:
+ enum {
+ K_Record,
+ K_Imm
+ } Kind;
+
+ ResultOperand(StringRef N, Record *r) : Name(N), R(r), Kind(K_Record) {}
+ ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {}
+
+ bool isRecord() const { return Kind == K_Record; }
+ bool isImm() const { return Kind == K_Imm; }
+
+ StringRef getName() const { assert(isRecord()); return Name; }
+ Record *getRecord() const { assert(isRecord()); return R; }
+ int64_t getImm() const { assert(isImm()); return Imm; }
};
/// ResultOperands - The decoded operands for the result instruction.