Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -4934,14 +4934,25 @@ } // fold (srl (shl x, c), c) -> (and x, cst2) - if (N0.getOpcode() == ISD::SHL && N0.getOperand(1) == N1 && - isConstantOrConstantVector(N1, /* NoOpaques */ true)) { - SDLoc DL(N); - APInt AllBits = APInt::getAllOnesValue(N0.getScalarValueSizeInBits()); - SDValue Mask = - DAG.getNode(ISD::SRL, DL, VT, DAG.getConstant(AllBits, DL, VT), N1); - AddToWorklist(Mask.getNode()); - return DAG.getNode(ISD::AND, DL, VT, N0.getOperand(0), Mask); + if (N0.getOpcode() == ISD::SHL) { + bool fold = N0.getOperand(1) == N1 && + isConstantOrConstantVector(N1, /* NoOpaques */ true); + + if (!fold && isa(N0.getOperand(1))) { + APInt c1 = cast(N0.getOperand(1))->getAPIntValue(); + APInt c0 = N1C->getAPIntValue(); + zeroExtendToMatch(c1, c0); + fold = c1.eq(c0); + } + + if (fold) { + SDLoc DL(N); + APInt AllBits = APInt::getAllOnesValue(N0.getScalarValueSizeInBits()); + SDValue Mask = + DAG.getNode(ISD::SRL, DL, VT, DAG.getConstant(AllBits, DL, VT), N1); + AddToWorklist(Mask.getNode()); + return DAG.getNode(ISD::AND, DL, VT, N0.getOperand(0), Mask); + } } // fold (srl (anyextend x), c) -> (and (anyextend (srl x, c)), mask) Index: test/CodeGen/X86/cmp-zext-combine.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/cmp-zext-combine.ll @@ -0,0 +1,40 @@ +; RUN: llc -march=x86-64 < %s | FileCheck %s + +define i32 @nonzero16(i16) { +; CHECK-LABEL: nonzero16: +; CHECK: xorl %eax, %eax +; CHECK-NEXT: testl %edi, %edi +; CHECK-NEXT: setne %al +; CHECK-NEXT: retq + %b = zext i16 %0 to i32 + %c = shl i32 %b, 16 + %d = icmp ugt i32 %c, 65535 + %rv = zext i1 %d to i32 + ret i32 %rv +} + +define i32 @nonzero32(i32) { +; CHECK-LABEL: nonzero32: +; CHECK: xorl %eax, %eax +; CHECK-NEXT: testl %edi, %edi +; CHECK-NEXT: setne %al +; CHECK-NEXT: retq + %b = zext i32 %0 to i64 + %c = shl i64 %b, 32 + %d = icmp ugt i64 %c, 4294967295 + %rv = zext i1 %d to i32 + ret i32 %rv +} + +define i32 @nonzero64(i64) { +; CHECK-LABEL: nonzero64: +; CHECK: xorl %eax, %eax +; CHECK-NEXT: testq %rdi, %rdi +; CHECK-NEXT: setne %al +; CHECK-NEXT: retq + %b = zext i64 %0 to i128 + %c = shl i128 %b, 64 + %d = icmp ugt i128 %c, 18446744073709551615 + %rv = zext i1 %d to i32 + ret i32 %rv +}