diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 66315b5af113..ec37585de9ad 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -36028,7 +36028,7 @@ static SDValue getDivRem8(SDNode *N, SelectionDAG &DAG) { // promotion). static SDValue combineToExtendCMOV(SDNode *Extend, SelectionDAG &DAG) { SDValue CMovN = Extend->getOperand(0); - if (CMovN.getOpcode() != X86ISD::CMOV) + if (CMovN.getOpcode() != X86ISD::CMOV || !CMovN.hasOneUse()) return SDValue(); EVT TargetVT = Extend->getValueType(0); @@ -36039,20 +36039,35 @@ static SDValue combineToExtendCMOV(SDNode *Extend, SelectionDAG &DAG) { SDValue CMovOp0 = CMovN.getOperand(0); SDValue CMovOp1 = CMovN.getOperand(1); - bool DoPromoteCMOV = - (VT == MVT::i16 && (TargetVT == MVT::i32 || TargetVT == MVT::i64)) && - CMovN.hasOneUse() && - (isa(CMovOp0.getNode()) && - isa(CMovOp1.getNode())); - - if (!DoPromoteCMOV) + if (!isa(CMovOp0.getNode()) || + !isa(CMovOp0.getNode())) return SDValue(); - CMovOp0 = DAG.getNode(ExtendOpcode, DL, TargetVT, CMovOp0); - CMovOp1 = DAG.getNode(ExtendOpcode, DL, TargetVT, CMovOp1); + // Only extend to i32 or i64. + if (TargetVT != MVT::i32 && TargetVT != MVT::i64) + return SDValue(); - return DAG.getNode(X86ISD::CMOV, DL, TargetVT, CMovOp0, CMovOp1, - CMovN.getOperand(2), CMovN.getOperand(3)); + // Only extend from i16. + if (VT != MVT::i16) + return SDValue(); + + // If this a zero extend to i64, we should only extend to i32 and use a free + // zero extend to finish. + EVT ExtendVT = TargetVT; + if (TargetVT == MVT::i64 && ExtendOpcode == ISD::ZERO_EXTEND) + ExtendVT = MVT::i32; + + CMovOp0 = DAG.getNode(ExtendOpcode, DL, ExtendVT, CMovOp0); + CMovOp1 = DAG.getNode(ExtendOpcode, DL, ExtendVT, CMovOp1); + + SDValue Res = DAG.getNode(X86ISD::CMOV, DL, ExtendVT, CMovOp0, CMovOp1, + CMovN.getOperand(2), CMovN.getOperand(3)); + + // Finish extending if needed. + if (ExtendVT != TargetVT) + Res = DAG.getNode(ISD::ZERO_EXTEND, DL, TargetVT, Res); + + return Res; } // Convert (vXiY *ext(vXi1 bitcast(iX))) to extend_in_reg(broadcast(iX)). diff --git a/llvm/test/CodeGen/X86/cmov-promotion.ll b/llvm/test/CodeGen/X86/cmov-promotion.ll index 78a461281978..9dc137aab287 100644 --- a/llvm/test/CodeGen/X86/cmov-promotion.ll +++ b/llvm/test/CodeGen/X86/cmov-promotion.ll @@ -115,7 +115,7 @@ define i64 @cmov_zpromotion_16_to_64(i1 %c) { ; CMOV-NEXT: testb $1, %dil ; CMOV-NEXT: movl $12414, %ecx # imm = 0x307E ; CMOV-NEXT: movl $65535, %eax # imm = 0xFFFF -; CMOV-NEXT: cmovneq %rcx, %rax +; CMOV-NEXT: cmovnel %ecx, %eax ; CMOV-NEXT: retq ; ; NO_CMOV-LABEL: cmov_zpromotion_16_to_64: