Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -853,6 +853,39 @@ return Result; } +/// Transform (a == 0) : 0 : a - 1 into usub.sat(a, 1) +static Value *canonicalizeSaturatedDecrement(const ICmpInst *ICI, + const Value *TrueVal, + const Value *FalseVal, + InstCombiner::BuilderTy &Builder) { + ICmpInst::Predicate Pred = ICI->getPredicate(); + if (Pred != ICmpInst::ICMP_EQ) + return nullptr; + + Value *A = ICI->getOperand(0); + Value *B = ICI->getOperand(1); + + if (match(A, m_Zero())) + std::swap(A, B); + + if (!match(B, m_Zero())) + return nullptr; + + if (match(FalseVal, m_Zero())) + std::swap(TrueVal, FalseVal); + + if (!match(TrueVal, m_Zero())) + return nullptr; + + Value *One = ConstantInt::get(A->getType(), 1); + Value *NegOne = Builder.CreateNeg(One); + if (match(FalseVal, m_Sub(m_Specific(A), m_Specific(One))) || + match(FalseVal, m_Add(m_Specific(A), m_Specific(NegOne)))) { + return Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, A, One); + } + return nullptr; +} + static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal, InstCombiner::BuilderTy &Builder) { if (!Cmp->hasOneUse()) @@ -1741,6 +1774,10 @@ if (Value *V = canonicalizeSaturatedSubtract(ICI, TrueVal, FalseVal, Builder)) return replaceInstUsesWith(SI, V); + if (Value *V = + canonicalizeSaturatedDecrement(ICI, TrueVal, FalseVal, Builder)) + return replaceInstUsesWith(SI, V); + if (Value *V = canonicalizeSaturatedAdd(ICI, TrueVal, FalseVal, Builder)) return replaceInstUsesWith(SI, V); Index: llvm/test/Transforms/InstCombine/saturating-add-sub.ll =================================================================== --- llvm/test/Transforms/InstCombine/saturating-add-sub.ll +++ llvm/test/Transforms/InstCombine/saturating-add-sub.ll @@ -520,6 +520,18 @@ ret i8 %x2 } +; Can simplify zero check followed by decrement +define i8 @test_simplify_decrement(i8 %a) { +; CHECK-LABEL: @test_simplify_decrement( +; CHECK-NEXT: [[I2:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 1) +; CHECK-NEXT: ret i8 [[I2]] +; + %i = icmp eq i8 %a, 0 + %i1 = sub i8 %a, 1 + %i2 = select i1 %i, i8 0, i8 %i1 + ret i8 %i2 +} + define <2 x i8> @test_vector_usub_combine(<2 x i8> %a) { ; CHECK-LABEL: @test_vector_usub_combine( ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> )