Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -803,6 +803,36 @@ const Value *FalseVal, InstCombiner::BuilderTy &Builder) { ICmpInst::Predicate Pred = ICI->getPredicate(); + // (a == 0) : 0 : a - 1 -> usub.sat(a, 1) + if (ICmpInst::isEquality(Pred)) { + Value *A = ICI->getOperand(0); + Value *B = ICI->getOperand(1); + + if (!match(B, m_Zero())) + return nullptr; + + if (match(FalseVal, m_Zero())) { + if (Pred == ICmpInst::ICMP_NE) { + Pred = ICmpInst::getSwappedPredicate(Pred); + std::swap(TrueVal, FalseVal); + } + } + + if (!match(TrueVal, m_Zero())) + return nullptr; + + const APInt *Added; + if (match(FalseVal, m_Add(m_Specific(A), m_APInt(Added)))) { + // add a, -1 + if (Added->isAllOnes()) { + return Builder.CreateBinaryIntrinsic( + Intrinsic::usub_sat, A, ConstantInt::get(A->getType(), -*Added)); + } + return nullptr; + } + return nullptr; + } + if (!ICmpInst::isUnsigned(Pred)) return nullptr; 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,130 @@ 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 i8 @test_simplify_decrement_ne(i8 %a) { +; CHECK-LABEL: @test_simplify_decrement_ne( +; CHECK-NEXT: [[I2:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 1) +; CHECK-NEXT: ret i8 [[I2]] +; + %i = icmp ne i8 %a, 0 + %i1 = sub i8 %a, 1 + %i2 = select i1 %i, i8 %i1, i8 0 + ret i8 %i2 +} + +declare void @use.i1(i1) + +define i8 @test_simplify_decrement_ne_2(i8 %a) { +; CHECK-LABEL: @test_simplify_decrement_ne_2( +; CHECK-NEXT: [[I:%.*]] = icmp ne i8 [[A:%.*]], 0 +; CHECK-NEXT: call void @use.i1(i1 [[I]]) +; CHECK-NEXT: [[I2:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A]], i8 1) +; CHECK-NEXT: ret i8 [[I2]] +; + %i = icmp ne i8 %a, 0 + call void @use.i1(i1 %i) + %i1 = add i8 %a, -1 + %i2 = select i1 %i, i8 %i1, i8 0 + ret i8 %i2 +} + + +define <2 x i8> @test_simplify_decrement_vec(<2 x i8> %a) { +; CHECK-LABEL: @test_simplify_decrement_vec( +; CHECK-NEXT: [[I2:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> ) +; CHECK-NEXT: ret <2 x i8> [[I2]] +; + %i = icmp eq <2 x i8> %a, + %i1 = sub <2 x i8> %a, + %i2 = select <2 x i1> %i, <2 x i8> , <2 x i8> %i1 + ret <2 x i8> %i2 +} + +define <2 x i8> @test_simplify_decrement_vec_undef(<2 x i8> %a) { +; CHECK-LABEL: @test_simplify_decrement_vec_undef( +; CHECK-NEXT: [[I2:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> ) +; CHECK-NEXT: ret <2 x i8> [[I2]] +; + %i = icmp eq <2 x i8> %a, + %i1 = sub <2 x i8> %a, + %i2 = select <2 x i1> %i, <2 x i8> , <2 x i8> %i1 + ret <2 x i8> %i2 +} + +define i8 @test_simplify_decrement_invalid_ne(i8 %a) { +; CHECK-LABEL: @test_simplify_decrement_invalid_ne( +; CHECK-NEXT: [[I_NOT:%.*]] = icmp eq i8 [[A:%.*]], 0 +; CHECK-NEXT: [[I2:%.*]] = sext i1 [[I_NOT]] to i8 +; CHECK-NEXT: ret i8 [[I2]] +; + %i = icmp ne i8 %a, 0 + %i1 = sub i8 %a, 1 + %i2 = select i1 %i, i8 0, i8 %i1 + ret i8 %i2 +} + +define i8 @test_invalid_simplify_sub2(i8 %a) { +; CHECK-LABEL: @test_invalid_simplify_sub2( +; CHECK-NEXT: [[I:%.*]] = icmp eq i8 [[A:%.*]], 0 +; CHECK-NEXT: [[I1:%.*]] = add i8 [[A]], -2 +; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], i8 0, i8 [[I1]] +; CHECK-NEXT: ret i8 [[I2]] +; + %i = icmp eq i8 %a, 0 + %i1 = sub i8 %a, 2 + %i2 = select i1 %i, i8 0, i8 %i1 + ret i8 %i2 +} + +define i8 @test_invalid_simplify_eq1(i8 %a) { +; CHECK-LABEL: @test_invalid_simplify_eq1( +; CHECK-NEXT: [[I1:%.*]] = add i8 [[A:%.*]], -1 +; CHECK-NEXT: ret i8 [[I1]] +; + %i = icmp eq i8 %a, 1 + %i1 = sub i8 %a, 1 + %i2 = select i1 %i, i8 0, i8 %i1 + ret i8 %i2 +} + +define i8 @test_invalid_simplify_select_1(i8 %a) { +; CHECK-LABEL: @test_invalid_simplify_select_1( +; CHECK-NEXT: [[I:%.*]] = icmp eq i8 [[A:%.*]], 0 +; CHECK-NEXT: [[I1:%.*]] = add i8 [[A]], -1 +; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], i8 1, i8 [[I1]] +; CHECK-NEXT: ret i8 [[I2]] +; + %i = icmp eq i8 %a, 0 + %i1 = sub i8 %a, 1 + %i2 = select i1 %i, i8 1, i8 %i1 + ret i8 %i2 +} + +define i8 @test_invalid_simplify_other(i8 %a, i8 %b) { +; CHECK-LABEL: @test_invalid_simplify_other( +; CHECK-NEXT: [[I:%.*]] = icmp eq i8 [[A:%.*]], 1 +; CHECK-NEXT: [[I1:%.*]] = add i8 [[B:%.*]], -1 +; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], i8 0, i8 [[I1]] +; CHECK-NEXT: ret i8 [[I2]] +; + %i = icmp eq i8 %a, 1 + %i1 = sub i8 %b, 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> ) Index: llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll =================================================================== --- llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll +++ llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll @@ -265,9 +265,7 @@ define i32 @max_sub_ugt_c01(i32 %a) { ; CHECK-LABEL: @max_sub_ugt_c01( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0 -; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -1 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 0, i32 [[SUB]] +; CHECK-NEXT: [[SEL:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 1) ; CHECK-NEXT: ret i32 [[SEL]] ; %cmp = icmp ugt i32 %a, 0 Index: llvm/test/Transforms/PhaseOrdering/pr44461-br-to-switch-rotate.ll =================================================================== --- llvm/test/Transforms/PhaseOrdering/pr44461-br-to-switch-rotate.ll +++ llvm/test/Transforms/PhaseOrdering/pr44461-br-to-switch-rotate.ll @@ -19,8 +19,7 @@ ; CHECK: bb3.i.i: ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[ITER1_SROA_5_0]], 0 ; CHECK-NEXT: [[TMP3]] = zext i1 [[TMP2]] to i8 -; CHECK-NEXT: [[_5_0_I_I_I_I:%.*]] = add i64 [[ITER1_SROA_5_0]], -1 -; CHECK-NEXT: [[SPEC_SELECT]] = select i1 [[TMP2]], i64 0, i64 [[_5_0_I_I_I_I]] +; CHECK-NEXT: [[SPEC_SELECT]] = tail call i64 @llvm.usub.sat.i64(i64 [[ITER1_SROA_5_0]], i64 1) ; CHECK-NEXT: [[TMP4]] = add i64 [[COUNT_1]], [[ITER1_SROA_5_0]] ; CHECK-NEXT: br label [[BB10]] ; CHECK: bb12: