mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-14 00:14:19 +00:00
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:
parent
2e9f3686f8
commit
a8df1b4296
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user