[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Chris Lattner
lattner at cs.uiuc.edu
Mon Oct 17 23:04:36 PDT 2005
Changes in directory llvm/lib/CodeGen/SelectionDAG:
DAGCombiner.cpp updated: 1.46 -> 1.47
---
Log message:
Fold (select C, load A, load B) -> load (select C, A, B). This happens quite
a lot throughout many programs. In particular, specfp triggers it a bunch for
constant FP nodes when you have code like cond ? 1.0 : -1.0.
If the PPC ISel exposed the loads implicit in pic references to external globals,
we would be able to eliminate a load in cases like this as well:
%X = external global int
%Y = external global int
int* %test4(bool %C) {
%G = select bool %C, int* %X, int* %Y
ret int* %G
}
Note that this breaks things that use SrcValue's (see the fixme), but since nothing
uses them yet, this is ok.
Also, simplify some code to use hasOneUse() on an SDOperand instead of hasNUsesOfValue directly.
---
Diffs of the changes: (+82 -7)
DAGCombiner.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 82 insertions(+), 7 deletions(-)
Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.46 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.47
--- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.46 Mon Oct 17 19:28:13 2005
+++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Tue Oct 18 01:04:22 2005
@@ -22,10 +22,8 @@
//
// 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: Dead stores -> nuke
-// FIXME: shr X, (and Y,31) -> shr X, Y
-// FIXME: TRUNC (LOAD) -> EXT_LOAD/LOAD(smaller)
+// FIXME: shr X, (and Y,31) -> shr X, Y (TRICKY!)
// FIXME: mul (x, const) -> shifts + adds
// FIXME: undef values
// FIXME: make truncate see through SIGN_EXTEND and AND
@@ -176,6 +174,7 @@
SDOperand visitLOAD(SDNode *N);
SDOperand visitSTORE(SDNode *N);
+ bool SimplifySelectOps(SDNode *SELECT, SDOperand LHS, SDOperand RHS);
SDOperand SimplifySelect(SDOperand N0, SDOperand N1, SDOperand N2);
SDOperand SimplifySelectCC(SDOperand N0, SDOperand N1, SDOperand N2,
SDOperand N3, ISD::CondCode CC);
@@ -831,7 +830,7 @@
}
}
// fold (zext_inreg (sextload x)) -> (zextload x) iff load has one use
- if (N0.getOpcode() == ISD::SEXTLOAD && N0.Val->hasNUsesOfValue(1, 0)) {
+ if (N0.getOpcode() == ISD::SEXTLOAD && N0.hasOneUse()) {
MVT::ValueType EVT = cast<VTSDNode>(N0.getOperand(3))->getVT();
// If we zero all the possible extended bits, then we can turn this into
// a zextload if we are running before legalize or the operation is legal.
@@ -1209,6 +1208,11 @@
// fold X ? Y : X --> X ? Y : 0 --> X & Y
if (MVT::i1 == VT && N0 == N2)
return DAG.getNode(ISD::AND, VT, N0, N1);
+
+ // If we can fold this based on the true/false value, do so.
+ if (SimplifySelectOps(N, N1, N2))
+ return SDOperand();
+
// fold selects based on a setcc into other things, such as min/max/abs
if (N0.getOpcode() == ISD::SETCC)
return SimplifySelect(N0, N1, N2);
@@ -1233,6 +1237,11 @@
// fold select_cc lhs, rhs, x, x, cc -> x
if (N2 == N3)
return N2;
+
+ // If we can fold this based on the true/false value, do so.
+ if (SimplifySelectOps(N, N2, N3))
+ return SDOperand();
+
// fold select_cc into other things, such as min/max/abs
return SimplifySelectCC(N0, N1, N2, N3, CC);
}
@@ -1297,7 +1306,7 @@
if (N0.getOpcode() == ISD::SEXTLOAD && VT == N0.getValueType())
return N0;
// fold (sext (load x)) -> (sextload x)
- if (N0.getOpcode() == ISD::LOAD && N0.Val->hasNUsesOfValue(1, 0)) {
+ if (N0.getOpcode() == ISD::LOAD && N0.hasOneUse()) {
SDOperand ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, N0.getOperand(0),
N0.getOperand(1), N0.getOperand(2),
N0.getValueType());
@@ -1384,7 +1393,7 @@
return SDOperand();
}
// fold (sext_inreg (zextload x)) -> (sextload x) iff load has one use
- if (N0.getOpcode() == ISD::ZEXTLOAD && N0.Val->hasNUsesOfValue(1, 0) &&
+ if (N0.getOpcode() == ISD::ZEXTLOAD && N0.hasOneUse() &&
EVT == cast<VTSDNode>(N0.getOperand(3))->getVT() &&
(!AfterLegalize || TLI.isOperationLegal(ISD::SEXTLOAD, EVT))) {
SDOperand ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, N0.getOperand(0),
@@ -1425,7 +1434,7 @@
return N0.getOperand(0);
}
// fold (truncate (load x)) -> (smaller load x)
- if (N0.getOpcode() == ISD::LOAD && N0.Val->hasNUsesOfValue(1, 0)) {
+ if (N0.getOpcode() == ISD::LOAD && N0.hasOneUse()) {
assert(MVT::getSizeInBits(N0.getValueType()) > MVT::getSizeInBits(VT) &&
"Cannot truncate to larger type!");
MVT::ValueType PtrType = N0.getOperand(1).getValueType();
@@ -1778,6 +1787,72 @@
return SDOperand();
}
+/// SimplifySelectOps - Given a SELECT or a SELECT_CC node, where LHS and RHS
+/// are the two values being selected between, see if we can simplify the
+/// select.
+///
+bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDOperand LHS,
+ SDOperand RHS) {
+
+ // If this is a select from two identical things, try to pull the operation
+ // through the select.
+ if (LHS.getOpcode() == RHS.getOpcode() && LHS.hasOneUse() && RHS.hasOneUse()){
+#if 0
+ std::cerr << "SELECT: ["; LHS.Val->dump();
+ std::cerr << "] ["; RHS.Val->dump();
+ std::cerr << "]\n";
+#endif
+
+ // If this is a load and the token chain is identical, replace the select
+ // of two loads with a load through a select of the address to load from.
+ // This triggers in things like "select bool X, 10.0, 123.0" after the FP
+ // constants have been dropped into the constant pool.
+ if ((LHS.getOpcode() == ISD::LOAD ||
+ LHS.getOpcode() == ISD::EXTLOAD ||
+ LHS.getOpcode() == ISD::ZEXTLOAD ||
+ LHS.getOpcode() == ISD::SEXTLOAD) &&
+ // Token chains must be identical.
+ LHS.getOperand(0) == RHS.getOperand(0) &&
+ // If this is an EXTLOAD, the VT's must match.
+ (LHS.getOpcode() == ISD::LOAD ||
+ LHS.getOperand(3) == RHS.getOperand(3))) {
+ // FIXME: this conflates two src values, discarding one. This is not
+ // the right thing to do, but nothing uses srcvalues now. When they do,
+ // turn SrcValue into a list of locations.
+ SDOperand Addr;
+ if (TheSelect->getOpcode() == ISD::SELECT)
+ Addr = DAG.getNode(ISD::SELECT, LHS.getOperand(1).getValueType(),
+ TheSelect->getOperand(0), LHS.getOperand(1),
+ RHS.getOperand(1));
+ else
+ Addr = DAG.getNode(ISD::SELECT_CC, LHS.getOperand(1).getValueType(),
+ TheSelect->getOperand(0),
+ TheSelect->getOperand(1),
+ LHS.getOperand(1), RHS.getOperand(1),
+ TheSelect->getOperand(4));
+
+ SDOperand Load;
+ if (LHS.getOpcode() == ISD::LOAD)
+ Load = DAG.getLoad(TheSelect->getValueType(0), LHS.getOperand(0),
+ Addr, LHS.getOperand(2));
+ else
+ Load = DAG.getExtLoad(LHS.getOpcode(), TheSelect->getValueType(0),
+ LHS.getOperand(0), Addr, LHS.getOperand(2),
+ cast<VTSDNode>(LHS.getOperand(3))->getVT());
+ // Users of the select now use the result of the load.
+ CombineTo(TheSelect, Load);
+
+ // Users of the old loads now use the new load's chain. We know the
+ // old-load value is dead now.
+ CombineTo(LHS.Val, Load.getValue(0), Load.getValue(1));
+ CombineTo(RHS.Val, Load.getValue(0), Load.getValue(1));
+ return true;
+ }
+ }
+
+ return false;
+}
+
SDOperand DAGCombiner::SimplifySelectCC(SDOperand N0, SDOperand N1,
SDOperand N2, SDOperand N3,
ISD::CondCode CC) {
More information about the llvm-commits
mailing list