summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-08-09 06:05:33 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-08-09 06:05:33 +0000
commit2b54481a77696d47dc9220cd7a36155599750904 (patch)
tree59b998de1c2765482f82040fc56119ef0cca4e99 /utils
parent1ff446fef66a56558afaf427087767424e7a999b (diff)
downloadllvm-2b54481a77696d47dc9220cd7a36155599750904.tar.gz
llvm-2b54481a77696d47dc9220cd7a36155599750904.tar.bz2
llvm-2b54481a77696d47dc9220cd7a36155599750904.tar.xz
llvm-mc/AsmParser: Separate instruction ordering for ambiguity detection.
- We want the ordering operation to be simple, since we run it on every match. The old ordering is also not a strict weak ordering when there are ambiguities, which makes MSVC unhappy. - While we are at it, detect all ambiguities instead of just the adjacent ones. There are actually 655, for X86. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78526 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp81
1 files changed, 45 insertions, 36 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index cbe214d3f3..aafc09fcd6 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -263,7 +263,7 @@ static bool IsAssemblerInstruction(const StringRef &Name,
DEBUG({
errs() << "warning: '" << Name << "': "
<< "ignoring instruction; tied operand '"
- << Tokens[i] << "', \n";
+ << Tokens[i] << "'\n";
});
return false;
}
@@ -368,34 +368,45 @@ struct InstructionInfo {
/// operator< - Compare two instructions.
bool operator<(const InstructionInfo &RHS) const {
- // Order first by the number of operands (which is unambiguous).
if (Operands.size() != RHS.Operands.size())
return Operands.size() < RHS.Operands.size();
-
- // Otherwise, order by lexicographic comparison of tokens and operand kinds
- // (these can never be ambiguous).
+
for (unsigned i = 0, e = Operands.size(); i != e; ++i)
- if (Operands[i].Class->Kind != RHS.Operands[i].Class->Kind ||
- Operands[i].Class->Kind == ClassInfo::Token)
- if (*Operands[i].Class < *RHS.Operands[i].Class)
- return true;
+ if (*Operands[i].Class < *RHS.Operands[i].Class)
+ return true;
- // Finally, order by the component wise comparison of operand classes. We
- // don't want to rely on the lexigraphic ordering of elements, so we define
- // only define the ordering when it is unambiguous. That is, when some pair
- // compares less than and no pair compares greater than.
+ return false;
+ }
- // Check that no pair compares greater than.
- for (unsigned i = 0, e = Operands.size(); i != e; ++i)
- if (*RHS.Operands[i].Class < *Operands[i].Class)
- return false;
+ /// CouldMatchAmiguouslyWith - Check whether this instruction could
+ /// ambiguously match the same set of operands as \arg RHS (without being a
+ /// strictly superior match).
+ bool CouldMatchAmiguouslyWith(const InstructionInfo &RHS) {
+ // The number of operands is unambiguous.
+ if (Operands.size() != RHS.Operands.size())
+ return false;
- // Otherwise, return true if some pair compares less than.
+ // Tokens and operand kinds are unambiguous (assuming a correct target
+ // specific parser).
for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ if (Operands[i].Class->Kind != RHS.Operands[i].Class->Kind ||
+ Operands[i].Class->Kind == ClassInfo::Token)
+ if (*Operands[i].Class < *RHS.Operands[i].Class ||
+ *RHS.Operands[i].Class < *Operands[i].Class)
+ return false;
+
+ // Otherwise, this operand could commute if all operands are equivalent, or
+ // there is a pair of operands that compare less than and a pair that
+ // compare greater than.
+ bool HasLT = false, HasGT = false;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (*Operands[i].Class < *RHS.Operands[i].Class)
- return true;
+ HasLT = true;
+ if (*RHS.Operands[i].Class < *Operands[i].Class)
+ HasGT = true;
+ }
- return false;
+ return !(HasLT ^ HasGT);
}
public:
@@ -991,23 +1002,21 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Check for ambiguous instructions.
unsigned NumAmbiguous = 0;
- for (std::vector<InstructionInfo*>::const_iterator it =
- Info.Instructions.begin(), ie = Info.Instructions.end() - 1;
- it != ie;) {
- InstructionInfo &II = **it;
- ++it;
-
- InstructionInfo &Next = **it;
+ for (unsigned i = 0, e = Info.Instructions.size(); i != e; ++i) {
+ for (unsigned j = i + 1; j != e; ++j) {
+ InstructionInfo &A = *Info.Instructions[i];
+ InstructionInfo &B = *Info.Instructions[j];
- if (!(II < Next)){
- DEBUG_WITH_TYPE("ambiguous_instrs", {
- errs() << "warning: ambiguous instruction match:\n";
- II.dump();
- errs() << "\nis incomparable with:\n";
- Next.dump();
- errs() << "\n\n";
- });
- ++NumAmbiguous;
+ if (A.CouldMatchAmiguouslyWith(B)) {
+ DEBUG_WITH_TYPE("ambiguous_instrs", {
+ errs() << "warning: ambiguous instruction match:\n";
+ A.dump();
+ errs() << "\nis incomparable with:\n";
+ B.dump();
+ errs() << "\n\n";
+ });
+ ++NumAmbiguous;
+ }
}
}
if (NumAmbiguous)