[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Evan Cheng
evan.cheng at apple.com
Thu Nov 2 19:06:35 PST 2006
Changes in directory llvm/lib/CodeGen/SelectionDAG:
DAGCombiner.cpp updated: 1.232 -> 1.233
---
Log message:
Added DAG combiner transformation to generate pre-indexed loads.
---
Diffs of the changes: (+112 -0)
DAGCombiner.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 112 insertions(+)
Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.232 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.233
--- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.232 Thu Nov 2 14:25:49 2006
+++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Thu Nov 2 21:06:21 2006
@@ -174,6 +174,114 @@
return true;
}
+ bool CombineToIndexedLoadStore(SDNode *N) {
+ SDOperand Ptr;
+ bool isLoad = true;
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
+ Ptr = LD->getBasePtr();
+ } else
+ return false;
+
+ if (AfterLegalize &&
+ (Ptr.getOpcode() == ISD::ADD || Ptr.getOpcode() == ISD::SUB) &&
+ Ptr.Val->use_size() > 1) {
+ SDOperand BasePtr;
+ SDOperand Offset;
+ ISD::MemOpAddrMode AM = ISD::UNINDEXED;
+ if (TLI.getLegalPreIndexedAddressBase(N, BasePtr, Offset, AM, DAG)) {
+ // Try turning it into a pre-indexed load / store except when
+ // 1) Another use of base ptr is a predecessor of N. If ptr is folded
+ // that would create a cycle.
+ // 2) All uses are load / store ops that use it as base ptr and offset
+ // is just an addressing mode immediate.
+ // 3) If the would-be new base may not to be dead at N. FIXME: The
+ // proper check is too expensive (in turns of compile time) to
+ // check. Just make sure other uses of the new base are not also
+ // themselves use of loads / stores.
+
+ bool OffIsAMImm = Offset.getOpcode() == ISD::Constant &&
+ TLI.isLegalAddressImmediate(cast<ConstantSDNode>(Offset)->getValue());
+
+ // Check for #3.
+ if (OffIsAMImm && BasePtr.Val->use_size() > 1) {
+ for (SDNode::use_iterator I = BasePtr.Val->use_begin(),
+ E = BasePtr.Val->use_end(); I != E; ++I) {
+ SDNode *Use = *I;
+ if (Use == Ptr.Val)
+ continue;
+ if (Use->getOpcode() == ISD::ADD || Use->getOpcode() == ISD::SUB) {
+ for (SDNode::use_iterator II = Use->use_begin(),
+ EE = Use->use_end(); II != EE; ++II) {
+ SDNode *UseUse = *II;
+ if (UseUse->getOpcode() == ISD::LOAD &&
+ cast<LoadSDNode>(UseUse)->getBasePtr().Val == Use)
+ return false;
+ else if (UseUse->getOpcode() == ISD::STORE &&
+ cast<StoreSDNode>(UseUse)->getBasePtr().Val == Use)
+ return false;
+ }
+ }
+ }
+ }
+
+ // Now check for #1 and #2.
+ unsigned NumRealUses = 0;
+ for (SDNode::use_iterator I = Ptr.Val->use_begin(),
+ E = Ptr.Val->use_end(); I != E; ++I) {
+ SDNode *Use = *I;
+ if (Use == N)
+ continue;
+ if (Use->isPredecessor(N))
+ return false;
+
+ if (!OffIsAMImm)
+ NumRealUses++;
+ // FIXME: Do we need a target hook here
+ else if (Use->getOpcode() == ISD::LOAD) {
+ if (cast<LoadSDNode>(Use)->getBasePtr().Val != Ptr.Val)
+ NumRealUses++;
+ } else if (Use->getOpcode() == ISD::STORE) {
+ if (cast<StoreSDNode>(Use)->getBasePtr().Val != Ptr.Val)
+ NumRealUses++;
+ } else
+ NumRealUses++;
+ }
+ if (NumRealUses == 0)
+ return false;
+
+ SDOperand Result =
+ DAG.getIndexedLoad(SDOperand(N,0), BasePtr, Offset, AM);
+ ++NodesCombined;
+ DEBUG(std::cerr << "\nReplacing.4 "; N->dump();
+ std::cerr << "\nWith: "; Result.Val->dump(&DAG);
+ std::cerr << '\n');
+ std::vector<SDNode*> NowDead;
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0),
+ NowDead);
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2),
+ NowDead);
+
+ // Nodes can end up on the worklist more than once. Make sure we do
+ // not process a node that has been replaced.
+ for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
+ removeFromWorkList(NowDead[i]);
+ // Finally, since the node is now dead, remove it from the graph.
+ DAG.DeleteNode(N);
+
+ // Replace the uses of Ptr with uses of the updated base value.
+ DAG.ReplaceAllUsesOfValueWith(Ptr, Result.getValue(1), NowDead);
+ removeFromWorkList(Ptr.Val);
+ for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
+ removeFromWorkList(NowDead[i]);
+ DAG.DeleteNode(Ptr.Val);
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/// visit - call the node-specific routine that knows how to fold each
/// particular type of node.
SDOperand visit(SDNode *N);
@@ -2752,6 +2860,10 @@
}
}
+ // Try transforming N to an indexed load.
+ if (CombineToIndexedLoadStore(N))
+ return SDOperand(N, 0);
+
return SDOperand();
}
More information about the llvm-commits
mailing list