mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-01 00:33:09 +00:00
Add support for CombineTo, allowing the dag combiner to replace nodes with
multiple results. Use this support to implement trivial store->load forwarding, implementing CodeGen/PowerPC/store-load-fwd.ll. Though this is the most simple case and can be extended in the future, it is still useful. For example, it speeds up 197.parser by 6.2% by avoiding an LSU reject in xalloc: stw r6, lo16(l5_end_of_array)(r2) addi r2, r5, -4 stwx r5, r4, r2 - lwzx r5, r4, r2 - rlwinm r5, r5, 0, 0, 30 stwx r5, r4, r2 lwz r2, -4(r4) ori r2, r2, 1 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23690 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e64dfbc10b
commit
01a2202138
@ -23,7 +23,6 @@
|
||||
// FIXME: select C, pow2, pow2 -> something smart
|
||||
// FIXME: trunc(select X, Y, Z) -> select X, trunc(Y), trunc(Z)
|
||||
// FIXME: (select C, load A, load B) -> load (select C, A, B)
|
||||
// FIXME: store -> load -> forward substitute
|
||||
// FIXME: Dead stores -> nuke
|
||||
// FIXME: shr X, (and Y,31) -> shr X, Y
|
||||
// FIXME: TRUNC (LOAD) -> EXT_LOAD/LOAD(smaller)
|
||||
@ -36,6 +35,7 @@
|
||||
// FIXME: divide by zero is currently left unfolded. do we want to turn this
|
||||
// into an undef?
|
||||
// FIXME: select ne (select cc, 1, 0), 0, true, false -> select cc, true, false
|
||||
// FIXME: reassociate (X+C)+Y into (X+Y)+C if the inner expression has one use
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -76,6 +76,37 @@ namespace {
|
||||
WorkList.end());
|
||||
}
|
||||
|
||||
SDOperand CombineTo(SDNode *N, const std::vector<SDOperand> &To) {
|
||||
DEBUG(std::cerr << "\nReplacing "; N->dump();
|
||||
std::cerr << "\nWith: "; To[0].Val->dump();
|
||||
std::cerr << " and " << To.size()-1 << " other values\n");
|
||||
std::vector<SDNode*> NowDead;
|
||||
DAG.ReplaceAllUsesWith(N, To, &NowDead);
|
||||
|
||||
// Push the new nodes and any users onto the worklist
|
||||
for (unsigned i = 0, e = To.size(); i != e; ++i) {
|
||||
WorkList.push_back(To[i].Val);
|
||||
AddUsersToWorkList(To[i].Val);
|
||||
}
|
||||
|
||||
// Nodes can end up on the worklist more than once. Make sure we do
|
||||
// not process a node that has been replaced.
|
||||
removeFromWorkList(N);
|
||||
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);
|
||||
return SDOperand(N, 0);
|
||||
}
|
||||
|
||||
SDOperand CombineTo(SDNode *N, SDOperand Res0, SDOperand Res1) {
|
||||
std::vector<SDOperand> To;
|
||||
To.push_back(Res0);
|
||||
To.push_back(Res1);
|
||||
return CombineTo(N, To);
|
||||
}
|
||||
|
||||
/// visit - call the node-specific routine that knows how to fold each
|
||||
/// particular type of node.
|
||||
SDOperand visit(SDNode *N);
|
||||
@ -84,6 +115,7 @@ namespace {
|
||||
// node types. The semantics are as follows:
|
||||
// Return Value:
|
||||
// SDOperand.Val == 0 - No change was made
|
||||
// SDOperand.Val == N - N was replaced, is dead, and is already handled.
|
||||
// otherwise - N should be replaced by the returned Operand.
|
||||
//
|
||||
SDOperand visitTokenFactor(SDNode *N);
|
||||
@ -132,6 +164,8 @@ namespace {
|
||||
SDOperand visitBR_CC(SDNode *N);
|
||||
SDOperand visitBRTWOWAY_CC(SDNode *N);
|
||||
|
||||
SDOperand visitLOAD(SDNode *N);
|
||||
|
||||
SDOperand SimplifySelect(SDOperand N0, SDOperand N1, SDOperand N2);
|
||||
SDOperand SimplifySelectCC(SDOperand N0, SDOperand N1, SDOperand N2,
|
||||
SDOperand N3, ISD::CondCode CC);
|
||||
@ -334,7 +368,8 @@ void DAGCombiner::Run(bool RunningAfterLegalize) {
|
||||
DEBUG(std::cerr << "\nReplacing "; N->dump();
|
||||
std::cerr << "\nWith: "; RV.Val->dump();
|
||||
std::cerr << '\n');
|
||||
DAG.ReplaceAllUsesWith(N, std::vector<SDOperand>(1, RV));
|
||||
std::vector<SDNode*> NowDead;
|
||||
DAG.ReplaceAllUsesWith(N, std::vector<SDOperand>(1, RV), &NowDead);
|
||||
|
||||
// Push the new node and any users onto the worklist
|
||||
WorkList.push_back(RV.Val);
|
||||
@ -343,6 +378,8 @@ void DAGCombiner::Run(bool RunningAfterLegalize) {
|
||||
// Nodes can end up on the worklist more than once. Make sure we do
|
||||
// not process a node that has been replaced.
|
||||
removeFromWorkList(N);
|
||||
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);
|
||||
@ -401,6 +438,7 @@ SDOperand DAGCombiner::visit(SDNode *N) {
|
||||
case ISD::BRCONDTWOWAY: return visitBRCONDTWOWAY(N);
|
||||
case ISD::BR_CC: return visitBR_CC(N);
|
||||
case ISD::BRTWOWAY_CC: return visitBRTWOWAY_CC(N);
|
||||
case ISD::LOAD: return visitLOAD(N);
|
||||
}
|
||||
return SDOperand();
|
||||
}
|
||||
@ -1513,6 +1551,22 @@ SDOperand DAGCombiner::visitBRTWOWAY_CC(SDNode *N) {
|
||||
return SDOperand();
|
||||
}
|
||||
|
||||
SDOperand DAGCombiner::visitLOAD(SDNode *N) {
|
||||
SDOperand Chain = N->getOperand(0);
|
||||
SDOperand Ptr = N->getOperand(1);
|
||||
SDOperand SrcValue = N->getOperand(2);
|
||||
|
||||
// If this load is directly stored, replace the load value with the stored
|
||||
// value.
|
||||
// TODO: Handle store large -> read small portion.
|
||||
// TODO: Handle TRUNCSTORE/EXTLOAD
|
||||
if (Chain.getOpcode() == ISD::STORE && Chain.getOperand(2) == Ptr &&
|
||||
Chain.getOperand(1).getValueType() == N->getValueType(0))
|
||||
return CombineTo(N, Chain.getOperand(1), Chain);
|
||||
|
||||
return SDOperand();
|
||||
}
|
||||
|
||||
SDOperand DAGCombiner::SimplifySelect(SDOperand N0, SDOperand N1, SDOperand N2){
|
||||
assert(N0.getOpcode() ==ISD::SETCC && "First argument must be a SetCC node!");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user