[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
Evan Cheng
evan.cheng at apple.com
Thu Jul 27 09:44:50 PDT 2006
Changes in directory llvm/lib/Target/X86:
X86ISelDAGToDAG.cpp updated: 1.75 -> 1.76
---
Log message:
Use reachbility information to determine whether a node can be folded into another during isel.
---
Diffs of the changes: (+118 -3)
X86ISelDAGToDAG.cpp | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 118 insertions(+), 3 deletions(-)
Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
diff -u llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.75 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.76
--- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.75 Wed Jun 28 18:27:49 2006
+++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp Thu Jul 27 11:44:36 2006
@@ -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 @@
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 @@
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 @@
/// 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 @@
#ifndef NDEBUG
DEBUG(std::cerr << "===== Instruction selection ends:\n");
#endif
+ if (ReachibilityMatrix) {
+ delete[] ReachibilityMatrix;
+ ReachibilityMatrix = NULL;
+ }
CodeGenMap.clear();
HandleMap.clear();
ReplaceMap.clear();
More information about the llvm-commits
mailing list