diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index d7c4927e4546f..1815fc858c679 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3395,6 +3395,11 @@ Instruction *InstCombinerImpl::foldICmpEqIntrinsicWithConstant( break; } + case Intrinsic::ssub_sat: + // ssub.sat(a, b) == 0 -> a == b + if (C.isZero()) + return new ICmpInst(Pred, II->getArgOperand(0), II->getArgOperand(1)); + break; case Intrinsic::usub_sat: { // usub.sat(a, b) == 0 -> a <= b if (C.isZero()) { @@ -3593,6 +3598,21 @@ Instruction *InstCombinerImpl::foldICmpIntrinsicWithConstant(ICmpInst &Cmp, } break; } + case Intrinsic::ssub_sat: + // ssub.sat(a, b) spred 0 -> a spred b + if (ICmpInst::isSigned(Pred)) { + if (C.isZero()) + return new ICmpInst(Pred, II->getArgOperand(0), II->getArgOperand(1)); + // X s<= 0 is cannonicalized to X s< 1 + if (Pred == ICmpInst::ICMP_SLT && C.isOne()) + return new ICmpInst(ICmpInst::ICMP_SLE, II->getArgOperand(0), + II->getArgOperand(1)); + // X s>= 0 is cannonicalized to X s> -1 + if (Pred == ICmpInst::ICMP_SGT && C.isAllOnes()) + return new ICmpInst(ICmpInst::ICMP_SGE, II->getArgOperand(0), + II->getArgOperand(1)); + } + break; default: break; } diff --git a/llvm/test/Transforms/InstCombine/cmp-intrinsic.ll b/llvm/test/Transforms/InstCombine/cmp-intrinsic.ll index 625cf9a0211be..5955650167c21 100644 --- a/llvm/test/Transforms/InstCombine/cmp-intrinsic.ll +++ b/llvm/test/Transforms/InstCombine/cmp-intrinsic.ll @@ -885,8 +885,7 @@ define i1 @uadd_sat_ne_zero_fail_multiuse(i8 %x, i8 %y) { define i1 @ssub_sat_ne_zero(i8 %x, i8 %y) { ; CHECK-LABEL: @ssub_sat_ne_zero( -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[M]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %m = call i8 @llvm.ssub.sat.i8(i8 %x, i8 %y) @@ -907,8 +906,7 @@ define i1 @ssub_sat_ne_fail_nonzero(i8 %x, i8 %y) { define i1 @ssub_sat_eq_zero(i8 %x, i8 %y) { ; CHECK-LABEL: @ssub_sat_eq_zero( -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %m = call i8 @llvm.ssub.sat.i8(i8 %x, i8 %y) @@ -918,8 +916,7 @@ define i1 @ssub_sat_eq_zero(i8 %x, i8 %y) { define i1 @ssub_sat_sle_zero(i8 %x, i8 %y) { ; CHECK-LABEL: @ssub_sat_sle_zero( -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[M]], 1 +; CHECK-NEXT: [[R:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %m = call i8 @llvm.ssub.sat.i8(i8 %x, i8 %y) @@ -929,8 +926,7 @@ define i1 @ssub_sat_sle_zero(i8 %x, i8 %y) { define i1 @ssub_sat_sge_zero(i8 %x, i8 %y) { ; CHECK-LABEL: @ssub_sat_sge_zero( -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[M]], -1 +; CHECK-NEXT: [[R:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %m = call i8 @llvm.ssub.sat.i8(i8 %x, i8 %y) @@ -940,8 +936,7 @@ define i1 @ssub_sat_sge_zero(i8 %x, i8 %y) { define i1 @ssub_sat_slt_zero(i8 %x, i8 %y) { ; CHECK-LABEL: @ssub_sat_slt_zero( -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[M]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %m = call i8 @llvm.ssub.sat.i8(i8 %x, i8 %y) @@ -962,8 +957,7 @@ define i1 @ssub_sat_slt_neg1_fail(i8 %x, i8 %y) { define i1 @ssub_sat_sgt_zero(i8 %x, i8 %y) { ; CHECK-LABEL: @ssub_sat_sgt_zero( -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[M]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %m = call i8 @llvm.ssub.sat.i8(i8 %x, i8 %y)