Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1712,6 +1712,27 @@ assert(I.isBitwiseLogicOp() && "Unexpected opcode for bitwise logic folding"); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + // ( A << (X - 1) ) | ((A > 0) zext to iX) <=> A < 0 | A > 0 + // <=> (A != 0) zext to iX + Value *A; + ConstantInt *B; + ICmpInst::Predicate pred; + if (LogicOpc == Instruction::Or && + ((match(Op0, m_LShr(m_Value(A), m_ConstantInt(B))) && + match(Op1, m_ZExt(m_ICmp(pred, m_Specific(A), m_SpecificInt(0))))) || + (match(Op1, m_LShr(m_Value(A), m_ConstantInt(B))) && + match(Op0, m_ZExt(m_ICmp(pred, m_Specific(A), m_SpecificInt(0))))))) { + uint64_t X = A->getType()->getIntegerBitWidth(); + if (pred == ICmpInst::ICMP_SGT && B->getValue() == X - 1 && + A->getType()->isIntegerTy()) { + Value *cmp = Builder.CreateICmp( + ICmpInst::ICMP_NE, A, + Builder.getInt(APInt::getZero(A->getType()->getIntegerBitWidth()))); + return new ZExtInst(cmp, A->getType()); + } + } + CastInst *Cast0 = dyn_cast(Op0); if (!Cast0) return nullptr; Index: llvm/test/Transforms/InstCombine/and-or-icmps.ll =================================================================== --- llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -2571,10 +2571,8 @@ define i32 @icmp_slt_0_or_icmp_sgt_0_i32(i32 %x) { ; CHECK-LABEL: @icmp_slt_0_or_icmp_sgt_0_i32( -; CHECK-NEXT: [[B:%.*]] = icmp sgt i32 [[X:%.*]], 0 -; CHECK-NEXT: [[X_LOBIT:%.*]] = lshr i32 [[X]], 31 -; CHECK-NEXT: [[D:%.*]] = zext i1 [[B]] to i32 -; CHECK-NEXT: [[E:%.*]] = or i32 [[X_LOBIT]], [[D]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], 0 +; CHECK-NEXT: [[E:%.*]] = zext i1 [[TMP1]] to i32 ; CHECK-NEXT: ret i32 [[E]] ; %A = icmp slt i32 %x, 0 @@ -2587,10 +2585,8 @@ define i64 @icmp_slt_0_or_icmp_sgt_0_i64(i64 %x) { ; CHECK-LABEL: @icmp_slt_0_or_icmp_sgt_0_i64( -; CHECK-NEXT: [[B:%.*]] = icmp sgt i64 [[X:%.*]], 0 -; CHECK-NEXT: [[X_LOBIT:%.*]] = lshr i64 [[X]], 63 -; CHECK-NEXT: [[D:%.*]] = zext i1 [[B]] to i64 -; CHECK-NEXT: [[E:%.*]] = or i64 [[X_LOBIT]], [[D]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[X:%.*]], 0 +; CHECK-NEXT: [[E:%.*]] = zext i1 [[TMP1]] to i64 ; CHECK-NEXT: ret i64 [[E]] ; %A = icmp slt i64 %x, 0