diff options
| author | Roman Lebedev <lebedev.ri@gmail.com> | 2019-03-15 21:18:05 +0000 |
|---|---|---|
| committer | Roman Lebedev <lebedev.ri@gmail.com> | 2019-03-15 21:18:05 +0000 |
| commit | 9f377906088f1c26134d96353857e4c3dd5e8f34 (patch) | |
| tree | 60b07293f4a9a11bcfdd146974feb475955cae23 /llvm/lib/Target | |
| parent | b6e376ddfa1715c0ea0e975fc7fb033da2814661 (diff) | |
| download | bcm5719-llvm-9f377906088f1c26134d96353857e4c3dd5e8f34.tar.gz bcm5719-llvm-9f377906088f1c26134d96353857e4c3dd5e8f34.zip | |
[X86] X86ISelLowering::combineSextInRegCmov(): also handle i8 CMOV's
Summary:
As noted by @andreadb in https://reviews.llvm.org/D59035#inline-525780
If we have `sext (trunc (cmov C0, C1) to i8)`,
we can instead do `cmov (sext (trunc C0 to i8)), (sext (trunc C1 to i8))`
Reviewers: craig.topper, andreadb, RKSimon
Reviewed By: craig.topper
Subscribers: llvm-commits, andreadb
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59412
llvm-svn: 356301
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 56f0c09d210..21e60994eac 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -39937,18 +39937,24 @@ static SDValue combineBT(SDNode *N, SelectionDAG &DAG, // Try to combine sext_in_reg of a cmov of constants by extending the constants. static SDValue combineSextInRegCmov(SDNode *N, SelectionDAG &DAG) { - EVT VT = N->getValueType(0); + assert(N->getOpcode() == ISD::SIGN_EXTEND_INREG); + + EVT DstVT = N->getValueType(0); SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); EVT ExtraVT = cast<VTSDNode>(N1)->getVT(); - if (ExtraVT != MVT::i16) + if (ExtraVT != MVT::i8 && ExtraVT != MVT::i16) return SDValue(); - // Look through single use any_extends. - if (N0.getOpcode() == ISD::ANY_EXTEND && N0.hasOneUse()) + // Look through single use any_extends / truncs. + SDValue IntermediateBitwidthOp; + if ((N0.getOpcode() == ISD::ANY_EXTEND || N0.getOpcode() == ISD::TRUNCATE) && + N0.hasOneUse()) { + IntermediateBitwidthOp = N0; N0 = N0.getOperand(0); + } // See if we have a single use cmov. if (N0.getOpcode() != X86ISD::CMOV || !N0.hasOneUse()) @@ -39964,21 +39970,37 @@ static SDValue combineSextInRegCmov(SDNode *N, SelectionDAG &DAG) { SDLoc DL(N); - // If we looked through an any_extend above, add one to the constants. - if (N0.getValueType() != VT) { - CMovOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, VT, CMovOp0); - CMovOp1 = DAG.getNode(ISD::ANY_EXTEND, DL, VT, CMovOp1); + // If we looked through an any_extend/trunc above, add one to the constants. + if (IntermediateBitwidthOp) { + unsigned IntermediateOpc = IntermediateBitwidthOp.getOpcode(); + CMovOp0 = DAG.getNode(IntermediateOpc, DL, DstVT, CMovOp0); + CMovOp1 = DAG.getNode(IntermediateOpc, DL, DstVT, CMovOp1); } - CMovOp0 = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, CMovOp0, N1); - CMovOp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, CMovOp1, N1); + CMovOp0 = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, DstVT, CMovOp0, N1); + CMovOp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, DstVT, CMovOp1, N1); - return DAG.getNode(X86ISD::CMOV, DL, VT, CMovOp0, CMovOp1, - N0.getOperand(2), N0.getOperand(3)); + EVT CMovVT = DstVT; + // We do not want i16 CMOV's. Promote to i32 and truncate afterwards. + if (DstVT == MVT::i16) { + CMovVT = MVT::i32; + CMovOp0 = DAG.getNode(ISD::ZERO_EXTEND, DL, CMovVT, CMovOp0); + CMovOp1 = DAG.getNode(ISD::ZERO_EXTEND, DL, CMovVT, CMovOp1); + } + + SDValue CMov = DAG.getNode(X86ISD::CMOV, DL, CMovVT, CMovOp0, CMovOp1, + N0.getOperand(2), N0.getOperand(3)); + + if (CMovVT != DstVT) + CMov = DAG.getNode(ISD::TRUNCATE, DL, DstVT, CMov); + + return CMov; } static SDValue combineSignExtendInReg(SDNode *N, SelectionDAG &DAG, const X86Subtarget &Subtarget) { + assert(N->getOpcode() == ISD::SIGN_EXTEND_INREG); + if (SDValue V = combineSextInRegCmov(N, DAG)) return V; |

