2005-09-07 23:44:43 +00:00
|
|
|
//===- DAGISelEmitter.cpp - Generate an instruction selector --------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file was developed by Chris Lattner and is distributed under
|
|
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This tablegen backend emits a DAG instruction selector.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "DAGISelEmitter.h"
|
|
|
|
#include "Record.h"
|
|
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
2006-10-11 03:35:34 +00:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2006-12-07 22:21:48 +00:00
|
|
|
#include "llvm/Support/Streams.h"
|
2005-09-25 19:04:43 +00:00
|
|
|
#include <algorithm>
|
2005-09-07 23:44:43 +00:00
|
|
|
#include <set>
|
|
|
|
using namespace llvm;
|
|
|
|
|
2005-10-14 06:12:03 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Helpers for working with extended types.
|
|
|
|
|
|
|
|
/// FilterVTs - Filter a list of VT's according to a predicate.
|
|
|
|
///
|
|
|
|
template<typename T>
|
|
|
|
static std::vector<MVT::ValueType>
|
|
|
|
FilterVTs(const std::vector<MVT::ValueType> &InVTs, T Filter) {
|
|
|
|
std::vector<MVT::ValueType> Result;
|
|
|
|
for (unsigned i = 0, e = InVTs.size(); i != e; ++i)
|
|
|
|
if (Filter(InVTs[i]))
|
|
|
|
Result.push_back(InVTs[i]);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2005-12-30 00:12:56 +00:00
|
|
|
template<typename T>
|
|
|
|
static std::vector<unsigned char>
|
|
|
|
FilterEVTs(const std::vector<unsigned char> &InVTs, T Filter) {
|
|
|
|
std::vector<unsigned char> Result;
|
|
|
|
for (unsigned i = 0, e = InVTs.size(); i != e; ++i)
|
|
|
|
if (Filter((MVT::ValueType)InVTs[i]))
|
|
|
|
Result.push_back(InVTs[i]);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::vector<unsigned char>
|
|
|
|
ConvertVTs(const std::vector<MVT::ValueType> &InVTs) {
|
|
|
|
std::vector<unsigned char> Result;
|
|
|
|
for (unsigned i = 0, e = InVTs.size(); i != e; ++i)
|
|
|
|
Result.push_back(InVTs[i]);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool LHSIsSubsetOfRHS(const std::vector<unsigned char> &LHS,
|
|
|
|
const std::vector<unsigned char> &RHS) {
|
|
|
|
if (LHS.size() > RHS.size()) return false;
|
|
|
|
for (unsigned i = 0, e = LHS.size(); i != e; ++i)
|
2005-12-30 16:41:48 +00:00
|
|
|
if (std::find(RHS.begin(), RHS.end(), LHS[i]) == RHS.end())
|
2005-12-30 00:12:56 +00:00
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// isExtIntegerVT - Return true if the specified extended value type vector
|
|
|
|
/// contains isInt or an integer value type.
|
2006-03-20 05:39:48 +00:00
|
|
|
static bool isExtIntegerInVTs(const std::vector<unsigned char> &EVTs) {
|
2005-12-30 00:12:56 +00:00
|
|
|
assert(!EVTs.empty() && "Cannot check for integer in empty ExtVT list!");
|
|
|
|
return EVTs[0] == MVT::isInt || !(FilterEVTs(EVTs, MVT::isInteger).empty());
|
2005-10-14 06:12:03 +00:00
|
|
|
}
|
|
|
|
|
2005-12-30 00:12:56 +00:00
|
|
|
/// isExtFloatingPointVT - Return true if the specified extended value type
|
|
|
|
/// vector contains isFP or a FP value type.
|
2006-03-20 05:39:48 +00:00
|
|
|
static bool isExtFloatingPointInVTs(const std::vector<unsigned char> &EVTs) {
|
2005-12-30 00:12:56 +00:00
|
|
|
assert(!EVTs.empty() && "Cannot check for integer in empty ExtVT list!");
|
2006-01-28 19:06:51 +00:00
|
|
|
return EVTs[0] == MVT::isFP ||
|
|
|
|
!(FilterEVTs(EVTs, MVT::isFloatingPoint).empty());
|
2005-10-14 06:12:03 +00:00
|
|
|
}
|
|
|
|
|
2005-09-08 21:27:15 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// SDTypeConstraint implementation
|
|
|
|
//
|
|
|
|
|
|
|
|
SDTypeConstraint::SDTypeConstraint(Record *R) {
|
|
|
|
OperandNo = R->getValueAsInt("OperandNum");
|
|
|
|
|
|
|
|
if (R->isSubClassOf("SDTCisVT")) {
|
|
|
|
ConstraintType = SDTCisVT;
|
|
|
|
x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
|
2005-12-09 22:57:42 +00:00
|
|
|
} else if (R->isSubClassOf("SDTCisPtrTy")) {
|
|
|
|
ConstraintType = SDTCisPtrTy;
|
2005-09-08 21:27:15 +00:00
|
|
|
} else if (R->isSubClassOf("SDTCisInt")) {
|
|
|
|
ConstraintType = SDTCisInt;
|
|
|
|
} else if (R->isSubClassOf("SDTCisFP")) {
|
|
|
|
ConstraintType = SDTCisFP;
|
|
|
|
} else if (R->isSubClassOf("SDTCisSameAs")) {
|
|
|
|
ConstraintType = SDTCisSameAs;
|
|
|
|
x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum");
|
|
|
|
} else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) {
|
|
|
|
ConstraintType = SDTCisVTSmallerThanOp;
|
|
|
|
x.SDTCisVTSmallerThanOp_Info.OtherOperandNum =
|
|
|
|
R->getValueAsInt("OtherOperandNum");
|
2005-10-14 04:53:53 +00:00
|
|
|
} else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) {
|
|
|
|
ConstraintType = SDTCisOpSmallerThanOp;
|
|
|
|
x.SDTCisOpSmallerThanOp_Info.BigOperandNum =
|
|
|
|
R->getValueAsInt("BigOperandNum");
|
2006-03-20 05:39:48 +00:00
|
|
|
} else if (R->isSubClassOf("SDTCisIntVectorOfSameSize")) {
|
|
|
|
ConstraintType = SDTCisIntVectorOfSameSize;
|
|
|
|
x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum =
|
|
|
|
R->getValueAsInt("OtherOpNum");
|
2005-09-08 21:27:15 +00:00
|
|
|
} else {
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n";
|
2005-09-08 21:27:15 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
/// getOperandNum - Return the node corresponding to operand #OpNo in tree
|
|
|
|
/// N, which has NumResults results.
|
|
|
|
TreePatternNode *SDTypeConstraint::getOperandNum(unsigned OpNo,
|
|
|
|
TreePatternNode *N,
|
|
|
|
unsigned NumResults) const {
|
2005-12-04 08:18:16 +00:00
|
|
|
assert(NumResults <= 1 &&
|
|
|
|
"We only work with nodes with zero or one result so far!");
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
|
2006-06-13 21:47:27 +00:00
|
|
|
if (OpNo >= (NumResults + N->getNumChildren())) {
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "Invalid operand number " << OpNo << " ";
|
2006-06-13 21:47:27 +00:00
|
|
|
N->dump();
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << '\n';
|
2006-06-13 21:47:27 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
if (OpNo < NumResults)
|
|
|
|
return N; // FIXME: need value #
|
|
|
|
else
|
|
|
|
return N->getChild(OpNo-NumResults);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ApplyTypeConstraint - Given a node in a pattern, apply this type
|
|
|
|
/// constraint to the nodes operands. This returns true if it makes a
|
|
|
|
/// change, false otherwise. If a type contradiction is found, throw an
|
|
|
|
/// exception.
|
|
|
|
bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
|
|
|
|
const SDNodeInfo &NodeInfo,
|
|
|
|
TreePattern &TP) const {
|
|
|
|
unsigned NumResults = NodeInfo.getNumResults();
|
2005-12-04 08:18:16 +00:00
|
|
|
assert(NumResults <= 1 &&
|
|
|
|
"We only work with nodes with zero or one result so far!");
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
|
2006-06-16 18:25:06 +00:00
|
|
|
// Check that the number of operands is sane. Negative operands -> varargs.
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
if (NodeInfo.getNumOperands() >= 0) {
|
|
|
|
if (N->getNumChildren() != (unsigned)NodeInfo.getNumOperands())
|
|
|
|
TP.error(N->getOperator()->getName() + " node requires exactly " +
|
|
|
|
itostr(NodeInfo.getNumOperands()) + " operands!");
|
|
|
|
}
|
2005-10-14 04:11:13 +00:00
|
|
|
|
|
|
|
const CodeGenTarget &CGT = TP.getDAGISelEmitter().getTargetInfo();
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
|
|
|
|
TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NumResults);
|
|
|
|
|
|
|
|
switch (ConstraintType) {
|
|
|
|
default: assert(0 && "Unknown constraint type!");
|
|
|
|
case SDTCisVT:
|
|
|
|
// Operand must be a particular type.
|
|
|
|
return NodeToApply->UpdateNodeType(x.SDTCisVT_Info.VT, TP);
|
2005-12-09 22:57:42 +00:00
|
|
|
case SDTCisPtrTy: {
|
|
|
|
// Operand must be same as target pointer type.
|
2006-05-17 20:37:59 +00:00
|
|
|
return NodeToApply->UpdateNodeType(MVT::iPTR, TP);
|
2005-12-09 22:57:42 +00:00
|
|
|
}
|
2005-10-14 04:11:13 +00:00
|
|
|
case SDTCisInt: {
|
|
|
|
// If there is only one integer type supported, this must be it.
|
2005-10-14 05:08:37 +00:00
|
|
|
std::vector<MVT::ValueType> IntVTs =
|
|
|
|
FilterVTs(CGT.getLegalValueTypes(), MVT::isInteger);
|
2005-10-14 04:11:13 +00:00
|
|
|
|
|
|
|
// If we found exactly one supported integer type, apply it.
|
2005-10-14 05:08:37 +00:00
|
|
|
if (IntVTs.size() == 1)
|
|
|
|
return NodeToApply->UpdateNodeType(IntVTs[0], TP);
|
2005-10-14 06:12:03 +00:00
|
|
|
return NodeToApply->UpdateNodeType(MVT::isInt, TP);
|
2005-10-14 04:11:13 +00:00
|
|
|
}
|
|
|
|
case SDTCisFP: {
|
|
|
|
// If there is only one FP type supported, this must be it.
|
2005-10-14 05:08:37 +00:00
|
|
|
std::vector<MVT::ValueType> FPVTs =
|
|
|
|
FilterVTs(CGT.getLegalValueTypes(), MVT::isFloatingPoint);
|
2005-10-14 04:11:13 +00:00
|
|
|
|
|
|
|
// If we found exactly one supported FP type, apply it.
|
2005-10-14 05:08:37 +00:00
|
|
|
if (FPVTs.size() == 1)
|
|
|
|
return NodeToApply->UpdateNodeType(FPVTs[0], TP);
|
2005-10-14 06:12:03 +00:00
|
|
|
return NodeToApply->UpdateNodeType(MVT::isFP, TP);
|
2005-10-14 04:11:13 +00:00
|
|
|
}
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
case SDTCisSameAs: {
|
|
|
|
TreePatternNode *OtherNode =
|
|
|
|
getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NumResults);
|
2005-12-30 00:12:56 +00:00
|
|
|
return NodeToApply->UpdateNodeType(OtherNode->getExtTypes(), TP) |
|
|
|
|
OtherNode->UpdateNodeType(NodeToApply->getExtTypes(), TP);
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
}
|
|
|
|
case SDTCisVTSmallerThanOp: {
|
|
|
|
// The NodeToApply must be a leaf node that is a VT. OtherOperandNum must
|
|
|
|
// have an integer type that is smaller than the VT.
|
|
|
|
if (!NodeToApply->isLeaf() ||
|
|
|
|
!dynamic_cast<DefInit*>(NodeToApply->getLeafValue()) ||
|
|
|
|
!static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()
|
|
|
|
->isSubClassOf("ValueType"))
|
|
|
|
TP.error(N->getOperator()->getName() + " expects a VT operand!");
|
|
|
|
MVT::ValueType VT =
|
|
|
|
getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef());
|
|
|
|
if (!MVT::isInteger(VT))
|
|
|
|
TP.error(N->getOperator()->getName() + " VT operand must be integer!");
|
|
|
|
|
|
|
|
TreePatternNode *OtherNode =
|
|
|
|
getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N,NumResults);
|
2005-10-14 06:12:03 +00:00
|
|
|
|
|
|
|
// It must be integer.
|
|
|
|
bool MadeChange = false;
|
|
|
|
MadeChange |= OtherNode->UpdateNodeType(MVT::isInt, TP);
|
|
|
|
|
2005-12-30 00:12:56 +00:00
|
|
|
// This code only handles nodes that have one type set. Assert here so
|
|
|
|
// that we can change this if we ever need to deal with multiple value
|
|
|
|
// types at this point.
|
|
|
|
assert(OtherNode->getExtTypes().size() == 1 && "Node has too many types!");
|
|
|
|
if (OtherNode->hasTypeSet() && OtherNode->getTypeNum(0) <= VT)
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
OtherNode->UpdateNodeType(MVT::Other, TP); // Throw an error.
|
|
|
|
return false;
|
|
|
|
}
|
2005-10-14 04:53:53 +00:00
|
|
|
case SDTCisOpSmallerThanOp: {
|
2005-10-14 06:25:00 +00:00
|
|
|
TreePatternNode *BigOperand =
|
|
|
|
getOperandNum(x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NumResults);
|
|
|
|
|
|
|
|
// Both operands must be integer or FP, but we don't care which.
|
|
|
|
bool MadeChange = false;
|
|
|
|
|
2005-12-30 00:12:56 +00:00
|
|
|
// This code does not currently handle nodes which have multiple types,
|
|
|
|
// where some types are integer, and some are fp. Assert that this is not
|
|
|
|
// the case.
|
|
|
|
assert(!(isExtIntegerInVTs(NodeToApply->getExtTypes()) &&
|
|
|
|
isExtFloatingPointInVTs(NodeToApply->getExtTypes())) &&
|
|
|
|
!(isExtIntegerInVTs(BigOperand->getExtTypes()) &&
|
|
|
|
isExtFloatingPointInVTs(BigOperand->getExtTypes())) &&
|
|
|
|
"SDTCisOpSmallerThanOp does not handle mixed int/fp types!");
|
|
|
|
if (isExtIntegerInVTs(NodeToApply->getExtTypes()))
|
2005-10-14 06:25:00 +00:00
|
|
|
MadeChange |= BigOperand->UpdateNodeType(MVT::isInt, TP);
|
2005-12-30 00:12:56 +00:00
|
|
|
else if (isExtFloatingPointInVTs(NodeToApply->getExtTypes()))
|
2005-10-14 06:25:00 +00:00
|
|
|
MadeChange |= BigOperand->UpdateNodeType(MVT::isFP, TP);
|
2005-12-30 00:12:56 +00:00
|
|
|
if (isExtIntegerInVTs(BigOperand->getExtTypes()))
|
2005-10-14 06:25:00 +00:00
|
|
|
MadeChange |= NodeToApply->UpdateNodeType(MVT::isInt, TP);
|
2005-12-30 00:12:56 +00:00
|
|
|
else if (isExtFloatingPointInVTs(BigOperand->getExtTypes()))
|
2005-10-14 06:25:00 +00:00
|
|
|
MadeChange |= NodeToApply->UpdateNodeType(MVT::isFP, TP);
|
|
|
|
|
|
|
|
std::vector<MVT::ValueType> VTs = CGT.getLegalValueTypes();
|
|
|
|
|
2005-12-30 00:12:56 +00:00
|
|
|
if (isExtIntegerInVTs(NodeToApply->getExtTypes())) {
|
2005-10-14 06:25:00 +00:00
|
|
|
VTs = FilterVTs(VTs, MVT::isInteger);
|
2005-12-30 00:12:56 +00:00
|
|
|
} else if (isExtFloatingPointInVTs(NodeToApply->getExtTypes())) {
|
2005-10-14 06:25:00 +00:00
|
|
|
VTs = FilterVTs(VTs, MVT::isFloatingPoint);
|
|
|
|
} else {
|
|
|
|
VTs.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (VTs.size()) {
|
|
|
|
default: // Too many VT's to pick from.
|
|
|
|
case 0: break; // No info yet.
|
|
|
|
case 1:
|
|
|
|
// Only one VT of this flavor. Cannot ever satisify the constraints.
|
|
|
|
return NodeToApply->UpdateNodeType(MVT::Other, TP); // throw
|
|
|
|
case 2:
|
|
|
|
// If we have exactly two possible types, the little operand must be the
|
|
|
|
// small one, the big operand should be the big one. Common with
|
|
|
|
// float/double for example.
|
|
|
|
assert(VTs[0] < VTs[1] && "Should be sorted!");
|
|
|
|
MadeChange |= NodeToApply->UpdateNodeType(VTs[0], TP);
|
|
|
|
MadeChange |= BigOperand->UpdateNodeType(VTs[1], TP);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return MadeChange;
|
2005-10-14 04:53:53 +00:00
|
|
|
}
|
2006-03-20 05:39:48 +00:00
|
|
|
case SDTCisIntVectorOfSameSize: {
|
|
|
|
TreePatternNode *OtherOperand =
|
|
|
|
getOperandNum(x.SDTCisIntVectorOfSameSize_Info.OtherOperandNum,
|
|
|
|
N, NumResults);
|
|
|
|
if (OtherOperand->hasTypeSet()) {
|
|
|
|
if (!MVT::isVector(OtherOperand->getTypeNum(0)))
|
|
|
|
TP.error(N->getOperator()->getName() + " VT operand must be a vector!");
|
|
|
|
MVT::ValueType IVT = OtherOperand->getTypeNum(0);
|
|
|
|
IVT = MVT::getIntVectorWithNumElements(MVT::getVectorNumElements(IVT));
|
|
|
|
return NodeToApply->UpdateNodeType(IVT, TP);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-08 21:03:01 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// SDNodeInfo implementation
|
|
|
|
//
|
|
|
|
SDNodeInfo::SDNodeInfo(Record *R) : Def(R) {
|
|
|
|
EnumName = R->getValueAsString("Opcode");
|
|
|
|
SDClassName = R->getValueAsString("SDClass");
|
2005-09-08 21:27:15 +00:00
|
|
|
Record *TypeProfile = R->getValueAsDef("TypeProfile");
|
|
|
|
NumResults = TypeProfile->getValueAsInt("NumResults");
|
|
|
|
NumOperands = TypeProfile->getValueAsInt("NumOperands");
|
|
|
|
|
2005-09-28 18:28:29 +00:00
|
|
|
// Parse the properties.
|
|
|
|
Properties = 0;
|
2005-10-28 22:49:02 +00:00
|
|
|
std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
|
2005-10-28 22:43:25 +00:00
|
|
|
for (unsigned i = 0, e = PropList.size(); i != e; ++i) {
|
|
|
|
if (PropList[i]->getName() == "SDNPCommutative") {
|
2005-09-28 18:28:29 +00:00
|
|
|
Properties |= 1 << SDNPCommutative;
|
2005-10-28 22:43:25 +00:00
|
|
|
} else if (PropList[i]->getName() == "SDNPAssociative") {
|
2005-09-28 20:58:06 +00:00
|
|
|
Properties |= 1 << SDNPAssociative;
|
2005-12-04 08:18:16 +00:00
|
|
|
} else if (PropList[i]->getName() == "SDNPHasChain") {
|
|
|
|
Properties |= 1 << SDNPHasChain;
|
2006-01-09 18:27:06 +00:00
|
|
|
} else if (PropList[i]->getName() == "SDNPOutFlag") {
|
|
|
|
Properties |= 1 << SDNPOutFlag;
|
|
|
|
} else if (PropList[i]->getName() == "SDNPInFlag") {
|
|
|
|
Properties |= 1 << SDNPInFlag;
|
|
|
|
} else if (PropList[i]->getName() == "SDNPOptInFlag") {
|
|
|
|
Properties |= 1 << SDNPOptInFlag;
|
2005-09-28 18:28:29 +00:00
|
|
|
} else {
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "Unknown SD Node property '" << PropList[i]->getName()
|
|
|
|
<< "' on node '" << R->getName() << "'!\n";
|
2005-09-28 18:28:29 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-08 21:27:15 +00:00
|
|
|
// Parse the type constraints.
|
2005-10-28 22:49:02 +00:00
|
|
|
std::vector<Record*> ConstraintList =
|
|
|
|
TypeProfile->getValueAsListOfDefs("Constraints");
|
|
|
|
TypeConstraints.assign(ConstraintList.begin(), ConstraintList.end());
|
2005-09-08 21:03:01 +00:00
|
|
|
}
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TreePatternNode implementation
|
|
|
|
//
|
|
|
|
|
|
|
|
TreePatternNode::~TreePatternNode() {
|
|
|
|
#if 0 // FIXME: implement refcounted tree nodes!
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
|
|
|
delete getChild(i);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
/// UpdateNodeType - Set the node type of N to VT if VT contains
|
|
|
|
/// information. If N already contains a conflicting type, then throw an
|
|
|
|
/// exception. This returns true if any information was updated.
|
|
|
|
///
|
2005-12-30 00:12:56 +00:00
|
|
|
bool TreePatternNode::UpdateNodeType(const std::vector<unsigned char> &ExtVTs,
|
|
|
|
TreePattern &TP) {
|
|
|
|
assert(!ExtVTs.empty() && "Cannot update node type with empty type vector!");
|
|
|
|
|
|
|
|
if (ExtVTs[0] == MVT::isUnknown || LHSIsSubsetOfRHS(getExtTypes(), ExtVTs))
|
|
|
|
return false;
|
|
|
|
if (isTypeCompletelyUnknown() || LHSIsSubsetOfRHS(ExtVTs, getExtTypes())) {
|
|
|
|
setTypes(ExtVTs);
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
return true;
|
|
|
|
}
|
2006-05-17 20:37:59 +00:00
|
|
|
|
|
|
|
if (getExtTypeNum(0) == MVT::iPTR) {
|
|
|
|
if (ExtVTs[0] == MVT::iPTR || ExtVTs[0] == MVT::isInt)
|
|
|
|
return false;
|
|
|
|
if (isExtIntegerInVTs(ExtVTs)) {
|
|
|
|
std::vector<unsigned char> FVTs = FilterEVTs(ExtVTs, MVT::isInteger);
|
|
|
|
if (FVTs.size()) {
|
|
|
|
setTypes(ExtVTs);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
|
2005-12-30 00:12:56 +00:00
|
|
|
if (ExtVTs[0] == MVT::isInt && isExtIntegerInVTs(getExtTypes())) {
|
|
|
|
assert(hasTypeSet() && "should be handled above!");
|
|
|
|
std::vector<unsigned char> FVTs = FilterEVTs(getExtTypes(), MVT::isInteger);
|
|
|
|
if (getExtTypes() == FVTs)
|
|
|
|
return false;
|
|
|
|
setTypes(FVTs);
|
|
|
|
return true;
|
|
|
|
}
|
2006-05-17 20:37:59 +00:00
|
|
|
if (ExtVTs[0] == MVT::iPTR && isExtIntegerInVTs(getExtTypes())) {
|
|
|
|
//assert(hasTypeSet() && "should be handled above!");
|
|
|
|
std::vector<unsigned char> FVTs = FilterEVTs(getExtTypes(), MVT::isInteger);
|
|
|
|
if (getExtTypes() == FVTs)
|
|
|
|
return false;
|
|
|
|
if (FVTs.size()) {
|
|
|
|
setTypes(FVTs);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2005-12-30 00:12:56 +00:00
|
|
|
if (ExtVTs[0] == MVT::isFP && isExtFloatingPointInVTs(getExtTypes())) {
|
|
|
|
assert(hasTypeSet() && "should be handled above!");
|
2006-01-28 19:06:51 +00:00
|
|
|
std::vector<unsigned char> FVTs =
|
|
|
|
FilterEVTs(getExtTypes(), MVT::isFloatingPoint);
|
2005-12-30 00:12:56 +00:00
|
|
|
if (getExtTypes() == FVTs)
|
|
|
|
return false;
|
|
|
|
setTypes(FVTs);
|
|
|
|
return true;
|
|
|
|
}
|
2005-10-14 06:12:03 +00:00
|
|
|
|
|
|
|
// If we know this is an int or fp type, and we are told it is a specific one,
|
|
|
|
// take the advice.
|
2005-12-30 00:12:56 +00:00
|
|
|
//
|
|
|
|
// Similarly, we should probably set the type here to the intersection of
|
|
|
|
// {isInt|isFP} and ExtVTs
|
|
|
|
if ((getExtTypeNum(0) == MVT::isInt && isExtIntegerInVTs(ExtVTs)) ||
|
|
|
|
(getExtTypeNum(0) == MVT::isFP && isExtFloatingPointInVTs(ExtVTs))) {
|
|
|
|
setTypes(ExtVTs);
|
2005-10-14 06:12:03 +00:00
|
|
|
return true;
|
2006-05-17 20:37:59 +00:00
|
|
|
}
|
|
|
|
if (getExtTypeNum(0) == MVT::isInt && ExtVTs[0] == MVT::iPTR) {
|
|
|
|
setTypes(ExtVTs);
|
|
|
|
return true;
|
|
|
|
}
|
2005-10-14 06:12:03 +00:00
|
|
|
|
2005-10-26 16:59:37 +00:00
|
|
|
if (isLeaf()) {
|
|
|
|
dump();
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << " ";
|
2005-10-26 16:59:37 +00:00
|
|
|
TP.error("Type inference contradiction found in node!");
|
|
|
|
} else {
|
|
|
|
TP.error("Type inference contradiction found in node " +
|
|
|
|
getOperator()->getName() + "!");
|
|
|
|
}
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
return true; // unreachable
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
void TreePatternNode::print(std::ostream &OS) const {
|
|
|
|
if (isLeaf()) {
|
|
|
|
OS << *getLeafValue();
|
|
|
|
} else {
|
|
|
|
OS << "(" << getOperator()->getName();
|
|
|
|
}
|
|
|
|
|
2005-12-30 00:12:56 +00:00
|
|
|
// FIXME: At some point we should handle printing all the value types for
|
|
|
|
// nodes that are multiply typed.
|
|
|
|
switch (getExtTypeNum(0)) {
|
2005-10-14 06:12:03 +00:00
|
|
|
case MVT::Other: OS << ":Other"; break;
|
|
|
|
case MVT::isInt: OS << ":isInt"; break;
|
|
|
|
case MVT::isFP : OS << ":isFP"; break;
|
|
|
|
case MVT::isUnknown: ; /*OS << ":?";*/ break;
|
2006-05-17 20:37:59 +00:00
|
|
|
case MVT::iPTR: OS << ":iPTR"; break;
|
2006-06-20 00:56:37 +00:00
|
|
|
default: {
|
|
|
|
std::string VTName = llvm::getName(getTypeNum(0));
|
|
|
|
// Strip off MVT:: prefix if present.
|
|
|
|
if (VTName.substr(0,5) == "MVT::")
|
|
|
|
VTName = VTName.substr(5);
|
|
|
|
OS << ":" << VTName;
|
|
|
|
break;
|
|
|
|
}
|
2005-10-14 06:12:03 +00:00
|
|
|
}
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
if (!isLeaf()) {
|
|
|
|
if (getNumChildren() != 0) {
|
|
|
|
OS << " ";
|
|
|
|
getChild(0)->print(OS);
|
|
|
|
for (unsigned i = 1, e = getNumChildren(); i != e; ++i) {
|
|
|
|
OS << ", ";
|
|
|
|
getChild(i)->print(OS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PredicateFn.empty())
|
2005-09-13 21:51:00 +00:00
|
|
|
OS << "<<P:" << PredicateFn << ">>";
|
2005-09-14 22:55:26 +00:00
|
|
|
if (TransformFn)
|
|
|
|
OS << "<<X:" << TransformFn->getName() << ">>";
|
2005-09-07 23:44:43 +00:00
|
|
|
if (!getName().empty())
|
|
|
|
OS << ":$" << getName();
|
|
|
|
|
|
|
|
}
|
|
|
|
void TreePatternNode::dump() const {
|
2006-12-07 22:21:48 +00:00
|
|
|
print(*cerr.stream());
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
|
|
|
|
2005-09-29 19:28:10 +00:00
|
|
|
/// isIsomorphicTo - Return true if this node is recursively isomorphic to
|
|
|
|
/// the specified node. For this comparison, all of the state of the node
|
|
|
|
/// is considered, except for the assigned name. Nodes with differing names
|
|
|
|
/// that are otherwise identical are considered isomorphic.
|
|
|
|
bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N) const {
|
|
|
|
if (N == this) return true;
|
2005-12-30 00:12:56 +00:00
|
|
|
if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() ||
|
2005-09-29 19:28:10 +00:00
|
|
|
getPredicateFn() != N->getPredicateFn() ||
|
|
|
|
getTransformFn() != N->getTransformFn())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (isLeaf()) {
|
|
|
|
if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue()))
|
|
|
|
if (DefInit *NDI = dynamic_cast<DefInit*>(N->getLeafValue()))
|
|
|
|
return DI->getDef() == NDI->getDef();
|
|
|
|
return getLeafValue() == N->getLeafValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (N->getOperator() != getOperator() ||
|
|
|
|
N->getNumChildren() != getNumChildren()) return false;
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
|
|
|
if (!getChild(i)->isIsomorphicTo(N->getChild(i)))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
/// clone - Make a copy of this tree and all of its children.
|
|
|
|
///
|
|
|
|
TreePatternNode *TreePatternNode::clone() const {
|
|
|
|
TreePatternNode *New;
|
|
|
|
if (isLeaf()) {
|
|
|
|
New = new TreePatternNode(getLeafValue());
|
|
|
|
} else {
|
|
|
|
std::vector<TreePatternNode*> CChildren;
|
|
|
|
CChildren.reserve(Children.size());
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
|
|
|
CChildren.push_back(getChild(i)->clone());
|
|
|
|
New = new TreePatternNode(getOperator(), CChildren);
|
|
|
|
}
|
|
|
|
New->setName(getName());
|
2005-12-30 00:12:56 +00:00
|
|
|
New->setTypes(getExtTypes());
|
2005-09-07 23:44:43 +00:00
|
|
|
New->setPredicateFn(getPredicateFn());
|
2005-09-13 21:51:00 +00:00
|
|
|
New->setTransformFn(getTransformFn());
|
2005-09-07 23:44:43 +00:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
/// SubstituteFormalArguments - Replace the formal arguments in this tree
|
|
|
|
/// with actual values specified by ArgMap.
|
2005-09-07 23:44:43 +00:00
|
|
|
void TreePatternNode::
|
|
|
|
SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) {
|
|
|
|
if (isLeaf()) return;
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
|
|
|
|
TreePatternNode *Child = getChild(i);
|
|
|
|
if (Child->isLeaf()) {
|
|
|
|
Init *Val = Child->getLeafValue();
|
|
|
|
if (dynamic_cast<DefInit*>(Val) &&
|
|
|
|
static_cast<DefInit*>(Val)->getDef()->getName() == "node") {
|
|
|
|
// We found a use of a formal argument, replace it with its value.
|
|
|
|
Child = ArgMap[Child->getName()];
|
|
|
|
assert(Child && "Couldn't find formal argument!");
|
|
|
|
setChild(i, Child);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
getChild(i)->SubstituteFormalArguments(ArgMap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// InlinePatternFragments - If this pattern refers to any pattern
|
|
|
|
/// fragments, inline them into place, giving us a pattern without any
|
|
|
|
/// PatFrag references.
|
|
|
|
TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
|
|
|
|
if (isLeaf()) return this; // nothing to do.
|
|
|
|
Record *Op = getOperator();
|
|
|
|
|
|
|
|
if (!Op->isSubClassOf("PatFrag")) {
|
|
|
|
// Just recursively inline children nodes.
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
|
|
|
setChild(i, getChild(i)->InlinePatternFragments(TP));
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we found a reference to a fragment. First, look up its
|
|
|
|
// TreePattern record.
|
|
|
|
TreePattern *Frag = TP.getDAGISelEmitter().getPatternFragment(Op);
|
|
|
|
|
|
|
|
// Verify that we are passing the right number of operands.
|
|
|
|
if (Frag->getNumArgs() != Children.size())
|
|
|
|
TP.error("'" + Op->getName() + "' fragment requires " +
|
|
|
|
utostr(Frag->getNumArgs()) + " operands!");
|
|
|
|
|
2005-09-09 01:15:01 +00:00
|
|
|
TreePatternNode *FragTree = Frag->getOnlyTree()->clone();
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
// Resolve formal arguments to their actual value.
|
|
|
|
if (Frag->getNumArgs()) {
|
|
|
|
// Compute the map of formal to actual arguments.
|
|
|
|
std::map<std::string, TreePatternNode*> ArgMap;
|
|
|
|
for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i)
|
|
|
|
ArgMap[Frag->getArgName(i)] = getChild(i)->InlinePatternFragments(TP);
|
|
|
|
|
|
|
|
FragTree->SubstituteFormalArguments(ArgMap);
|
|
|
|
}
|
|
|
|
|
2005-09-08 17:45:12 +00:00
|
|
|
FragTree->setName(getName());
|
2005-12-30 00:12:56 +00:00
|
|
|
FragTree->UpdateNodeType(getExtTypes(), TP);
|
2005-09-08 17:45:12 +00:00
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
// Get a new copy of this fragment to stitch into here.
|
|
|
|
//delete this; // FIXME: implement refcounting!
|
|
|
|
return FragTree;
|
|
|
|
}
|
|
|
|
|
2006-04-06 20:19:52 +00:00
|
|
|
/// getImplicitType - Check to see if the specified record has an implicit
|
2005-10-14 04:11:13 +00:00
|
|
|
/// type which should be applied to it. This infer the type of register
|
|
|
|
/// references from the register file information, for example.
|
|
|
|
///
|
2006-04-06 20:19:52 +00:00
|
|
|
static std::vector<unsigned char> getImplicitType(Record *R, bool NotRegisters,
|
2005-10-14 06:12:03 +00:00
|
|
|
TreePattern &TP) {
|
2005-12-30 00:12:56 +00:00
|
|
|
// Some common return values
|
|
|
|
std::vector<unsigned char> Unknown(1, MVT::isUnknown);
|
|
|
|
std::vector<unsigned char> Other(1, MVT::Other);
|
|
|
|
|
2005-10-14 04:11:13 +00:00
|
|
|
// Check to see if this is a register or a register class...
|
|
|
|
if (R->isSubClassOf("RegisterClass")) {
|
2005-12-30 00:12:56 +00:00
|
|
|
if (NotRegisters)
|
|
|
|
return Unknown;
|
2005-12-01 04:51:06 +00:00
|
|
|
const CodeGenRegisterClass &RC =
|
|
|
|
TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(R);
|
2005-12-30 00:12:56 +00:00
|
|
|
return ConvertVTs(RC.getValueTypes());
|
2005-10-14 04:11:13 +00:00
|
|
|
} else if (R->isSubClassOf("PatFrag")) {
|
|
|
|
// Pattern fragment types will be resolved when they are inlined.
|
2005-12-30 00:12:56 +00:00
|
|
|
return Unknown;
|
2005-10-14 04:11:13 +00:00
|
|
|
} else if (R->isSubClassOf("Register")) {
|
2006-01-15 10:04:45 +00:00
|
|
|
if (NotRegisters)
|
|
|
|
return Unknown;
|
2005-12-05 02:36:37 +00:00
|
|
|
const CodeGenTarget &T = TP.getDAGISelEmitter().getTargetInfo();
|
2006-05-16 07:05:30 +00:00
|
|
|
return T.getRegisterVTs(R);
|
2005-10-26 16:59:37 +00:00
|
|
|
} else if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) {
|
|
|
|
// Using a VTSDNode or CondCodeSDNode.
|
2005-12-30 00:12:56 +00:00
|
|
|
return Other;
|
2005-12-08 02:00:36 +00:00
|
|
|
} else if (R->isSubClassOf("ComplexPattern")) {
|
2006-01-17 07:36:41 +00:00
|
|
|
if (NotRegisters)
|
|
|
|
return Unknown;
|
2005-12-30 00:12:56 +00:00
|
|
|
std::vector<unsigned char>
|
|
|
|
ComplexPat(1, TP.getDAGISelEmitter().getComplexPattern(R).getValueType());
|
|
|
|
return ComplexPat;
|
2006-11-14 21:18:40 +00:00
|
|
|
} else if (R->getName() == "ptr_rc") {
|
|
|
|
Other[0] = MVT::iPTR;
|
|
|
|
return Other;
|
2005-12-14 02:21:57 +00:00
|
|
|
} else if (R->getName() == "node" || R->getName() == "srcvalue") {
|
2005-10-14 04:11:13 +00:00
|
|
|
// Placeholder.
|
2005-12-30 00:12:56 +00:00
|
|
|
return Unknown;
|
2005-10-14 04:11:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TP.error("Unknown node flavor used in pattern: " + R->getName());
|
2005-12-30 00:12:56 +00:00
|
|
|
return Other;
|
2005-10-14 04:11:13 +00:00
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
/// ApplyTypeConstraints - Apply all of the type constraints relevent to
|
|
|
|
/// this node and its children in the tree. This returns true if it makes a
|
|
|
|
/// change, false otherwise. If a type contradiction is found, throw an
|
|
|
|
/// exception.
|
2005-10-14 04:11:13 +00:00
|
|
|
bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
|
2006-03-24 23:10:39 +00:00
|
|
|
DAGISelEmitter &ISE = TP.getDAGISelEmitter();
|
2005-10-14 04:11:13 +00:00
|
|
|
if (isLeaf()) {
|
2005-11-03 05:46:11 +00:00
|
|
|
if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue())) {
|
2005-10-14 04:11:13 +00:00
|
|
|
// If it's a regclass or something else known, include the type.
|
2006-04-06 20:19:52 +00:00
|
|
|
return UpdateNodeType(getImplicitType(DI->getDef(), NotRegisters, TP),TP);
|
2005-11-03 05:46:11 +00:00
|
|
|
} else if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) {
|
|
|
|
// Int inits are always integers. :)
|
|
|
|
bool MadeChange = UpdateNodeType(MVT::isInt, TP);
|
|
|
|
|
|
|
|
if (hasTypeSet()) {
|
2005-12-30 00:12:56 +00:00
|
|
|
// At some point, it may make sense for this tree pattern to have
|
|
|
|
// multiple types. Assert here that it does not, so we revisit this
|
|
|
|
// code when appropriate.
|
2006-05-17 20:37:59 +00:00
|
|
|
assert(getExtTypes().size() >= 1 && "TreePattern doesn't have a type!");
|
2006-05-16 07:05:30 +00:00
|
|
|
MVT::ValueType VT = getTypeNum(0);
|
|
|
|
for (unsigned i = 1, e = getExtTypes().size(); i != e; ++i)
|
|
|
|
assert(getTypeNum(i) == VT && "TreePattern has too many types!");
|
2005-12-30 00:12:56 +00:00
|
|
|
|
2006-05-17 20:37:59 +00:00
|
|
|
VT = getTypeNum(0);
|
|
|
|
if (VT != MVT::iPTR) {
|
|
|
|
unsigned Size = MVT::getSizeInBits(VT);
|
|
|
|
// Make sure that the value is representable for this type.
|
|
|
|
if (Size < 32) {
|
|
|
|
int Val = (II->getValue() << (32-Size)) >> (32-Size);
|
|
|
|
if (Val != II->getValue())
|
|
|
|
TP.error("Sign-extended integer value '" + itostr(II->getValue())+
|
|
|
|
"' is out of range for type '" +
|
|
|
|
getEnumName(getTypeNum(0)) + "'!");
|
|
|
|
}
|
2005-11-03 05:46:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return MadeChange;
|
|
|
|
}
|
2005-10-14 04:11:13 +00:00
|
|
|
return false;
|
|
|
|
}
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
|
|
|
|
// special handling for set, which isn't really an SDNode.
|
|
|
|
if (getOperator()->getName() == "set") {
|
|
|
|
assert (getNumChildren() == 2 && "Only handle 2 operand set's for now!");
|
2005-10-14 04:11:13 +00:00
|
|
|
bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
|
|
|
|
MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters);
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
|
|
|
|
// Types of operands must match.
|
2005-12-30 00:12:56 +00:00
|
|
|
MadeChange |= getChild(0)->UpdateNodeType(getChild(1)->getExtTypes(), TP);
|
|
|
|
MadeChange |= getChild(1)->UpdateNodeType(getChild(0)->getExtTypes(), TP);
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
|
|
|
|
return MadeChange;
|
2006-03-24 23:10:39 +00:00
|
|
|
} else if (getOperator() == ISE.get_intrinsic_void_sdnode() ||
|
|
|
|
getOperator() == ISE.get_intrinsic_w_chain_sdnode() ||
|
|
|
|
getOperator() == ISE.get_intrinsic_wo_chain_sdnode()) {
|
|
|
|
unsigned IID =
|
|
|
|
dynamic_cast<IntInit*>(getChild(0)->getLeafValue())->getValue();
|
|
|
|
const CodeGenIntrinsic &Int = ISE.getIntrinsicInfo(IID);
|
|
|
|
bool MadeChange = false;
|
|
|
|
|
|
|
|
// Apply the result type to the node.
|
|
|
|
MadeChange = UpdateNodeType(Int.ArgVTs[0], TP);
|
|
|
|
|
|
|
|
if (getNumChildren() != Int.ArgVTs.size())
|
2006-03-27 22:21:18 +00:00
|
|
|
TP.error("Intrinsic '" + Int.Name + "' expects " +
|
2006-03-24 23:10:39 +00:00
|
|
|
utostr(Int.ArgVTs.size()-1) + " operands, not " +
|
|
|
|
utostr(getNumChildren()-1) + " operands!");
|
|
|
|
|
|
|
|
// Apply type info to the intrinsic ID.
|
2006-05-17 20:37:59 +00:00
|
|
|
MadeChange |= getChild(0)->UpdateNodeType(MVT::iPTR, TP);
|
2006-03-24 23:10:39 +00:00
|
|
|
|
|
|
|
for (unsigned i = 1, e = getNumChildren(); i != e; ++i) {
|
|
|
|
MVT::ValueType OpVT = Int.ArgVTs[i];
|
|
|
|
MadeChange |= getChild(i)->UpdateNodeType(OpVT, TP);
|
|
|
|
MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
|
|
|
|
}
|
|
|
|
return MadeChange;
|
2005-09-15 21:42:00 +00:00
|
|
|
} else if (getOperator()->isSubClassOf("SDNode")) {
|
2006-03-24 23:10:39 +00:00
|
|
|
const SDNodeInfo &NI = ISE.getSDNodeInfo(getOperator());
|
2005-09-15 21:42:00 +00:00
|
|
|
|
|
|
|
bool MadeChange = NI.ApplyTypeConstraints(this, TP);
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
2005-10-14 04:11:13 +00:00
|
|
|
MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
|
2005-12-04 08:18:16 +00:00
|
|
|
// Branch, etc. do not produce results and top-level forms in instr pattern
|
|
|
|
// must have void types.
|
|
|
|
if (NI.getNumResults() == 0)
|
|
|
|
MadeChange |= UpdateNodeType(MVT::isVoid, TP);
|
2006-04-06 20:36:51 +00:00
|
|
|
|
|
|
|
// If this is a vector_shuffle operation, apply types to the build_vector
|
|
|
|
// operation. The types of the integers don't matter, but this ensures they
|
|
|
|
// won't get checked.
|
|
|
|
if (getOperator()->getName() == "vector_shuffle" &&
|
|
|
|
getChild(2)->getOperator()->getName() == "build_vector") {
|
|
|
|
TreePatternNode *BV = getChild(2);
|
|
|
|
const std::vector<MVT::ValueType> &LegalVTs
|
|
|
|
= ISE.getTargetInfo().getLegalValueTypes();
|
|
|
|
MVT::ValueType LegalIntVT = MVT::Other;
|
|
|
|
for (unsigned i = 0, e = LegalVTs.size(); i != e; ++i)
|
|
|
|
if (MVT::isInteger(LegalVTs[i]) && !MVT::isVector(LegalVTs[i])) {
|
|
|
|
LegalIntVT = LegalVTs[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
assert(LegalIntVT != MVT::Other && "No legal integer VT?");
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = BV->getNumChildren(); i != e; ++i)
|
|
|
|
MadeChange |= BV->getChild(i)->UpdateNodeType(LegalIntVT, TP);
|
|
|
|
}
|
2005-09-15 21:42:00 +00:00
|
|
|
return MadeChange;
|
2005-09-15 22:23:50 +00:00
|
|
|
} else if (getOperator()->isSubClassOf("Instruction")) {
|
2006-03-24 23:10:39 +00:00
|
|
|
const DAGInstruction &Inst = ISE.getInstruction(getOperator());
|
2005-12-04 08:18:16 +00:00
|
|
|
bool MadeChange = false;
|
|
|
|
unsigned NumResults = Inst.getNumResults();
|
2005-09-15 21:57:35 +00:00
|
|
|
|
2005-12-04 08:18:16 +00:00
|
|
|
assert(NumResults <= 1 &&
|
|
|
|
"Only supports zero or one result instrs!");
|
2006-07-20 23:36:20 +00:00
|
|
|
|
|
|
|
CodeGenInstruction &InstInfo =
|
|
|
|
ISE.getTargetInfo().getInstruction(getOperator()->getName());
|
2005-09-15 22:23:50 +00:00
|
|
|
// Apply the result type to the node
|
2006-11-14 21:18:40 +00:00
|
|
|
if (NumResults == 0 || InstInfo.noResults) { // FIXME: temporary hack.
|
2005-12-04 08:18:16 +00:00
|
|
|
MadeChange = UpdateNodeType(MVT::isVoid, TP);
|
|
|
|
} else {
|
|
|
|
Record *ResultNode = Inst.getResult(0);
|
2006-11-14 21:18:40 +00:00
|
|
|
|
|
|
|
if (ResultNode->getName() == "ptr_rc") {
|
|
|
|
std::vector<unsigned char> VT;
|
|
|
|
VT.push_back(MVT::iPTR);
|
|
|
|
MadeChange = UpdateNodeType(VT, TP);
|
|
|
|
} else {
|
|
|
|
assert(ResultNode->isSubClassOf("RegisterClass") &&
|
|
|
|
"Operands should be register classes!");
|
2005-12-01 00:06:14 +00:00
|
|
|
|
2006-11-14 21:18:40 +00:00
|
|
|
const CodeGenRegisterClass &RC =
|
|
|
|
ISE.getTargetInfo().getRegisterClass(ResultNode);
|
|
|
|
MadeChange = UpdateNodeType(ConvertVTs(RC.getValueTypes()), TP);
|
|
|
|
}
|
2005-12-04 08:18:16 +00:00
|
|
|
}
|
2005-09-15 22:23:50 +00:00
|
|
|
|
2006-11-04 01:35:50 +00:00
|
|
|
unsigned ChildNo = 0;
|
|
|
|
for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {
|
2005-12-01 00:06:14 +00:00
|
|
|
Record *OperandNode = Inst.getOperand(i);
|
2006-11-04 01:35:50 +00:00
|
|
|
|
|
|
|
// If the instruction expects a predicate operand, we codegen this by
|
|
|
|
// setting the predicate to it's "execute always" value.
|
|
|
|
if (OperandNode->isSubClassOf("PredicateOperand"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Verify that we didn't run out of provided operands.
|
|
|
|
if (ChildNo >= getNumChildren())
|
|
|
|
TP.error("Instruction '" + getOperator()->getName() +
|
|
|
|
"' expects more operands than were provided.");
|
|
|
|
|
2005-12-01 00:06:14 +00:00
|
|
|
MVT::ValueType VT;
|
2006-11-04 01:35:50 +00:00
|
|
|
TreePatternNode *Child = getChild(ChildNo++);
|
2005-12-01 00:06:14 +00:00
|
|
|
if (OperandNode->isSubClassOf("RegisterClass")) {
|
|
|
|
const CodeGenRegisterClass &RC =
|
2006-03-24 23:10:39 +00:00
|
|
|
ISE.getTargetInfo().getRegisterClass(OperandNode);
|
2006-11-04 01:35:50 +00:00
|
|
|
MadeChange |= Child->UpdateNodeType(ConvertVTs(RC.getValueTypes()), TP);
|
2005-12-01 00:06:14 +00:00
|
|
|
} else if (OperandNode->isSubClassOf("Operand")) {
|
|
|
|
VT = getValueType(OperandNode->getValueAsDef("Type"));
|
2006-11-04 01:35:50 +00:00
|
|
|
MadeChange |= Child->UpdateNodeType(VT, TP);
|
2006-11-14 21:18:40 +00:00
|
|
|
} else if (OperandNode->getName() == "ptr_rc") {
|
|
|
|
MadeChange |= Child->UpdateNodeType(MVT::iPTR, TP);
|
2005-12-01 00:06:14 +00:00
|
|
|
} else {
|
|
|
|
assert(0 && "Unknown operand type!");
|
|
|
|
abort();
|
|
|
|
}
|
2006-11-04 01:35:50 +00:00
|
|
|
MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters);
|
2005-09-15 22:23:50 +00:00
|
|
|
}
|
2006-11-04 01:35:50 +00:00
|
|
|
|
|
|
|
if (ChildNo != getNumChildren())
|
|
|
|
TP.error("Instruction '" + getOperator()->getName() +
|
|
|
|
"' was provided too many operands!");
|
|
|
|
|
2005-09-15 22:23:50 +00:00
|
|
|
return MadeChange;
|
|
|
|
} else {
|
|
|
|
assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
|
|
|
|
|
2006-03-20 08:09:17 +00:00
|
|
|
// Node transforms always take one operand.
|
2005-09-15 22:23:50 +00:00
|
|
|
if (getNumChildren() != 1)
|
|
|
|
TP.error("Node transform '" + getOperator()->getName() +
|
|
|
|
"' requires one operand!");
|
2006-03-21 06:42:58 +00:00
|
|
|
|
|
|
|
// If either the output or input of the xform does not have exact
|
|
|
|
// type info. We assume they must be the same. Otherwise, it is perfectly
|
|
|
|
// legal to transform from one type to a completely different type.
|
|
|
|
if (!hasTypeSet() || !getChild(0)->hasTypeSet()) {
|
2006-03-20 08:09:17 +00:00
|
|
|
bool MadeChange = UpdateNodeType(getChild(0)->getExtTypes(), TP);
|
|
|
|
MadeChange |= getChild(0)->UpdateNodeType(getExtTypes(), TP);
|
|
|
|
return MadeChange;
|
|
|
|
}
|
|
|
|
return false;
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-21 20:46:13 +00:00
|
|
|
/// OnlyOnRHSOfCommutative - Return true if this value is only allowed on the
|
|
|
|
/// RHS of a commutative operation, not the on LHS.
|
|
|
|
static bool OnlyOnRHSOfCommutative(TreePatternNode *N) {
|
|
|
|
if (!N->isLeaf() && N->getOperator()->getName() == "imm")
|
|
|
|
return true;
|
|
|
|
if (N->isLeaf() && dynamic_cast<IntInit*>(N->getLeafValue()))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
/// canPatternMatch - If it is impossible for this pattern to match on this
|
|
|
|
/// target, fill in Reason and return false. Otherwise, return true. This is
|
|
|
|
/// used as a santity check for .td files (to prevent people from writing stuff
|
|
|
|
/// that can never possibly work), and to prevent the pattern permuter from
|
|
|
|
/// generating stuff that is useless.
|
2005-09-28 20:58:06 +00:00
|
|
|
bool TreePatternNode::canPatternMatch(std::string &Reason, DAGISelEmitter &ISE){
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
if (isLeaf()) return true;
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
|
|
|
if (!getChild(i)->canPatternMatch(Reason, ISE))
|
|
|
|
return false;
|
2005-12-08 02:00:36 +00:00
|
|
|
|
2006-03-24 21:48:51 +00:00
|
|
|
// If this is an intrinsic, handle cases that would make it not match. For
|
|
|
|
// example, if an operand is required to be an immediate.
|
|
|
|
if (getOperator()->isSubClassOf("Intrinsic")) {
|
|
|
|
// TODO:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
// If this node is a commutative operator, check that the LHS isn't an
|
|
|
|
// immediate.
|
|
|
|
const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(getOperator());
|
2006-10-11 21:02:01 +00:00
|
|
|
if (NodeInfo.hasProperty(SDNPCommutative)) {
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
// Scan all of the operands of the node and make sure that only the last one
|
2006-09-14 23:54:24 +00:00
|
|
|
// is a constant node, unless the RHS also is.
|
2006-09-21 20:46:13 +00:00
|
|
|
if (!OnlyOnRHSOfCommutative(getChild(getNumChildren()-1))) {
|
2006-09-14 23:54:24 +00:00
|
|
|
for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i)
|
2006-09-21 20:46:13 +00:00
|
|
|
if (OnlyOnRHSOfCommutative(getChild(i))) {
|
2006-09-21 18:28:27 +00:00
|
|
|
Reason="Immediate value must be on the RHS of commutative operators!";
|
2006-09-14 23:54:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TreePattern implementation
|
|
|
|
//
|
|
|
|
|
2005-10-21 01:19:59 +00:00
|
|
|
TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput,
|
2005-09-13 21:20:49 +00:00
|
|
|
DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) {
|
2005-10-21 01:19:59 +00:00
|
|
|
isInputPattern = isInput;
|
2005-09-15 22:23:50 +00:00
|
|
|
for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i)
|
|
|
|
Trees.push_back(ParseTreePattern((DagInit*)RawPat->getElement(i)));
|
|
|
|
}
|
2005-09-07 23:44:43 +00:00
|
|
|
|
2005-10-21 01:19:59 +00:00
|
|
|
TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput,
|
2005-09-15 22:23:50 +00:00
|
|
|
DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) {
|
2005-10-21 01:19:59 +00:00
|
|
|
isInputPattern = isInput;
|
2005-09-15 22:23:50 +00:00
|
|
|
Trees.push_back(ParseTreePattern(Pat));
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
|
|
|
|
2005-10-21 01:19:59 +00:00
|
|
|
TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
|
2005-09-15 22:23:50 +00:00
|
|
|
DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) {
|
2005-10-21 01:19:59 +00:00
|
|
|
isInputPattern = isInput;
|
2005-09-15 22:23:50 +00:00
|
|
|
Trees.push_back(Pat);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
void TreePattern::error(const std::string &Msg) const {
|
2005-09-14 20:53:42 +00:00
|
|
|
dump();
|
2005-09-13 21:20:49 +00:00
|
|
|
throw "In " + TheRecord->getName() + ": " + Msg;
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TreePatternNode *TreePattern::ParseTreePattern(DagInit *Dag) {
|
2006-03-30 22:50:40 +00:00
|
|
|
DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator());
|
|
|
|
if (!OpDef) error("Pattern has unexpected operator type!");
|
|
|
|
Record *Operator = OpDef->getDef();
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
if (Operator->isSubClassOf("ValueType")) {
|
|
|
|
// If the operator is a ValueType, then this must be "type cast" of a leaf
|
|
|
|
// node.
|
|
|
|
if (Dag->getNumArgs() != 1)
|
2005-10-14 04:11:13 +00:00
|
|
|
error("Type cast only takes one operand!");
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
Init *Arg = Dag->getArg(0);
|
|
|
|
TreePatternNode *New;
|
|
|
|
if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
|
2005-09-24 00:40:24 +00:00
|
|
|
Record *R = DI->getDef();
|
|
|
|
if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) {
|
2006-03-30 22:50:40 +00:00
|
|
|
Dag->setArg(0, new DagInit(DI,
|
2005-09-24 00:40:24 +00:00
|
|
|
std::vector<std::pair<Init*, std::string> >()));
|
2005-11-16 23:14:54 +00:00
|
|
|
return ParseTreePattern(Dag);
|
2005-12-04 08:18:16 +00:00
|
|
|
}
|
2005-09-07 23:44:43 +00:00
|
|
|
New = new TreePatternNode(DI);
|
|
|
|
} else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
|
|
|
|
New = ParseTreePattern(DI);
|
2005-11-02 06:49:14 +00:00
|
|
|
} else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
|
|
|
|
New = new TreePatternNode(II);
|
|
|
|
if (!Dag->getArgName(0).empty())
|
|
|
|
error("Constant int argument should not have a name!");
|
2006-03-31 05:25:56 +00:00
|
|
|
} else if (BitsInit *BI = dynamic_cast<BitsInit*>(Arg)) {
|
|
|
|
// Turn this into an IntInit.
|
|
|
|
Init *II = BI->convertInitializerTo(new IntRecTy());
|
|
|
|
if (II == 0 || !dynamic_cast<IntInit*>(II))
|
|
|
|
error("Bits value must be constants!");
|
|
|
|
|
|
|
|
New = new TreePatternNode(dynamic_cast<IntInit*>(II));
|
|
|
|
if (!Dag->getArgName(0).empty())
|
|
|
|
error("Constant int argument should not have a name!");
|
2005-09-07 23:44:43 +00:00
|
|
|
} else {
|
|
|
|
Arg->dump();
|
|
|
|
error("Unknown leaf value for tree pattern!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
// Apply the type cast.
|
|
|
|
New->UpdateNodeType(getValueType(Operator), *this);
|
2005-11-16 23:14:54 +00:00
|
|
|
New->setName(Dag->getArgName(0));
|
2005-09-07 23:44:43 +00:00
|
|
|
return New;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that this is something that makes sense for an operator.
|
|
|
|
if (!Operator->isSubClassOf("PatFrag") && !Operator->isSubClassOf("SDNode") &&
|
2005-09-15 21:42:00 +00:00
|
|
|
!Operator->isSubClassOf("Instruction") &&
|
|
|
|
!Operator->isSubClassOf("SDNodeXForm") &&
|
2006-03-24 21:48:51 +00:00
|
|
|
!Operator->isSubClassOf("Intrinsic") &&
|
2005-09-07 23:44:43 +00:00
|
|
|
Operator->getName() != "set")
|
|
|
|
error("Unrecognized node '" + Operator->getName() + "'!");
|
|
|
|
|
2005-10-21 01:19:59 +00:00
|
|
|
// Check to see if this is something that is illegal in an input pattern.
|
|
|
|
if (isInputPattern && (Operator->isSubClassOf("Instruction") ||
|
2006-03-24 23:10:39 +00:00
|
|
|
Operator->isSubClassOf("SDNodeXForm")))
|
2005-10-21 01:19:59 +00:00
|
|
|
error("Cannot use '" + Operator->getName() + "' in an input pattern!");
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
std::vector<TreePatternNode*> Children;
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
|
|
|
|
Init *Arg = Dag->getArg(i);
|
|
|
|
if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
|
|
|
|
Children.push_back(ParseTreePattern(DI));
|
2005-11-16 23:14:54 +00:00
|
|
|
if (Children.back()->getName().empty())
|
|
|
|
Children.back()->setName(Dag->getArgName(i));
|
2005-09-07 23:44:43 +00:00
|
|
|
} else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) {
|
|
|
|
Record *R = DefI->getDef();
|
|
|
|
// Direct reference to a leaf DagNode or PatFrag? Turn it into a
|
|
|
|
// TreePatternNode if its own.
|
|
|
|
if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) {
|
2006-03-30 22:50:40 +00:00
|
|
|
Dag->setArg(i, new DagInit(DefI,
|
2005-09-07 23:44:43 +00:00
|
|
|
std::vector<std::pair<Init*, std::string> >()));
|
|
|
|
--i; // Revisit this node...
|
|
|
|
} else {
|
|
|
|
TreePatternNode *Node = new TreePatternNode(DefI);
|
|
|
|
Node->setName(Dag->getArgName(i));
|
|
|
|
Children.push_back(Node);
|
|
|
|
|
|
|
|
// Input argument?
|
|
|
|
if (R->getName() == "node") {
|
|
|
|
if (Dag->getArgName(i).empty())
|
|
|
|
error("'node' argument requires a name to match with operand list");
|
|
|
|
Args.push_back(Dag->getArgName(i));
|
|
|
|
}
|
|
|
|
}
|
2005-10-19 04:30:56 +00:00
|
|
|
} else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
|
|
|
|
TreePatternNode *Node = new TreePatternNode(II);
|
|
|
|
if (!Dag->getArgName(i).empty())
|
|
|
|
error("Constant int argument should not have a name!");
|
|
|
|
Children.push_back(Node);
|
2006-03-31 05:25:56 +00:00
|
|
|
} else if (BitsInit *BI = dynamic_cast<BitsInit*>(Arg)) {
|
|
|
|
// Turn this into an IntInit.
|
|
|
|
Init *II = BI->convertInitializerTo(new IntRecTy());
|
|
|
|
if (II == 0 || !dynamic_cast<IntInit*>(II))
|
|
|
|
error("Bits value must be constants!");
|
|
|
|
|
|
|
|
TreePatternNode *Node = new TreePatternNode(dynamic_cast<IntInit*>(II));
|
|
|
|
if (!Dag->getArgName(i).empty())
|
|
|
|
error("Constant int argument should not have a name!");
|
|
|
|
Children.push_back(Node);
|
2005-09-07 23:44:43 +00:00
|
|
|
} else {
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << '"';
|
2005-09-07 23:44:43 +00:00
|
|
|
Arg->dump();
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "\": ";
|
2005-09-07 23:44:43 +00:00
|
|
|
error("Unknown leaf value for tree pattern!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-24 23:10:39 +00:00
|
|
|
// If the operator is an intrinsic, then this is just syntactic sugar for for
|
|
|
|
// (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and
|
|
|
|
// convert the intrinsic name to a number.
|
|
|
|
if (Operator->isSubClassOf("Intrinsic")) {
|
|
|
|
const CodeGenIntrinsic &Int = getDAGISelEmitter().getIntrinsic(Operator);
|
|
|
|
unsigned IID = getDAGISelEmitter().getIntrinsicID(Operator)+1;
|
|
|
|
|
|
|
|
// If this intrinsic returns void, it must have side-effects and thus a
|
|
|
|
// chain.
|
|
|
|
if (Int.ArgVTs[0] == MVT::isVoid) {
|
|
|
|
Operator = getDAGISelEmitter().get_intrinsic_void_sdnode();
|
|
|
|
} else if (Int.ModRef != CodeGenIntrinsic::NoMem) {
|
|
|
|
// Has side-effects, requires chain.
|
|
|
|
Operator = getDAGISelEmitter().get_intrinsic_w_chain_sdnode();
|
|
|
|
} else {
|
|
|
|
// Otherwise, no chain.
|
|
|
|
Operator = getDAGISelEmitter().get_intrinsic_wo_chain_sdnode();
|
|
|
|
}
|
|
|
|
|
|
|
|
TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID));
|
|
|
|
Children.insert(Children.begin(), IIDNode);
|
|
|
|
}
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
return new TreePatternNode(Operator, Children);
|
|
|
|
}
|
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
/// InferAllTypes - Infer/propagate as many types throughout the expression
|
|
|
|
/// patterns as possible. Return true if all types are infered, false
|
|
|
|
/// otherwise. Throw an exception if a type contradiction is found.
|
|
|
|
bool TreePattern::InferAllTypes() {
|
|
|
|
bool MadeChange = true;
|
|
|
|
while (MadeChange) {
|
|
|
|
MadeChange = false;
|
|
|
|
for (unsigned i = 0, e = Trees.size(); i != e; ++i)
|
2005-10-14 04:11:13 +00:00
|
|
|
MadeChange |= Trees[i]->ApplyTypeConstraints(*this, false);
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool HasUnresolvedTypes = false;
|
|
|
|
for (unsigned i = 0, e = Trees.size(); i != e; ++i)
|
|
|
|
HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType();
|
|
|
|
return !HasUnresolvedTypes;
|
|
|
|
}
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
void TreePattern::print(std::ostream &OS) const {
|
|
|
|
OS << getRecord()->getName();
|
|
|
|
if (!Args.empty()) {
|
|
|
|
OS << "(" << Args[0];
|
|
|
|
for (unsigned i = 1, e = Args.size(); i != e; ++i)
|
|
|
|
OS << ", " << Args[i];
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
OS << ": ";
|
|
|
|
|
|
|
|
if (Trees.size() > 1)
|
|
|
|
OS << "[\n";
|
|
|
|
for (unsigned i = 0, e = Trees.size(); i != e; ++i) {
|
|
|
|
OS << "\t";
|
|
|
|
Trees[i]->print(OS);
|
|
|
|
OS << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Trees.size() > 1)
|
|
|
|
OS << "]\n";
|
|
|
|
}
|
|
|
|
|
2006-12-07 22:21:48 +00:00
|
|
|
void TreePattern::dump() const { print(*cerr.stream()); }
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DAGISelEmitter implementation
|
|
|
|
//
|
|
|
|
|
2005-09-08 21:03:01 +00:00
|
|
|
// Parse all of the SDNode definitions for the target, populating SDNodes.
|
|
|
|
void DAGISelEmitter::ParseNodeInfo() {
|
|
|
|
std::vector<Record*> Nodes = Records.getAllDerivedDefinitions("SDNode");
|
|
|
|
while (!Nodes.empty()) {
|
|
|
|
SDNodes.insert(std::make_pair(Nodes.back(), Nodes.back()));
|
|
|
|
Nodes.pop_back();
|
|
|
|
}
|
2006-03-24 23:10:39 +00:00
|
|
|
|
|
|
|
// Get the buildin intrinsic nodes.
|
|
|
|
intrinsic_void_sdnode = getSDNodeNamed("intrinsic_void");
|
|
|
|
intrinsic_w_chain_sdnode = getSDNodeNamed("intrinsic_w_chain");
|
|
|
|
intrinsic_wo_chain_sdnode = getSDNodeNamed("intrinsic_wo_chain");
|
2005-09-08 21:03:01 +00:00
|
|
|
}
|
|
|
|
|
2005-09-13 21:51:00 +00:00
|
|
|
/// ParseNodeTransforms - Parse all SDNodeXForm instances into the SDNodeXForms
|
|
|
|
/// map, and emit them to the file as functions.
|
|
|
|
void DAGISelEmitter::ParseNodeTransforms(std::ostream &OS) {
|
|
|
|
OS << "\n// Node transformations.\n";
|
|
|
|
std::vector<Record*> Xforms = Records.getAllDerivedDefinitions("SDNodeXForm");
|
|
|
|
while (!Xforms.empty()) {
|
|
|
|
Record *XFormNode = Xforms.back();
|
|
|
|
Record *SDNode = XFormNode->getValueAsDef("Opcode");
|
|
|
|
std::string Code = XFormNode->getValueAsCode("XFormFunction");
|
|
|
|
SDNodeXForms.insert(std::make_pair(XFormNode,
|
|
|
|
std::make_pair(SDNode, Code)));
|
|
|
|
|
2005-09-13 22:03:37 +00:00
|
|
|
if (!Code.empty()) {
|
2005-09-13 21:51:00 +00:00
|
|
|
std::string ClassName = getSDNodeInfo(SDNode).getSDClassName();
|
|
|
|
const char *C2 = ClassName == "SDNode" ? "N" : "inN";
|
|
|
|
|
2005-09-13 22:03:37 +00:00
|
|
|
OS << "inline SDOperand Transform_" << XFormNode->getName()
|
2005-09-13 21:51:00 +00:00
|
|
|
<< "(SDNode *" << C2 << ") {\n";
|
|
|
|
if (ClassName != "SDNode")
|
|
|
|
OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
|
|
|
|
OS << Code << "\n}\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
Xforms.pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-08 02:00:36 +00:00
|
|
|
void DAGISelEmitter::ParseComplexPatterns() {
|
|
|
|
std::vector<Record*> AMs = Records.getAllDerivedDefinitions("ComplexPattern");
|
|
|
|
while (!AMs.empty()) {
|
|
|
|
ComplexPatterns.insert(std::make_pair(AMs.back(), AMs.back()));
|
|
|
|
AMs.pop_back();
|
|
|
|
}
|
|
|
|
}
|
2005-09-13 21:51:00 +00:00
|
|
|
|
|
|
|
|
2005-09-15 02:38:02 +00:00
|
|
|
/// ParsePatternFragments - Parse all of the PatFrag definitions in the .td
|
|
|
|
/// file, building up the PatternFragments map. After we've collected them all,
|
|
|
|
/// inline fragments together as necessary, so that there are no references left
|
|
|
|
/// inside a pattern fragment to a pattern fragment.
|
2005-09-07 23:44:43 +00:00
|
|
|
///
|
|
|
|
/// This also emits all of the predicate functions to the output file.
|
|
|
|
///
|
2005-09-15 02:38:02 +00:00
|
|
|
void DAGISelEmitter::ParsePatternFragments(std::ostream &OS) {
|
2005-09-07 23:44:43 +00:00
|
|
|
std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag");
|
|
|
|
|
|
|
|
// First step, parse all of the fragments and emit predicate functions.
|
|
|
|
OS << "\n// Predicate functions.\n";
|
|
|
|
for (unsigned i = 0, e = Fragments.size(); i != e; ++i) {
|
2005-09-15 22:23:50 +00:00
|
|
|
DagInit *Tree = Fragments[i]->getValueAsDag("Fragment");
|
2005-10-21 01:19:59 +00:00
|
|
|
TreePattern *P = new TreePattern(Fragments[i], Tree, true, *this);
|
2005-09-07 23:44:43 +00:00
|
|
|
PatternFragments[Fragments[i]] = P;
|
2005-09-13 21:20:49 +00:00
|
|
|
|
|
|
|
// Validate the argument list, converting it to map, to discard duplicates.
|
|
|
|
std::vector<std::string> &Args = P->getArgList();
|
|
|
|
std::set<std::string> OperandsMap(Args.begin(), Args.end());
|
|
|
|
|
|
|
|
if (OperandsMap.count(""))
|
|
|
|
P->error("Cannot have unnamed 'node' values in pattern fragment!");
|
|
|
|
|
|
|
|
// Parse the operands list.
|
|
|
|
DagInit *OpsList = Fragments[i]->getValueAsDag("Operands");
|
2006-03-30 22:50:40 +00:00
|
|
|
DefInit *OpsOp = dynamic_cast<DefInit*>(OpsList->getOperator());
|
|
|
|
if (!OpsOp || OpsOp->getDef()->getName() != "ops")
|
2005-09-13 21:20:49 +00:00
|
|
|
P->error("Operands list should start with '(ops ... '!");
|
|
|
|
|
|
|
|
// Copy over the arguments.
|
|
|
|
Args.clear();
|
|
|
|
for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) {
|
|
|
|
if (!dynamic_cast<DefInit*>(OpsList->getArg(j)) ||
|
|
|
|
static_cast<DefInit*>(OpsList->getArg(j))->
|
|
|
|
getDef()->getName() != "node")
|
|
|
|
P->error("Operands list should all be 'node' values.");
|
|
|
|
if (OpsList->getArgName(j).empty())
|
|
|
|
P->error("Operands list should have names for each operand!");
|
|
|
|
if (!OperandsMap.count(OpsList->getArgName(j)))
|
|
|
|
P->error("'" + OpsList->getArgName(j) +
|
|
|
|
"' does not occur in pattern or was multiply specified!");
|
|
|
|
OperandsMap.erase(OpsList->getArgName(j));
|
|
|
|
Args.push_back(OpsList->getArgName(j));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!OperandsMap.empty())
|
|
|
|
P->error("Operands list does not contain an entry for operand '" +
|
|
|
|
*OperandsMap.begin() + "'!");
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
// If there is a code init for this fragment, emit the predicate code and
|
|
|
|
// keep track of the fact that this fragment uses it.
|
2005-09-13 21:51:00 +00:00
|
|
|
std::string Code = Fragments[i]->getValueAsCode("Predicate");
|
|
|
|
if (!Code.empty()) {
|
2006-09-19 19:08:04 +00:00
|
|
|
if (P->getOnlyTree()->isLeaf())
|
|
|
|
OS << "inline bool Predicate_" << Fragments[i]->getName()
|
|
|
|
<< "(SDNode *N) {\n";
|
|
|
|
else {
|
|
|
|
std::string ClassName =
|
|
|
|
getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
|
|
|
|
const char *C2 = ClassName == "SDNode" ? "N" : "inN";
|
2005-09-07 23:44:43 +00:00
|
|
|
|
2006-09-19 19:08:04 +00:00
|
|
|
OS << "inline bool Predicate_" << Fragments[i]->getName()
|
|
|
|
<< "(SDNode *" << C2 << ") {\n";
|
|
|
|
if (ClassName != "SDNode")
|
|
|
|
OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
|
|
|
|
}
|
2005-09-13 21:51:00 +00:00
|
|
|
OS << Code << "\n}\n";
|
2005-09-09 01:15:01 +00:00
|
|
|
P->getOnlyTree()->setPredicateFn("Predicate_"+Fragments[i]->getName());
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
2005-09-13 21:59:15 +00:00
|
|
|
|
|
|
|
// If there is a node transformation corresponding to this, keep track of
|
|
|
|
// it.
|
|
|
|
Record *Transform = Fragments[i]->getValueAsDef("OperandTransform");
|
|
|
|
if (!getSDNodeTransform(Transform).second.empty()) // not noop xform?
|
2005-09-14 22:55:26 +00:00
|
|
|
P->getOnlyTree()->setTransformFn(Transform);
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
OS << "\n\n";
|
|
|
|
|
|
|
|
// Now that we've parsed all of the tree fragments, do a closure on them so
|
|
|
|
// that there are not references to PatFrags left inside of them.
|
|
|
|
for (std::map<Record*, TreePattern*>::iterator I = PatternFragments.begin(),
|
|
|
|
E = PatternFragments.end(); I != E; ++I) {
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
TreePattern *ThePat = I->second;
|
|
|
|
ThePat->InlinePatternFragments();
|
2005-09-13 21:20:49 +00:00
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
// Infer as many types as possible. Don't worry about it if we don't infer
|
|
|
|
// all of them, some may depend on the inputs of the pattern.
|
|
|
|
try {
|
|
|
|
ThePat->InferAllTypes();
|
|
|
|
} catch (...) {
|
|
|
|
// If this pattern fragment is not supported by this target (no types can
|
|
|
|
// satisfy its constraints), just ignore it. If the bogus pattern is
|
|
|
|
// actually used by instructions, the type consistency error will be
|
|
|
|
// reported there.
|
|
|
|
}
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
// If debugging, print out the pattern fragment result.
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
DEBUG(ThePat->dump());
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-04 05:12:02 +00:00
|
|
|
void DAGISelEmitter::ParsePredicateOperands() {
|
|
|
|
std::vector<Record*> PredOps =
|
|
|
|
Records.getAllDerivedDefinitions("PredicateOperand");
|
|
|
|
|
|
|
|
// Find some SDNode.
|
|
|
|
assert(!SDNodes.empty() && "No SDNodes parsed?");
|
|
|
|
Init *SomeSDNode = new DefInit(SDNodes.begin()->first);
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = PredOps.size(); i != e; ++i) {
|
|
|
|
DagInit *AlwaysInfo = PredOps[i]->getValueAsDag("ExecuteAlways");
|
|
|
|
|
|
|
|
// Clone the AlwaysInfo dag node, changing the operator from 'ops' to
|
|
|
|
// SomeSDnode so that we can parse this.
|
|
|
|
std::vector<std::pair<Init*, std::string> > Ops;
|
|
|
|
for (unsigned op = 0, e = AlwaysInfo->getNumArgs(); op != e; ++op)
|
|
|
|
Ops.push_back(std::make_pair(AlwaysInfo->getArg(op),
|
|
|
|
AlwaysInfo->getArgName(op)));
|
|
|
|
DagInit *DI = new DagInit(SomeSDNode, Ops);
|
|
|
|
|
|
|
|
// Create a TreePattern to parse this.
|
|
|
|
TreePattern P(PredOps[i], DI, false, *this);
|
|
|
|
assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!");
|
|
|
|
|
|
|
|
// Copy the operands over into a DAGPredicateOperand.
|
|
|
|
DAGPredicateOperand PredOpInfo;
|
|
|
|
|
|
|
|
TreePatternNode *T = P.getTree(0);
|
|
|
|
for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) {
|
|
|
|
TreePatternNode *TPN = T->getChild(op);
|
|
|
|
while (TPN->ApplyTypeConstraints(P, false))
|
|
|
|
/* Resolve all types */;
|
|
|
|
|
|
|
|
if (TPN->ContainsUnresolvedType())
|
|
|
|
throw "Value #" + utostr(i) + " of PredicateOperand '" +
|
|
|
|
PredOps[i]->getName() + "' doesn't have a concrete type!";
|
|
|
|
|
|
|
|
PredOpInfo.AlwaysOps.push_back(TPN);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert it into the PredicateOperands map so we can find it later.
|
|
|
|
PredicateOperands[PredOps[i]] = PredOpInfo;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
/// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an
|
2005-09-14 23:05:13 +00:00
|
|
|
/// instruction input. Return true if this is a real use.
|
|
|
|
static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
|
2005-12-23 22:11:47 +00:00
|
|
|
std::map<std::string, TreePatternNode*> &InstInputs,
|
|
|
|
std::vector<Record*> &InstImpInputs) {
|
2005-09-14 20:53:42 +00:00
|
|
|
// No name -> not interesting.
|
2005-09-14 22:06:36 +00:00
|
|
|
if (Pat->getName().empty()) {
|
|
|
|
if (Pat->isLeaf()) {
|
|
|
|
DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue());
|
|
|
|
if (DI && DI->getDef()->isSubClassOf("RegisterClass"))
|
|
|
|
I->error("Input " + DI->getDef()->getName() + " must be named!");
|
2005-12-23 22:11:47 +00:00
|
|
|
else if (DI && DI->getDef()->isSubClassOf("Register"))
|
|
|
|
InstImpInputs.push_back(DI->getDef());
|
2005-09-14 22:06:36 +00:00
|
|
|
}
|
2005-09-14 23:05:13 +00:00
|
|
|
return false;
|
2005-09-14 22:06:36 +00:00
|
|
|
}
|
2005-09-14 20:53:42 +00:00
|
|
|
|
|
|
|
Record *Rec;
|
|
|
|
if (Pat->isLeaf()) {
|
|
|
|
DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue());
|
|
|
|
if (!DI) I->error("Input $" + Pat->getName() + " must be an identifier!");
|
|
|
|
Rec = DI->getDef();
|
|
|
|
} else {
|
|
|
|
assert(Pat->getNumChildren() == 0 && "can't be a use with children!");
|
|
|
|
Rec = Pat->getOperator();
|
|
|
|
}
|
|
|
|
|
2005-12-14 02:21:57 +00:00
|
|
|
// SRCVALUE nodes are ignored.
|
|
|
|
if (Rec->getName() == "srcvalue")
|
|
|
|
return false;
|
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
TreePatternNode *&Slot = InstInputs[Pat->getName()];
|
|
|
|
if (!Slot) {
|
|
|
|
Slot = Pat;
|
|
|
|
} else {
|
|
|
|
Record *SlotRec;
|
|
|
|
if (Slot->isLeaf()) {
|
2005-09-16 00:29:46 +00:00
|
|
|
SlotRec = dynamic_cast<DefInit*>(Slot->getLeafValue())->getDef();
|
2005-09-14 20:53:42 +00:00
|
|
|
} else {
|
|
|
|
assert(Slot->getNumChildren() == 0 && "can't be a use with children!");
|
|
|
|
SlotRec = Slot->getOperator();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that the inputs agree if we've already seen this input.
|
|
|
|
if (Rec != SlotRec)
|
|
|
|
I->error("All $" + Pat->getName() + " inputs must agree with each other");
|
2005-12-30 00:12:56 +00:00
|
|
|
if (Slot->getExtTypes() != Pat->getExtTypes())
|
2005-09-14 20:53:42 +00:00
|
|
|
I->error("All $" + Pat->getName() + " inputs must agree with each other");
|
|
|
|
}
|
2005-09-14 23:05:13 +00:00
|
|
|
return true;
|
2005-09-14 20:53:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is
|
|
|
|
/// part of "I", the instruction), computing the set of inputs and outputs of
|
|
|
|
/// the pattern. Report errors if we see anything naughty.
|
|
|
|
void DAGISelEmitter::
|
|
|
|
FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
|
|
|
|
std::map<std::string, TreePatternNode*> &InstInputs,
|
2006-03-24 21:52:20 +00:00
|
|
|
std::map<std::string, TreePatternNode*>&InstResults,
|
2005-12-23 22:11:47 +00:00
|
|
|
std::vector<Record*> &InstImpInputs,
|
2005-12-17 01:19:28 +00:00
|
|
|
std::vector<Record*> &InstImpResults) {
|
2005-09-14 20:53:42 +00:00
|
|
|
if (Pat->isLeaf()) {
|
2005-12-23 22:11:47 +00:00
|
|
|
bool isUse = HandleUse(I, Pat, InstInputs, InstImpInputs);
|
2005-09-14 23:05:13 +00:00
|
|
|
if (!isUse && Pat->getTransformFn())
|
|
|
|
I->error("Cannot specify a transform function for a non-input value!");
|
2005-09-14 20:53:42 +00:00
|
|
|
return;
|
|
|
|
} else if (Pat->getOperator()->getName() != "set") {
|
|
|
|
// If this is not a set, verify that the children nodes are not void typed,
|
|
|
|
// and recurse.
|
|
|
|
for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
|
2005-12-30 00:12:56 +00:00
|
|
|
if (Pat->getChild(i)->getExtTypeNum(0) == MVT::isVoid)
|
2005-09-14 20:53:42 +00:00
|
|
|
I->error("Cannot have void nodes inside of patterns!");
|
2005-12-17 01:19:28 +00:00
|
|
|
FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults,
|
2005-12-23 22:11:47 +00:00
|
|
|
InstImpInputs, InstImpResults);
|
2005-09-14 20:53:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If this is a non-leaf node with no children, treat it basically as if
|
|
|
|
// it were a leaf. This handles nodes like (imm).
|
2005-09-14 23:05:13 +00:00
|
|
|
bool isUse = false;
|
2005-09-14 20:53:42 +00:00
|
|
|
if (Pat->getNumChildren() == 0)
|
2005-12-23 22:11:47 +00:00
|
|
|
isUse = HandleUse(I, Pat, InstInputs, InstImpInputs);
|
2005-09-14 20:53:42 +00:00
|
|
|
|
2005-09-14 23:05:13 +00:00
|
|
|
if (!isUse && Pat->getTransformFn())
|
|
|
|
I->error("Cannot specify a transform function for a non-input value!");
|
2005-09-14 20:53:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, this is a set, validate and collect instruction results.
|
|
|
|
if (Pat->getNumChildren() == 0)
|
|
|
|
I->error("set requires operands!");
|
|
|
|
else if (Pat->getNumChildren() & 1)
|
|
|
|
I->error("set requires an even number of operands");
|
|
|
|
|
2005-09-14 23:05:13 +00:00
|
|
|
if (Pat->getTransformFn())
|
|
|
|
I->error("Cannot specify a transform function on a set node!");
|
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
// Check the set destinations.
|
|
|
|
unsigned NumValues = Pat->getNumChildren()/2;
|
|
|
|
for (unsigned i = 0; i != NumValues; ++i) {
|
|
|
|
TreePatternNode *Dest = Pat->getChild(i);
|
|
|
|
if (!Dest->isLeaf())
|
2005-12-12 19:37:43 +00:00
|
|
|
I->error("set destination should be a register!");
|
2005-09-14 20:53:42 +00:00
|
|
|
|
|
|
|
DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue());
|
|
|
|
if (!Val)
|
2005-12-12 19:37:43 +00:00
|
|
|
I->error("set destination should be a register!");
|
2005-09-14 20:53:42 +00:00
|
|
|
|
2006-11-14 21:18:40 +00:00
|
|
|
if (Val->getDef()->isSubClassOf("RegisterClass") ||
|
|
|
|
Val->getDef()->getName() == "ptr_rc") {
|
2005-12-17 01:19:28 +00:00
|
|
|
if (Dest->getName().empty())
|
|
|
|
I->error("set destination must have a name!");
|
|
|
|
if (InstResults.count(Dest->getName()))
|
|
|
|
I->error("cannot set '" + Dest->getName() +"' multiple times");
|
2006-03-20 06:04:09 +00:00
|
|
|
InstResults[Dest->getName()] = Dest;
|
2005-12-23 22:11:47 +00:00
|
|
|
} else if (Val->getDef()->isSubClassOf("Register")) {
|
2005-12-17 01:19:28 +00:00
|
|
|
InstImpResults.push_back(Val->getDef());
|
|
|
|
} else {
|
|
|
|
I->error("set destination should be a register!");
|
|
|
|
}
|
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
// Verify and collect info from the computation.
|
|
|
|
FindPatternInputsAndOutputs(I, Pat->getChild(i+NumValues),
|
2005-12-23 22:11:47 +00:00
|
|
|
InstInputs, InstResults,
|
|
|
|
InstImpInputs, InstImpResults);
|
2005-09-14 20:53:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-15 02:38:02 +00:00
|
|
|
/// ParseInstructions - Parse all of the instructions, inlining and resolving
|
|
|
|
/// any fragments involved. This populates the Instructions list with fully
|
|
|
|
/// resolved instructions.
|
|
|
|
void DAGISelEmitter::ParseInstructions() {
|
2005-09-07 23:44:43 +00:00
|
|
|
std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction");
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = Instrs.size(); i != e; ++i) {
|
2005-10-19 01:27:22 +00:00
|
|
|
ListInit *LI = 0;
|
2005-09-07 23:44:43 +00:00
|
|
|
|
2005-10-19 01:27:22 +00:00
|
|
|
if (dynamic_cast<ListInit*>(Instrs[i]->getValueInit("Pattern")))
|
|
|
|
LI = Instrs[i]->getValueAsListInit("Pattern");
|
|
|
|
|
|
|
|
// If there is no pattern, only collect minimal information about the
|
|
|
|
// instruction for its operand list. We have to assume that there is one
|
|
|
|
// result, as we have no detailed info.
|
|
|
|
if (!LI || LI->getSize() == 0) {
|
2005-12-01 00:06:14 +00:00
|
|
|
std::vector<Record*> Results;
|
|
|
|
std::vector<Record*> Operands;
|
2005-10-19 01:27:22 +00:00
|
|
|
|
|
|
|
CodeGenInstruction &InstInfo =Target.getInstruction(Instrs[i]->getName());
|
2005-12-04 08:18:16 +00:00
|
|
|
|
2005-12-22 02:35:21 +00:00
|
|
|
if (InstInfo.OperandList.size() != 0) {
|
|
|
|
// FIXME: temporary hack...
|
2005-12-26 09:11:45 +00:00
|
|
|
if (InstInfo.noResults) {
|
2005-12-22 02:35:21 +00:00
|
|
|
// These produce no results
|
|
|
|
for (unsigned j = 0, e = InstInfo.OperandList.size(); j < e; ++j)
|
|
|
|
Operands.push_back(InstInfo.OperandList[j].Rec);
|
|
|
|
} else {
|
|
|
|
// Assume the first operand is the result.
|
|
|
|
Results.push_back(InstInfo.OperandList[0].Rec);
|
2005-10-19 01:27:22 +00:00
|
|
|
|
2005-12-22 02:35:21 +00:00
|
|
|
// The rest are inputs.
|
|
|
|
for (unsigned j = 1, e = InstInfo.OperandList.size(); j < e; ++j)
|
|
|
|
Operands.push_back(InstInfo.OperandList[j].Rec);
|
|
|
|
}
|
2005-12-04 08:18:16 +00:00
|
|
|
}
|
2005-10-19 01:27:22 +00:00
|
|
|
|
|
|
|
// Create and insert the instruction.
|
2005-12-17 01:19:28 +00:00
|
|
|
std::vector<Record*> ImpResults;
|
|
|
|
std::vector<Record*> ImpOperands;
|
2005-10-19 01:27:22 +00:00
|
|
|
Instructions.insert(std::make_pair(Instrs[i],
|
2005-12-23 22:11:47 +00:00
|
|
|
DAGInstruction(0, Results, Operands, ImpResults,
|
|
|
|
ImpOperands)));
|
2005-10-19 01:27:22 +00:00
|
|
|
continue; // no pattern.
|
|
|
|
}
|
2005-09-07 23:44:43 +00:00
|
|
|
|
|
|
|
// Parse the instruction.
|
2005-10-21 01:19:59 +00:00
|
|
|
TreePattern *I = new TreePattern(Instrs[i], LI, true, *this);
|
2005-09-07 23:44:43 +00:00
|
|
|
// Inline pattern fragments into it.
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
I->InlinePatternFragments();
|
|
|
|
|
2005-09-08 23:26:30 +00:00
|
|
|
// Infer as many types as possible. If we cannot infer all of them, we can
|
|
|
|
// never do anything with this instruction pattern: report it to the user.
|
2005-09-15 21:42:00 +00:00
|
|
|
if (!I->InferAllTypes())
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
I->error("Could not infer all types in pattern!");
|
2005-09-09 01:11:44 +00:00
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
// InstInputs - Keep track of all of the inputs of the instruction, along
|
|
|
|
// with the record they are declared as.
|
|
|
|
std::map<std::string, TreePatternNode*> InstInputs;
|
|
|
|
|
|
|
|
// InstResults - Keep track of all the virtual registers that are 'set'
|
2005-09-14 02:11:12 +00:00
|
|
|
// in the instruction, including what reg class they are.
|
2006-03-20 06:04:09 +00:00
|
|
|
std::map<std::string, TreePatternNode*> InstResults;
|
2005-12-23 22:11:47 +00:00
|
|
|
|
|
|
|
std::vector<Record*> InstImpInputs;
|
2005-12-17 01:19:28 +00:00
|
|
|
std::vector<Record*> InstImpResults;
|
2005-09-14 20:53:42 +00:00
|
|
|
|
2005-09-14 00:09:24 +00:00
|
|
|
// Verify that the top-level forms in the instruction are of void type, and
|
2005-09-14 20:53:42 +00:00
|
|
|
// fill in the InstResults map.
|
2005-09-14 00:09:24 +00:00
|
|
|
for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
|
|
|
|
TreePatternNode *Pat = I->getTree(j);
|
2005-12-30 00:12:56 +00:00
|
|
|
if (Pat->getExtTypeNum(0) != MVT::isVoid)
|
2005-09-09 01:11:44 +00:00
|
|
|
I->error("Top-level forms in instruction pattern should have"
|
|
|
|
" void types");
|
2005-09-14 20:53:42 +00:00
|
|
|
|
|
|
|
// Find inputs and outputs, and verify the structure of the uses/defs.
|
2005-12-17 01:19:28 +00:00
|
|
|
FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,
|
2005-12-23 22:11:47 +00:00
|
|
|
InstImpInputs, InstImpResults);
|
2005-09-14 00:09:24 +00:00
|
|
|
}
|
2005-09-14 02:11:12 +00:00
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
// Now that we have inputs and outputs of the pattern, inspect the operands
|
|
|
|
// list for the instruction. This determines the order that operands are
|
|
|
|
// added to the machine instruction the node corresponds to.
|
|
|
|
unsigned NumResults = InstResults.size();
|
2005-09-14 18:19:25 +00:00
|
|
|
|
|
|
|
// Parse the operands list from the (ops) list, validating it.
|
|
|
|
std::vector<std::string> &Args = I->getArgList();
|
|
|
|
assert(Args.empty() && "Args list should still be empty here!");
|
|
|
|
CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]->getName());
|
|
|
|
|
|
|
|
// Check that all of the results occur first in the list.
|
2005-12-01 00:06:14 +00:00
|
|
|
std::vector<Record*> Results;
|
2006-03-20 06:04:09 +00:00
|
|
|
TreePatternNode *Res0Node = NULL;
|
2005-09-14 18:19:25 +00:00
|
|
|
for (unsigned i = 0; i != NumResults; ++i) {
|
2005-09-14 21:04:12 +00:00
|
|
|
if (i == CGI.OperandList.size())
|
2005-09-14 20:53:42 +00:00
|
|
|
I->error("'" + InstResults.begin()->first +
|
|
|
|
"' set but does not appear in operand list!");
|
2005-09-14 18:19:25 +00:00
|
|
|
const std::string &OpName = CGI.OperandList[i].Name;
|
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
// Check that it exists in InstResults.
|
2006-03-20 06:04:09 +00:00
|
|
|
TreePatternNode *RNode = InstResults[OpName];
|
2006-03-25 22:12:44 +00:00
|
|
|
if (RNode == 0)
|
|
|
|
I->error("Operand $" + OpName + " does not exist in operand list!");
|
|
|
|
|
2006-03-20 06:04:09 +00:00
|
|
|
if (i == 0)
|
|
|
|
Res0Node = RNode;
|
|
|
|
Record *R = dynamic_cast<DefInit*>(RNode->getLeafValue())->getDef();
|
2005-09-14 18:19:25 +00:00
|
|
|
if (R == 0)
|
|
|
|
I->error("Operand $" + OpName + " should be a set destination: all "
|
|
|
|
"outputs must occur before inputs in operand list!");
|
|
|
|
|
|
|
|
if (CGI.OperandList[i].Rec != R)
|
|
|
|
I->error("Operand $" + OpName + " class mismatch!");
|
|
|
|
|
2005-09-15 21:51:12 +00:00
|
|
|
// Remember the return type.
|
2005-12-01 00:06:14 +00:00
|
|
|
Results.push_back(CGI.OperandList[i].Rec);
|
2005-09-15 21:51:12 +00:00
|
|
|
|
2005-09-14 18:19:25 +00:00
|
|
|
// Okay, this one checks out.
|
2005-09-14 20:53:42 +00:00
|
|
|
InstResults.erase(OpName);
|
2005-09-14 18:19:25 +00:00
|
|
|
}
|
2005-09-14 02:11:12 +00:00
|
|
|
|
2005-09-14 21:59:34 +00:00
|
|
|
// Loop over the inputs next. Make a copy of InstInputs so we can destroy
|
|
|
|
// the copy while we're checking the inputs.
|
|
|
|
std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs);
|
2005-09-14 22:55:26 +00:00
|
|
|
|
|
|
|
std::vector<TreePatternNode*> ResultNodeOperands;
|
2005-12-01 00:06:14 +00:00
|
|
|
std::vector<Record*> Operands;
|
2005-09-14 20:53:42 +00:00
|
|
|
for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) {
|
2006-11-04 01:35:50 +00:00
|
|
|
CodeGenInstruction::OperandInfo &Op = CGI.OperandList[i];
|
|
|
|
const std::string &OpName = Op.Name;
|
2005-09-14 20:53:42 +00:00
|
|
|
if (OpName.empty())
|
|
|
|
I->error("Operand #" + utostr(i) + " in operands list has no name!");
|
|
|
|
|
2006-11-04 01:35:50 +00:00
|
|
|
if (!InstInputsCheck.count(OpName)) {
|
|
|
|
// If this is an predicate operand with an ExecuteAlways set filled in,
|
|
|
|
// we can ignore this. When we codegen it, we will do so as always
|
|
|
|
// executed.
|
|
|
|
if (Op.Rec->isSubClassOf("PredicateOperand")) {
|
|
|
|
// Does it have a non-empty ExecuteAlways field? If so, ignore this
|
|
|
|
// operand.
|
2006-11-04 05:12:02 +00:00
|
|
|
if (!getPredicateOperand(Op.Rec).AlwaysOps.empty())
|
2006-11-04 01:35:50 +00:00
|
|
|
continue;
|
|
|
|
}
|
2005-09-14 20:53:42 +00:00
|
|
|
I->error("Operand $" + OpName +
|
|
|
|
" does not appear in the instruction pattern");
|
2006-11-04 01:35:50 +00:00
|
|
|
}
|
2005-09-14 21:59:34 +00:00
|
|
|
TreePatternNode *InVal = InstInputsCheck[OpName];
|
2005-09-14 22:55:26 +00:00
|
|
|
InstInputsCheck.erase(OpName); // It occurred, remove from map.
|
2005-12-01 00:06:14 +00:00
|
|
|
|
|
|
|
if (InVal->isLeaf() &&
|
|
|
|
dynamic_cast<DefInit*>(InVal->getLeafValue())) {
|
|
|
|
Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
|
2006-11-04 01:35:50 +00:00
|
|
|
if (Op.Rec != InRec && !InRec->isSubClassOf("ComplexPattern"))
|
2006-01-28 19:06:51 +00:00
|
|
|
I->error("Operand $" + OpName + "'s register class disagrees"
|
|
|
|
" between the operand and pattern");
|
2005-12-01 00:06:14 +00:00
|
|
|
}
|
2006-11-04 01:35:50 +00:00
|
|
|
Operands.push_back(Op.Rec);
|
2005-09-14 22:55:26 +00:00
|
|
|
|
2005-09-14 23:01:59 +00:00
|
|
|
// Construct the result for the dest-pattern operand list.
|
|
|
|
TreePatternNode *OpNode = InVal->clone();
|
|
|
|
|
|
|
|
// No predicate is useful on the result.
|
|
|
|
OpNode->setPredicateFn("");
|
|
|
|
|
|
|
|
// Promote the xform function to be an explicit node if set.
|
|
|
|
if (Record *Xform = OpNode->getTransformFn()) {
|
|
|
|
OpNode->setTransformFn(0);
|
|
|
|
std::vector<TreePatternNode*> Children;
|
|
|
|
Children.push_back(OpNode);
|
|
|
|
OpNode = new TreePatternNode(Xform, Children);
|
|
|
|
}
|
|
|
|
|
|
|
|
ResultNodeOperands.push_back(OpNode);
|
2005-09-14 20:53:42 +00:00
|
|
|
}
|
|
|
|
|
2005-09-14 21:59:34 +00:00
|
|
|
if (!InstInputsCheck.empty())
|
|
|
|
I->error("Input operand $" + InstInputsCheck.begin()->first +
|
|
|
|
" occurs in pattern but not in operands list!");
|
2005-09-14 22:55:26 +00:00
|
|
|
|
|
|
|
TreePatternNode *ResultPattern =
|
|
|
|
new TreePatternNode(I->getRecord(), ResultNodeOperands);
|
2006-03-20 06:04:09 +00:00
|
|
|
// Copy fully inferred output node type to instruction result pattern.
|
|
|
|
if (NumResults > 0)
|
|
|
|
ResultPattern->setTypes(Res0Node->getExtTypes());
|
2005-09-15 22:23:50 +00:00
|
|
|
|
|
|
|
// Create and insert the instruction.
|
2005-12-23 22:11:47 +00:00
|
|
|
DAGInstruction TheInst(I, Results, Operands, InstImpResults, InstImpInputs);
|
2005-09-15 22:23:50 +00:00
|
|
|
Instructions.insert(std::make_pair(I->getRecord(), TheInst));
|
|
|
|
|
|
|
|
// Use a temporary tree pattern to infer all types and make sure that the
|
|
|
|
// constructed result is correct. This depends on the instruction already
|
|
|
|
// being inserted into the Instructions map.
|
2005-10-21 01:19:59 +00:00
|
|
|
TreePattern Temp(I->getRecord(), ResultPattern, false, *this);
|
2005-09-15 22:23:50 +00:00
|
|
|
Temp.InferAllTypes();
|
|
|
|
|
|
|
|
DAGInstruction &TheInsertedInst = Instructions.find(I->getRecord())->second;
|
|
|
|
TheInsertedInst.setResultPattern(Temp.getOnlyTree());
|
2005-09-14 22:55:26 +00:00
|
|
|
|
Implement a complete type inference system for dag patterns, based on the
constraints defined in the DAG node definitions in the .td files. This
allows us to infer (and check!) the types for all nodes in the current
ppc .td file. For example, instead of:
Inst pattern EQV: (set GPRC:i32:$rT, (xor (xor GPRC:i32:$rA, GPRC:i32:$rB), (imm)<<Predicate_immAllOnes>>))
we now fully infer:
Inst pattern EQV: (set:void GPRC:i32:$rT, (xor:i32 (xor:i32 GPRC:i32:$rA, GPRC:i32:$rB), (imm:i32)<<Predicate_immAllOnes>>))
from: (set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23284 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-08 23:22:48 +00:00
|
|
|
DEBUG(I->dump());
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
2005-09-14 00:09:24 +00:00
|
|
|
|
2005-09-14 20:53:42 +00:00
|
|
|
// If we can, convert the instructions to be patterns that are matched!
|
2005-09-15 21:57:35 +00:00
|
|
|
for (std::map<Record*, DAGInstruction>::iterator II = Instructions.begin(),
|
|
|
|
E = Instructions.end(); II != E; ++II) {
|
2005-12-04 08:18:16 +00:00
|
|
|
DAGInstruction &TheInst = II->second;
|
|
|
|
TreePattern *I = TheInst.getPattern();
|
2005-10-19 01:27:22 +00:00
|
|
|
if (I == 0) continue; // No pattern.
|
2005-12-05 23:08:55 +00:00
|
|
|
|
2005-09-14 00:09:24 +00:00
|
|
|
if (I->getNumTrees() != 1) {
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "CANNOT HANDLE: " << I->getRecord()->getName() << " yet!";
|
2005-09-14 00:09:24 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TreePatternNode *Pattern = I->getTree(0);
|
2005-12-04 08:18:16 +00:00
|
|
|
TreePatternNode *SrcPattern;
|
2005-12-17 01:19:28 +00:00
|
|
|
if (Pattern->getOperator()->getName() == "set") {
|
2005-12-04 08:18:16 +00:00
|
|
|
if (Pattern->getNumChildren() != 2)
|
|
|
|
continue; // Not a set of a single value (not handled so far)
|
|
|
|
|
|
|
|
SrcPattern = Pattern->getChild(1)->clone();
|
2005-12-17 01:19:28 +00:00
|
|
|
} else{
|
|
|
|
// Not a set (store or something?)
|
|
|
|
SrcPattern = Pattern;
|
2005-12-04 08:18:16 +00:00
|
|
|
}
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
|
|
|
|
std::string Reason;
|
|
|
|
if (!SrcPattern->canPatternMatch(Reason, *this))
|
|
|
|
I->error("Instruction can never match: " + Reason);
|
|
|
|
|
2005-12-14 22:02:59 +00:00
|
|
|
Record *Instr = II->first;
|
2005-12-04 08:18:16 +00:00
|
|
|
TreePatternNode *DstPattern = TheInst.getResultPattern();
|
2005-12-14 22:02:59 +00:00
|
|
|
PatternsToMatch.
|
|
|
|
push_back(PatternToMatch(Instr->getValueAsListInit("Predicates"),
|
2006-04-19 18:07:24 +00:00
|
|
|
SrcPattern, DstPattern,
|
2006-04-19 20:36:09 +00:00
|
|
|
Instr->getValueAsInt("AddedComplexity")));
|
2005-09-14 00:09:24 +00:00
|
|
|
}
|
2005-09-07 23:44:43 +00:00
|
|
|
}
|
|
|
|
|
2005-09-15 02:38:02 +00:00
|
|
|
void DAGISelEmitter::ParsePatterns() {
|
2005-09-15 21:42:00 +00:00
|
|
|
std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern");
|
2005-09-15 02:38:02 +00:00
|
|
|
|
2005-09-15 21:42:00 +00:00
|
|
|
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
|
2005-09-15 22:23:50 +00:00
|
|
|
DagInit *Tree = Patterns[i]->getValueAsDag("PatternToMatch");
|
2005-10-21 01:19:59 +00:00
|
|
|
TreePattern *Pattern = new TreePattern(Patterns[i], Tree, true, *this);
|
2005-09-15 02:38:02 +00:00
|
|
|
|
2005-09-15 21:42:00 +00:00
|
|
|
// Inline pattern fragments into it.
|
|
|
|
Pattern->InlinePatternFragments();
|
|
|
|
|
|
|
|
ListInit *LI = Patterns[i]->getValueAsListInit("ResultInstrs");
|
|
|
|
if (LI->getSize() == 0) continue; // no pattern.
|
|
|
|
|
|
|
|
// Parse the instruction.
|
2005-10-21 01:19:59 +00:00
|
|
|
TreePattern *Result = new TreePattern(Patterns[i], LI, false, *this);
|
2005-09-15 21:42:00 +00:00
|
|
|
|
|
|
|
// Inline pattern fragments into it.
|
|
|
|
Result->InlinePatternFragments();
|
2006-06-20 00:18:02 +00:00
|
|
|
|
2005-09-15 21:42:00 +00:00
|
|
|
if (Result->getNumTrees() != 1)
|
|
|
|
Result->error("Cannot handle instructions producing instructions "
|
|
|
|
"with temporaries yet!");
|
2006-06-20 00:18:02 +00:00
|
|
|
|
|
|
|
bool IterateInference;
|
2006-06-20 00:31:27 +00:00
|
|
|
bool InferredAllPatternTypes, InferredAllResultTypes;
|
2006-06-20 00:18:02 +00:00
|
|
|
do {
|
|
|
|
// Infer as many types as possible. If we cannot infer all of them, we
|
|
|
|
// can never do anything with this pattern: report it to the user.
|
2006-06-20 00:31:27 +00:00
|
|
|
InferredAllPatternTypes = Pattern->InferAllTypes();
|
2006-06-20 00:18:02 +00:00
|
|
|
|
2006-09-21 18:28:27 +00:00
|
|
|
// Infer as many types as possible. If we cannot infer all of them, we
|
|
|
|
// can never do anything with this pattern: report it to the user.
|
2006-06-20 00:31:27 +00:00
|
|
|
InferredAllResultTypes = Result->InferAllTypes();
|
|
|
|
|
2006-06-20 00:18:02 +00:00
|
|
|
// Apply the type of the result to the source pattern. This helps us
|
|
|
|
// resolve cases where the input type is known to be a pointer type (which
|
|
|
|
// is considered resolved), but the result knows it needs to be 32- or
|
|
|
|
// 64-bits. Infer the other way for good measure.
|
|
|
|
IterateInference = Pattern->getOnlyTree()->
|
|
|
|
UpdateNodeType(Result->getOnlyTree()->getExtTypes(), *Result);
|
|
|
|
IterateInference |= Result->getOnlyTree()->
|
|
|
|
UpdateNodeType(Pattern->getOnlyTree()->getExtTypes(), *Result);
|
|
|
|
} while (IterateInference);
|
2006-06-20 00:31:27 +00:00
|
|
|
|
|
|
|
// Verify that we inferred enough types that we can do something with the
|
|
|
|
// pattern and result. If these fire the user has to add type casts.
|
|
|
|
if (!InferredAllPatternTypes)
|
|
|
|
Pattern->error("Could not infer all types in pattern!");
|
|
|
|
if (!InferredAllResultTypes)
|
|
|
|
Result->error("Could not infer all types in pattern result!");
|
2006-06-20 00:18:02 +00:00
|
|
|
|
|
|
|
// Validate that the input pattern is correct.
|
|
|
|
{
|
|
|
|
std::map<std::string, TreePatternNode*> InstInputs;
|
|
|
|
std::map<std::string, TreePatternNode*> InstResults;
|
|
|
|
std::vector<Record*> InstImpInputs;
|
|
|
|
std::vector<Record*> InstImpResults;
|
|
|
|
FindPatternInputsAndOutputs(Pattern, Pattern->getOnlyTree(),
|
|
|
|
InstInputs, InstResults,
|
|
|
|
InstImpInputs, InstImpResults);
|
|
|
|
}
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
|
2006-03-21 20:44:17 +00:00
|
|
|
// Promote the xform function to be an explicit node if set.
|
|
|
|
std::vector<TreePatternNode*> ResultNodeOperands;
|
|
|
|
TreePatternNode *DstPattern = Result->getOnlyTree();
|
|
|
|
for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) {
|
|
|
|
TreePatternNode *OpNode = DstPattern->getChild(ii);
|
|
|
|
if (Record *Xform = OpNode->getTransformFn()) {
|
|
|
|
OpNode->setTransformFn(0);
|
|
|
|
std::vector<TreePatternNode*> Children;
|
|
|
|
Children.push_back(OpNode);
|
|
|
|
OpNode = new TreePatternNode(Xform, Children);
|
|
|
|
}
|
|
|
|
ResultNodeOperands.push_back(OpNode);
|
|
|
|
}
|
2006-03-23 02:35:32 +00:00
|
|
|
DstPattern = Result->getOnlyTree();
|
|
|
|
if (!DstPattern->isLeaf())
|
|
|
|
DstPattern = new TreePatternNode(DstPattern->getOperator(),
|
|
|
|
ResultNodeOperands);
|
2006-03-21 20:44:17 +00:00
|
|
|
DstPattern->setTypes(Result->getOnlyTree()->getExtTypes());
|
|
|
|
TreePattern Temp(Result->getRecord(), DstPattern, false, *this);
|
|
|
|
Temp.InferAllTypes();
|
|
|
|
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
std::string Reason;
|
|
|
|
if (!Pattern->getOnlyTree()->canPatternMatch(Reason, *this))
|
|
|
|
Pattern->error("Pattern can never match: " + Reason);
|
|
|
|
|
2005-12-14 22:02:59 +00:00
|
|
|
PatternsToMatch.
|
|
|
|
push_back(PatternToMatch(Patterns[i]->getValueAsListInit("Predicates"),
|
|
|
|
Pattern->getOnlyTree(),
|
2006-04-19 18:07:24 +00:00
|
|
|
Temp.getOnlyTree(),
|
2006-04-19 20:36:09 +00:00
|
|
|
Patterns[i]->getValueAsInt("AddedComplexity")));
|
2005-09-15 21:42:00 +00:00
|
|
|
}
|
2005-09-29 19:28:10 +00:00
|
|
|
}
|
2005-09-15 02:38:02 +00:00
|
|
|
|
2005-09-29 19:28:10 +00:00
|
|
|
/// CombineChildVariants - Given a bunch of permutations of each child of the
|
|
|
|
/// 'operator' node, put them together in all possible ways.
|
|
|
|
static void CombineChildVariants(TreePatternNode *Orig,
|
2005-09-29 22:36:54 +00:00
|
|
|
const std::vector<std::vector<TreePatternNode*> > &ChildVariants,
|
2005-09-29 19:28:10 +00:00
|
|
|
std::vector<TreePatternNode*> &OutVariants,
|
|
|
|
DAGISelEmitter &ISE) {
|
2005-09-29 22:36:54 +00:00
|
|
|
// Make sure that each operand has at least one variant to choose from.
|
|
|
|
for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
|
|
|
|
if (ChildVariants[i].empty())
|
|
|
|
return;
|
|
|
|
|
2005-09-29 19:28:10 +00:00
|
|
|
// The end result is an all-pairs construction of the resultant pattern.
|
|
|
|
std::vector<unsigned> Idxs;
|
|
|
|
Idxs.resize(ChildVariants.size());
|
|
|
|
bool NotDone = true;
|
|
|
|
while (NotDone) {
|
|
|
|
// Create the variant and add it to the output list.
|
|
|
|
std::vector<TreePatternNode*> NewChildren;
|
|
|
|
for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
|
|
|
|
NewChildren.push_back(ChildVariants[i][Idxs[i]]);
|
|
|
|
TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren);
|
|
|
|
|
|
|
|
// Copy over properties.
|
|
|
|
R->setName(Orig->getName());
|
|
|
|
R->setPredicateFn(Orig->getPredicateFn());
|
|
|
|
R->setTransformFn(Orig->getTransformFn());
|
2005-12-30 00:12:56 +00:00
|
|
|
R->setTypes(Orig->getExtTypes());
|
2005-09-29 19:28:10 +00:00
|
|
|
|
|
|
|
// If this pattern cannot every match, do not include it as a variant.
|
|
|
|
std::string ErrString;
|
|
|
|
if (!R->canPatternMatch(ErrString, ISE)) {
|
|
|
|
delete R;
|
|
|
|
} else {
|
|
|
|
bool AlreadyExists = false;
|
|
|
|
|
|
|
|
// Scan to see if this pattern has already been emitted. We can get
|
|
|
|
// duplication due to things like commuting:
|
|
|
|
// (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
|
|
|
|
// which are the same pattern. Ignore the dups.
|
|
|
|
for (unsigned i = 0, e = OutVariants.size(); i != e; ++i)
|
|
|
|
if (R->isIsomorphicTo(OutVariants[i])) {
|
|
|
|
AlreadyExists = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (AlreadyExists)
|
|
|
|
delete R;
|
|
|
|
else
|
|
|
|
OutVariants.push_back(R);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Increment indices to the next permutation.
|
|
|
|
NotDone = false;
|
|
|
|
// Look for something we can increment without causing a wrap-around.
|
|
|
|
for (unsigned IdxsIdx = 0; IdxsIdx != Idxs.size(); ++IdxsIdx) {
|
|
|
|
if (++Idxs[IdxsIdx] < ChildVariants[IdxsIdx].size()) {
|
|
|
|
NotDone = true; // Found something to increment.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Idxs[IdxsIdx] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-29 22:36:54 +00:00
|
|
|
/// CombineChildVariants - A helper function for binary operators.
|
|
|
|
///
|
|
|
|
static void CombineChildVariants(TreePatternNode *Orig,
|
|
|
|
const std::vector<TreePatternNode*> &LHS,
|
|
|
|
const std::vector<TreePatternNode*> &RHS,
|
|
|
|
std::vector<TreePatternNode*> &OutVariants,
|
|
|
|
DAGISelEmitter &ISE) {
|
|
|
|
std::vector<std::vector<TreePatternNode*> > ChildVariants;
|
|
|
|
ChildVariants.push_back(LHS);
|
|
|
|
ChildVariants.push_back(RHS);
|
|
|
|
CombineChildVariants(Orig, ChildVariants, OutVariants, ISE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void GatherChildrenOfAssociativeOpcode(TreePatternNode *N,
|
|
|
|
std::vector<TreePatternNode *> &Children) {
|
|
|
|
assert(N->getNumChildren()==2 &&"Associative but doesn't have 2 children!");
|
|
|
|
Record *Operator = N->getOperator();
|
|
|
|
|
|
|
|
// Only permit raw nodes.
|
|
|
|
if (!N->getName().empty() || !N->getPredicateFn().empty() ||
|
|
|
|
N->getTransformFn()) {
|
|
|
|
Children.push_back(N);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (N->getChild(0)->isLeaf() || N->getChild(0)->getOperator() != Operator)
|
|
|
|
Children.push_back(N->getChild(0));
|
|
|
|
else
|
|
|
|
GatherChildrenOfAssociativeOpcode(N->getChild(0), Children);
|
|
|
|
|
|
|
|
if (N->getChild(1)->isLeaf() || N->getChild(1)->getOperator() != Operator)
|
|
|
|
Children.push_back(N->getChild(1));
|
|
|
|
else
|
|
|
|
GatherChildrenOfAssociativeOpcode(N->getChild(1), Children);
|
|
|
|
}
|
|
|
|
|
2005-09-29 19:28:10 +00:00
|
|
|
/// GenerateVariantsOf - Given a pattern N, generate all permutations we can of
|
|
|
|
/// the (potentially recursive) pattern by using algebraic laws.
|
|
|
|
///
|
|
|
|
static void GenerateVariantsOf(TreePatternNode *N,
|
|
|
|
std::vector<TreePatternNode*> &OutVariants,
|
|
|
|
DAGISelEmitter &ISE) {
|
|
|
|
// We cannot permute leaves.
|
|
|
|
if (N->isLeaf()) {
|
|
|
|
OutVariants.push_back(N);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look up interesting info about the node.
|
2006-03-24 23:10:39 +00:00
|
|
|
const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(N->getOperator());
|
2005-09-29 19:28:10 +00:00
|
|
|
|
|
|
|
// If this node is associative, reassociate.
|
2006-10-11 21:02:01 +00:00
|
|
|
if (NodeInfo.hasProperty(SDNPAssociative)) {
|
2005-09-29 22:36:54 +00:00
|
|
|
// Reassociate by pulling together all of the linked operators
|
|
|
|
std::vector<TreePatternNode*> MaximalChildren;
|
|
|
|
GatherChildrenOfAssociativeOpcode(N, MaximalChildren);
|
|
|
|
|
|
|
|
// Only handle child sizes of 3. Otherwise we'll end up trying too many
|
|
|
|
// permutations.
|
|
|
|
if (MaximalChildren.size() == 3) {
|
|
|
|
// Find the variants of all of our maximal children.
|
|
|
|
std::vector<TreePatternNode*> AVariants, BVariants, CVariants;
|
|
|
|
GenerateVariantsOf(MaximalChildren[0], AVariants, ISE);
|
|
|
|
GenerateVariantsOf(MaximalChildren[1], BVariants, ISE);
|
|
|
|
GenerateVariantsOf(MaximalChildren[2], CVariants, ISE);
|
|
|
|
|
|
|
|
// There are only two ways we can permute the tree:
|
|
|
|
// (A op B) op C and A op (B op C)
|
|
|
|
// Within these forms, we can also permute A/B/C.
|
|
|
|
|
|
|
|
// Generate legal pair permutations of A/B/C.
|
|
|
|
std::vector<TreePatternNode*> ABVariants;
|
|
|
|
std::vector<TreePatternNode*> BAVariants;
|
|
|
|
std::vector<TreePatternNode*> ACVariants;
|
|
|
|
std::vector<TreePatternNode*> CAVariants;
|
|
|
|
std::vector<TreePatternNode*> BCVariants;
|
|
|
|
std::vector<TreePatternNode*> CBVariants;
|
|
|
|
CombineChildVariants(N, AVariants, BVariants, ABVariants, ISE);
|
|
|
|
CombineChildVariants(N, BVariants, AVariants, BAVariants, ISE);
|
|
|
|
CombineChildVariants(N, AVariants, CVariants, ACVariants, ISE);
|
|
|
|
CombineChildVariants(N, CVariants, AVariants, CAVariants, ISE);
|
|
|
|
CombineChildVariants(N, BVariants, CVariants, BCVariants, ISE);
|
|
|
|
CombineChildVariants(N, CVariants, BVariants, CBVariants, ISE);
|
|
|
|
|
|
|
|
// Combine those into the result: (x op x) op x
|
|
|
|
CombineChildVariants(N, ABVariants, CVariants, OutVariants, ISE);
|
|
|
|
CombineChildVariants(N, BAVariants, CVariants, OutVariants, ISE);
|
|
|
|
CombineChildVariants(N, ACVariants, BVariants, OutVariants, ISE);
|
|
|
|
CombineChildVariants(N, CAVariants, BVariants, OutVariants, ISE);
|
|
|
|
CombineChildVariants(N, BCVariants, AVariants, OutVariants, ISE);
|
|
|
|
CombineChildVariants(N, CBVariants, AVariants, OutVariants, ISE);
|
|
|
|
|
|
|
|
// Combine those into the result: x op (x op x)
|
|
|
|
CombineChildVariants(N, CVariants, ABVariants, OutVariants, ISE);
|
|
|
|
CombineChildVariants(N, CVariants, BAVariants, OutVariants, ISE);
|
|
|
|
CombineChildVariants(N, BVariants, ACVariants, OutVariants, ISE);
|
|
|
|
CombineChildVariants(N, BVariants, CAVariants, OutVariants, ISE);
|
|
|
|
CombineChildVariants(N, AVariants, BCVariants, OutVariants, ISE);
|
|
|
|
CombineChildVariants(N, AVariants, CBVariants, OutVariants, ISE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2005-09-29 19:28:10 +00:00
|
|
|
|
|
|
|
// Compute permutations of all children.
|
|
|
|
std::vector<std::vector<TreePatternNode*> > ChildVariants;
|
|
|
|
ChildVariants.resize(N->getNumChildren());
|
|
|
|
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
|
|
|
|
GenerateVariantsOf(N->getChild(i), ChildVariants[i], ISE);
|
|
|
|
|
|
|
|
// Build all permutations based on how the children were formed.
|
|
|
|
CombineChildVariants(N, ChildVariants, OutVariants, ISE);
|
|
|
|
|
|
|
|
// If this node is commutative, consider the commuted order.
|
2006-10-11 21:02:01 +00:00
|
|
|
if (NodeInfo.hasProperty(SDNPCommutative)) {
|
2005-09-29 19:28:10 +00:00
|
|
|
assert(N->getNumChildren()==2 &&"Commutative but doesn't have 2 children!");
|
2006-08-09 16:44:44 +00:00
|
|
|
// Don't count children which are actually register references.
|
|
|
|
unsigned NC = 0;
|
|
|
|
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
|
|
|
|
TreePatternNode *Child = N->getChild(i);
|
|
|
|
if (Child->isLeaf())
|
|
|
|
if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
|
|
|
|
Record *RR = DI->getDef();
|
|
|
|
if (RR->isSubClassOf("Register"))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
NC++;
|
|
|
|
}
|
2005-09-29 22:36:54 +00:00
|
|
|
// Consider the commuted order.
|
2006-08-09 16:44:44 +00:00
|
|
|
if (NC == 2)
|
|
|
|
CombineChildVariants(N, ChildVariants[1], ChildVariants[0],
|
|
|
|
OutVariants, ISE);
|
2005-09-29 19:28:10 +00:00
|
|
|
}
|
2005-09-15 02:38:02 +00:00
|
|
|
}
|
|
|
|
|
2005-09-29 19:28:10 +00:00
|
|
|
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
// GenerateVariants - Generate variants. For example, commutative patterns can
|
|
|
|
// match multiple ways. Add them to PatternsToMatch as well.
|
|
|
|
void DAGISelEmitter::GenerateVariants() {
|
2005-09-29 19:28:10 +00:00
|
|
|
|
2006-12-07 22:21:48 +00:00
|
|
|
DOUT << "Generating instruction variants.\n";
|
2005-09-29 19:28:10 +00:00
|
|
|
|
|
|
|
// Loop over all of the patterns we've collected, checking to see if we can
|
|
|
|
// generate variants of the instruction, through the exploitation of
|
|
|
|
// identities. This permits the target to provide agressive matching without
|
|
|
|
// the .td file having to contain tons of variants of instructions.
|
|
|
|
//
|
|
|
|
// Note that this loop adds new patterns to the PatternsToMatch list, but we
|
|
|
|
// intentionally do not reconsider these. Any variants of added patterns have
|
|
|
|
// already been added.
|
|
|
|
//
|
|
|
|
for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
|
|
|
|
std::vector<TreePatternNode*> Variants;
|
2005-12-14 22:02:59 +00:00
|
|
|
GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this);
|
2005-09-29 19:28:10 +00:00
|
|
|
|
|
|
|
assert(!Variants.empty() && "Must create at least original variant!");
|
|
|
|
Variants.erase(Variants.begin()); // Remove the original pattern.
|
|
|
|
|
|
|
|
if (Variants.empty()) // No variants for this pattern.
|
|
|
|
continue;
|
|
|
|
|
2006-12-07 22:21:48 +00:00
|
|
|
DOUT << "FOUND VARIANTS OF: ";
|
|
|
|
DEBUG(PatternsToMatch[i].getSrcPattern()->dump());
|
|
|
|
DOUT << "\n";
|
2005-09-29 19:28:10 +00:00
|
|
|
|
|
|
|
for (unsigned v = 0, e = Variants.size(); v != e; ++v) {
|
|
|
|
TreePatternNode *Variant = Variants[v];
|
|
|
|
|
2006-12-07 22:21:48 +00:00
|
|
|
DOUT << " VAR#" << v << ": ";
|
|
|
|
DEBUG(Variant->dump());
|
|
|
|
DOUT << "\n";
|
2005-09-29 19:28:10 +00:00
|
|
|
|
|
|
|
// Scan to see if an instruction or explicit pattern already matches this.
|
|
|
|
bool AlreadyExists = false;
|
|
|
|
for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) {
|
|
|
|
// Check to see if this variant already exists.
|
2005-12-14 22:02:59 +00:00
|
|
|
if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern())) {
|
2006-12-07 22:21:48 +00:00
|
|
|
DOUT << " *** ALREADY EXISTS, ignoring variant.\n";
|
2005-09-29 19:28:10 +00:00
|
|
|
AlreadyExists = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If we already have it, ignore the variant.
|
|
|
|
if (AlreadyExists) continue;
|
|
|
|
|
|
|
|
// Otherwise, add it to the list of patterns we have.
|
2005-12-14 22:02:59 +00:00
|
|
|
PatternsToMatch.
|
|
|
|
push_back(PatternToMatch(PatternsToMatch[i].getPredicates(),
|
2006-04-19 18:07:24 +00:00
|
|
|
Variant, PatternsToMatch[i].getDstPattern(),
|
2006-04-19 20:36:09 +00:00
|
|
|
PatternsToMatch[i].getAddedComplexity()));
|
2005-09-29 19:28:10 +00:00
|
|
|
}
|
|
|
|
|
2006-12-07 22:21:48 +00:00
|
|
|
DOUT << "\n";
|
2005-09-29 19:28:10 +00:00
|
|
|
}
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 02:00:36 +00:00
|
|
|
// NodeIsComplexPattern - return true if N is a leaf node and a subclass of
|
|
|
|
// ComplexPattern.
|
|
|
|
static bool NodeIsComplexPattern(TreePatternNode *N)
|
|
|
|
{
|
|
|
|
return (N->isLeaf() &&
|
|
|
|
dynamic_cast<DefInit*>(N->getLeafValue()) &&
|
|
|
|
static_cast<DefInit*>(N->getLeafValue())->getDef()->
|
|
|
|
isSubClassOf("ComplexPattern"));
|
|
|
|
}
|
|
|
|
|
|
|
|
// NodeGetComplexPattern - return the pointer to the ComplexPattern if N
|
|
|
|
// is a leaf node and a subclass of ComplexPattern, else it returns NULL.
|
|
|
|
static const ComplexPattern *NodeGetComplexPattern(TreePatternNode *N,
|
|
|
|
DAGISelEmitter &ISE)
|
|
|
|
{
|
|
|
|
if (N->isLeaf() &&
|
|
|
|
dynamic_cast<DefInit*>(N->getLeafValue()) &&
|
|
|
|
static_cast<DefInit*>(N->getLeafValue())->getDef()->
|
|
|
|
isSubClassOf("ComplexPattern")) {
|
|
|
|
return &ISE.getComplexPattern(static_cast<DefInit*>(N->getLeafValue())
|
|
|
|
->getDef());
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-09-28 17:57:56 +00:00
|
|
|
/// getPatternSize - Return the 'size' of this pattern. We want to match large
|
|
|
|
/// patterns before small ones. This is used to determine the size of a
|
|
|
|
/// pattern.
|
2005-12-08 02:00:36 +00:00
|
|
|
static unsigned getPatternSize(TreePatternNode *P, DAGISelEmitter &ISE) {
|
2006-05-17 20:37:59 +00:00
|
|
|
assert((isExtIntegerInVTs(P->getExtTypes()) ||
|
|
|
|
isExtFloatingPointInVTs(P->getExtTypes()) ||
|
|
|
|
P->getExtTypeNum(0) == MVT::isVoid ||
|
|
|
|
P->getExtTypeNum(0) == MVT::Flag ||
|
|
|
|
P->getExtTypeNum(0) == MVT::iPTR) &&
|
2006-01-06 22:19:44 +00:00
|
|
|
"Not a valid pattern node to size!");
|
2006-09-08 07:26:39 +00:00
|
|
|
unsigned Size = 3; // The node itself.
|
2006-02-01 06:06:31 +00:00
|
|
|
// If the root node is a ConstantSDNode, increases its size.
|
|
|
|
// e.g. (set R32:$dst, 0).
|
|
|
|
if (P->isLeaf() && dynamic_cast<IntInit*>(P->getLeafValue()))
|
2006-09-08 07:26:39 +00:00
|
|
|
Size += 2;
|
2005-12-08 02:00:36 +00:00
|
|
|
|
|
|
|
// FIXME: This is a hack to statically increase the priority of patterns
|
|
|
|
// which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD.
|
|
|
|
// Later we can allow complexity / cost for each pattern to be (optionally)
|
|
|
|
// specified. To get best possible pattern match we'll need to dynamically
|
|
|
|
// calculate the complexity of all patterns a dag can potentially map to.
|
|
|
|
const ComplexPattern *AM = NodeGetComplexPattern(P, ISE);
|
|
|
|
if (AM)
|
2006-09-08 07:26:39 +00:00
|
|
|
Size += AM->getNumOperands() * 3;
|
2006-02-03 18:06:02 +00:00
|
|
|
|
|
|
|
// If this node has some predicate function that must match, it adds to the
|
|
|
|
// complexity of this node.
|
|
|
|
if (!P->getPredicateFn().empty())
|
|
|
|
++Size;
|
|
|
|
|
2005-09-28 17:57:56 +00:00
|
|
|
// Count children in the count if they are also nodes.
|
|
|
|
for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) {
|
|
|
|
TreePatternNode *Child = P->getChild(i);
|
2005-12-30 00:12:56 +00:00
|
|
|
if (!Child->isLeaf() && Child->getExtTypeNum(0) != MVT::Other)
|
2005-12-08 02:00:36 +00:00
|
|
|
Size += getPatternSize(Child, ISE);
|
|
|
|
else if (Child->isLeaf()) {
|
|
|
|
if (dynamic_cast<IntInit*>(Child->getLeafValue()))
|
2006-09-08 07:26:39 +00:00
|
|
|
Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
|
2006-01-06 22:19:44 +00:00
|
|
|
else if (NodeIsComplexPattern(Child))
|
|
|
|
Size += getPatternSize(Child, ISE);
|
2006-02-03 18:06:02 +00:00
|
|
|
else if (!Child->getPredicateFn().empty())
|
|
|
|
++Size;
|
2005-10-19 04:41:05 +00:00
|
|
|
}
|
2005-09-28 17:57:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return Size;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getResultPatternCost - Compute the number of instructions for this pattern.
|
|
|
|
/// This is a temporary hack. We should really include the instruction
|
|
|
|
/// latencies in this calculation.
|
2006-02-18 02:33:09 +00:00
|
|
|
static unsigned getResultPatternCost(TreePatternNode *P, DAGISelEmitter &ISE) {
|
2005-09-28 17:57:56 +00:00
|
|
|
if (P->isLeaf()) return 0;
|
|
|
|
|
2006-02-18 02:33:09 +00:00
|
|
|
unsigned Cost = 0;
|
|
|
|
Record *Op = P->getOperator();
|
|
|
|
if (Op->isSubClassOf("Instruction")) {
|
|
|
|
Cost++;
|
|
|
|
CodeGenInstruction &II = ISE.getTargetInfo().getInstruction(Op->getName());
|
|
|
|
if (II.usesCustomDAGSchedInserter)
|
|
|
|
Cost += 10;
|
|
|
|
}
|
2005-09-28 17:57:56 +00:00
|
|
|
for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
|
2006-02-18 02:33:09 +00:00
|
|
|
Cost += getResultPatternCost(P->getChild(i), ISE);
|
2005-09-28 17:57:56 +00:00
|
|
|
return Cost;
|
|
|
|
}
|
|
|
|
|
2006-07-19 00:24:41 +00:00
|
|
|
/// getResultPatternCodeSize - Compute the code size of instructions for this
|
|
|
|
/// pattern.
|
|
|
|
static unsigned getResultPatternSize(TreePatternNode *P, DAGISelEmitter &ISE) {
|
|
|
|
if (P->isLeaf()) return 0;
|
|
|
|
|
|
|
|
unsigned Cost = 0;
|
|
|
|
Record *Op = P->getOperator();
|
|
|
|
if (Op->isSubClassOf("Instruction")) {
|
|
|
|
Cost += Op->getValueAsInt("CodeSize");
|
|
|
|
}
|
|
|
|
for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
|
|
|
|
Cost += getResultPatternSize(P->getChild(i), ISE);
|
|
|
|
return Cost;
|
|
|
|
}
|
|
|
|
|
2005-09-28 17:57:56 +00:00
|
|
|
// PatternSortingPredicate - return true if we prefer to match LHS before RHS.
|
|
|
|
// In particular, we want to match maximal patterns first and lowest cost within
|
|
|
|
// a particular complexity first.
|
|
|
|
struct PatternSortingPredicate {
|
2005-12-08 02:00:36 +00:00
|
|
|
PatternSortingPredicate(DAGISelEmitter &ise) : ISE(ise) {};
|
|
|
|
DAGISelEmitter &ISE;
|
|
|
|
|
2005-12-14 22:02:59 +00:00
|
|
|
bool operator()(PatternToMatch *LHS,
|
|
|
|
PatternToMatch *RHS) {
|
|
|
|
unsigned LHSSize = getPatternSize(LHS->getSrcPattern(), ISE);
|
|
|
|
unsigned RHSSize = getPatternSize(RHS->getSrcPattern(), ISE);
|
2006-04-19 20:36:09 +00:00
|
|
|
LHSSize += LHS->getAddedComplexity();
|
|
|
|
RHSSize += RHS->getAddedComplexity();
|
2005-09-28 17:57:56 +00:00
|
|
|
if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
|
|
|
|
if (LHSSize < RHSSize) return false;
|
|
|
|
|
|
|
|
// If the patterns have equal complexity, compare generated instruction cost
|
2006-07-19 00:24:41 +00:00
|
|
|
unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), ISE);
|
|
|
|
unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), ISE);
|
|
|
|
if (LHSCost < RHSCost) return true;
|
|
|
|
if (LHSCost > RHSCost) return false;
|
|
|
|
|
|
|
|
return getResultPatternSize(LHS->getDstPattern(), ISE) <
|
|
|
|
getResultPatternSize(RHS->getDstPattern(), ISE);
|
2005-09-28 17:57:56 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2005-12-09 22:45:35 +00:00
|
|
|
/// getRegisterValueType - Look up and return the first ValueType of specified
|
|
|
|
/// RegisterClass record
|
|
|
|
static MVT::ValueType getRegisterValueType(Record *R, const CodeGenTarget &T) {
|
|
|
|
if (const CodeGenRegisterClass *RC = T.getRegisterClassForRegister(R))
|
|
|
|
return RC->getValueTypeNum(0);
|
|
|
|
return MVT::Other;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// RemoveAllTypes - A quick recursive walk over a pattern which removes all
|
|
|
|
/// type information from it.
|
|
|
|
static void RemoveAllTypes(TreePatternNode *N) {
|
2005-12-30 00:12:56 +00:00
|
|
|
N->removeTypes();
|
2005-12-09 22:45:35 +00:00
|
|
|
if (!N->isLeaf())
|
|
|
|
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
|
|
|
|
RemoveAllTypes(N->getChild(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
Record *DAGISelEmitter::getSDNodeNamed(const std::string &Name) const {
|
|
|
|
Record *N = Records.getDef(Name);
|
2006-03-24 23:10:39 +00:00
|
|
|
if (!N || !N->isSubClassOf("SDNode")) {
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "Error getting SDNode '" << Name << "'!\n";
|
2006-03-24 23:10:39 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2005-12-09 22:45:35 +00:00
|
|
|
return N;
|
|
|
|
}
|
|
|
|
|
2006-01-09 18:27:06 +00:00
|
|
|
/// NodeHasProperty - return true if TreePatternNode has the specified
|
|
|
|
/// property.
|
2006-10-11 21:02:01 +00:00
|
|
|
static bool NodeHasProperty(TreePatternNode *N, SDNP Property,
|
2006-01-09 18:27:06 +00:00
|
|
|
DAGISelEmitter &ISE)
|
2005-12-23 22:11:47 +00:00
|
|
|
{
|
2006-10-11 21:02:01 +00:00
|
|
|
if (N->isLeaf()) {
|
|
|
|
const ComplexPattern *CP = NodeGetComplexPattern(N, ISE);
|
|
|
|
if (CP)
|
|
|
|
return CP->hasProperty(Property);
|
|
|
|
return false;
|
|
|
|
}
|
2005-12-23 22:11:47 +00:00
|
|
|
Record *Operator = N->getOperator();
|
|
|
|
if (!Operator->isSubClassOf("SDNode")) return false;
|
|
|
|
|
|
|
|
const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(Operator);
|
2006-01-09 18:27:06 +00:00
|
|
|
return NodeInfo.hasProperty(Property);
|
2005-12-23 22:11:47 +00:00
|
|
|
}
|
|
|
|
|
2006-10-11 21:02:01 +00:00
|
|
|
static bool PatternHasProperty(TreePatternNode *N, SDNP Property,
|
2006-01-09 18:27:06 +00:00
|
|
|
DAGISelEmitter &ISE)
|
2005-12-23 22:11:47 +00:00
|
|
|
{
|
2006-01-09 18:27:06 +00:00
|
|
|
if (NodeHasProperty(N, Property, ISE))
|
2005-12-23 22:11:47 +00:00
|
|
|
return true;
|
2006-01-09 18:27:06 +00:00
|
|
|
|
|
|
|
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
|
|
|
|
TreePatternNode *Child = N->getChild(i);
|
|
|
|
if (PatternHasProperty(Child, Property, ISE))
|
|
|
|
return true;
|
2005-12-23 22:11:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-12-09 22:45:35 +00:00
|
|
|
class PatternCodeEmitter {
|
|
|
|
private:
|
|
|
|
DAGISelEmitter &ISE;
|
|
|
|
|
2005-12-14 22:02:59 +00:00
|
|
|
// Predicates.
|
|
|
|
ListInit *Predicates;
|
2006-04-19 18:07:24 +00:00
|
|
|
// Pattern cost.
|
|
|
|
unsigned Cost;
|
2005-12-14 22:02:59 +00:00
|
|
|
// Instruction selector pattern.
|
|
|
|
TreePatternNode *Pattern;
|
|
|
|
// Matched instruction.
|
|
|
|
TreePatternNode *Instruction;
|
2006-01-28 20:31:24 +00:00
|
|
|
|
2005-12-09 22:45:35 +00:00
|
|
|
// Node to name mapping
|
2006-01-12 19:35:54 +00:00
|
|
|
std::map<std::string, std::string> VariableMap;
|
|
|
|
// Node to operator mapping
|
|
|
|
std::map<std::string, Record*> OperatorMap;
|
2005-12-09 22:45:35 +00:00
|
|
|
// Names of all the folded nodes which produce chains.
|
2005-12-19 07:18:51 +00:00
|
|
|
std::vector<std::pair<std::string, unsigned> > FoldedChains;
|
2006-10-12 02:08:53 +00:00
|
|
|
// Original input chain(s).
|
|
|
|
std::vector<std::pair<std::string, std::string> > OrigChains;
|
2006-01-19 01:55:45 +00:00
|
|
|
std::set<std::string> Duplicates;
|
2005-12-09 22:45:35 +00:00
|
|
|
|
2006-08-26 00:59:04 +00:00
|
|
|
/// GeneratedCode - This is the buffer that we emit code to. The first int
|
2006-01-28 20:31:24 +00:00
|
|
|
/// indicates whether this is an exit predicate (something that should be
|
2006-08-26 00:59:04 +00:00
|
|
|
/// tested, and if true, the match fails) [when 1], or normal code to emit
|
|
|
|
/// [when 0], or initialization code to emit [when 2].
|
|
|
|
std::vector<std::pair<unsigned, std::string> > &GeneratedCode;
|
2006-02-07 00:37:41 +00:00
|
|
|
/// GeneratedDecl - This is the set of all SDOperand declarations needed for
|
|
|
|
/// the set of patterns for each top-level opcode.
|
2006-08-26 01:02:19 +00:00
|
|
|
std::set<std::string> &GeneratedDecl;
|
2006-07-15 08:45:20 +00:00
|
|
|
/// TargetOpcodes - The target specific opcodes used by the resulting
|
|
|
|
/// instructions.
|
|
|
|
std::vector<std::string> &TargetOpcodes;
|
2006-07-16 06:12:52 +00:00
|
|
|
std::vector<std::string> &TargetVTs;
|
2006-01-28 20:31:24 +00:00
|
|
|
|
2006-02-03 06:22:41 +00:00
|
|
|
std::string ChainName;
|
2006-01-28 20:31:24 +00:00
|
|
|
unsigned TmpNo;
|
2006-07-15 08:45:20 +00:00
|
|
|
unsigned OpcNo;
|
2006-07-16 06:12:52 +00:00
|
|
|
unsigned VTNo;
|
2006-01-28 20:31:24 +00:00
|
|
|
|
|
|
|
void emitCheck(const std::string &S) {
|
|
|
|
if (!S.empty())
|
2006-08-26 00:59:04 +00:00
|
|
|
GeneratedCode.push_back(std::make_pair(1, S));
|
2006-01-28 20:31:24 +00:00
|
|
|
}
|
|
|
|
void emitCode(const std::string &S) {
|
|
|
|
if (!S.empty())
|
2006-08-26 00:59:04 +00:00
|
|
|
GeneratedCode.push_back(std::make_pair(0, S));
|
|
|
|
}
|
|
|
|
void emitInit(const std::string &S) {
|
|
|
|
if (!S.empty())
|
|
|
|
GeneratedCode.push_back(std::make_pair(2, S));
|
2006-01-28 20:31:24 +00:00
|
|
|
}
|
2006-08-26 01:02:19 +00:00
|
|
|
void emitDecl(const std::string &S) {
|
2006-02-07 00:37:41 +00:00
|
|
|
assert(!S.empty() && "Invalid declaration");
|
2006-08-26 01:02:19 +00:00
|
|
|
GeneratedDecl.insert(S);
|
2006-02-07 00:37:41 +00:00
|
|
|
}
|
2006-07-15 08:45:20 +00:00
|
|
|
void emitOpcode(const std::string &Opc) {
|
|
|
|
TargetOpcodes.push_back(Opc);
|
|
|
|
OpcNo++;
|
|
|
|
}
|
2006-07-16 06:12:52 +00:00
|
|
|
void emitVT(const std::string &VT) {
|
|
|
|
TargetVTs.push_back(VT);
|
|
|
|
VTNo++;
|
|
|
|
}
|
2005-12-09 22:45:35 +00:00
|
|
|
public:
|
2005-12-14 22:02:59 +00:00
|
|
|
PatternCodeEmitter(DAGISelEmitter &ise, ListInit *preds,
|
|
|
|
TreePatternNode *pattern, TreePatternNode *instr,
|
2006-08-26 00:59:04 +00:00
|
|
|
std::vector<std::pair<unsigned, std::string> > &gc,
|
2006-08-26 01:02:19 +00:00
|
|
|
std::set<std::string> &gd,
|
2006-07-15 08:45:20 +00:00
|
|
|
std::vector<std::string> &to,
|
2006-08-09 16:44:44 +00:00
|
|
|
std::vector<std::string> &tv)
|
2006-01-28 20:31:24 +00:00
|
|
|
: ISE(ise), Predicates(preds), Pattern(pattern), Instruction(instr),
|
2006-08-26 00:59:04 +00:00
|
|
|
GeneratedCode(gc), GeneratedDecl(gd),
|
|
|
|
TargetOpcodes(to), TargetVTs(tv),
|
2006-08-09 16:44:44 +00:00
|
|
|
TmpNo(0), OpcNo(0), VTNo(0) {}
|
2005-12-21 05:31:05 +00:00
|
|
|
|
2005-12-09 22:45:35 +00:00
|
|
|
/// EmitMatchCode - Emit a matcher for N, going to the label for PatternNo
|
|
|
|
/// if the match fails. At this point, we already know that the opcode for N
|
|
|
|
/// matches, and the SDNode for the result has the RootName specified name.
|
2006-10-16 06:33:44 +00:00
|
|
|
void EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
|
|
|
|
const std::string &RootName, const std::string &ChainSuffix,
|
|
|
|
bool &FoundChain) {
|
2006-02-05 06:43:12 +00:00
|
|
|
bool isRoot = (P == NULL);
|
2005-12-14 22:02:59 +00:00
|
|
|
// Emit instruction predicates. Each predicate is just a string for now.
|
|
|
|
if (isRoot) {
|
2006-01-28 20:31:24 +00:00
|
|
|
std::string PredicateCheck;
|
2005-12-14 22:02:59 +00:00
|
|
|
for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
|
|
|
|
if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
|
|
|
|
Record *Def = Pred->getDef();
|
2006-01-28 20:31:24 +00:00
|
|
|
if (!Def->isSubClassOf("Predicate")) {
|
2006-07-11 18:25:13 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
Def->dump();
|
|
|
|
#endif
|
2005-12-14 22:02:59 +00:00
|
|
|
assert(0 && "Unknown predicate type!");
|
|
|
|
}
|
2006-01-28 20:31:24 +00:00
|
|
|
if (!PredicateCheck.empty())
|
2006-09-19 00:41:36 +00:00
|
|
|
PredicateCheck += " && ";
|
2006-01-28 20:43:52 +00:00
|
|
|
PredicateCheck += "(" + Def->getValueAsString("CondString") + ")";
|
2005-12-14 22:02:59 +00:00
|
|
|
}
|
|
|
|
}
|
2006-01-28 20:31:24 +00:00
|
|
|
|
|
|
|
emitCheck(PredicateCheck);
|
2005-12-14 22:02:59 +00:00
|
|
|
}
|
|
|
|
|
2005-12-09 22:45:35 +00:00
|
|
|
if (N->isLeaf()) {
|
|
|
|
if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
|
2006-01-28 20:31:24 +00:00
|
|
|
emitCheck("cast<ConstantSDNode>(" + RootName +
|
2006-01-28 20:43:52 +00:00
|
|
|
")->getSignExtended() == " + itostr(II->getValue()));
|
2005-12-09 22:45:35 +00:00
|
|
|
return;
|
|
|
|
} else if (!NodeIsComplexPattern(N)) {
|
|
|
|
assert(0 && "Cannot match this as a leaf value!");
|
|
|
|
abort();
|
|
|
|
}
|
2005-11-02 06:49:14 +00:00
|
|
|
}
|
2005-09-24 00:40:24 +00:00
|
|
|
|
2006-01-28 19:06:51 +00:00
|
|
|
// If this node has a name associated with it, capture it in VariableMap. If
|
2005-12-09 22:45:35 +00:00
|
|
|
// we already saw this in the pattern, emit code to verify dagness.
|
|
|
|
if (!N->getName().empty()) {
|
|
|
|
std::string &VarMapEntry = VariableMap[N->getName()];
|
|
|
|
if (VarMapEntry.empty()) {
|
|
|
|
VarMapEntry = RootName;
|
|
|
|
} else {
|
|
|
|
// If we get here, this is a second reference to a specific name. Since
|
|
|
|
// we already have checked that the first reference is valid, we don't
|
|
|
|
// have to recursively match it, just check that it's the same as the
|
|
|
|
// previously named thing.
|
2006-01-28 20:43:52 +00:00
|
|
|
emitCheck(VarMapEntry + " == " + RootName);
|
2005-12-09 22:45:35 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-01-12 19:35:54 +00:00
|
|
|
|
|
|
|
if (!N->isLeaf())
|
|
|
|
OperatorMap[N->getName()] = N->getOperator();
|
2005-09-24 00:40:24 +00:00
|
|
|
}
|
2005-12-04 08:18:16 +00:00
|
|
|
|
2005-12-09 00:48:42 +00:00
|
|
|
|
2005-12-09 22:45:35 +00:00
|
|
|
// Emit code to load the child nodes and match their contents recursively.
|
|
|
|
unsigned OpNo = 0;
|
2006-10-11 21:02:01 +00:00
|
|
|
bool NodeHasChain = NodeHasProperty (N, SDNPHasChain, ISE);
|
|
|
|
bool HasChain = PatternHasProperty(N, SDNPHasChain, ISE);
|
2006-01-26 19:13:45 +00:00
|
|
|
bool EmittedUseCheck = false;
|
2005-12-12 19:37:43 +00:00
|
|
|
if (HasChain) {
|
Prevent folding of a node with multiple uses if the node already folds a load!
Here is an example where the load ended up being done twice:
%A = global uint 0
uint %test(uint %B, ubyte %C) {
%tmp = load uint *%A;
%X = shl uint %tmp, ubyte %C
%Cv = sub ubyte 32, %C
%Y = shr uint %B, ubyte %Cv
%Z = or uint %Y, %X
store uint %Z, uint* %A
ret uint %Z
}
==>
subl $4, %esp
movl %ebx, (%esp)
movl 8(%esp), %edx
movl A, %eax
movb 12(%esp), %bl
movb %bl, %cl
shldl %cl, %edx, %eax
movb %bl, %cl
shldl %cl, %edx, A
movl (%esp), %ebx
addl $4, %esp
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25471 91177308-0d34-0410-b5e6-96231b3b80d8
2006-01-20 01:11:03 +00:00
|
|
|
if (NodeHasChain)
|
|
|
|
OpNo = 1;
|
2005-12-09 22:45:35 +00:00
|
|
|
if (!isRoot) {
|
2006-01-28 20:31:24 +00:00
|
|
|
// Multiple uses of actual result?
|
2006-01-28 20:43:52 +00:00
|
|
|
emitCheck(RootName + ".hasOneUse()");
|
2006-01-26 19:13:45 +00:00
|
|
|
EmittedUseCheck = true;
|
2006-02-05 06:43:12 +00:00
|
|
|
if (NodeHasChain) {
|
|
|
|
// If the immediate use can somehow reach this node through another
|
|
|
|
// path, then can't fold it either or it will create a cycle.
|
|
|
|
// e.g. In the following diagram, XX can reach ld through YY. If
|
|
|
|
// ld is folded into XX, then YY is both a predecessor and a successor
|
|
|
|
// of XX.
|
|
|
|
//
|
|
|
|
// [ld]
|
|
|
|
// ^ ^
|
|
|
|
// | |
|
|
|
|
// / \---
|
|
|
|
// / [YY]
|
|
|
|
// | ^
|
|
|
|
// [XX]-------|
|
2006-10-16 06:33:44 +00:00
|
|
|
bool NeedCheck = false;
|
|
|
|
if (P != Pattern)
|
|
|
|
NeedCheck = true;
|
|
|
|
else {
|
|
|
|
const SDNodeInfo &PInfo = ISE.getSDNodeInfo(P->getOperator());
|
|
|
|
NeedCheck =
|
|
|
|
P->getOperator() == ISE.get_intrinsic_void_sdnode() ||
|
|
|
|
P->getOperator() == ISE.get_intrinsic_w_chain_sdnode() ||
|
|
|
|
P->getOperator() == ISE.get_intrinsic_wo_chain_sdnode() ||
|
2006-10-14 08:30:15 +00:00
|
|
|
PInfo.getNumOperands() > 1 ||
|
2006-10-11 21:02:01 +00:00
|
|
|
PInfo.hasProperty(SDNPHasChain) ||
|
|
|
|
PInfo.hasProperty(SDNPInFlag) ||
|
2006-10-16 06:33:44 +00:00
|
|
|
PInfo.hasProperty(SDNPOptInFlag);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NeedCheck) {
|
2006-10-11 03:35:34 +00:00
|
|
|
std::string ParentName(RootName.begin(), RootName.end()-1);
|
2006-08-09 16:44:44 +00:00
|
|
|
emitCheck("CanBeFoldedBy(" + RootName + ".Val, " + ParentName +
|
2006-10-14 08:30:15 +00:00
|
|
|
".Val, N.Val)");
|
2006-10-11 03:35:34 +00:00
|
|
|
}
|
2006-02-05 06:43:12 +00:00
|
|
|
}
|
2005-12-09 22:45:35 +00:00
|
|
|
}
|
2006-02-05 06:43:12 +00:00
|
|
|
|
2006-01-27 22:13:45 +00:00
|
|
|
if (NodeHasChain) {
|
2006-10-12 02:08:53 +00:00
|
|
|
if (FoundChain) {
|
|
|
|
emitCheck("(" + ChainName + ".Val == " + RootName + ".Val || "
|
|
|
|
"IsChainCompatible(" + ChainName + ".Val, " +
|
|
|
|
RootName + ".Val))");
|
|
|
|
OrigChains.push_back(std::make_pair(ChainName, RootName));
|
|
|
|
} else
|
2006-07-21 22:19:51 +00:00
|
|
|
FoundChain = true;
|
2006-02-03 06:22:41 +00:00
|
|
|
ChainName = "Chain" + ChainSuffix;
|
2006-08-26 00:59:04 +00:00
|
|
|
emitInit("SDOperand " + ChainName + " = " + RootName +
|
2006-07-21 22:19:51 +00:00
|
|
|
".getOperand(0);");
|
2006-01-06 00:41:12 +00:00
|
|
|
}
|
2005-12-09 00:48:42 +00:00
|
|
|
}
|
|
|
|
|
2006-01-26 00:22:25 +00:00
|
|
|
// Don't fold any node which reads or writes a flag and has multiple uses.
|
2006-02-05 06:43:12 +00:00
|
|
|
// FIXME: We really need to separate the concepts of flag and "glue". Those
|
2006-01-26 00:22:25 +00:00
|
|
|
// real flag results, e.g. X86CMP output, can have multiple uses.
|
2006-02-05 06:43:12 +00:00
|
|
|
// FIXME: If the optional incoming flag does not exist. Then it is ok to
|
|
|
|
// fold it.
|
2006-01-26 19:13:45 +00:00
|
|
|
if (!isRoot &&
|
2006-10-11 21:02:01 +00:00
|
|
|
(PatternHasProperty(N, SDNPInFlag, ISE) ||
|
|
|
|
PatternHasProperty(N, SDNPOptInFlag, ISE) ||
|
|
|
|
PatternHasProperty(N, SDNPOutFlag, ISE))) {
|
2006-01-26 19:13:45 +00:00
|
|
|
if (!EmittedUseCheck) {
|
2006-01-28 20:31:24 +00:00
|
|
|
// Multiple uses of actual result?
|
2006-01-28 20:43:52 +00:00
|
|
|
emitCheck(RootName + ".hasOneUse()");
|
2006-01-26 00:22:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-09 21:02:17 +00:00
|
|
|
// If there is a node predicate for this, emit the call.
|
|
|
|
if (!N->getPredicateFn().empty())
|
|
|
|
emitCheck(N->getPredicateFn() + "(" + RootName + ".Val)");
|
|
|
|
|
2006-10-11 03:35:34 +00:00
|
|
|
|
Special case tblgen generated code for patterns like (and X, 255) or (or X, 42).
The dag/inst combiners often 'simplify' the masked value based on whether
or not the bits are live or known zero/one. This is good and dandy, but
often causes special case patterns to fail, such as alpha's CMPBGE pattern,
which looks like "(set GPRC:$RC, (setuge (and GPRC:$RA, 255), (and GPRC:$RB, 255)))".
Here the pattern for (and X, 255) should match actual dags like (and X, 254) if
the dag combiner proved that the missing bits are already zero (one for 'or').
For CodeGen/Alpha/cmpbge.ll:test2 for example, this results in:
sll $16,1,$0
cmpbge $0,$17,$0
ret $31,($26),1
instead of:
sll $16,1,$0
and $0,254,$0
and $17,255,$1
cmpule $1,$0,$0
ret $31,($26),1
... and requires no target-specific code.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30871 91177308-0d34-0410-b5e6-96231b3b80d8
2006-10-11 04:05:55 +00:00
|
|
|
// If this is an 'and R, 1234' where the operation is AND/OR and the RHS is
|
|
|
|
// a constant without a predicate fn that has more that one bit set, handle
|
|
|
|
// this as a special case. This is usually for targets that have special
|
|
|
|
// handling of certain large constants (e.g. alpha with it's 8/16/32-bit
|
|
|
|
// handling stuff). Using these instructions is often far more efficient
|
|
|
|
// than materializing the constant. Unfortunately, both the instcombiner
|
|
|
|
// and the dag combiner can often infer that bits are dead, and thus drop
|
|
|
|
// them from the mask in the dag. For example, it might turn 'AND X, 255'
|
|
|
|
// into 'AND X, 254' if it knows the low bit is set. Emit code that checks
|
|
|
|
// to handle this.
|
|
|
|
if (!N->isLeaf() &&
|
|
|
|
(N->getOperator()->getName() == "and" ||
|
|
|
|
N->getOperator()->getName() == "or") &&
|
|
|
|
N->getChild(1)->isLeaf() &&
|
|
|
|
N->getChild(1)->getPredicateFn().empty()) {
|
|
|
|
if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) {
|
|
|
|
if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
|
|
|
|
emitInit("SDOperand " + RootName + "0" + " = " +
|
|
|
|
RootName + ".getOperand(" + utostr(0) + ");");
|
|
|
|
emitInit("SDOperand " + RootName + "1" + " = " +
|
|
|
|
RootName + ".getOperand(" + utostr(1) + ");");
|
|
|
|
|
|
|
|
emitCheck("isa<ConstantSDNode>(" + RootName + "1)");
|
|
|
|
const char *MaskPredicate = N->getOperator()->getName() == "or"
|
|
|
|
? "CheckOrMask(" : "CheckAndMask(";
|
|
|
|
emitCheck(MaskPredicate + RootName + "0, cast<ConstantSDNode>(" +
|
|
|
|
RootName + "1), " + itostr(II->getValue()) + ")");
|
|
|
|
|
2006-10-16 06:33:44 +00:00
|
|
|
EmitChildMatchCode(N->getChild(0), N, RootName + utostr(0),
|
Special case tblgen generated code for patterns like (and X, 255) or (or X, 42).
The dag/inst combiners often 'simplify' the masked value based on whether
or not the bits are live or known zero/one. This is good and dandy, but
often causes special case patterns to fail, such as alpha's CMPBGE pattern,
which looks like "(set GPRC:$RC, (setuge (and GPRC:$RA, 255), (and GPRC:$RB, 255)))".
Here the pattern for (and X, 255) should match actual dags like (and X, 254) if
the dag combiner proved that the missing bits are already zero (one for 'or').
For CodeGen/Alpha/cmpbge.ll:test2 for example, this results in:
sll $16,1,$0
cmpbge $0,$17,$0
ret $31,($26),1
instead of:
sll $16,1,$0
and $0,254,$0
and $17,255,$1
cmpule $1,$0,$0
ret $31,($26),1
... and requires no target-specific code.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30871 91177308-0d34-0410-b5e6-96231b3b80d8
2006-10-11 04:05:55 +00:00
|
|
|
ChainSuffix + utostr(0), FoundChain);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 22:45:35 +00:00
|
|
|
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
|
2006-08-26 00:59:04 +00:00
|
|
|
emitInit("SDOperand " + RootName + utostr(OpNo) + " = " +
|
2006-01-28 20:31:24 +00:00
|
|
|
RootName + ".getOperand(" +utostr(OpNo) + ");");
|
2006-08-26 00:59:04 +00:00
|
|
|
|
2006-10-16 06:33:44 +00:00
|
|
|
EmitChildMatchCode(N->getChild(i), N, RootName + utostr(OpNo),
|
2006-10-11 03:35:34 +00:00
|
|
|
ChainSuffix + utostr(OpNo), FoundChain);
|
2005-09-23 21:33:23 +00:00
|
|
|
}
|
2005-12-04 08:18:16 +00:00
|
|
|
|
2006-08-26 00:59:04 +00:00
|
|
|
// Handle cases when root is a complex pattern.
|
2006-10-11 03:35:34 +00:00
|
|
|
const ComplexPattern *CP;
|
2006-08-26 00:59:04 +00:00
|
|
|
if (isRoot && N->isLeaf() && (CP = NodeGetComplexPattern(N, ISE))) {
|
|
|
|
std::string Fn = CP->getSelectFunc();
|
|
|
|
unsigned NumOps = CP->getNumOperands();
|
|
|
|
for (unsigned i = 0; i < NumOps; ++i) {
|
|
|
|
emitDecl("CPTmp" + utostr(i));
|
|
|
|
emitCode("SDOperand CPTmp" + utostr(i) + ";");
|
|
|
|
}
|
2006-10-11 21:02:01 +00:00
|
|
|
if (CP->hasProperty(SDNPHasChain)) {
|
|
|
|
emitDecl("CPInChain");
|
|
|
|
emitDecl("Chain" + ChainSuffix);
|
|
|
|
emitCode("SDOperand CPInChain;");
|
|
|
|
emitCode("SDOperand Chain" + ChainSuffix + ";");
|
|
|
|
}
|
2006-08-26 00:59:04 +00:00
|
|
|
|
2006-11-08 20:31:10 +00:00
|
|
|
std::string Code = Fn + "(" + RootName + ", " + RootName;
|
2006-08-26 00:59:04 +00:00
|
|
|
for (unsigned i = 0; i < NumOps; i++)
|
|
|
|
Code += ", CPTmp" + utostr(i);
|
2006-10-11 21:02:01 +00:00
|
|
|
if (CP->hasProperty(SDNPHasChain)) {
|
|
|
|
ChainName = "Chain" + ChainSuffix;
|
|
|
|
Code += ", CPInChain, Chain" + ChainSuffix;
|
|
|
|
}
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCheck(Code + ")");
|
|
|
|
}
|
Teach tblgen to accept register source operands in patterns, e.g.
def SHL8rCL : I<0xD2, MRM4r, (ops R8 :$dst, R8 :$src),
"shl{b} {%cl, $dst|$dst, %CL}",
[(set R8:$dst, (shl R8:$src, CL))]>, Imp<[CL],[]>;
This generates a CopyToReg operand and added its 2nd result to the shl as
a flag operand.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24557 91177308-0d34-0410-b5e6-96231b3b80d8
2005-12-01 00:18:45 +00:00
|
|
|
}
|
Special case tblgen generated code for patterns like (and X, 255) or (or X, 42).
The dag/inst combiners often 'simplify' the masked value based on whether
or not the bits are live or known zero/one. This is good and dandy, but
often causes special case patterns to fail, such as alpha's CMPBGE pattern,
which looks like "(set GPRC:$RC, (setuge (and GPRC:$RA, 255), (and GPRC:$RB, 255)))".
Here the pattern for (and X, 255) should match actual dags like (and X, 254) if
the dag combiner proved that the missing bits are already zero (one for 'or').
For CodeGen/Alpha/cmpbge.ll:test2 for example, this results in:
sll $16,1,$0
cmpbge $0,$17,$0
ret $31,($26),1
instead of:
sll $16,1,$0
and $0,254,$0
and $17,255,$1
cmpule $1,$0,$0
ret $31,($26),1
... and requires no target-specific code.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30871 91177308-0d34-0410-b5e6-96231b3b80d8
2006-10-11 04:05:55 +00:00
|
|
|
|
2006-10-16 06:33:44 +00:00
|
|
|
void EmitChildMatchCode(TreePatternNode *Child, TreePatternNode *Parent,
|
|
|
|
const std::string &RootName,
|
2006-10-11 03:35:34 +00:00
|
|
|
const std::string &ChainSuffix, bool &FoundChain) {
|
|
|
|
if (!Child->isLeaf()) {
|
|
|
|
// If it's not a leaf, recursively match.
|
|
|
|
const SDNodeInfo &CInfo = ISE.getSDNodeInfo(Child->getOperator());
|
|
|
|
emitCheck(RootName + ".getOpcode() == " +
|
|
|
|
CInfo.getEnumName());
|
2006-10-16 06:33:44 +00:00
|
|
|
EmitMatchCode(Child, Parent, RootName, ChainSuffix, FoundChain);
|
2006-10-11 21:02:01 +00:00
|
|
|
if (NodeHasProperty(Child, SDNPHasChain, ISE))
|
2006-10-11 03:35:34 +00:00
|
|
|
FoldedChains.push_back(std::make_pair(RootName, CInfo.getNumResults()));
|
|
|
|
} else {
|
|
|
|
// If this child has a name associated with it, capture it in VarMap. If
|
|
|
|
// we already saw this in the pattern, emit code to verify dagness.
|
|
|
|
if (!Child->getName().empty()) {
|
|
|
|
std::string &VarMapEntry = VariableMap[Child->getName()];
|
|
|
|
if (VarMapEntry.empty()) {
|
|
|
|
VarMapEntry = RootName;
|
|
|
|
} else {
|
|
|
|
// If we get here, this is a second reference to a specific name.
|
|
|
|
// Since we already have checked that the first reference is valid,
|
|
|
|
// we don't have to recursively match it, just check that it's the
|
|
|
|
// same as the previously named thing.
|
|
|
|
emitCheck(VarMapEntry + " == " + RootName);
|
|
|
|
Duplicates.insert(RootName);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle leaves of various types.
|
|
|
|
if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
|
|
|
|
Record *LeafRec = DI->getDef();
|
2006-11-14 21:18:40 +00:00
|
|
|
if (LeafRec->isSubClassOf("RegisterClass") ||
|
|
|
|
LeafRec->getName() == "ptr_rc") {
|
2006-10-11 03:35:34 +00:00
|
|
|
// Handle register references. Nothing to do here.
|
|
|
|
} else if (LeafRec->isSubClassOf("Register")) {
|
|
|
|
// Handle register references.
|
|
|
|
} else if (LeafRec->isSubClassOf("ComplexPattern")) {
|
|
|
|
// Handle complex pattern.
|
|
|
|
const ComplexPattern *CP = NodeGetComplexPattern(Child, ISE);
|
|
|
|
std::string Fn = CP->getSelectFunc();
|
|
|
|
unsigned NumOps = CP->getNumOperands();
|
|
|
|
for (unsigned i = 0; i < NumOps; ++i) {
|
|
|
|
emitDecl("CPTmp" + utostr(i));
|
|
|
|
emitCode("SDOperand CPTmp" + utostr(i) + ";");
|
|
|
|
}
|
2006-10-11 21:02:01 +00:00
|
|
|
if (CP->hasProperty(SDNPHasChain)) {
|
|
|
|
const SDNodeInfo &PInfo = ISE.getSDNodeInfo(Parent->getOperator());
|
|
|
|
FoldedChains.push_back(std::make_pair("CPInChain",
|
|
|
|
PInfo.getNumResults()));
|
|
|
|
ChainName = "Chain" + ChainSuffix;
|
|
|
|
emitDecl("CPInChain");
|
|
|
|
emitDecl(ChainName);
|
|
|
|
emitCode("SDOperand CPInChain;");
|
|
|
|
emitCode("SDOperand " + ChainName + ";");
|
|
|
|
}
|
2006-10-11 03:35:34 +00:00
|
|
|
|
2006-11-08 20:31:10 +00:00
|
|
|
std::string Code = Fn + "(N, ";
|
2006-10-16 06:33:44 +00:00
|
|
|
if (CP->hasProperty(SDNPHasChain)) {
|
|
|
|
std::string ParentName(RootName.begin(), RootName.end()-1);
|
2006-11-08 20:31:10 +00:00
|
|
|
Code += ParentName + ", ";
|
2006-10-16 06:33:44 +00:00
|
|
|
}
|
|
|
|
Code += RootName;
|
2006-10-11 03:35:34 +00:00
|
|
|
for (unsigned i = 0; i < NumOps; i++)
|
|
|
|
Code += ", CPTmp" + utostr(i);
|
2006-10-11 21:02:01 +00:00
|
|
|
if (CP->hasProperty(SDNPHasChain))
|
|
|
|
Code += ", CPInChain, Chain" + ChainSuffix;
|
2006-10-11 03:35:34 +00:00
|
|
|
emitCheck(Code + ")");
|
|
|
|
} else if (LeafRec->getName() == "srcvalue") {
|
|
|
|
// Place holder for SRCVALUE nodes. Nothing to do here.
|
|
|
|
} else if (LeafRec->isSubClassOf("ValueType")) {
|
|
|
|
// Make sure this is the specified value type.
|
|
|
|
emitCheck("cast<VTSDNode>(" + RootName +
|
|
|
|
")->getVT() == MVT::" + LeafRec->getName());
|
|
|
|
} else if (LeafRec->isSubClassOf("CondCode")) {
|
|
|
|
// Make sure this is the specified cond code.
|
|
|
|
emitCheck("cast<CondCodeSDNode>(" + RootName +
|
|
|
|
")->get() == ISD::" + LeafRec->getName());
|
|
|
|
} else {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
Child->dump();
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << " ";
|
2006-10-11 03:35:34 +00:00
|
|
|
#endif
|
|
|
|
assert(0 && "Unknown leaf type!");
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is a node predicate for this, emit the call.
|
|
|
|
if (!Child->getPredicateFn().empty())
|
|
|
|
emitCheck(Child->getPredicateFn() + "(" + RootName +
|
|
|
|
".Val)");
|
|
|
|
} else if (IntInit *II =
|
|
|
|
dynamic_cast<IntInit*>(Child->getLeafValue())) {
|
|
|
|
emitCheck("isa<ConstantSDNode>(" + RootName + ")");
|
|
|
|
unsigned CTmp = TmpNo++;
|
|
|
|
emitCode("int64_t CN"+utostr(CTmp)+" = cast<ConstantSDNode>("+
|
|
|
|
RootName + ")->getSignExtended();");
|
|
|
|
|
|
|
|
emitCheck("CN" + utostr(CTmp) + " == " +itostr(II->getValue()));
|
|
|
|
} else {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
Child->dump();
|
|
|
|
#endif
|
|
|
|
assert(0 && "Unknown leaf type!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-12-08 02:00:36 +00:00
|
|
|
|
2005-12-09 22:45:35 +00:00
|
|
|
/// EmitResultCode - Emit the action for a pattern. Now that it has matched
|
|
|
|
/// we actually have to build a DAG!
|
2006-08-26 00:59:04 +00:00
|
|
|
std::vector<std::string>
|
|
|
|
EmitResultCode(TreePatternNode *N, bool RetSelected,
|
|
|
|
bool InFlagDecled, bool ResNodeDecled,
|
|
|
|
bool LikeLeaf = false, bool isRoot = false) {
|
|
|
|
// List of arguments of getTargetNode() or SelectNodeTo().
|
|
|
|
std::vector<std::string> NodeOps;
|
2005-12-09 22:45:35 +00:00
|
|
|
// This is something selected from the pattern we matched.
|
|
|
|
if (!N->getName().empty()) {
|
|
|
|
std::string &Val = VariableMap[N->getName()];
|
|
|
|
assert(!Val.empty() &&
|
|
|
|
"Variable referenced but not defined and not caught earlier!");
|
|
|
|
if (Val[0] == 'T' && Val[1] == 'm' && Val[2] == 'p') {
|
|
|
|
// Already selected this operand, just return the tmpval.
|
2006-08-26 00:59:04 +00:00
|
|
|
NodeOps.push_back(Val);
|
|
|
|
return NodeOps;
|
2005-09-28 16:58:06 +00:00
|
|
|
}
|
2005-12-09 22:45:35 +00:00
|
|
|
|
|
|
|
const ComplexPattern *CP;
|
|
|
|
unsigned ResNo = TmpNo++;
|
|
|
|
if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
|
2005-12-30 00:12:56 +00:00
|
|
|
assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
|
2006-01-29 20:01:35 +00:00
|
|
|
std::string CastType;
|
2005-12-30 00:12:56 +00:00
|
|
|
switch (N->getTypeNum(0)) {
|
2007-01-17 07:45:12 +00:00
|
|
|
default:
|
|
|
|
cerr << "Cannot handle " << getEnumName(N->getTypeNum(0))
|
|
|
|
<< " type as an immediate constant. Aborting\n";
|
|
|
|
abort();
|
2006-01-29 20:01:35 +00:00
|
|
|
case MVT::i1: CastType = "bool"; break;
|
|
|
|
case MVT::i8: CastType = "unsigned char"; break;
|
|
|
|
case MVT::i16: CastType = "unsigned short"; break;
|
|
|
|
case MVT::i32: CastType = "unsigned"; break;
|
|
|
|
case MVT::i64: CastType = "uint64_t"; break;
|
2005-12-09 22:45:35 +00:00
|
|
|
}
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("SDOperand Tmp" + utostr(ResNo) +
|
2006-07-15 08:45:20 +00:00
|
|
|
" = CurDAG->getTargetConstant(((" + CastType +
|
|
|
|
") cast<ConstantSDNode>(" + Val + ")->getValue()), " +
|
|
|
|
getEnumName(N->getTypeNum(0)) + ");");
|
2006-08-26 00:59:04 +00:00
|
|
|
NodeOps.push_back("Tmp" + utostr(ResNo));
|
|
|
|
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
|
|
|
|
// value if used multiple times by this pattern result.
|
|
|
|
Val = "Tmp"+utostr(ResNo);
|
2006-01-12 07:54:57 +00:00
|
|
|
} else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
|
2006-01-12 19:35:54 +00:00
|
|
|
Record *Op = OperatorMap[N->getName()];
|
|
|
|
// Transform ExternalSymbol to TargetExternalSymbol
|
|
|
|
if (Op && Op->getName() == "externalsym") {
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
|
2006-01-28 20:31:24 +00:00
|
|
|
"ExternalSymbol(cast<ExternalSymbolSDNode>(" +
|
2006-05-17 20:37:59 +00:00
|
|
|
Val + ")->getSymbol(), " +
|
2006-01-28 20:31:24 +00:00
|
|
|
getEnumName(N->getTypeNum(0)) + ");");
|
2006-08-26 00:59:04 +00:00
|
|
|
NodeOps.push_back("Tmp" + utostr(ResNo));
|
2006-09-21 18:28:27 +00:00
|
|
|
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select
|
|
|
|
// this value if used multiple times by this pattern result.
|
2006-08-26 00:59:04 +00:00
|
|
|
Val = "Tmp"+utostr(ResNo);
|
2006-01-28 20:31:24 +00:00
|
|
|
} else {
|
2006-08-26 00:59:04 +00:00
|
|
|
NodeOps.push_back(Val);
|
2006-01-28 20:31:24 +00:00
|
|
|
}
|
2006-01-12 07:54:57 +00:00
|
|
|
} else if (!N->isLeaf() && N->getOperator()->getName() == "tglobaladdr") {
|
2006-01-12 19:35:54 +00:00
|
|
|
Record *Op = OperatorMap[N->getName()];
|
|
|
|
// Transform GlobalAddress to TargetGlobalAddress
|
|
|
|
if (Op && Op->getName() == "globaladdr") {
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
|
2006-01-28 20:31:24 +00:00
|
|
|
"GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
|
2006-05-17 20:37:59 +00:00
|
|
|
")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
|
2006-01-28 20:31:24 +00:00
|
|
|
");");
|
2006-08-26 00:59:04 +00:00
|
|
|
NodeOps.push_back("Tmp" + utostr(ResNo));
|
2006-09-21 18:28:27 +00:00
|
|
|
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select
|
|
|
|
// this value if used multiple times by this pattern result.
|
2006-08-26 00:59:04 +00:00
|
|
|
Val = "Tmp"+utostr(ResNo);
|
2006-01-28 20:31:24 +00:00
|
|
|
} else {
|
2006-08-26 00:59:04 +00:00
|
|
|
NodeOps.push_back(Val);
|
2006-01-28 20:31:24 +00:00
|
|
|
}
|
2006-01-03 22:55:16 +00:00
|
|
|
} else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
|
2006-08-26 00:59:04 +00:00
|
|
|
NodeOps.push_back(Val);
|
|
|
|
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
|
|
|
|
// value if used multiple times by this pattern result.
|
|
|
|
Val = "Tmp"+utostr(ResNo);
|
2006-01-12 07:54:57 +00:00
|
|
|
} else if (!N->isLeaf() && N->getOperator()->getName() == "tconstpool") {
|
2006-08-26 00:59:04 +00:00
|
|
|
NodeOps.push_back(Val);
|
|
|
|
// Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
|
|
|
|
// value if used multiple times by this pattern result.
|
|
|
|
Val = "Tmp"+utostr(ResNo);
|
2005-12-09 22:45:35 +00:00
|
|
|
} else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, ISE))) {
|
2006-08-26 00:59:04 +00:00
|
|
|
for (unsigned i = 0; i < CP->getNumOperands(); ++i) {
|
|
|
|
emitCode("AddToISelQueue(CPTmp" + utostr(i) + ");");
|
|
|
|
NodeOps.push_back("CPTmp" + utostr(i));
|
2006-05-25 00:21:44 +00:00
|
|
|
}
|
2005-12-09 22:45:35 +00:00
|
|
|
} else {
|
2006-08-26 00:59:04 +00:00
|
|
|
// This node, probably wrapped in a SDNodeXForm, behaves like a leaf
|
2006-03-20 22:53:06 +00:00
|
|
|
// node even if it isn't one. Don't select it.
|
2006-08-26 00:59:04 +00:00
|
|
|
if (!LikeLeaf) {
|
|
|
|
emitCode("AddToISelQueue(" + Val + ");");
|
2006-08-09 16:44:44 +00:00
|
|
|
if (isRoot && N->isLeaf()) {
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("ReplaceUses(N, " + Val + ");");
|
2006-08-11 08:59:35 +00:00
|
|
|
emitCode("return NULL;");
|
2006-08-09 16:44:44 +00:00
|
|
|
}
|
2006-03-23 02:35:32 +00:00
|
|
|
}
|
2006-08-26 00:59:04 +00:00
|
|
|
NodeOps.push_back(Val);
|
2005-12-08 02:00:36 +00:00
|
|
|
}
|
2006-08-26 00:59:04 +00:00
|
|
|
return NodeOps;
|
2005-09-24 00:40:24 +00:00
|
|
|
}
|
2005-12-09 22:45:35 +00:00
|
|
|
if (N->isLeaf()) {
|
|
|
|
// If this is an explicit register reference, handle it.
|
|
|
|
if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
|
|
|
|
unsigned ResNo = TmpNo++;
|
|
|
|
if (DI->getDef()->isSubClassOf("Register")) {
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getRegister(" +
|
2006-05-17 20:37:59 +00:00
|
|
|
ISE.getQualifiedName(DI->getDef()) + ", " +
|
2006-01-28 20:31:24 +00:00
|
|
|
getEnumName(N->getTypeNum(0)) + ");");
|
2006-08-26 00:59:04 +00:00
|
|
|
NodeOps.push_back("Tmp" + utostr(ResNo));
|
|
|
|
return NodeOps;
|
2005-12-09 22:45:35 +00:00
|
|
|
}
|
|
|
|
} else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
|
|
|
|
unsigned ResNo = TmpNo++;
|
2005-12-30 00:12:56 +00:00
|
|
|
assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("SDOperand Tmp" + utostr(ResNo) +
|
2006-01-28 20:31:24 +00:00
|
|
|
" = CurDAG->getTargetConstant(" + itostr(II->getValue()) +
|
2006-05-17 20:37:59 +00:00
|
|
|
", " + getEnumName(N->getTypeNum(0)) + ");");
|
2006-08-26 00:59:04 +00:00
|
|
|
NodeOps.push_back("Tmp" + utostr(ResNo));
|
|
|
|
return NodeOps;
|
2005-10-19 02:07:26 +00:00
|
|
|
}
|
|
|
|
|
2006-07-11 18:25:13 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
N->dump();
|
|
|
|
#endif
|
2005-12-09 22:45:35 +00:00
|
|
|
assert(0 && "Unknown leaf type!");
|
2006-08-26 00:59:04 +00:00
|
|
|
return NodeOps;
|
2005-12-09 00:48:42 +00:00
|
|
|
}
|
|
|
|
|
2005-12-09 22:45:35 +00:00
|
|
|
Record *Op = N->getOperator();
|
|
|
|
if (Op->isSubClassOf("Instruction")) {
|
2005-12-23 22:11:47 +00:00
|
|
|
const CodeGenTarget &CGT = ISE.getTargetInfo();
|
|
|
|
CodeGenInstruction &II = CGT.getInstruction(Op->getName());
|
2005-12-20 07:37:41 +00:00
|
|
|
const DAGInstruction &Inst = ISE.getInstruction(Op);
|
2006-05-10 00:05:46 +00:00
|
|
|
TreePattern *InstPat = Inst.getPattern();
|
|
|
|
TreePatternNode *InstPatNode =
|
|
|
|
isRoot ? (InstPat ? InstPat->getOnlyTree() : Pattern)
|
|
|
|
: (InstPat ? InstPat->getOnlyTree() : NULL);
|
|
|
|
if (InstPatNode && InstPatNode->getOperator()->getName() == "set") {
|
|
|
|
InstPatNode = InstPatNode->getChild(1);
|
|
|
|
}
|
2006-06-14 22:22:20 +00:00
|
|
|
bool HasVarOps = isRoot && II.hasVariableNumberOfOperands;
|
2006-05-10 00:05:46 +00:00
|
|
|
bool HasImpInputs = isRoot && Inst.getNumImpOperands() > 0;
|
|
|
|
bool HasImpResults = isRoot && Inst.getNumImpResults() > 0;
|
|
|
|
bool NodeHasOptInFlag = isRoot &&
|
2006-10-11 21:02:01 +00:00
|
|
|
PatternHasProperty(Pattern, SDNPOptInFlag, ISE);
|
2006-05-10 00:05:46 +00:00
|
|
|
bool NodeHasInFlag = isRoot &&
|
2006-10-11 21:02:01 +00:00
|
|
|
PatternHasProperty(Pattern, SDNPInFlag, ISE);
|
2006-05-10 00:05:46 +00:00
|
|
|
bool NodeHasOutFlag = HasImpResults || (isRoot &&
|
2006-10-11 21:02:01 +00:00
|
|
|
PatternHasProperty(Pattern, SDNPOutFlag, ISE));
|
2006-05-10 00:05:46 +00:00
|
|
|
bool NodeHasChain = InstPatNode &&
|
2006-10-11 21:02:01 +00:00
|
|
|
PatternHasProperty(InstPatNode, SDNPHasChain, ISE);
|
2006-05-10 02:47:57 +00:00
|
|
|
bool InputHasChain = isRoot &&
|
2006-10-11 21:02:01 +00:00
|
|
|
NodeHasProperty(Pattern, SDNPHasChain, ISE);
|
2006-11-04 05:12:02 +00:00
|
|
|
unsigned NumResults = Inst.getNumResults();
|
2006-05-10 00:05:46 +00:00
|
|
|
|
2006-07-15 08:45:20 +00:00
|
|
|
if (NodeHasOptInFlag) {
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("bool HasInFlag = "
|
2006-07-16 06:12:52 +00:00
|
|
|
"(N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag);");
|
2006-07-15 08:45:20 +00:00
|
|
|
}
|
2006-06-14 22:22:20 +00:00
|
|
|
if (HasVarOps)
|
2006-08-27 08:11:28 +00:00
|
|
|
emitCode("SmallVector<SDOperand, 8> Ops" + utostr(OpcNo) + ";");
|
2005-12-20 07:37:41 +00:00
|
|
|
|
2006-01-19 21:57:10 +00:00
|
|
|
// How many results is this pattern expected to produce?
|
2006-03-09 08:19:11 +00:00
|
|
|
unsigned PatResults = 0;
|
2006-01-19 21:57:10 +00:00
|
|
|
for (unsigned i = 0, e = Pattern->getExtTypes().size(); i != e; i++) {
|
|
|
|
MVT::ValueType VT = Pattern->getTypeNum(i);
|
|
|
|
if (VT != MVT::isVoid && VT != MVT::Flag)
|
2006-03-09 08:19:11 +00:00
|
|
|
PatResults++;
|
2006-01-19 21:57:10 +00:00
|
|
|
}
|
|
|
|
|
2006-10-12 02:08:53 +00:00
|
|
|
if (OrigChains.size() > 0) {
|
|
|
|
// The original input chain is being ignored. If it is not just
|
|
|
|
// pointing to the op that's being folded, we should create a
|
|
|
|
// TokenFactor with it and the chain of the folded op as the new chain.
|
|
|
|
// We could potentially be doing multiple levels of folding, in that
|
|
|
|
// case, the TokenFactor can have more operands.
|
|
|
|
emitCode("SmallVector<SDOperand, 8> InChains;");
|
|
|
|
for (unsigned i = 0, e = OrigChains.size(); i < e; ++i) {
|
|
|
|
emitCode("if (" + OrigChains[i].first + ".Val != " +
|
|
|
|
OrigChains[i].second + ".Val) {");
|
|
|
|
emitCode(" AddToISelQueue(" + OrigChains[i].first + ");");
|
|
|
|
emitCode(" InChains.push_back(" + OrigChains[i].first + ");");
|
|
|
|
emitCode("}");
|
|
|
|
}
|
|
|
|
emitCode("AddToISelQueue(" + ChainName + ");");
|
|
|
|
emitCode("InChains.push_back(" + ChainName + ");");
|
|
|
|
emitCode(ChainName + " = CurDAG->getNode(ISD::TokenFactor, MVT::Other, "
|
|
|
|
"&InChains[0], InChains.size());");
|
|
|
|
}
|
|
|
|
|
2006-11-04 05:12:02 +00:00
|
|
|
// Loop over all of the operands of the instruction pattern, emitting code
|
|
|
|
// to fill them all in. The node 'N' usually has number children equal to
|
|
|
|
// the number of input operands of the instruction. However, in cases
|
|
|
|
// where there are predicate operands for an instruction, we need to fill
|
|
|
|
// in the 'execute always' values. Match up the node operands to the
|
|
|
|
// instruction operands to do this.
|
2006-08-26 00:59:04 +00:00
|
|
|
std::vector<std::string> AllOps;
|
2006-11-04 05:12:02 +00:00
|
|
|
for (unsigned ChildNo = 0, InstOpNo = NumResults;
|
|
|
|
InstOpNo != II.OperandList.size(); ++InstOpNo) {
|
|
|
|
std::vector<std::string> Ops;
|
|
|
|
|
|
|
|
// If this is a normal operand, emit it.
|
|
|
|
if (!II.OperandList[InstOpNo].Rec->isSubClassOf("PredicateOperand")) {
|
|
|
|
Ops = EmitResultCode(N->getChild(ChildNo), RetSelected,
|
|
|
|
InFlagDecled, ResNodeDecled);
|
|
|
|
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
|
|
|
|
++ChildNo;
|
|
|
|
} else {
|
|
|
|
// Otherwise, this is a predicate operand, emit the 'execute always'
|
|
|
|
// operands.
|
|
|
|
const DAGPredicateOperand &Pred =
|
|
|
|
ISE.getPredicateOperand(II.OperandList[InstOpNo].Rec);
|
|
|
|
for (unsigned i = 0, e = Pred.AlwaysOps.size(); i != e; ++i) {
|
|
|
|
Ops = EmitResultCode(Pred.AlwaysOps[i], RetSelected,
|
|
|
|
InFlagDecled, ResNodeDecled);
|
|
|
|
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
|
|
|
|
}
|
|
|
|
}
|
2005-12-04 08:18:16 +00:00
|
|
|
}
|
2005-12-09 22:45:35 +00:00
|
|
|
|
|
|
|
// Emit all the chain and CopyToReg stuff.
|
2006-05-10 00:05:46 +00:00
|
|
|
bool ChainEmitted = NodeHasChain;
|
|
|
|
if (NodeHasChain)
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("AddToISelQueue(" + ChainName + ");");
|
2006-06-14 19:27:50 +00:00
|
|
|
if (NodeHasInFlag || HasImpInputs)
|
2006-08-26 00:59:04 +00:00
|
|
|
EmitInFlagSelectCode(Pattern, "N", ChainEmitted,
|
|
|
|
InFlagDecled, ResNodeDecled, true);
|
2006-08-27 08:11:28 +00:00
|
|
|
if (NodeHasOptInFlag || NodeHasInFlag || HasImpInputs) {
|
2006-08-26 00:59:04 +00:00
|
|
|
if (!InFlagDecled) {
|
|
|
|
emitCode("SDOperand InFlag(0, 0);");
|
|
|
|
InFlagDecled = true;
|
|
|
|
}
|
2006-08-27 08:11:28 +00:00
|
|
|
if (NodeHasOptInFlag) {
|
|
|
|
emitCode("if (HasInFlag) {");
|
|
|
|
emitCode(" InFlag = N.getOperand(N.getNumOperands()-1);");
|
|
|
|
emitCode(" AddToISelQueue(InFlag);");
|
|
|
|
emitCode("}");
|
|
|
|
}
|
2006-06-14 19:27:50 +00:00
|
|
|
}
|
2005-12-09 22:45:35 +00:00
|
|
|
|
|
|
|
unsigned ResNo = TmpNo++;
|
2006-05-10 02:47:57 +00:00
|
|
|
if (!isRoot || InputHasChain || NodeHasChain || NodeHasOutFlag ||
|
|
|
|
NodeHasOptInFlag) {
|
2006-06-14 22:22:20 +00:00
|
|
|
std::string Code;
|
|
|
|
std::string Code2;
|
|
|
|
std::string NodeName;
|
|
|
|
if (!isRoot) {
|
|
|
|
NodeName = "Tmp" + utostr(ResNo);
|
2006-08-26 00:59:04 +00:00
|
|
|
Code2 = "SDOperand " + NodeName + " = SDOperand(";
|
2006-01-24 20:46:50 +00:00
|
|
|
} else {
|
2006-06-14 22:22:20 +00:00
|
|
|
NodeName = "ResNode";
|
2006-08-26 00:59:04 +00:00
|
|
|
if (!ResNodeDecled)
|
|
|
|
Code2 = "SDNode *" + NodeName + " = ";
|
|
|
|
else
|
|
|
|
Code2 = NodeName + " = ";
|
2006-06-14 22:22:20 +00:00
|
|
|
}
|
2006-08-27 08:11:28 +00:00
|
|
|
|
2006-07-15 08:45:20 +00:00
|
|
|
Code = "CurDAG->getTargetNode(Opc" + utostr(OpcNo);
|
2006-08-27 08:11:28 +00:00
|
|
|
unsigned OpsNo = OpcNo;
|
2006-07-15 08:45:20 +00:00
|
|
|
emitOpcode(II.Namespace + "::" + II.TheDef->getName());
|
2006-06-14 22:22:20 +00:00
|
|
|
|
|
|
|
// Output order: results, chain, flags
|
|
|
|
// Result types.
|
2006-07-16 06:12:52 +00:00
|
|
|
if (NumResults > 0 && N->getTypeNum(0) != MVT::isVoid) {
|
|
|
|
Code += ", VT" + utostr(VTNo);
|
|
|
|
emitVT(getEnumName(N->getTypeNum(0)));
|
|
|
|
}
|
2006-06-14 22:22:20 +00:00
|
|
|
if (NodeHasChain)
|
|
|
|
Code += ", MVT::Other";
|
|
|
|
if (NodeHasOutFlag)
|
|
|
|
Code += ", MVT::Flag";
|
|
|
|
|
2006-11-14 18:41:38 +00:00
|
|
|
// Figure out how many fixed inputs the node has. This is important to
|
|
|
|
// know which inputs are the variable ones if present.
|
|
|
|
unsigned NumInputs = AllOps.size();
|
|
|
|
NumInputs += NodeHasChain;
|
|
|
|
|
2006-06-14 22:22:20 +00:00
|
|
|
// Inputs.
|
2006-08-27 08:11:28 +00:00
|
|
|
if (HasVarOps) {
|
|
|
|
for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
|
|
|
|
emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
|
|
|
|
AllOps.clear();
|
2006-06-14 22:22:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (HasVarOps) {
|
2006-11-14 18:41:38 +00:00
|
|
|
// Figure out whether any operands at the end of the op list are not
|
|
|
|
// part of the variable section.
|
|
|
|
std::string EndAdjust;
|
2006-06-14 22:22:20 +00:00
|
|
|
if (NodeHasInFlag || HasImpInputs)
|
2006-11-14 18:41:38 +00:00
|
|
|
EndAdjust = "-1"; // Always has one flag.
|
|
|
|
else if (NodeHasOptInFlag)
|
|
|
|
EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
|
|
|
|
|
|
|
|
emitCode("for (unsigned i = " + utostr(NumInputs) +
|
|
|
|
", e = N.getNumOperands()" + EndAdjust + "; i != e; ++i) {");
|
|
|
|
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode(" AddToISelQueue(N.getOperand(i));");
|
2006-08-27 08:11:28 +00:00
|
|
|
emitCode(" Ops" + utostr(OpsNo) + ".push_back(N.getOperand(i));");
|
2006-06-14 22:22:20 +00:00
|
|
|
emitCode("}");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NodeHasChain) {
|
|
|
|
if (HasVarOps)
|
2006-08-27 08:11:28 +00:00
|
|
|
emitCode("Ops" + utostr(OpsNo) + ".push_back(" + ChainName + ");");
|
2006-06-14 22:22:20 +00:00
|
|
|
else
|
2006-08-27 08:11:28 +00:00
|
|
|
AllOps.push_back(ChainName);
|
2006-06-14 22:22:20 +00:00
|
|
|
}
|
2006-08-27 08:11:28 +00:00
|
|
|
|
|
|
|
if (HasVarOps) {
|
|
|
|
if (NodeHasInFlag || HasImpInputs)
|
|
|
|
emitCode("Ops" + utostr(OpsNo) + ".push_back(InFlag);");
|
|
|
|
else if (NodeHasOptInFlag) {
|
|
|
|
emitCode("if (HasInFlag)");
|
|
|
|
emitCode(" Ops" + utostr(OpsNo) + ".push_back(InFlag);");
|
2006-08-26 00:59:04 +00:00
|
|
|
}
|
2006-08-27 08:11:28 +00:00
|
|
|
Code += ", &Ops" + utostr(OpsNo) + "[0], Ops" + utostr(OpsNo) +
|
|
|
|
".size()";
|
|
|
|
} else if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
|
|
|
|
AllOps.push_back("InFlag");
|
|
|
|
|
|
|
|
unsigned NumOps = AllOps.size();
|
|
|
|
if (NumOps) {
|
|
|
|
if (!NodeHasOptInFlag && NumOps < 4) {
|
|
|
|
for (unsigned i = 0; i != NumOps; ++i)
|
|
|
|
Code += ", " + AllOps[i];
|
|
|
|
} else {
|
|
|
|
std::string OpsCode = "SDOperand Ops" + utostr(OpsNo) + "[] = { ";
|
|
|
|
for (unsigned i = 0; i != NumOps; ++i) {
|
|
|
|
OpsCode += AllOps[i];
|
|
|
|
if (i != NumOps-1)
|
|
|
|
OpsCode += ", ";
|
|
|
|
}
|
|
|
|
emitCode(OpsCode + " };");
|
|
|
|
Code += ", Ops" + utostr(OpsNo) + ", ";
|
|
|
|
if (NodeHasOptInFlag) {
|
|
|
|
Code += "HasInFlag ? ";
|
|
|
|
Code += utostr(NumOps) + " : " + utostr(NumOps-1);
|
|
|
|
} else
|
|
|
|
Code += utostr(NumOps);
|
2006-08-26 00:59:04 +00:00
|
|
|
}
|
|
|
|
}
|
2006-08-27 08:11:28 +00:00
|
|
|
|
2006-06-14 22:22:20 +00:00
|
|
|
if (!isRoot)
|
|
|
|
Code += "), 0";
|
|
|
|
emitCode(Code2 + Code + ");");
|
|
|
|
|
|
|
|
if (NodeHasChain)
|
|
|
|
// Remember which op produces the chain.
|
|
|
|
if (!isRoot)
|
|
|
|
emitCode(ChainName + " = SDOperand(" + NodeName +
|
|
|
|
".Val, " + utostr(PatResults) + ");");
|
|
|
|
else
|
|
|
|
emitCode(ChainName + " = SDOperand(" + NodeName +
|
|
|
|
", " + utostr(PatResults) + ");");
|
|
|
|
|
2006-08-26 00:59:04 +00:00
|
|
|
if (!isRoot) {
|
|
|
|
NodeOps.push_back("Tmp" + utostr(ResNo));
|
|
|
|
return NodeOps;
|
|
|
|
}
|
2006-05-10 00:05:46 +00:00
|
|
|
|
2006-08-11 08:59:35 +00:00
|
|
|
bool NeedReplace = false;
|
2006-08-26 00:59:04 +00:00
|
|
|
if (NodeHasOutFlag) {
|
|
|
|
if (!InFlagDecled) {
|
|
|
|
emitCode("SDOperand InFlag = SDOperand(ResNode, " +
|
|
|
|
utostr(NumResults + (unsigned)NodeHasChain) + ");");
|
|
|
|
InFlagDecled = true;
|
|
|
|
} else
|
|
|
|
emitCode("InFlag = SDOperand(ResNode, " +
|
|
|
|
utostr(NumResults + (unsigned)NodeHasChain) + ");");
|
|
|
|
}
|
2006-01-28 20:31:24 +00:00
|
|
|
|
2006-08-26 00:59:04 +00:00
|
|
|
if (HasImpResults && EmitCopyFromRegs(N, ResNodeDecled, ChainEmitted)) {
|
2006-08-09 16:44:44 +00:00
|
|
|
emitCode("ReplaceUses(SDOperand(N.Val, 0), SDOperand(ResNode, 0));");
|
2006-03-09 08:19:11 +00:00
|
|
|
NumResults = 1;
|
2005-12-22 02:24:50 +00:00
|
|
|
}
|
2005-12-20 07:37:41 +00:00
|
|
|
|
2005-12-22 02:24:50 +00:00
|
|
|
if (FoldedChains.size() > 0) {
|
2006-01-28 20:31:24 +00:00
|
|
|
std::string Code;
|
2005-12-19 07:18:51 +00:00
|
|
|
for (unsigned j = 0, e = FoldedChains.size(); j < e; j++)
|
2006-08-09 16:44:44 +00:00
|
|
|
emitCode("ReplaceUses(SDOperand(" +
|
2006-02-09 22:12:27 +00:00
|
|
|
FoldedChains[j].first + ".Val, " +
|
2006-08-09 16:44:44 +00:00
|
|
|
utostr(FoldedChains[j].second) + "), SDOperand(ResNode, " +
|
|
|
|
utostr(NumResults) + "));");
|
2006-08-11 08:59:35 +00:00
|
|
|
NeedReplace = true;
|
2005-12-09 22:45:35 +00:00
|
|
|
}
|
2005-12-19 22:40:04 +00:00
|
|
|
|
2006-08-11 08:59:35 +00:00
|
|
|
if (NodeHasOutFlag) {
|
2006-08-09 16:44:44 +00:00
|
|
|
emitCode("ReplaceUses(SDOperand(N.Val, " +
|
|
|
|
utostr(PatResults + (unsigned)InputHasChain) +"), InFlag);");
|
2006-08-11 08:59:35 +00:00
|
|
|
NeedReplace = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NeedReplace) {
|
|
|
|
for (unsigned i = 0; i < NumResults; i++)
|
|
|
|
emitCode("ReplaceUses(SDOperand(N.Val, " +
|
|
|
|
utostr(i) + "), SDOperand(ResNode, " + utostr(i) + "));");
|
|
|
|
if (InputHasChain)
|
|
|
|
emitCode("ReplaceUses(SDOperand(N.Val, " +
|
2006-09-21 18:28:27 +00:00
|
|
|
utostr(PatResults) + "), SDOperand(" + ChainName + ".Val, "
|
|
|
|
+ ChainName + ".ResNo" + "));");
|
2006-08-27 08:11:28 +00:00
|
|
|
} else
|
2006-08-11 08:59:35 +00:00
|
|
|
RetSelected = true;
|
2005-12-22 02:24:50 +00:00
|
|
|
|
2006-03-09 08:19:11 +00:00
|
|
|
// User does not expect the instruction would produce a chain!
|
2006-08-11 08:59:35 +00:00
|
|
|
if ((!InputHasChain && NodeHasChain) && NodeHasOutFlag) {
|
2006-08-26 05:34:46 +00:00
|
|
|
;
|
2006-05-10 02:47:57 +00:00
|
|
|
} else if (InputHasChain && !NodeHasChain) {
|
|
|
|
// One of the inner node produces a chain.
|
2006-08-26 05:34:46 +00:00
|
|
|
if (NodeHasOutFlag)
|
2006-08-11 08:59:35 +00:00
|
|
|
emitCode("ReplaceUses(SDOperand(N.Val, " + utostr(PatResults+1) +
|
|
|
|
"), SDOperand(ResNode, N.ResNo-1));");
|
|
|
|
for (unsigned i = 0; i < PatResults; ++i)
|
|
|
|
emitCode("ReplaceUses(SDOperand(N.Val, " + utostr(i) +
|
|
|
|
"), SDOperand(ResNode, " + utostr(i) + "));");
|
|
|
|
emitCode("ReplaceUses(SDOperand(N.Val, " + utostr(PatResults) +
|
|
|
|
"), " + ChainName + ");");
|
|
|
|
RetSelected = false;
|
2005-12-20 07:37:41 +00:00
|
|
|
}
|
2006-08-11 08:59:35 +00:00
|
|
|
|
|
|
|
if (RetSelected)
|
2006-08-26 05:34:46 +00:00
|
|
|
emitCode("return ResNode;");
|
2006-08-11 08:59:35 +00:00
|
|
|
else
|
|
|
|
emitCode("return NULL;");
|
2005-12-09 22:45:35 +00:00
|
|
|
} else {
|
2006-08-26 05:34:46 +00:00
|
|
|
std::string Code = "return CurDAG->SelectNodeTo(N.Val, Opc" +
|
2006-07-15 08:45:20 +00:00
|
|
|
utostr(OpcNo);
|
2005-12-30 00:12:56 +00:00
|
|
|
if (N->getTypeNum(0) != MVT::isVoid)
|
2006-07-16 06:12:52 +00:00
|
|
|
Code += ", VT" + utostr(VTNo);
|
2006-01-26 00:22:25 +00:00
|
|
|
if (NodeHasOutFlag)
|
2006-01-28 20:31:24 +00:00
|
|
|
Code += ", MVT::Flag";
|
2006-08-27 08:11:28 +00:00
|
|
|
|
|
|
|
if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
|
|
|
|
AllOps.push_back("InFlag");
|
|
|
|
|
|
|
|
unsigned NumOps = AllOps.size();
|
|
|
|
if (NumOps) {
|
|
|
|
if (!NodeHasOptInFlag && NumOps < 4) {
|
|
|
|
for (unsigned i = 0; i != NumOps; ++i)
|
|
|
|
Code += ", " + AllOps[i];
|
|
|
|
} else {
|
|
|
|
std::string OpsCode = "SDOperand Ops" + utostr(OpcNo) + "[] = { ";
|
|
|
|
for (unsigned i = 0; i != NumOps; ++i) {
|
|
|
|
OpsCode += AllOps[i];
|
|
|
|
if (i != NumOps-1)
|
|
|
|
OpsCode += ", ";
|
|
|
|
}
|
|
|
|
emitCode(OpsCode + " };");
|
|
|
|
Code += ", Ops" + utostr(OpcNo) + ", ";
|
|
|
|
Code += utostr(NumOps);
|
|
|
|
}
|
|
|
|
}
|
2006-08-26 08:00:10 +00:00
|
|
|
emitCode(Code + ");");
|
2006-07-15 08:45:20 +00:00
|
|
|
emitOpcode(II.Namespace + "::" + II.TheDef->getName());
|
2006-08-26 00:59:04 +00:00
|
|
|
if (N->getTypeNum(0) != MVT::isVoid)
|
2006-07-16 06:12:52 +00:00
|
|
|
emitVT(getEnumName(N->getTypeNum(0)));
|
2005-12-04 08:18:16 +00:00
|
|
|
}
|
2005-12-20 07:37:41 +00:00
|
|
|
|
2006-08-26 00:59:04 +00:00
|
|
|
return NodeOps;
|
2005-12-09 22:45:35 +00:00
|
|
|
} else if (Op->isSubClassOf("SDNodeXForm")) {
|
|
|
|
assert(N->getNumChildren() == 1 && "node xform should have one child!");
|
2006-03-20 22:53:06 +00:00
|
|
|
// PatLeaf node - the operand may or may not be a leaf node. But it should
|
|
|
|
// behave like one.
|
2006-08-26 00:59:04 +00:00
|
|
|
std::vector<std::string> Ops =
|
|
|
|
EmitResultCode(N->getChild(0), RetSelected, InFlagDecled,
|
|
|
|
ResNodeDecled, true);
|
2005-12-09 22:45:35 +00:00
|
|
|
unsigned ResNo = TmpNo++;
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("SDOperand Tmp" + utostr(ResNo) + " = Transform_" + Op->getName()
|
|
|
|
+ "(" + Ops.back() + ".Val);");
|
|
|
|
NodeOps.push_back("Tmp" + utostr(ResNo));
|
2006-08-26 05:34:46 +00:00
|
|
|
if (isRoot)
|
|
|
|
emitCode("return Tmp" + utostr(ResNo) + ".Val;");
|
2006-08-26 00:59:04 +00:00
|
|
|
return NodeOps;
|
2005-12-09 22:45:35 +00:00
|
|
|
} else {
|
|
|
|
N->dump();
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "\n";
|
2006-01-11 01:33:49 +00:00
|
|
|
throw std::string("Unknown node in result pattern!");
|
2005-10-16 01:41:58 +00:00
|
|
|
}
|
2005-09-24 00:40:24 +00:00
|
|
|
}
|
|
|
|
|
2006-01-28 19:06:51 +00:00
|
|
|
/// InsertOneTypeCheck - Insert a type-check for an unresolved type in 'Pat'
|
|
|
|
/// and add it to the tree. 'Pat' and 'Other' are isomorphic trees except that
|
2005-12-09 22:45:35 +00:00
|
|
|
/// 'Pat' may be missing types. If we find an unresolved type to add a check
|
|
|
|
/// for, this returns true otherwise false if Pat has all types.
|
|
|
|
bool InsertOneTypeCheck(TreePatternNode *Pat, TreePatternNode *Other,
|
2006-08-09 16:44:44 +00:00
|
|
|
const std::string &Prefix, bool isRoot = false) {
|
2005-12-09 22:45:35 +00:00
|
|
|
// Did we find one?
|
2006-05-19 07:24:32 +00:00
|
|
|
if (Pat->getExtTypes() != Other->getExtTypes()) {
|
2005-12-09 22:45:35 +00:00
|
|
|
// Move a type over from 'other' to 'pat'.
|
2005-12-30 00:12:56 +00:00
|
|
|
Pat->setTypes(Other->getExtTypes());
|
2006-08-09 16:44:44 +00:00
|
|
|
// The top level node type is checked outside of the select function.
|
|
|
|
if (!isRoot)
|
|
|
|
emitCheck(Prefix + ".Val->getValueType(0) == " +
|
|
|
|
getName(Pat->getTypeNum(0)));
|
2005-12-09 22:45:35 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-01-09 18:27:06 +00:00
|
|
|
unsigned OpNo =
|
2006-10-11 21:02:01 +00:00
|
|
|
(unsigned) NodeHasProperty(Pat, SDNPHasChain, ISE);
|
2005-12-09 22:45:35 +00:00
|
|
|
for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i, ++OpNo)
|
|
|
|
if (InsertOneTypeCheck(Pat->getChild(i), Other->getChild(i),
|
|
|
|
Prefix + utostr(OpNo)))
|
|
|
|
return true;
|
2005-10-15 21:34:21 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-12-09 22:45:35 +00:00
|
|
|
private:
|
2006-01-26 00:22:25 +00:00
|
|
|
/// EmitInFlagSelectCode - Emit the flag operands for the DAG that is
|
2005-12-09 22:45:35 +00:00
|
|
|
/// being built.
|
2006-01-26 00:22:25 +00:00
|
|
|
void EmitInFlagSelectCode(TreePatternNode *N, const std::string &RootName,
|
2006-08-26 00:59:04 +00:00
|
|
|
bool &ChainEmitted, bool &InFlagDecled,
|
|
|
|
bool &ResNodeDecled, bool isRoot = false) {
|
2005-12-09 22:45:35 +00:00
|
|
|
const CodeGenTarget &T = ISE.getTargetInfo();
|
2006-01-09 18:27:06 +00:00
|
|
|
unsigned OpNo =
|
2006-10-11 21:02:01 +00:00
|
|
|
(unsigned) NodeHasProperty(N, SDNPHasChain, ISE);
|
|
|
|
bool HasInFlag = NodeHasProperty(N, SDNPInFlag, ISE);
|
2005-12-09 22:45:35 +00:00
|
|
|
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
|
|
|
|
TreePatternNode *Child = N->getChild(i);
|
|
|
|
if (!Child->isLeaf()) {
|
2006-08-26 00:59:04 +00:00
|
|
|
EmitInFlagSelectCode(Child, RootName + utostr(OpNo), ChainEmitted,
|
|
|
|
InFlagDecled, ResNodeDecled);
|
2005-12-09 22:45:35 +00:00
|
|
|
} else {
|
|
|
|
if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
|
2006-01-19 01:55:45 +00:00
|
|
|
if (!Child->getName().empty()) {
|
|
|
|
std::string Name = RootName + utostr(OpNo);
|
|
|
|
if (Duplicates.find(Name) != Duplicates.end())
|
|
|
|
// A duplicate! Do not emit a copy for this node.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2005-12-09 22:45:35 +00:00
|
|
|
Record *RR = DI->getDef();
|
|
|
|
if (RR->isSubClassOf("Register")) {
|
|
|
|
MVT::ValueType RVT = getRegisterValueType(RR, T);
|
2005-12-17 01:19:28 +00:00
|
|
|
if (RVT == MVT::Flag) {
|
2006-08-26 00:59:04 +00:00
|
|
|
if (!InFlagDecled) {
|
|
|
|
emitCode("SDOperand InFlag = " + RootName + utostr(OpNo) + ";");
|
|
|
|
InFlagDecled = true;
|
|
|
|
} else
|
|
|
|
emitCode("InFlag = " + RootName + utostr(OpNo) + ";");
|
|
|
|
emitCode("AddToISelQueue(InFlag);");
|
2006-01-11 22:16:13 +00:00
|
|
|
} else {
|
|
|
|
if (!ChainEmitted) {
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("SDOperand Chain = CurDAG->getEntryNode();");
|
2006-02-03 06:22:41 +00:00
|
|
|
ChainName = "Chain";
|
2006-01-11 22:16:13 +00:00
|
|
|
ChainEmitted = true;
|
|
|
|
}
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("AddToISelQueue(" + RootName + utostr(OpNo) + ");");
|
|
|
|
if (!InFlagDecled) {
|
|
|
|
emitCode("SDOperand InFlag(0, 0);");
|
|
|
|
InFlagDecled = true;
|
|
|
|
}
|
|
|
|
std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
|
|
|
|
emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName +
|
2006-08-26 07:39:28 +00:00
|
|
|
", " + ISE.getQualifiedName(RR) +
|
|
|
|
", " + RootName + utostr(OpNo) + ", InFlag).Val;");
|
2006-08-26 00:59:04 +00:00
|
|
|
ResNodeDecled = true;
|
2006-02-09 22:12:27 +00:00
|
|
|
emitCode(ChainName + " = SDOperand(ResNode, 0);");
|
|
|
|
emitCode("InFlag = SDOperand(ResNode, 1);");
|
2005-12-09 22:45:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-01-26 00:22:25 +00:00
|
|
|
|
2006-08-26 00:59:04 +00:00
|
|
|
if (HasInFlag) {
|
|
|
|
if (!InFlagDecled) {
|
|
|
|
emitCode("SDOperand InFlag = " + RootName +
|
|
|
|
".getOperand(" + utostr(OpNo) + ");");
|
|
|
|
InFlagDecled = true;
|
|
|
|
} else
|
|
|
|
emitCode("InFlag = " + RootName +
|
|
|
|
".getOperand(" + utostr(OpNo) + ");");
|
|
|
|
emitCode("AddToISelQueue(InFlag);");
|
|
|
|
}
|
2005-12-09 22:45:35 +00:00
|
|
|
}
|
2005-12-20 07:37:41 +00:00
|
|
|
|
|
|
|
/// EmitCopyFromRegs - Emit code to copy result to physical registers
|
2005-12-23 22:11:47 +00:00
|
|
|
/// as specified by the instruction. It returns true if any copy is
|
|
|
|
/// emitted.
|
2006-08-26 00:59:04 +00:00
|
|
|
bool EmitCopyFromRegs(TreePatternNode *N, bool &ResNodeDecled,
|
|
|
|
bool &ChainEmitted) {
|
2005-12-23 22:11:47 +00:00
|
|
|
bool RetVal = false;
|
2005-12-20 07:37:41 +00:00
|
|
|
Record *Op = N->getOperator();
|
|
|
|
if (Op->isSubClassOf("Instruction")) {
|
|
|
|
const DAGInstruction &Inst = ISE.getInstruction(Op);
|
|
|
|
const CodeGenTarget &CGT = ISE.getTargetInfo();
|
|
|
|
unsigned NumImpResults = Inst.getNumImpResults();
|
|
|
|
for (unsigned i = 0; i < NumImpResults; i++) {
|
|
|
|
Record *RR = Inst.getImpResult(i);
|
|
|
|
if (RR->isSubClassOf("Register")) {
|
|
|
|
MVT::ValueType RVT = getRegisterValueType(RR, CGT);
|
|
|
|
if (RVT != MVT::Flag) {
|
2006-01-11 22:16:13 +00:00
|
|
|
if (!ChainEmitted) {
|
2006-08-26 00:59:04 +00:00
|
|
|
emitCode("SDOperand Chain = CurDAG->getEntryNode();");
|
2006-01-11 22:16:13 +00:00
|
|
|
ChainEmitted = true;
|
2006-02-03 06:22:41 +00:00
|
|
|
ChainName = "Chain";
|
2005-12-20 07:37:41 +00:00
|
|
|
}
|
2006-08-26 00:59:04 +00:00
|
|
|
std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
|
|
|
|
emitCode(Decl + "ResNode = CurDAG->getCopyFromReg(" + ChainName +
|
2006-07-15 08:45:20 +00:00
|
|
|
", " + ISE.getQualifiedName(RR) + ", " + getEnumName(RVT) +
|
2006-02-09 07:16:09 +00:00
|
|
|
", InFlag).Val;");
|
2006-08-26 00:59:04 +00:00
|
|
|
ResNodeDecled = true;
|
2006-02-09 07:16:09 +00:00
|
|
|
emitCode(ChainName + " = SDOperand(ResNode, 1);");
|
|
|
|
emitCode("InFlag = SDOperand(ResNode, 2);");
|
2005-12-23 22:11:47 +00:00
|
|
|
RetVal = true;
|
2005-12-20 07:37:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-12-23 22:11:47 +00:00
|
|
|
return RetVal;
|
2005-12-20 07:37:41 +00:00
|
|
|
}
|
2005-12-09 22:45:35 +00:00
|
|
|
};
|
2005-11-02 06:49:14 +00:00
|
|
|
|
2005-09-23 21:33:23 +00:00
|
|
|
/// EmitCodeForPattern - Given a pattern to match, emit code to the specified
|
|
|
|
/// stream to match the pattern, and generate the code for the match if it
|
2006-01-29 02:43:35 +00:00
|
|
|
/// succeeds. Returns true if the pattern is not guaranteed to match.
|
2006-01-29 04:25:26 +00:00
|
|
|
void DAGISelEmitter::GenerateCodeForPattern(PatternToMatch &Pattern,
|
2006-08-26 00:59:04 +00:00
|
|
|
std::vector<std::pair<unsigned, std::string> > &GeneratedCode,
|
2006-08-26 01:02:19 +00:00
|
|
|
std::set<std::string> &GeneratedDecl,
|
2006-07-15 08:45:20 +00:00
|
|
|
std::vector<std::string> &TargetOpcodes,
|
2006-08-26 01:02:19 +00:00
|
|
|
std::vector<std::string> &TargetVTs) {
|
2005-12-14 22:02:59 +00:00
|
|
|
PatternCodeEmitter Emitter(*this, Pattern.getPredicates(),
|
|
|
|
Pattern.getSrcPattern(), Pattern.getDstPattern(),
|
2006-07-16 06:12:52 +00:00
|
|
|
GeneratedCode, GeneratedDecl,
|
2006-08-09 16:44:44 +00:00
|
|
|
TargetOpcodes, TargetVTs);
|
2005-12-09 22:45:35 +00:00
|
|
|
|
2005-09-23 23:16:51 +00:00
|
|
|
// Emit the matcher, capturing named arguments in VariableMap.
|
2005-12-23 22:11:47 +00:00
|
|
|
bool FoundChain = false;
|
2006-10-16 06:33:44 +00:00
|
|
|
Emitter.EmitMatchCode(Pattern.getSrcPattern(), NULL, "N", "", FoundChain);
|
2005-12-09 22:45:35 +00:00
|
|
|
|
2005-10-14 04:11:13 +00:00
|
|
|
// TP - Get *SOME* tree pattern, we don't care which.
|
|
|
|
TreePattern &TP = *PatternFragments.begin()->second;
|
|
|
|
|
|
|
|
// At this point, we know that we structurally match the pattern, but the
|
|
|
|
// types of the nodes may not match. Figure out the fewest number of type
|
|
|
|
// comparisons we need to emit. For example, if there is only one integer
|
|
|
|
// type supported by a target, there should be no type comparisons at all for
|
|
|
|
// integer patterns!
|
|
|
|
//
|
|
|
|
// To figure out the fewest number of type checks needed, clone the pattern,
|
|
|
|
// remove the types, then perform type inference on the pattern as a whole.
|
|
|
|
// If there are unresolved types, emit an explicit check for those types,
|
|
|
|
// apply the type to the tree, then rerun type inference. Iterate until all
|
|
|
|
// types are resolved.
|
|
|
|
//
|
2005-12-14 22:02:59 +00:00
|
|
|
TreePatternNode *Pat = Pattern.getSrcPattern()->clone();
|
2005-10-14 04:11:13 +00:00
|
|
|
RemoveAllTypes(Pat);
|
|
|
|
|
2005-10-15 21:34:21 +00:00
|
|
|
do {
|
|
|
|
// Resolve/propagate as many types as possible.
|
|
|
|
try {
|
|
|
|
bool MadeChange = true;
|
|
|
|
while (MadeChange)
|
2006-01-28 19:06:51 +00:00
|
|
|
MadeChange = Pat->ApplyTypeConstraints(TP,
|
|
|
|
true/*Ignore reg constraints*/);
|
2005-10-15 21:34:21 +00:00
|
|
|
} catch (...) {
|
|
|
|
assert(0 && "Error: could not find consistent types for something we"
|
|
|
|
" already decided was ok!");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert a check for an unresolved type and add it to the tree. If we find
|
|
|
|
// an unresolved type to add a check for, this returns true and we iterate,
|
|
|
|
// otherwise we are done.
|
2006-08-09 16:44:44 +00:00
|
|
|
} while (Emitter.InsertOneTypeCheck(Pat, Pattern.getSrcPattern(), "N", true));
|
2005-12-09 22:45:35 +00:00
|
|
|
|
2006-08-26 00:59:04 +00:00
|
|
|
Emitter.EmitResultCode(Pattern.getDstPattern(),
|
|
|
|
false, false, false, false, true);
|
2005-10-14 04:11:13 +00:00
|
|
|
delete Pat;
|
2005-09-23 20:52:47 +00:00
|
|
|
}
|
|
|
|
|
2006-01-29 04:41:05 +00:00
|
|
|
/// EraseCodeLine - Erase one code line from all of the patterns. If removing
|
|
|
|
/// a line causes any of them to be empty, remove them and return true when
|
|
|
|
/// done.
|
|
|
|
static bool EraseCodeLine(std::vector<std::pair<PatternToMatch*,
|
2006-08-26 00:59:04 +00:00
|
|
|
std::vector<std::pair<unsigned, std::string> > > >
|
2006-01-29 04:41:05 +00:00
|
|
|
&Patterns) {
|
|
|
|
bool ErasedPatterns = false;
|
|
|
|
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
|
|
|
|
Patterns[i].second.pop_back();
|
|
|
|
if (Patterns[i].second.empty()) {
|
|
|
|
Patterns.erase(Patterns.begin()+i);
|
|
|
|
--i; --e;
|
|
|
|
ErasedPatterns = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ErasedPatterns;
|
|
|
|
}
|
|
|
|
|
2006-01-29 04:25:26 +00:00
|
|
|
/// EmitPatterns - Emit code for at least one pattern, but try to group common
|
|
|
|
/// code together between the patterns.
|
|
|
|
void DAGISelEmitter::EmitPatterns(std::vector<std::pair<PatternToMatch*,
|
2006-08-26 00:59:04 +00:00
|
|
|
std::vector<std::pair<unsigned, std::string> > > >
|
2006-01-29 04:25:26 +00:00
|
|
|
&Patterns, unsigned Indent,
|
|
|
|
std::ostream &OS) {
|
2006-08-26 00:59:04 +00:00
|
|
|
typedef std::pair<unsigned, std::string> CodeLine;
|
2006-01-29 04:25:26 +00:00
|
|
|
typedef std::vector<CodeLine> CodeList;
|
|
|
|
typedef std::vector<std::pair<PatternToMatch*, CodeList> > PatternList;
|
|
|
|
|
|
|
|
if (Patterns.empty()) return;
|
|
|
|
|
2006-01-29 04:41:05 +00:00
|
|
|
// Figure out how many patterns share the next code line. Explicitly copy
|
|
|
|
// FirstCodeLine so that we don't invalidate a reference when changing
|
|
|
|
// Patterns.
|
|
|
|
const CodeLine FirstCodeLine = Patterns.back().second.back();
|
2006-01-29 04:25:26 +00:00
|
|
|
unsigned LastMatch = Patterns.size()-1;
|
|
|
|
while (LastMatch != 0 && Patterns[LastMatch-1].second.back() == FirstCodeLine)
|
|
|
|
--LastMatch;
|
|
|
|
|
|
|
|
// If not all patterns share this line, split the list into two pieces. The
|
|
|
|
// first chunk will use this line, the second chunk won't.
|
|
|
|
if (LastMatch != 0) {
|
|
|
|
PatternList Shared(Patterns.begin()+LastMatch, Patterns.end());
|
|
|
|
PatternList Other(Patterns.begin(), Patterns.begin()+LastMatch);
|
|
|
|
|
|
|
|
// FIXME: Emit braces?
|
|
|
|
if (Shared.size() == 1) {
|
|
|
|
PatternToMatch &Pattern = *Shared.back().first;
|
|
|
|
OS << "\n" << std::string(Indent, ' ') << "// Pattern: ";
|
|
|
|
Pattern.getSrcPattern()->print(OS);
|
|
|
|
OS << "\n" << std::string(Indent, ' ') << "// Emits: ";
|
|
|
|
Pattern.getDstPattern()->print(OS);
|
|
|
|
OS << "\n";
|
2006-04-19 20:36:09 +00:00
|
|
|
unsigned AddedComplexity = Pattern.getAddedComplexity();
|
2006-01-29 04:25:26 +00:00
|
|
|
OS << std::string(Indent, ' ') << "// Pattern complexity = "
|
2006-04-19 20:36:09 +00:00
|
|
|
<< getPatternSize(Pattern.getSrcPattern(), *this) + AddedComplexity
|
2006-04-19 18:07:24 +00:00
|
|
|
<< " cost = "
|
2006-07-19 00:24:41 +00:00
|
|
|
<< getResultPatternCost(Pattern.getDstPattern(), *this)
|
|
|
|
<< " size = "
|
|
|
|
<< getResultPatternSize(Pattern.getDstPattern(), *this) << "\n";
|
2006-01-29 04:25:26 +00:00
|
|
|
}
|
2006-08-26 00:59:04 +00:00
|
|
|
if (FirstCodeLine.first != 1) {
|
2006-01-29 04:25:26 +00:00
|
|
|
OS << std::string(Indent, ' ') << "{\n";
|
|
|
|
Indent += 2;
|
|
|
|
}
|
|
|
|
EmitPatterns(Shared, Indent, OS);
|
2006-08-26 00:59:04 +00:00
|
|
|
if (FirstCodeLine.first != 1) {
|
2006-01-29 04:25:26 +00:00
|
|
|
Indent -= 2;
|
|
|
|
OS << std::string(Indent, ' ') << "}\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Other.size() == 1) {
|
|
|
|
PatternToMatch &Pattern = *Other.back().first;
|
|
|
|
OS << "\n" << std::string(Indent, ' ') << "// Pattern: ";
|
|
|
|
Pattern.getSrcPattern()->print(OS);
|
|
|
|
OS << "\n" << std::string(Indent, ' ') << "// Emits: ";
|
|
|
|
Pattern.getDstPattern()->print(OS);
|
|
|
|
OS << "\n";
|
2006-04-19 20:36:09 +00:00
|
|
|
unsigned AddedComplexity = Pattern.getAddedComplexity();
|
2006-01-29 04:25:26 +00:00
|
|
|
OS << std::string(Indent, ' ') << "// Pattern complexity = "
|
2006-04-19 20:36:09 +00:00
|
|
|
<< getPatternSize(Pattern.getSrcPattern(), *this) + AddedComplexity
|
2006-04-19 18:07:24 +00:00
|
|
|
<< " cost = "
|
2006-08-09 16:44:44 +00:00
|
|
|
<< getResultPatternCost(Pattern.getDstPattern(), *this)
|
|
|
|
<< " size = "
|
|
|
|
<< getResultPatternSize(Pattern.getDstPattern(), *this) << "\n";
|
2006-01-29 04:25:26 +00:00
|
|
|
}
|
|
|
|
EmitPatterns(Other, Indent, OS);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-01-29 04:41:05 +00:00
|
|
|
// Remove this code from all of the patterns that share it.
|
|
|
|
bool ErasedPatterns = EraseCodeLine(Patterns);
|
|
|
|
|
2006-08-26 00:59:04 +00:00
|
|
|
bool isPredicate = FirstCodeLine.first == 1;
|
2006-01-29 04:25:26 +00:00
|
|
|
|
|
|
|
// Otherwise, every pattern in the list has this line. Emit it.
|
|
|
|
if (!isPredicate) {
|
|
|
|
// Normal code.
|
|
|
|
OS << std::string(Indent, ' ') << FirstCodeLine.second << "\n";
|
|
|
|
} else {
|
2006-01-29 04:41:05 +00:00
|
|
|
OS << std::string(Indent, ' ') << "if (" << FirstCodeLine.second;
|
|
|
|
|
|
|
|
// If the next code line is another predicate, and if all of the pattern
|
|
|
|
// in this group share the same next line, emit it inline now. Do this
|
|
|
|
// until we run out of common predicates.
|
2006-08-26 00:59:04 +00:00
|
|
|
while (!ErasedPatterns && Patterns.back().second.back().first == 1) {
|
2006-01-29 04:41:05 +00:00
|
|
|
// Check that all of fhe patterns in Patterns end with the same predicate.
|
|
|
|
bool AllEndWithSamePredicate = true;
|
|
|
|
for (unsigned i = 0, e = Patterns.size(); i != e; ++i)
|
|
|
|
if (Patterns[i].second.back() != Patterns.back().second.back()) {
|
|
|
|
AllEndWithSamePredicate = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// If all of the predicates aren't the same, we can't share them.
|
|
|
|
if (!AllEndWithSamePredicate) break;
|
|
|
|
|
|
|
|
// Otherwise we can. Emit it shared now.
|
|
|
|
OS << " &&\n" << std::string(Indent+4, ' ')
|
|
|
|
<< Patterns.back().second.back().second;
|
|
|
|
ErasedPatterns = EraseCodeLine(Patterns);
|
2006-01-29 04:25:26 +00:00
|
|
|
}
|
2006-01-29 04:41:05 +00:00
|
|
|
|
|
|
|
OS << ") {\n";
|
|
|
|
Indent += 2;
|
2006-01-29 04:25:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EmitPatterns(Patterns, Indent, OS);
|
|
|
|
|
|
|
|
if (isPredicate)
|
|
|
|
OS << std::string(Indent-2, ' ') << "}\n";
|
|
|
|
}
|
|
|
|
|
2006-11-08 23:01:03 +00:00
|
|
|
static std::string getOpcodeName(Record *Op, DAGISelEmitter &ISE) {
|
|
|
|
const SDNodeInfo &OpcodeInfo = ISE.getSDNodeInfo(Op);
|
|
|
|
return OpcodeInfo.getEnumName();
|
|
|
|
}
|
2006-01-29 04:25:26 +00:00
|
|
|
|
2006-11-08 23:01:03 +00:00
|
|
|
static std::string getLegalCName(std::string OpName) {
|
|
|
|
std::string::size_type pos = OpName.find("::");
|
|
|
|
if (pos != std::string::npos)
|
|
|
|
OpName.replace(pos, 2, "_");
|
|
|
|
return OpName;
|
2005-09-26 21:59:35 +00:00
|
|
|
}
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
|
2006-11-20 18:54:33 +00:00
|
|
|
// Get the namespace to insert instructions into. Make sure not to pick up
|
|
|
|
// "TargetInstrInfo" by accidentally getting the namespace off the PHI
|
|
|
|
// instruction or something.
|
|
|
|
std::string InstNS;
|
|
|
|
for (CodeGenTarget::inst_iterator i = Target.inst_begin(),
|
|
|
|
e = Target.inst_end(); i != e; ++i) {
|
|
|
|
InstNS = i->second.Namespace;
|
|
|
|
if (InstNS != "TargetInstrInfo")
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-10-18 04:41:01 +00:00
|
|
|
if (!InstNS.empty()) InstNS += "::";
|
|
|
|
|
2006-01-04 00:25:00 +00:00
|
|
|
// Group the patterns by their top-level opcodes.
|
2006-11-08 23:01:03 +00:00
|
|
|
std::map<std::string, std::vector<PatternToMatch*> > PatternsByOpcode;
|
2006-07-15 08:45:20 +00:00
|
|
|
// All unique target node emission functions.
|
|
|
|
std::map<std::string, unsigned> EmitFunctions;
|
2006-01-04 00:25:00 +00:00
|
|
|
for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
|
|
|
|
TreePatternNode *Node = PatternsToMatch[i].getSrcPattern();
|
|
|
|
if (!Node->isLeaf()) {
|
2006-11-08 23:01:03 +00:00
|
|
|
PatternsByOpcode[getOpcodeName(Node->getOperator(), *this)].
|
|
|
|
push_back(&PatternsToMatch[i]);
|
2006-01-04 00:25:00 +00:00
|
|
|
} else {
|
|
|
|
const ComplexPattern *CP;
|
2006-11-03 01:11:05 +00:00
|
|
|
if (dynamic_cast<IntInit*>(Node->getLeafValue())) {
|
2006-11-08 23:01:03 +00:00
|
|
|
PatternsByOpcode[getOpcodeName(getSDNodeNamed("imm"), *this)].
|
|
|
|
push_back(&PatternsToMatch[i]);
|
2006-11-02 21:07:40 +00:00
|
|
|
} else if ((CP = NodeGetComplexPattern(Node, *this))) {
|
2006-01-04 00:25:00 +00:00
|
|
|
std::vector<Record*> OpNodes = CP->getRootNodes();
|
|
|
|
for (unsigned j = 0, e = OpNodes.size(); j != e; j++) {
|
2006-11-08 23:01:03 +00:00
|
|
|
PatternsByOpcode[getOpcodeName(OpNodes[j], *this)]
|
|
|
|
.insert(PatternsByOpcode[getOpcodeName(OpNodes[j], *this)].begin(),
|
|
|
|
&PatternsToMatch[i]);
|
2006-01-04 00:25:00 +00:00
|
|
|
}
|
|
|
|
} else {
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "Unrecognized opcode '";
|
2006-01-04 00:25:00 +00:00
|
|
|
Node->dump();
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "' on tree pattern '";
|
|
|
|
cerr << PatternsToMatch[i].getDstPattern()->getOperator()->getName();
|
|
|
|
cerr << "'!\n";
|
2006-01-04 00:25:00 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-08-09 16:44:44 +00:00
|
|
|
|
|
|
|
// For each opcode, there might be multiple select functions, one per
|
|
|
|
// ValueType of the node (or its first operand if it doesn't produce a
|
|
|
|
// non-chain result.
|
|
|
|
std::map<std::string, std::vector<std::string> > OpcodeVTMap;
|
|
|
|
|
2006-01-04 00:25:00 +00:00
|
|
|
// Emit one Select_* method for each top-level opcode. We do this instead of
|
|
|
|
// emitting one giant switch statement to support compilers where this will
|
|
|
|
// result in the recursive functions taking less stack space.
|
2006-11-08 23:01:03 +00:00
|
|
|
for (std::map<std::string, std::vector<PatternToMatch*> >::iterator
|
|
|
|
PBOI = PatternsByOpcode.begin(), E = PatternsByOpcode.end();
|
|
|
|
PBOI != E; ++PBOI) {
|
|
|
|
const std::string &OpName = PBOI->first;
|
2006-08-09 16:44:44 +00:00
|
|
|
std::vector<PatternToMatch*> &PatternsOfOp = PBOI->second;
|
|
|
|
assert(!PatternsOfOp.empty() && "No patterns but map has entry?");
|
|
|
|
|
2006-01-04 00:25:00 +00:00
|
|
|
// We want to emit all of the matching code now. However, we want to emit
|
|
|
|
// the matches in order of minimal cost. Sort the patterns so the least
|
|
|
|
// cost one is at the start.
|
2006-08-09 16:44:44 +00:00
|
|
|
std::stable_sort(PatternsOfOp.begin(), PatternsOfOp.end(),
|
2006-01-04 00:25:00 +00:00
|
|
|
PatternSortingPredicate(*this));
|
2006-02-07 00:37:41 +00:00
|
|
|
|
2006-08-09 16:44:44 +00:00
|
|
|
// Split them into groups by type.
|
|
|
|
std::map<MVT::ValueType, std::vector<PatternToMatch*> > PatternsByType;
|
|
|
|
for (unsigned i = 0, e = PatternsOfOp.size(); i != e; ++i) {
|
|
|
|
PatternToMatch *Pat = PatternsOfOp[i];
|
|
|
|
TreePatternNode *SrcPat = Pat->getSrcPattern();
|
|
|
|
MVT::ValueType VT = SrcPat->getTypeNum(0);
|
|
|
|
std::map<MVT::ValueType, std::vector<PatternToMatch*> >::iterator TI =
|
|
|
|
PatternsByType.find(VT);
|
|
|
|
if (TI != PatternsByType.end())
|
|
|
|
TI->second.push_back(Pat);
|
|
|
|
else {
|
|
|
|
std::vector<PatternToMatch*> PVec;
|
|
|
|
PVec.push_back(Pat);
|
|
|
|
PatternsByType.insert(std::make_pair(VT, PVec));
|
|
|
|
}
|
2006-08-09 16:41:21 +00:00
|
|
|
}
|
2006-08-09 16:44:44 +00:00
|
|
|
|
|
|
|
for (std::map<MVT::ValueType, std::vector<PatternToMatch*> >::iterator
|
|
|
|
II = PatternsByType.begin(), EE = PatternsByType.end(); II != EE;
|
|
|
|
++II) {
|
|
|
|
MVT::ValueType OpVT = II->first;
|
|
|
|
std::vector<PatternToMatch*> &Patterns = II->second;
|
2006-09-21 18:28:27 +00:00
|
|
|
typedef std::vector<std::pair<unsigned,std::string> > CodeList;
|
|
|
|
typedef std::vector<std::pair<unsigned,std::string> >::iterator CodeListI;
|
2006-07-28 22:51:01 +00:00
|
|
|
|
2006-08-09 16:44:44 +00:00
|
|
|
std::vector<std::pair<PatternToMatch*, CodeList> > CodeForPatterns;
|
|
|
|
std::vector<std::vector<std::string> > PatternOpcodes;
|
|
|
|
std::vector<std::vector<std::string> > PatternVTs;
|
2006-08-26 01:02:19 +00:00
|
|
|
std::vector<std::set<std::string> > PatternDecls;
|
2006-08-09 16:44:44 +00:00
|
|
|
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
|
|
|
|
CodeList GeneratedCode;
|
2006-08-26 01:02:19 +00:00
|
|
|
std::set<std::string> GeneratedDecl;
|
2006-08-09 16:44:44 +00:00
|
|
|
std::vector<std::string> TargetOpcodes;
|
|
|
|
std::vector<std::string> TargetVTs;
|
|
|
|
GenerateCodeForPattern(*Patterns[i], GeneratedCode, GeneratedDecl,
|
|
|
|
TargetOpcodes, TargetVTs);
|
|
|
|
CodeForPatterns.push_back(std::make_pair(Patterns[i], GeneratedCode));
|
|
|
|
PatternDecls.push_back(GeneratedDecl);
|
|
|
|
PatternOpcodes.push_back(TargetOpcodes);
|
|
|
|
PatternVTs.push_back(TargetVTs);
|
2006-08-09 16:41:21 +00:00
|
|
|
}
|
2006-08-09 16:44:44 +00:00
|
|
|
|
|
|
|
// Scan the code to see if all of the patterns are reachable and if it is
|
|
|
|
// possible that the last one might not match.
|
|
|
|
bool mightNotMatch = true;
|
|
|
|
for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) {
|
|
|
|
CodeList &GeneratedCode = CodeForPatterns[i].second;
|
|
|
|
mightNotMatch = false;
|
|
|
|
|
|
|
|
for (unsigned j = 0, e = GeneratedCode.size(); j != e; ++j) {
|
2006-08-26 00:59:04 +00:00
|
|
|
if (GeneratedCode[j].first == 1) { // predicate.
|
2006-08-09 16:44:44 +00:00
|
|
|
mightNotMatch = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-01-29 02:43:35 +00:00
|
|
|
|
2006-08-09 16:44:44 +00:00
|
|
|
// If this pattern definitely matches, and if it isn't the last one, the
|
|
|
|
// patterns after it CANNOT ever match. Error out.
|
|
|
|
if (mightNotMatch == false && i != CodeForPatterns.size()-1) {
|
2006-12-07 22:21:48 +00:00
|
|
|
cerr << "Pattern '";
|
|
|
|
CodeForPatterns[i].first->getSrcPattern()->print(*cerr.stream());
|
|
|
|
cerr << "' is impossible to select!\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
exit(1);
|
2006-07-28 22:51:01 +00:00
|
|
|
}
|
2006-08-09 16:41:21 +00:00
|
|
|
}
|
2006-07-28 22:51:01 +00:00
|
|
|
|
2006-08-09 16:44:44 +00:00
|
|
|
// Factor target node emission code (emitted by EmitResultCode) into
|
|
|
|
// separate functions. Uniquing and share them among all instruction
|
|
|
|
// selection routines.
|
|
|
|
for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) {
|
|
|
|
CodeList &GeneratedCode = CodeForPatterns[i].second;
|
|
|
|
std::vector<std::string> &TargetOpcodes = PatternOpcodes[i];
|
|
|
|
std::vector<std::string> &TargetVTs = PatternVTs[i];
|
2006-08-26 01:02:19 +00:00
|
|
|
std::set<std::string> Decls = PatternDecls[i];
|
2006-08-26 00:59:04 +00:00
|
|
|
std::vector<std::string> AddedInits;
|
2006-08-09 16:44:44 +00:00
|
|
|
int CodeSize = (int)GeneratedCode.size();
|
|
|
|
int LastPred = -1;
|
|
|
|
for (int j = CodeSize-1; j >= 0; --j) {
|
2006-08-26 00:59:04 +00:00
|
|
|
if (LastPred == -1 && GeneratedCode[j].first == 1)
|
2006-08-09 16:44:44 +00:00
|
|
|
LastPred = j;
|
2006-08-26 00:59:04 +00:00
|
|
|
else if (LastPred != -1 && GeneratedCode[j].first == 2)
|
|
|
|
AddedInits.push_back(GeneratedCode[j].second);
|
2006-08-09 16:44:44 +00:00
|
|
|
}
|
|
|
|
|
2006-08-26 05:34:46 +00:00
|
|
|
std::string CalleeCode = "(const SDOperand &N";
|
|
|
|
std::string CallerCode = "(N";
|
2006-08-09 16:44:44 +00:00
|
|
|
for (unsigned j = 0, e = TargetOpcodes.size(); j != e; ++j) {
|
|
|
|
CalleeCode += ", unsigned Opc" + utostr(j);
|
|
|
|
CallerCode += ", " + TargetOpcodes[j];
|
|
|
|
}
|
|
|
|
for (unsigned j = 0, e = TargetVTs.size(); j != e; ++j) {
|
|
|
|
CalleeCode += ", MVT::ValueType VT" + utostr(j);
|
|
|
|
CallerCode += ", " + TargetVTs[j];
|
|
|
|
}
|
2006-08-26 01:02:19 +00:00
|
|
|
for (std::set<std::string>::iterator
|
2006-08-09 16:44:44 +00:00
|
|
|
I = Decls.begin(), E = Decls.end(); I != E; ++I) {
|
2006-08-26 01:02:19 +00:00
|
|
|
std::string Name = *I;
|
2006-08-26 00:59:04 +00:00
|
|
|
CalleeCode += ", SDOperand &" + Name;
|
|
|
|
CallerCode += ", " + Name;
|
2006-08-09 16:44:44 +00:00
|
|
|
}
|
|
|
|
CallerCode += ");";
|
|
|
|
CalleeCode += ") ";
|
|
|
|
// Prevent emission routines from being inlined to reduce selection
|
|
|
|
// routines stack frame sizes.
|
2006-08-27 13:16:24 +00:00
|
|
|
CalleeCode += "DISABLE_INLINE ";
|
2006-08-26 00:59:04 +00:00
|
|
|
CalleeCode += "{\n";
|
|
|
|
|
|
|
|
for (std::vector<std::string>::const_reverse_iterator
|
|
|
|
I = AddedInits.rbegin(), E = AddedInits.rend(); I != E; ++I)
|
|
|
|
CalleeCode += " " + *I + "\n";
|
|
|
|
|
2006-08-26 01:02:19 +00:00
|
|
|
for (int j = LastPred+1; j < CodeSize; ++j)
|
|
|
|
CalleeCode += " " + GeneratedCode[j].second + "\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
for (int j = LastPred+1; j < CodeSize; ++j)
|
|
|
|
GeneratedCode.pop_back();
|
|
|
|
CalleeCode += "}\n";
|
|
|
|
|
|
|
|
// Uniquing the emission routines.
|
|
|
|
unsigned EmitFuncNum;
|
|
|
|
std::map<std::string, unsigned>::iterator EFI =
|
|
|
|
EmitFunctions.find(CalleeCode);
|
|
|
|
if (EFI != EmitFunctions.end()) {
|
|
|
|
EmitFuncNum = EFI->second;
|
2006-07-15 08:45:20 +00:00
|
|
|
} else {
|
2006-08-09 16:44:44 +00:00
|
|
|
EmitFuncNum = EmitFunctions.size();
|
|
|
|
EmitFunctions.insert(std::make_pair(CalleeCode, EmitFuncNum));
|
2006-08-11 08:59:35 +00:00
|
|
|
OS << "SDNode *Emit_" << utostr(EmitFuncNum) << CalleeCode;
|
2006-07-15 08:45:20 +00:00
|
|
|
}
|
2006-08-09 16:41:21 +00:00
|
|
|
|
2006-08-09 16:44:44 +00:00
|
|
|
// Replace the emission code within selection routines with calls to the
|
|
|
|
// emission functions.
|
2006-08-11 08:59:35 +00:00
|
|
|
CallerCode = "return Emit_" + utostr(EmitFuncNum) + CallerCode;
|
2006-08-09 16:44:44 +00:00
|
|
|
GeneratedCode.push_back(std::make_pair(false, CallerCode));
|
|
|
|
}
|
2006-08-09 16:41:21 +00:00
|
|
|
|
2006-08-09 16:44:44 +00:00
|
|
|
// Print function.
|
2006-11-14 21:32:01 +00:00
|
|
|
std::string OpVTStr;
|
2006-11-14 22:17:10 +00:00
|
|
|
if (OpVT == MVT::iPTR) {
|
|
|
|
OpVTStr = "_iPTR";
|
|
|
|
} else if (OpVT == MVT::isVoid) {
|
|
|
|
// Nodes with a void result actually have a first result type of either
|
|
|
|
// Other (a chain) or Flag. Since there is no one-to-one mapping from
|
|
|
|
// void to this case, we handle it specially here.
|
|
|
|
} else {
|
|
|
|
OpVTStr = "_" + getEnumName(OpVT).substr(5); // Skip 'MVT::'
|
|
|
|
}
|
2006-08-09 16:44:44 +00:00
|
|
|
std::map<std::string, std::vector<std::string> >::iterator OpVTI =
|
|
|
|
OpcodeVTMap.find(OpName);
|
|
|
|
if (OpVTI == OpcodeVTMap.end()) {
|
|
|
|
std::vector<std::string> VTSet;
|
|
|
|
VTSet.push_back(OpVTStr);
|
|
|
|
OpcodeVTMap.insert(std::make_pair(OpName, VTSet));
|
|
|
|
} else
|
|
|
|
OpVTI->second.push_back(OpVTStr);
|
|
|
|
|
2006-11-08 23:01:03 +00:00
|
|
|
OS << "SDNode *Select_" << getLegalCName(OpName)
|
2006-11-14 22:17:10 +00:00
|
|
|
<< OpVTStr << "(const SDOperand &N) {\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
|
|
|
|
// Loop through and reverse all of the CodeList vectors, as we will be
|
|
|
|
// accessing them from their logical front, but accessing the end of a
|
|
|
|
// vector is more efficient.
|
|
|
|
for (unsigned i = 0, e = CodeForPatterns.size(); i != e; ++i) {
|
|
|
|
CodeList &GeneratedCode = CodeForPatterns[i].second;
|
|
|
|
std::reverse(GeneratedCode.begin(), GeneratedCode.end());
|
|
|
|
}
|
2006-01-04 00:25:00 +00:00
|
|
|
|
2006-08-09 16:44:44 +00:00
|
|
|
// Next, reverse the list of patterns itself for the same reason.
|
|
|
|
std::reverse(CodeForPatterns.begin(), CodeForPatterns.end());
|
2006-01-29 04:25:26 +00:00
|
|
|
|
2006-08-09 16:44:44 +00:00
|
|
|
// Emit all of the patterns now, grouped together to share code.
|
|
|
|
EmitPatterns(CodeForPatterns, 2, OS);
|
2006-01-29 04:25:26 +00:00
|
|
|
|
2006-09-21 18:28:27 +00:00
|
|
|
// If the last pattern has predicates (which could fail) emit code to
|
|
|
|
// catch the case where nothing handles a pattern.
|
2006-08-09 16:44:44 +00:00
|
|
|
if (mightNotMatch) {
|
2006-12-07 22:21:48 +00:00
|
|
|
OS << " cerr << \"Cannot yet select: \";\n";
|
2006-11-08 23:01:03 +00:00
|
|
|
if (OpName != "ISD::INTRINSIC_W_CHAIN" &&
|
|
|
|
OpName != "ISD::INTRINSIC_WO_CHAIN" &&
|
|
|
|
OpName != "ISD::INTRINSIC_VOID") {
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << " N.Val->dump(CurDAG);\n";
|
|
|
|
} else {
|
|
|
|
OS << " unsigned iid = cast<ConstantSDNode>(N.getOperand("
|
|
|
|
"N.getOperand(0).getValueType() == MVT::Other))->getValue();\n"
|
2006-12-07 22:21:48 +00:00
|
|
|
<< " cerr << \"intrinsic %\"<< "
|
2006-08-09 16:44:44 +00:00
|
|
|
"Intrinsic::getName((Intrinsic::ID)iid);\n";
|
|
|
|
}
|
2006-12-07 22:21:48 +00:00
|
|
|
OS << " cerr << '\\n';\n"
|
2006-08-11 08:59:35 +00:00
|
|
|
<< " abort();\n"
|
|
|
|
<< " return NULL;\n";
|
2006-03-28 00:41:33 +00:00
|
|
|
}
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << "}\n\n";
|
2006-03-28 00:41:33 +00:00
|
|
|
}
|
2006-01-04 00:25:00 +00:00
|
|
|
}
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
// Emit boilerplate.
|
2006-08-26 05:34:46 +00:00
|
|
|
OS << "SDNode *Select_INLINEASM(SDOperand N) {\n"
|
2006-01-26 23:08:55 +00:00
|
|
|
<< " std::vector<SDOperand> Ops(N.Val->op_begin(), N.Val->op_end());\n"
|
2006-11-01 00:27:59 +00:00
|
|
|
<< " AddToISelQueue(N.getOperand(0)); // Select the chain.\n\n"
|
2006-01-26 23:08:55 +00:00
|
|
|
<< " // Select the flag operand.\n"
|
|
|
|
<< " if (Ops.back().getValueType() == MVT::Flag)\n"
|
2006-08-26 00:59:04 +00:00
|
|
|
<< " AddToISelQueue(Ops.back());\n"
|
2006-02-24 02:13:31 +00:00
|
|
|
<< " SelectInlineAsmMemoryOperands(Ops, *CurDAG);\n"
|
2006-01-26 23:08:55 +00:00
|
|
|
<< " std::vector<MVT::ValueType> VTs;\n"
|
|
|
|
<< " VTs.push_back(MVT::Other);\n"
|
|
|
|
<< " VTs.push_back(MVT::Flag);\n"
|
2006-08-09 16:44:44 +00:00
|
|
|
<< " SDOperand New = CurDAG->getNode(ISD::INLINEASM, VTs, &Ops[0], "
|
|
|
|
"Ops.size());\n"
|
2006-08-26 05:34:46 +00:00
|
|
|
<< " return New.Val;\n"
|
2006-01-26 23:08:55 +00:00
|
|
|
<< "}\n\n";
|
|
|
|
|
2007-01-26 17:29:20 +00:00
|
|
|
OS << "SDNode *Select_LABEL(const SDOperand &N) {\n"
|
|
|
|
<< " SDOperand Chain = N.getOperand(0);\n"
|
|
|
|
<< " SDOperand N1 = N.getOperand(1);\n"
|
2007-01-26 23:00:54 +00:00
|
|
|
<< " unsigned C = cast<ConstantSDNode>(N1)->getValue();\n"
|
|
|
|
<< " SDOperand Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n"
|
2007-01-26 17:29:20 +00:00
|
|
|
<< " AddToISelQueue(Chain);\n"
|
|
|
|
<< " return CurDAG->getTargetNode(TargetInstrInfo::LABEL,\n"
|
2007-01-26 23:00:54 +00:00
|
|
|
<< " MVT::Other, Tmp, Chain);\n"
|
2007-01-26 17:29:20 +00:00
|
|
|
<< "}\n\n";
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
OS << "// The main instruction selector code.\n"
|
2006-08-26 05:34:46 +00:00
|
|
|
<< "SDNode *SelectCode(SDOperand N) {\n"
|
2005-09-23 21:53:45 +00:00
|
|
|
<< " if (N.getOpcode() >= ISD::BUILTIN_OP_END &&\n"
|
2005-10-18 04:41:01 +00:00
|
|
|
<< " N.getOpcode() < (ISD::BUILTIN_OP_END+" << InstNS
|
2006-02-09 00:37:58 +00:00
|
|
|
<< "INSTRUCTION_LIST_END)) {\n"
|
2006-08-11 08:59:35 +00:00
|
|
|
<< " return NULL; // Already selected.\n"
|
2006-02-09 00:37:58 +00:00
|
|
|
<< " }\n\n"
|
2006-11-08 23:01:03 +00:00
|
|
|
<< " MVT::ValueType NVT = N.Val->getValueType(0);\n"
|
2005-09-23 21:53:45 +00:00
|
|
|
<< " switch (N.getOpcode()) {\n"
|
2005-09-07 23:44:43 +00:00
|
|
|
<< " default: break;\n"
|
|
|
|
<< " case ISD::EntryToken: // These leaves remain the same.\n"
|
2005-12-18 21:05:44 +00:00
|
|
|
<< " case ISD::BasicBlock:\n"
|
2006-01-11 19:52:27 +00:00
|
|
|
<< " case ISD::Register:\n"
|
2006-02-05 08:46:14 +00:00
|
|
|
<< " case ISD::HANDLENODE:\n"
|
2006-02-05 05:22:18 +00:00
|
|
|
<< " case ISD::TargetConstant:\n"
|
|
|
|
<< " case ISD::TargetConstantPool:\n"
|
|
|
|
<< " case ISD::TargetFrameIndex:\n"
|
2006-04-22 18:53:45 +00:00
|
|
|
<< " case ISD::TargetJumpTable:\n"
|
2006-02-09 00:37:58 +00:00
|
|
|
<< " case ISD::TargetGlobalAddress: {\n"
|
2006-08-11 08:59:35 +00:00
|
|
|
<< " return NULL;\n"
|
2006-02-09 00:37:58 +00:00
|
|
|
<< " }\n"
|
2005-09-07 23:44:43 +00:00
|
|
|
<< " case ISD::AssertSext:\n"
|
2005-09-26 22:10:24 +00:00
|
|
|
<< " case ISD::AssertZext: {\n"
|
2006-08-26 00:59:04 +00:00
|
|
|
<< " AddToISelQueue(N.getOperand(0));\n"
|
|
|
|
<< " ReplaceUses(N, N.getOperand(0));\n"
|
2006-08-11 08:59:35 +00:00
|
|
|
<< " return NULL;\n"
|
2005-10-25 20:35:14 +00:00
|
|
|
<< " }\n"
|
|
|
|
<< " case ISD::TokenFactor:\n"
|
2006-08-09 16:44:44 +00:00
|
|
|
<< " case ISD::CopyFromReg:\n"
|
2006-08-09 16:41:21 +00:00
|
|
|
<< " case ISD::CopyToReg: {\n"
|
2006-08-26 00:59:04 +00:00
|
|
|
<< " for (unsigned i = 0, e = N.getNumOperands(); i != e; ++i)\n"
|
|
|
|
<< " AddToISelQueue(N.getOperand(i));\n"
|
2006-08-11 08:59:35 +00:00
|
|
|
<< " return NULL;\n"
|
2006-01-26 23:08:55 +00:00
|
|
|
<< " }\n"
|
2007-01-26 17:29:20 +00:00
|
|
|
<< " case ISD::INLINEASM: return Select_INLINEASM(N);\n"
|
|
|
|
<< " case ISD::LABEL: return Select_LABEL(N);\n";
|
2006-01-26 23:08:55 +00:00
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
|
2006-01-04 00:25:00 +00:00
|
|
|
// Loop over all of the case statements, emiting a call to each method we
|
|
|
|
// emitted above.
|
2006-11-08 23:01:03 +00:00
|
|
|
for (std::map<std::string, std::vector<PatternToMatch*> >::iterator
|
|
|
|
PBOI = PatternsByOpcode.begin(), E = PatternsByOpcode.end();
|
|
|
|
PBOI != E; ++PBOI) {
|
|
|
|
const std::string &OpName = PBOI->first;
|
2006-08-09 16:44:44 +00:00
|
|
|
// Potentially multiple versions of select for this opcode. One for each
|
|
|
|
// ValueType of the node (or its first true operand if it doesn't produce a
|
|
|
|
// result.
|
|
|
|
std::map<std::string, std::vector<std::string> >::iterator OpVTI =
|
|
|
|
OpcodeVTMap.find(OpName);
|
|
|
|
std::vector<std::string> &OpVTs = OpVTI->second;
|
2006-11-08 23:01:03 +00:00
|
|
|
OS << " case " << OpName << ": {\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
if (OpVTs.size() == 1) {
|
|
|
|
std::string &VTStr = OpVTs[0];
|
2006-11-08 23:01:03 +00:00
|
|
|
OS << " return Select_" << getLegalCName(OpName)
|
2006-11-14 22:17:10 +00:00
|
|
|
<< VTStr << "(N);\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
} else {
|
2006-11-14 21:50:27 +00:00
|
|
|
// Keep track of whether we see a pattern that has an iPtr result.
|
|
|
|
bool HasPtrPattern = false;
|
2006-11-14 22:17:10 +00:00
|
|
|
bool HasDefaultPattern = false;
|
2006-11-14 21:50:27 +00:00
|
|
|
|
2006-08-11 08:59:35 +00:00
|
|
|
OS << " switch (NVT) {\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
for (unsigned i = 0, e = OpVTs.size(); i < e; ++i) {
|
|
|
|
std::string &VTStr = OpVTs[i];
|
2006-11-14 22:17:10 +00:00
|
|
|
if (VTStr.empty()) {
|
|
|
|
HasDefaultPattern = true;
|
|
|
|
continue;
|
|
|
|
}
|
2006-11-14 21:50:27 +00:00
|
|
|
|
|
|
|
// If this is a match on iPTR: don't emit it directly, we need special
|
|
|
|
// code.
|
2006-11-14 22:17:10 +00:00
|
|
|
if (VTStr == "_iPTR") {
|
2006-11-14 21:50:27 +00:00
|
|
|
HasPtrPattern = true;
|
|
|
|
continue;
|
|
|
|
}
|
2006-11-14 22:17:10 +00:00
|
|
|
OS << " case MVT::" << VTStr.substr(1) << ":\n"
|
2006-11-08 23:01:03 +00:00
|
|
|
<< " return Select_" << getLegalCName(OpName)
|
2006-11-14 22:17:10 +00:00
|
|
|
<< VTStr << "(N);\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
}
|
2006-08-11 08:59:35 +00:00
|
|
|
OS << " default:\n";
|
2006-11-14 21:50:27 +00:00
|
|
|
|
|
|
|
// If there is an iPTR result version of this pattern, emit it here.
|
|
|
|
if (HasPtrPattern) {
|
|
|
|
OS << " if (NVT == TLI.getPointerTy())\n";
|
|
|
|
OS << " return Select_" << getLegalCName(OpName) <<"_iPTR(N);\n";
|
|
|
|
}
|
2006-11-14 22:17:10 +00:00
|
|
|
if (HasDefaultPattern) {
|
|
|
|
OS << " return Select_" << getLegalCName(OpName) << "(N);\n";
|
|
|
|
}
|
2006-11-14 21:41:35 +00:00
|
|
|
OS << " break;\n";
|
2006-08-11 08:59:35 +00:00
|
|
|
OS << " }\n";
|
|
|
|
OS << " break;\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
}
|
|
|
|
OS << " }\n";
|
2005-09-23 19:36:15 +00:00
|
|
|
}
|
|
|
|
|
2005-09-07 23:44:43 +00:00
|
|
|
OS << " } // end of big switch.\n\n"
|
2006-12-07 22:21:48 +00:00
|
|
|
<< " cerr << \"Cannot yet select: \";\n"
|
2006-03-28 00:41:33 +00:00
|
|
|
<< " if (N.getOpcode() != ISD::INTRINSIC_W_CHAIN &&\n"
|
|
|
|
<< " N.getOpcode() != ISD::INTRINSIC_WO_CHAIN &&\n"
|
|
|
|
<< " N.getOpcode() != ISD::INTRINSIC_VOID) {\n"
|
2006-03-25 06:47:53 +00:00
|
|
|
<< " N.Val->dump(CurDAG);\n"
|
|
|
|
<< " } else {\n"
|
|
|
|
<< " unsigned iid = cast<ConstantSDNode>(N.getOperand("
|
|
|
|
"N.getOperand(0).getValueType() == MVT::Other))->getValue();\n"
|
2006-12-07 22:21:48 +00:00
|
|
|
<< " cerr << \"intrinsic %\"<< "
|
|
|
|
"Intrinsic::getName((Intrinsic::ID)iid);\n"
|
2006-03-25 06:47:53 +00:00
|
|
|
<< " }\n"
|
2006-12-07 22:21:48 +00:00
|
|
|
<< " cerr << '\\n';\n"
|
2005-09-07 23:44:43 +00:00
|
|
|
<< " abort();\n"
|
2006-08-11 08:59:35 +00:00
|
|
|
<< " return NULL;\n"
|
2005-09-07 23:44:43 +00:00
|
|
|
<< "}\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void DAGISelEmitter::run(std::ostream &OS) {
|
|
|
|
EmitSourceFileHeader("DAG Instruction Selector for the " + Target.getName() +
|
|
|
|
" target", OS);
|
|
|
|
|
2005-09-14 00:09:24 +00:00
|
|
|
OS << "// *** NOTE: This file is #included into the middle of the target\n"
|
|
|
|
<< "// *** instruction selector class. These functions are really "
|
|
|
|
<< "methods.\n\n";
|
2005-09-16 00:29:46 +00:00
|
|
|
|
2006-08-27 13:16:24 +00:00
|
|
|
OS << "#include \"llvm/Support/Compiler.h\"\n";
|
2006-07-26 23:06:27 +00:00
|
|
|
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << "// Instruction selector priority queue:\n"
|
|
|
|
<< "std::vector<SDNode*> ISelQueue;\n";
|
|
|
|
OS << "/// Keep track of nodes which have already been added to queue.\n"
|
|
|
|
<< "unsigned char *ISelQueued;\n";
|
|
|
|
OS << "/// Keep track of nodes which have already been selected.\n"
|
|
|
|
<< "unsigned char *ISelSelected;\n";
|
|
|
|
OS << "/// Dummy parameter to ReplaceAllUsesOfValueWith().\n"
|
|
|
|
<< "std::vector<SDNode*> ISelKilled;\n\n";
|
|
|
|
|
2006-10-12 02:08:53 +00:00
|
|
|
OS << "/// IsChainCompatible - Returns true if Chain is Op or Chain does\n";
|
|
|
|
OS << "/// not reach Op.\n";
|
|
|
|
OS << "static bool IsChainCompatible(SDNode *Chain, SDNode *Op) {\n";
|
|
|
|
OS << " if (Chain->getOpcode() == ISD::EntryToken)\n";
|
|
|
|
OS << " return true;\n";
|
|
|
|
OS << " else if (Chain->getOpcode() == ISD::TokenFactor)\n";
|
|
|
|
OS << " return false;\n";
|
|
|
|
OS << " else if (Chain->getNumOperands() > 0) {\n";
|
|
|
|
OS << " SDOperand C0 = Chain->getOperand(0);\n";
|
|
|
|
OS << " if (C0.getValueType() == MVT::Other)\n";
|
|
|
|
OS << " return C0.Val != Op && IsChainCompatible(C0.Val, Op);\n";
|
|
|
|
OS << " }\n";
|
|
|
|
OS << " return true;\n";
|
|
|
|
OS << "}\n";
|
|
|
|
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << "/// Sorting functions for the selection queue.\n"
|
|
|
|
<< "struct isel_sort : public std::binary_function"
|
|
|
|
<< "<SDNode*, SDNode*, bool> {\n"
|
|
|
|
<< " bool operator()(const SDNode* left, const SDNode* right) "
|
|
|
|
<< "const {\n"
|
|
|
|
<< " return (left->getNodeId() > right->getNodeId());\n"
|
|
|
|
<< " }\n"
|
|
|
|
<< "};\n\n";
|
2006-08-09 16:41:21 +00:00
|
|
|
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << "inline void setQueued(int Id) {\n";
|
|
|
|
OS << " ISelQueued[Id / 8] |= 1 << (Id % 8);\n";
|
2006-02-05 06:43:12 +00:00
|
|
|
OS << "}\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << "inline bool isQueued(int Id) {\n";
|
|
|
|
OS << " return ISelQueued[Id / 8] & (1 << (Id % 8));\n";
|
2006-02-06 08:12:55 +00:00
|
|
|
OS << "}\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << "inline void setSelected(int Id) {\n";
|
|
|
|
OS << " ISelSelected[Id / 8] |= 1 << (Id % 8);\n";
|
2006-02-05 06:43:12 +00:00
|
|
|
OS << "}\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << "inline bool isSelected(int Id) {\n";
|
|
|
|
OS << " return ISelSelected[Id / 8] & (1 << (Id % 8));\n";
|
|
|
|
OS << "}\n\n";
|
|
|
|
|
2006-08-27 13:16:24 +00:00
|
|
|
OS << "void AddToISelQueue(SDOperand N) DISABLE_INLINE {\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << " int Id = N.Val->getNodeId();\n";
|
|
|
|
OS << " if (Id != -1 && !isQueued(Id)) {\n";
|
|
|
|
OS << " ISelQueue.push_back(N.Val);\n";
|
|
|
|
OS << " std::push_heap(ISelQueue.begin(), ISelQueue.end(), isel_sort());\n";
|
|
|
|
OS << " setQueued(Id);\n";
|
2006-08-07 22:17:58 +00:00
|
|
|
OS << " }\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << "}\n\n";
|
|
|
|
|
|
|
|
OS << "inline void RemoveKilled() {\n";
|
|
|
|
OS << " unsigned NumKilled = ISelKilled.size();\n";
|
|
|
|
OS << " if (NumKilled) {\n";
|
|
|
|
OS << " for (unsigned i = 0; i != NumKilled; ++i) {\n";
|
|
|
|
OS << " SDNode *Temp = ISelKilled[i];\n";
|
2006-10-12 23:18:52 +00:00
|
|
|
OS << " ISelQueue.erase(std::remove(ISelQueue.begin(), ISelQueue.end(), "
|
|
|
|
<< "Temp), ISelQueue.end());\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << " };\n";
|
|
|
|
OS << " std::make_heap(ISelQueue.begin(), ISelQueue.end(), isel_sort());\n";
|
|
|
|
OS << " ISelKilled.clear();\n";
|
2006-08-07 22:17:58 +00:00
|
|
|
OS << " }\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << "}\n\n";
|
|
|
|
|
2006-08-27 13:16:24 +00:00
|
|
|
OS << "void ReplaceUses(SDOperand F, SDOperand T) DISABLE_INLINE {\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << " CurDAG->ReplaceAllUsesOfValueWith(F, T, ISelKilled);\n";
|
|
|
|
OS << " setSelected(F.Val->getNodeId());\n";
|
|
|
|
OS << " RemoveKilled();\n";
|
2006-08-11 08:59:35 +00:00
|
|
|
OS << "}\n";
|
|
|
|
OS << "inline void ReplaceUses(SDNode *F, SDNode *T) {\n";
|
|
|
|
OS << " CurDAG->ReplaceAllUsesWith(F, T, &ISelKilled);\n";
|
|
|
|
OS << " setSelected(F->getNodeId());\n";
|
|
|
|
OS << " RemoveKilled();\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << "}\n\n";
|
2006-02-05 06:43:12 +00:00
|
|
|
|
2006-08-09 16:41:21 +00:00
|
|
|
OS << "// SelectRoot - Top level entry to DAG isel.\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << "SDOperand SelectRoot(SDOperand Root) {\n";
|
|
|
|
OS << " SelectRootInit();\n";
|
|
|
|
OS << " unsigned NumBytes = (DAGSize + 7) / 8;\n";
|
|
|
|
OS << " ISelQueued = new unsigned char[NumBytes];\n";
|
|
|
|
OS << " ISelSelected = new unsigned char[NumBytes];\n";
|
|
|
|
OS << " memset(ISelQueued, 0, NumBytes);\n";
|
|
|
|
OS << " memset(ISelSelected, 0, NumBytes);\n";
|
|
|
|
OS << "\n";
|
2006-08-15 23:42:26 +00:00
|
|
|
OS << " // Create a dummy node (which is not added to allnodes), that adds\n"
|
|
|
|
<< " // a reference to the root node, preventing it from being deleted,\n"
|
|
|
|
<< " // and tracking any changes of the root.\n"
|
|
|
|
<< " HandleSDNode Dummy(CurDAG->getRoot());\n"
|
|
|
|
<< " ISelQueue.push_back(CurDAG->getRoot().Val);\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << " while (!ISelQueue.empty()) {\n";
|
|
|
|
OS << " SDNode *Node = ISelQueue.front();\n";
|
|
|
|
OS << " std::pop_heap(ISelQueue.begin(), ISelQueue.end(), isel_sort());\n";
|
|
|
|
OS << " ISelQueue.pop_back();\n";
|
2006-08-11 08:59:35 +00:00
|
|
|
OS << " if (!isSelected(Node->getNodeId())) {\n";
|
2006-08-26 05:34:46 +00:00
|
|
|
OS << " SDNode *ResNode = Select(SDOperand(Node, 0));\n";
|
2006-09-11 02:24:43 +00:00
|
|
|
OS << " if (ResNode != Node) {\n";
|
|
|
|
OS << " if (ResNode)\n";
|
|
|
|
OS << " ReplaceUses(Node, ResNode);\n";
|
2006-10-12 20:35:19 +00:00
|
|
|
OS << " if (Node->use_empty()) { // Don't delete EntryToken, etc.\n";
|
|
|
|
OS << " CurDAG->RemoveDeadNode(Node, ISelKilled);\n";
|
|
|
|
OS << " RemoveKilled();\n";
|
|
|
|
OS << " }\n";
|
2006-09-11 02:24:43 +00:00
|
|
|
OS << " }\n";
|
2006-08-11 08:59:35 +00:00
|
|
|
OS << " }\n";
|
2006-08-09 16:44:44 +00:00
|
|
|
OS << " }\n";
|
|
|
|
OS << "\n";
|
|
|
|
OS << " delete[] ISelQueued;\n";
|
|
|
|
OS << " ISelQueued = NULL;\n";
|
|
|
|
OS << " delete[] ISelSelected;\n";
|
|
|
|
OS << " ISelSelected = NULL;\n";
|
2006-08-15 23:42:26 +00:00
|
|
|
OS << " return Dummy.getValue();\n";
|
2006-02-05 06:43:12 +00:00
|
|
|
OS << "}\n";
|
2005-09-24 00:50:51 +00:00
|
|
|
|
2006-03-24 21:48:51 +00:00
|
|
|
Intrinsics = LoadIntrinsics(Records);
|
2005-09-08 21:03:01 +00:00
|
|
|
ParseNodeInfo();
|
2005-09-13 21:51:00 +00:00
|
|
|
ParseNodeTransforms(OS);
|
2005-12-08 02:00:36 +00:00
|
|
|
ParseComplexPatterns();
|
2005-09-15 02:38:02 +00:00
|
|
|
ParsePatternFragments(OS);
|
2006-11-04 05:12:02 +00:00
|
|
|
ParsePredicateOperands();
|
2005-09-15 02:38:02 +00:00
|
|
|
ParseInstructions();
|
|
|
|
ParsePatterns();
|
2005-09-23 20:52:47 +00:00
|
|
|
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
// Generate variants. For example, commutative patterns can match
|
2005-09-23 20:52:47 +00:00
|
|
|
// multiple ways. Add them to PatternsToMatch as well.
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
GenerateVariants();
|
2005-09-15 02:38:02 +00:00
|
|
|
|
2006-12-07 22:21:48 +00:00
|
|
|
DOUT << "\n\nALL PATTERNS TO MATCH:\n\n";
|
|
|
|
for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
|
|
|
|
DOUT << "PATTERN: "; DEBUG(PatternsToMatch[i].getSrcPattern()->dump());
|
|
|
|
DOUT << "\nRESULT: "; DEBUG(PatternsToMatch[i].getDstPattern()->dump());
|
|
|
|
DOUT << "\n";
|
|
|
|
}
|
2005-09-29 19:28:10 +00:00
|
|
|
|
2005-09-16 00:29:46 +00:00
|
|
|
// At this point, we have full information about the 'Patterns' we need to
|
|
|
|
// parse, both implicitly from instructions as well as from explicit pattern
|
Emit an error if instructions or patterns are defined but can never match.
Currently we check that immediate values live on the RHS of commutative
operators. Defining ORI like this, for example:
def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2",
[(set GPRC:$dst, (or immZExt16:$src2, GPRC:$src1))]>;
results in:
tblgen: In ORI: Instruction can never match: Immediate values must be on the RHS of commutative operators!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23501 91177308-0d34-0410-b5e6-96231b3b80d8
2005-09-28 19:27:25 +00:00
|
|
|
// definitions. Emit the resultant instruction selector.
|
2005-09-07 23:44:43 +00:00
|
|
|
EmitInstructionSelector(OS);
|
|
|
|
|
|
|
|
for (std::map<Record*, TreePattern*>::iterator I = PatternFragments.begin(),
|
|
|
|
E = PatternFragments.end(); I != E; ++I)
|
|
|
|
delete I->second;
|
|
|
|
PatternFragments.clear();
|
|
|
|
|
|
|
|
Instructions.clear();
|
|
|
|
}
|