forked from OSchip/llvm-project
Add patterns for CALL32m and CALL64m. They aren't matched in most
cases due to an isel deficiency already noted in lib/Target/X86/README.txt, but they can be matched in this fold-call.ll testcase, for example. This is interesting mainly because it exposes a tricky tblgen bug; tblgen was incorrectly computing the starting index for variable_ops in the case of a complex pattern. llvm-svn: 51706
This commit is contained in:
parent
33e396d041
commit
96af4ddb62
|
@ -101,7 +101,7 @@ let isCall = 1 in
|
||||||
def CALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst, variable_ops),
|
def CALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst, variable_ops),
|
||||||
"call\t{*}$dst", [(X86call GR64:$dst)]>;
|
"call\t{*}$dst", [(X86call GR64:$dst)]>;
|
||||||
def CALL64m : I<0xFF, MRM2m, (outs), (ins i64mem:$dst, variable_ops),
|
def CALL64m : I<0xFF, MRM2m, (outs), (ins i64mem:$dst, variable_ops),
|
||||||
"call\t{*}$dst", []>;
|
"call\t{*}$dst", [(X86call (loadi64 addr:$dst))]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -397,7 +397,7 @@ let isCall = 1 in
|
||||||
def CALL32r : I<0xFF, MRM2r, (outs), (ins GR32:$dst, variable_ops),
|
def CALL32r : I<0xFF, MRM2r, (outs), (ins GR32:$dst, variable_ops),
|
||||||
"call\t{*}$dst", [(X86call GR32:$dst)]>;
|
"call\t{*}$dst", [(X86call GR32:$dst)]>;
|
||||||
def CALL32m : I<0xFF, MRM2m, (outs), (ins i32mem:$dst, variable_ops),
|
def CALL32m : I<0xFF, MRM2m, (outs), (ins i32mem:$dst, variable_ops),
|
||||||
"call\t{*}$dst", []>;
|
"call\t{*}$dst", [(X86call (loadi32 addr:$dst))]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tail call stuff.
|
// Tail call stuff.
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
; RUN: llvm-as < %s | llc -march=x86 | not grep mov
|
||||||
|
; RUN: llvm-as < %s | llc -march=x86-64 | not grep mov
|
||||||
|
|
||||||
|
declare void @bar()
|
||||||
|
|
||||||
|
define void @foo(i32 %i0, i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, void()* %arg) nounwind {
|
||||||
|
call void @bar()
|
||||||
|
call void %arg()
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -947,7 +947,7 @@ public:
|
||||||
// instruction operands to do this.
|
// instruction operands to do this.
|
||||||
std::vector<std::string> AllOps;
|
std::vector<std::string> AllOps;
|
||||||
unsigned NumEAInputs = 0; // # of synthesized 'execute always' inputs.
|
unsigned NumEAInputs = 0; // # of synthesized 'execute always' inputs.
|
||||||
unsigned NumDiscardedInputs = 0; // # of 'discard' inputs to skip.
|
unsigned InputIndex = 0;
|
||||||
for (unsigned ChildNo = 0, InstOpNo = NumResults;
|
for (unsigned ChildNo = 0, InstOpNo = NumResults;
|
||||||
InstOpNo != II.OperandList.size(); ++InstOpNo) {
|
InstOpNo != II.OperandList.size(); ++InstOpNo) {
|
||||||
std::vector<std::string> Ops;
|
std::vector<std::string> Ops;
|
||||||
|
@ -956,7 +956,7 @@ public:
|
||||||
Record *OperandNode = II.OperandList[InstOpNo].Rec;
|
Record *OperandNode = II.OperandList[InstOpNo].Rec;
|
||||||
if (OperandNode->getName() == "discard") {
|
if (OperandNode->getName() == "discard") {
|
||||||
// This is a "discard" operand; emit nothing. Just note it.
|
// This is a "discard" operand; emit nothing. Just note it.
|
||||||
++NumDiscardedInputs;
|
++InputIndex;
|
||||||
} else if ((OperandNode->isSubClassOf("PredicateOperand") ||
|
} else if ((OperandNode->isSubClassOf("PredicateOperand") ||
|
||||||
OperandNode->isSubClassOf("OptionalDefOperand")) &&
|
OperandNode->isSubClassOf("OptionalDefOperand")) &&
|
||||||
!CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
|
!CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
|
||||||
|
@ -970,6 +970,7 @@ public:
|
||||||
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
|
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
|
||||||
NumEAInputs += Ops.size();
|
NumEAInputs += Ops.size();
|
||||||
}
|
}
|
||||||
|
++InputIndex;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise this is a normal operand or a predicate operand without
|
// Otherwise this is a normal operand or a predicate operand without
|
||||||
// 'execute always'; emit it.
|
// 'execute always'; emit it.
|
||||||
|
@ -977,6 +978,7 @@ public:
|
||||||
InFlagDecled, ResNodeDecled);
|
InFlagDecled, ResNodeDecled);
|
||||||
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
|
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
|
||||||
++ChildNo;
|
++ChildNo;
|
||||||
|
++InputIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1062,10 +1064,7 @@ public:
|
||||||
// number of operands that are 'execute always'. This is the index
|
// number of operands that are 'execute always'. This is the index
|
||||||
// where we should start copying operands into the 'variable_ops'
|
// where we should start copying operands into the 'variable_ops'
|
||||||
// portion of the output.
|
// portion of the output.
|
||||||
unsigned InputIndex = AllOps.size() +
|
InputIndex += NodeHasChain - NumEAInputs;
|
||||||
NumDiscardedInputs +
|
|
||||||
NodeHasChain -
|
|
||||||
NumEAInputs;
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
|
for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
|
||||||
emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
|
emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
|
||||||
|
|
Loading…
Reference in New Issue