aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Target/TargetLowering.h7
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp53
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp41
-rw-r--r--lib/Target/X86/X86ISelLowering.h2
4 files changed, 97 insertions, 6 deletions
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 3ee87c8c95..fca2453906 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -880,6 +880,13 @@ public:
/// more complex transformations.
///
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+
+ /// PerformDAGCombinePromotion - This method query the target whether it is
+ /// beneficial for dag combiner to promote the specified node. If true, it
+ /// should return the desired promotion type by reference.
+ virtual bool PerformDAGCombinePromotion(SDValue Op, EVT &PVT) const {
+ return false;
+ }
//===--------------------------------------------------------------------===//
// TargetLowering Configuration Methods - These methods should be invoked by
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
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 03b5942268..2b8c5408e6 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -64,6 +64,9 @@ DisableMMX("disable-mmx", cl::Hidden, cl::desc("Disable use of MMX"));
static cl::opt<bool>
Disable16Bit("disable-16bit", cl::Hidden,
cl::desc("Disable use of 16-bit instructions"));
+static cl::opt<bool>
+Promote16Bit("promote-16bit", cl::Hidden,
+ cl::desc("Promote 16-bit instructions"));
// Forward declarations.
static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1,
@@ -9906,6 +9909,44 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
return SDValue();
}
+/// PerformDAGCombinePromotion - This method query the target whether it is
+/// beneficial for dag combiner to promote the specified node. If true, it
+/// should return the desired promotion type by reference.
+bool X86TargetLowering::PerformDAGCombinePromotion(SDValue Op, EVT &PVT) const {
+ if (!Promote16Bit)
+ return false;
+
+ EVT VT = Op.getValueType();
+ if (VT != MVT::i16)
+ return false;
+
+ bool Commute = true;
+ switch (Op.getOpcode()) {
+ default: return false;
+ case ISD::SUB:
+ Commute = false;
+ // fallthrough
+ case ISD::ADD:
+ case ISD::MUL:
+ case ISD::AND:
+ case ISD::OR:
+ case ISD::XOR: {
+ SDValue N0 = Op.getOperand(0);
+ SDValue N1 = Op.getOperand(1);
+ if (!Commute && isa<LoadSDNode>(N1))
+ return false;
+ // Avoid disabling potential load folding opportunities.
+ if ((isa<LoadSDNode>(N0) && N0.hasOneUse()) && !isa<ConstantSDNode>(N1))
+ return false;
+ if ((isa<LoadSDNode>(N1) && N1.hasOneUse()) && !isa<ConstantSDNode>(N0))
+ return false;
+ }
+ }
+
+ PVT = MVT::i32;
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// X86 Inline Assembly Support
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index 4e4ba48b1a..7fa65cb473 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -452,6 +452,8 @@ namespace llvm {
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+ virtual bool PerformDAGCombinePromotion(SDValue Op, EVT &PVT) const;
+
virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *MBB,
DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const;