Use reachbility information to determine whether a node can be folded into another during isel.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29346 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2006-07-27 16:44:36 +00:00
parent 2e9f3686f8
commit a8df1b4296

View File

@ -34,6 +34,7 @@
#include "llvm/Support/Visibility.h"
#include "llvm/ADT/Statistic.h"
#include <iostream>
#include <list>
#include <set>
using namespace llvm;
@ -92,12 +93,13 @@ namespace {
const X86Subtarget *Subtarget;
unsigned GlobalBaseReg;
public:
X86DAGToDAGISel(X86TargetMachine &TM)
: SelectionDAGISel(X86Lowering),
X86Lowering(*TM.getTargetLowering()) {
Subtarget = &TM.getSubtarget<X86Subtarget>();
}
X86Lowering(*TM.getTargetLowering()),
Subtarget(&TM.getSubtarget<X86Subtarget>()),
DAGSize(0), ReachibilityMatrix(NULL) {}
virtual bool runOnFunction(Function &Fn) {
// Make sure we re-emit a set of the global base reg if necessary
@ -115,10 +117,15 @@ namespace {
virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
virtual bool IsFoldableBy(SDNode *N, SDNode *U);
// Include the pieces autogenerated from the target description.
#include "X86GenDAGISel.inc"
private:
void DetermineTopologicalOrdering();
void DeterminReachibility();
void Select(SDOperand &Result, SDOperand N);
bool MatchAddress(SDOperand N, X86ISelAddressMode &AM, bool isRoot = true);
@ -173,12 +180,116 @@ namespace {
/// base register. Return the virtual register that holds this value.
SDOperand getGlobalBaseReg();
/// DAGSize - Number of nodes in the DAG.
///
unsigned DAGSize;
/// TopOrder - Topological ordering of all nodes in the DAG.
///
std::vector<SDNode*> TopOrder;
/// ReachibilityMatrix - A N x N matrix representing all pairs reachibility
/// information. One bit per potential edge.
unsigned char *ReachibilityMatrix;
inline void setReachable(SDNode *f, SDNode *t) {
unsigned Idx = f->getNodeId() * DAGSize + t->getNodeId();
ReachibilityMatrix[Idx / 8] |= 1 << (Idx % 8);
}
inline bool isReachable(SDNode *f, SDNode *t) {
unsigned Idx = f->getNodeId() * DAGSize + t->getNodeId();
return ReachibilityMatrix[Idx / 8] & (1 << (Idx % 8));
}
#ifndef NDEBUG
unsigned Indent;
#endif
};
}
bool X86DAGToDAGISel::IsFoldableBy(SDNode *N, SDNode *U) {
// If U use can somehow reach N through another path then U can't fold N or
// it will create a cycle. e.g. In the following diagram, U can reach N
// through X. If N is foled into into U, then X is both a predecessor and
// a successor of U.
//
// [ N ]
// ^ ^
// | |
// / \---
// / [X]
// | ^
// [U]--------|
if (!ReachibilityMatrix)
DeterminReachibility();
assert(isReachable(U, N) && "Attempting to fold a non-operand node?");
for (SDNode::op_iterator I = U->op_begin(), E = U->op_end(); I != E; ++I) {
SDNode *P = I->Val;
if (P != N && isReachable(P, N))
return false;
}
return true;
}
/// DetermineTopologicalOrdering - Determine topological ordering of the nodes
/// in the DAG.
void X86DAGToDAGISel::DetermineTopologicalOrdering() {
DAGSize = CurDAG->AssignNodeIds();
TopOrder.reserve(DAGSize);
std::vector<unsigned> InDegree(DAGSize);
std::list<SDNode*> Sources;
for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
E = CurDAG->allnodes_end(); I != E; ++I) {
SDNode *N = I;
unsigned Degree = N->use_size();
InDegree[N->getNodeId()] = Degree;
if (Degree == 0)
Sources.push_back(I);
}
unsigned Order = 0;
while (!Sources.empty()) {
SDNode *N = Sources.front();
Sources.pop_front();
TopOrder[Order] = N;
Order++;
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) {
SDNode *P = I->Val;
int PId = P->getNodeId();
unsigned Degree = InDegree[PId] - 1;
if (Degree == 0)
Sources.push_back(P);
InDegree[PId] = Degree;
}
}
}
void X86DAGToDAGISel::DeterminReachibility() {
DetermineTopologicalOrdering();
ReachibilityMatrix = new unsigned char[DAGSize * DAGSize];
memset(ReachibilityMatrix, 0, DAGSize * DAGSize * sizeof(unsigned char));
for (unsigned i = 0; i < DAGSize; ++i) {
SDNode *N = TopOrder[i];
setReachable(N, N);
// If N is a leaf node, there is nothing more to do.
if (N->getNumOperands() == 0)
continue;
for (unsigned i2 = 0; ; ++i2) {
SDNode *M = TopOrder[i2];
if (isReachable(M, N)) {
// Update reachibility from M to N's operands.
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E;++I)
setReachable(M, I->Val);
}
if (M == N) break;
}
}
}
/// InstructionSelectBasicBlock - This callback is invoked by SelectionDAGISel
/// when it has created a SelectionDAG for us to codegen.
void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
@ -195,6 +306,10 @@ void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
#ifndef NDEBUG
DEBUG(std::cerr << "===== Instruction selection ends:\n");
#endif
if (ReachibilityMatrix) {
delete[] ReachibilityMatrix;
ReachibilityMatrix = NULL;
}
CodeGenMap.clear();
HandleMap.clear();
ReplaceMap.clear();