diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3251,11 +3251,14 @@ // extractvalue (any_mul_with_overflow X, -1), 0 --> -X Intrinsic::ID OvID = WO->getIntrinsicID(); - if (*EV.idx_begin() == 0 && - (OvID == Intrinsic::smul_with_overflow || - OvID == Intrinsic::umul_with_overflow) && - match(WO->getArgOperand(1), m_AllOnes())) { - return BinaryOperator::CreateNeg(WO->getArgOperand(0)); + const APInt *WORHSC = nullptr; + if (match(WO->getRHS(), m_APIntAllowUndef(WORHSC))) { + if (*EV.idx_begin() == 0 && + (OvID == Intrinsic::smul_with_overflow || + OvID == Intrinsic::umul_with_overflow) && + WORHSC->isAllOnes()) { + return BinaryOperator::CreateNeg(WO->getArgOperand(0)); + } } // We're extracting from an overflow intrinsic. See if we're the only user. @@ -3284,12 +3287,11 @@ // If only the overflow result is used, and the right hand side is a // constant (or constant splat), we can remove the intrinsic by directly // checking for overflow. - const APInt *C; - if (match(WO->getRHS(), m_APInt(C))) { + if (WORHSC) { // Compute the no-wrap range for LHS given RHS=C, then construct an // equivalent icmp, potentially using an offset. ConstantRange NWR = ConstantRange::makeExactNoWrapRegion( - WO->getBinaryOp(), *C, WO->getNoWrapKind()); + WO->getBinaryOp(), *WORHSC, WO->getNoWrapKind()); CmpInst::Predicate Pred; APInt NewRHSC, Offset; diff --git a/llvm/test/Transforms/InstCombine/with_overflow.ll b/llvm/test/Transforms/InstCombine/with_overflow.ll --- a/llvm/test/Transforms/InstCombine/with_overflow.ll +++ b/llvm/test/Transforms/InstCombine/with_overflow.ll @@ -793,13 +793,10 @@ ret <4 x i8> %r } -; TODO: partly failed to match vector constant with poison element - define <4 x i8> @smul_neg1_vec_poison(<4 x i8> %x, <4 x i1>* %p) { ; CHECK-LABEL: @smul_neg1_vec_poison( -; CHECK-NEXT: [[M:%.*]] = tail call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> [[X:%.*]], <4 x i8> ) -; CHECK-NEXT: [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X]] -; CHECK-NEXT: [[OV:%.*]] = extractvalue { <4 x i8>, <4 x i1> } [[M]], 1 +; CHECK-NEXT: [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[OV:%.*]] = icmp eq <4 x i8> [[X]], ; CHECK-NEXT: store <4 x i1> [[OV]], <4 x i1>* [[P:%.*]], align 1 ; CHECK-NEXT: ret <4 x i8> [[R]] ; @@ -853,13 +850,10 @@ ret <4 x i8> %r } -; TODO: partly failed to match vector constant with poison element - define <4 x i8> @umul_neg1_vec_poison(<4 x i8> %x, <4 x i1>* %p) { ; CHECK-LABEL: @umul_neg1_vec_poison( -; CHECK-NEXT: [[M:%.*]] = tail call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> [[X:%.*]], <4 x i8> ) -; CHECK-NEXT: [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X]] -; CHECK-NEXT: [[OV:%.*]] = extractvalue { <4 x i8>, <4 x i1> } [[M]], 1 +; CHECK-NEXT: [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[OV:%.*]] = icmp ugt <4 x i8> [[X]], ; CHECK-NEXT: store <4 x i1> [[OV]], <4 x i1>* [[P:%.*]], align 1 ; CHECK-NEXT: ret <4 x i8> [[R]] ;