Index: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp @@ -39937,18 +39937,24 @@ // 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(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 @@ 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; Index: llvm/trunk/test/CodeGen/X86/cmov-promotion.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/cmov-promotion.ll +++ llvm/trunk/test/CodeGen/X86/cmov-promotion.ll @@ -152,10 +152,9 @@ ; CMOV-LABEL: cmov_spromotion_8_to_16: ; CMOV: # %bb.0: ; CMOV-NEXT: testb $1, %dil -; CMOV-NEXT: movl $117, %eax -; CMOV-NEXT: movl $237, %ecx -; CMOV-NEXT: cmovnel %eax, %ecx -; CMOV-NEXT: movsbl %cl, %eax +; CMOV-NEXT: movl $117, %ecx +; CMOV-NEXT: movl $65517, %eax # imm = 0xFFED +; CMOV-NEXT: cmovnel %ecx, %eax ; CMOV-NEXT: # kill: def $ax killed $ax killed $eax ; CMOV-NEXT: retq ; @@ -179,10 +178,9 @@ ; CMOV-LABEL: cmov_spromotion_8_to_32: ; CMOV: # %bb.0: ; CMOV-NEXT: testb $1, %dil -; CMOV-NEXT: movl $126, %eax -; CMOV-NEXT: movl $255, %ecx -; CMOV-NEXT: cmovnel %eax, %ecx -; CMOV-NEXT: movsbl %cl, %eax +; CMOV-NEXT: movl $126, %ecx +; CMOV-NEXT: movl $-1, %eax +; CMOV-NEXT: cmovnel %ecx, %eax ; CMOV-NEXT: retq ; ; NO_CMOV-LABEL: cmov_spromotion_8_to_32: @@ -204,10 +202,9 @@ ; CMOV-LABEL: cmov_spromotion_8_to_64: ; CMOV: # %bb.0: ; CMOV-NEXT: testb $1, %dil -; CMOV-NEXT: movl $126, %eax -; CMOV-NEXT: movl $255, %ecx -; CMOV-NEXT: cmovnel %eax, %ecx -; CMOV-NEXT: movsbq %cl, %rax +; CMOV-NEXT: movl $126, %ecx +; CMOV-NEXT: movq $-1, %rax +; CMOV-NEXT: cmovneq %rcx, %rax ; CMOV-NEXT: retq ; ; NO_CMOV-LABEL: cmov_spromotion_8_to_64: