Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -30274,6 +30274,35 @@ EFLAGS)); } +// transforms (setcc CC, (cmp (zext:N x), const)) to (setcc CC (cmp x, const')) +// where N is some bit width greater than x's; const' has x's bit width; const +// == const' in value +static SDValue combineX86Cmp(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const X86Subtarget &Subtarget) { + if (N->uses().begin() != N->uses().end() && + all_of(N->uses().begin(), N->uses().end(), + [](const SDNode *user) { + X86::CondCode cc = X86::CondCode(user->getConstantOperandVal(0)); + return user->getOpcode() == X86ISD::SETCC && + (cc == X86::COND_E || cc == X86::COND_NE || + cc == X86::COND_NE || cc == X86::COND_NP || + cc == X86::COND_P); + }) && + N->getOperand(0).getOpcode() == ISD::ZERO_EXTEND) { + if (ConstantSDNode *rhs = dyn_cast(N->getOperand(1))) { + const SDValue &innerlhs = N->getOperand(0)->getOperand(0); + uint64_t rhsval = rhs->getZExtValue(); + if (isUIntN(innerlhs.getValueSizeInBits(), rhsval)) { + return DAG.getNode( + X86ISD::CMP, SDLoc(N), innerlhs.getValueType(), innerlhs, + DAG.getConstant(rhsval, SDLoc(rhs), innerlhs.getValueType())); + } + } + } + return SDValue(); +} + // Optimize RES = X86ISD::SETCC CONDCODE, EFLAG_INPUT static SDValue combineX86SetCC(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, @@ -30881,6 +30910,7 @@ case ISD::SIGN_EXTEND: return combineSext(N, DAG, DCI, Subtarget); case ISD::SIGN_EXTEND_INREG: return combineSignExtendInReg(N, DAG, Subtarget); case ISD::SETCC: return combineSetCC(N, DAG, Subtarget); + case X86ISD::CMP: return combineX86Cmp(N, DAG, DCI, Subtarget); case X86ISD::SETCC: return combineX86SetCC(N, DAG, DCI, Subtarget); case X86ISD::BRCOND: return combineBrCond(N, DAG, DCI, Subtarget); case X86ISD::VZEXT: return combineVZext(N, DAG, DCI, Subtarget); Index: test/CodeGen/X86/cmp-zext-combine.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/cmp-zext-combine.ll @@ -0,0 +1,21 @@ +; RUN: llc -mtriple=x86_64 < %s | FileCheck %s +; RUN: llc -mtriple=i686 < %s | FileCheck %s + +define i32 @f(i64*, i32, i32) { +; CHECK-LABEL: f + %4 = alloca i64*, align 8 + %5 = bitcast i64** %4 to i8* + store i64* %0, i64** %4, align 8 + %6 = call { i32, i32 } asm sideeffect "cmpxchg8b $2", "={ax},={dx},=*m,{bx},{cx},0,1,*m,~{flags},~{dirflag},~{fpsr},~{flags}"(i64** nonnull %4, i32 4, i32 5, i32 0, i32 0, i64** nonnull %4) #5 + %7 = extractvalue { i32, i32 } %6, 0 + %8 = extractvalue { i32, i32 } %6, 1 + %9 = zext i32 %8 to i64 + %10 = shl nuw i64 %9, 32 +; CHECK-DAG: testl %eax, %eax + %11 = icmp ne i32 %7, 0 +; CHECK-DAG: testl %edx, %edx + %12 = icmp ugt i64 %10, 4294967295 + %13 = and i1 %11, %12 + %14 = zext i1 %13 to i32 + ret i32 %14 +}