aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp53
1 files changed, 47 insertions, 6 deletions
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index ec70a5ed57..5c53a7f6bd 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -129,6 +129,7 @@ namespace {
bool CombineToPreIndexedLoadStore(SDNode *N);
bool CombineToPostIndexedLoadStore(SDNode *N);
+ SDValue PromoteIntBinOp(SDValue Op);
/// combine - call the node-specific routine that knows how to fold each
/// particular type of node. If that doesn't do anything, try the
@@ -633,6 +634,46 @@ bool DAGCombiner::SimplifyDemandedBits(SDValue Op, const APInt &Demanded) {
return true;
}
+static SDValue PromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG) {
+ unsigned Opc = ISD::ZERO_EXTEND;
+ if (Op.getOpcode() == ISD::Constant) {
+ // Zero extend things like i1, sign extend everything else. It shouldn't
+ // matter in theory which one we pick, but this tends to give better code?
+ // See DAGTypeLegalizer::PromoteIntRes_Constant.
+ if (Op.getValueType().isByteSized())
+ Opc = ISD::SIGN_EXTEND;
+ }
+ return DAG.getNode(Opc, Op.getDebugLoc(), PVT, Op);
+}
+
+/// PromoteIntBinOp - Promote the specified integer binary operation if the
+/// target indicates it is beneficial. e.g. On x86, it's usually better to
+/// promote i16 operations to i32 since i16 instructions are longer.
+SDValue DAGCombiner::PromoteIntBinOp(SDValue Op) {
+ if (!LegalOperations)
+ return SDValue();
+
+ EVT VT = Op.getValueType();
+ if (VT.isVector() || !VT.isInteger())
+ return SDValue();
+
+ EVT PVT = VT;
+ if (TLI.PerformDAGCombinePromotion(Op, PVT)) {
+ assert(PVT != VT && "Don't know what type to promote to!");
+
+ SDValue N0 = PromoteOperand(Op.getOperand(0), PVT, DAG);
+ AddToWorkList(N0.getNode());
+
+ SDValue N1 = PromoteOperand(Op.getOperand(1), PVT, DAG);
+ AddToWorkList(N1.getNode());
+
+ DebugLoc dl = Op.getDebugLoc();
+ return DAG.getNode(ISD::TRUNCATE, dl, VT,
+ DAG.getNode(Op.getOpcode(), dl, PVT, N0, N1));
+ }
+ return SDValue();
+}
+
//===----------------------------------------------------------------------===//
// Main DAG Combiner implementation
//===----------------------------------------------------------------------===//
@@ -1112,7 +1153,7 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
N0.getOperand(0).getOperand(1),
N0.getOperand(1)));
- return SDValue();
+ return PromoteIntBinOp(SDValue(N, 0));
}
SDValue DAGCombiner::visitADDC(SDNode *N) {
@@ -1250,7 +1291,7 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
VT);
}
- return SDValue();
+ return PromoteIntBinOp(SDValue(N, 0));
}
SDValue DAGCombiner::visitMUL(SDNode *N) {
@@ -1343,7 +1384,7 @@ SDValue DAGCombiner::visitMUL(SDNode *N) {
if (RMUL.getNode() != 0)
return RMUL;
- return SDValue();
+ return PromoteIntBinOp(SDValue(N, 0));
}
SDValue DAGCombiner::visitSDIV(SDNode *N) {
@@ -1987,7 +2028,7 @@ SDValue DAGCombiner::visitAND(SDNode *N) {
}
}
- return SDValue();
+ return PromoteIntBinOp(SDValue(N, 0));
}
SDValue DAGCombiner::visitOR(SDNode *N) {
@@ -2113,7 +2154,7 @@ SDValue DAGCombiner::visitOR(SDNode *N) {
if (SDNode *Rot = MatchRotate(N0, N1, N->getDebugLoc()))
return SDValue(Rot, 0);
- return SDValue();
+ return PromoteIntBinOp(SDValue(N, 0));
}
/// MatchRotateHalf - Match "(X shl/srl V1) & V2" where V2 may not be present.
@@ -2422,7 +2463,7 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
SimplifyDemandedBits(SDValue(N, 0)))
return SDValue(N, 0);
- return SDValue();
+ return PromoteIntBinOp(SDValue(N, 0));
}
/// visitShiftByConstant - Handle transforms common to the three shifts, when