summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86ISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/X86/X86ISelLowering.cpp')
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index f647c5de472..5f3bc076f65 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -34491,6 +34491,47 @@ static SDValue getDivRem8(SDNode *N, SelectionDAG &DAG) {
return R.getValue(1);
}
+// If we face {ANY,SIGN,ZERO}_EXTEND that is applied to a CMOV with constant
+// operands and the result of CMOV is not used anywhere else - promote CMOV
+// itself instead of promoting its result. This could be beneficial, because:
+// 1) X86TargetLowering::EmitLoweredSelect later can do merging of two
+// (or more) pseudo-CMOVs only when they go one-after-another and
+// getting rid of result extension code after CMOV will help that.
+// 2) Promotion of constant CMOV arguments is free, hence the
+// {ANY,SIGN,ZERO}_EXTEND will just be deleted.
+// 3) 16-bit CMOV encoding is 4 bytes, 32-bit CMOV is 3-byte, so this
+// promotion is also good in terms of code-size.
+// (64-bit CMOV is 4-bytes, that's why we don't do 32-bit => 64-bit
+// promotion).
+static SDValue combineToExtendCMOV(SDNode *Extend, SelectionDAG &DAG) {
+ SDValue CMovN = Extend->getOperand(0);
+ if (CMovN.getOpcode() != X86ISD::CMOV)
+ return SDValue();
+
+ EVT TargetVT = Extend->getValueType(0);
+ unsigned ExtendOpcode = Extend->getOpcode();
+ SDLoc DL(Extend);
+
+ EVT VT = CMovN.getValueType();
+ SDValue CMovOp0 = CMovN.getOperand(0);
+ SDValue CMovOp1 = CMovN.getOperand(1);
+
+ bool DoPromoteCMOV =
+ (VT == MVT::i16 && (TargetVT == MVT::i32 || TargetVT == MVT::i64)) &&
+ CMovN.hasOneUse() &&
+ (isa<ConstantSDNode>(CMovOp0.getNode()) &&
+ isa<ConstantSDNode>(CMovOp1.getNode()));
+
+ if (!DoPromoteCMOV)
+ return SDValue();
+
+ CMovOp0 = DAG.getNode(ExtendOpcode, DL, TargetVT, CMovOp0);
+ CMovOp1 = DAG.getNode(ExtendOpcode, DL, TargetVT, CMovOp1);
+
+ return DAG.getNode(X86ISD::CMOV, DL, TargetVT, CMovOp0, CMovOp1,
+ CMovN.getOperand(2), CMovN.getOperand(3));
+}
+
/// Convert a SEXT or ZEXT of a vector to a SIGN_EXTEND_VECTOR_INREG or
/// ZERO_EXTEND_VECTOR_INREG, this requires the splitting (or concatenating
/// with UNDEFs) of the input to vectors of the same size as the target type
@@ -34605,6 +34646,9 @@ static SDValue combineSext(SDNode *N, SelectionDAG &DAG,
if (SDValue DivRem8 = getDivRem8(N, DAG))
return DivRem8;
+ if (SDValue NewCMov = combineToExtendCMOV(N, DAG))
+ return NewCMov;
+
if (!DCI.isBeforeLegalizeOps()) {
if (InVT == MVT::i1) {
SDValue Zero = DAG.getConstant(0, DL, VT);
@@ -34757,6 +34801,9 @@ static SDValue combineZext(SDNode *N, SelectionDAG &DAG,
}
}
+ if (SDValue NewCMov = combineToExtendCMOV(N, DAG))
+ return NewCMov;
+
if (SDValue V = combineToExtendVectorInReg(N, DAG, DCI, Subtarget))
return V;
OpenPOWER on IntegriCloud