From: Nikita Popov Date: Sat, 15 Dec 2018 10:37:01 +0000 (+0000) Subject: [InstSimplify] Add tests for saturating add/sub + icmp; NFC X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7c45236930ce47db02cad9523c4ecbfb78ec99c8;p=llvm [InstSimplify] Add tests for saturating add/sub + icmp; NFC If a saturating add/sub with a constant operand is compared to another constant, we should be able to determine that the condition is always true/false in some cases (but currently don't). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349261 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/Transforms/InstSimplify/saturating-add-sub.ll b/test/Transforms/InstSimplify/saturating-add-sub.ll index 86be08fdaed..d16ed4256f6 100644 --- a/test/Transforms/InstSimplify/saturating-add-sub.ll +++ b/test/Transforms/InstSimplify/saturating-add-sub.ll @@ -406,3 +406,168 @@ define <2 x i8> @ssub_vector_same(<2 x i8> %a) { ret <2 x i8> %y6v } +define i1 @uadd_icmp_known(i8 %a) { +; CHECK-LABEL: @uadd_icmp_known( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[A:%.*]], i8 10) +; CHECK-NEXT: [[C:%.*]] = icmp uge i8 [[B]], 10 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.uadd.sat.i8(i8 %a, i8 10) + %c = icmp uge i8 %b, 10 + ret i1 %c +} + +define i1 @uadd_icmp_unknown(i8 %a) { +; CHECK-LABEL: @uadd_icmp_unknown( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[A:%.*]], i8 10) +; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[B]], 10 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.uadd.sat.i8(i8 %a, i8 10) + %c = icmp ugt i8 %b, 10 + ret i1 %c +} + +define i1 @sadd_icmp_pos_known(i8 %a) { +; CHECK-LABEL: @sadd_icmp_pos_known( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 10) +; CHECK-NEXT: [[C:%.*]] = icmp sge i8 [[B]], -118 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.sadd.sat.i8(i8 %a, i8 10) + %c = icmp sge i8 %b, -118 + ret i1 %c +} + +define i1 @sadd_icmp_pos_unknown(i8 %a) { +; CHECK-LABEL: @sadd_icmp_pos_unknown( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 10) +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[B]], -118 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.sadd.sat.i8(i8 %a, i8 10) + %c = icmp sgt i8 %b, -118 + ret i1 %c +} + +define i1 @sadd_icmp_neg_known(i8 %a) { +; CHECK-LABEL: @sadd_icmp_neg_known( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -10) +; CHECK-NEXT: [[C:%.*]] = icmp sle i8 [[B]], 117 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.sadd.sat.i8(i8 %a, i8 -10) + %c = icmp sle i8 %b, 117 + ret i1 %c +} + +define i1 @sadd_icmp_neg_unknown(i8 %a) { +; CHECK-LABEL: @sadd_icmp_neg_unknown( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -10) +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[B]], 117 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.sadd.sat.i8(i8 %a, i8 -10) + %c = icmp slt i8 %b, 117 + ret i1 %c +} + +define i1 @usub_icmp_op0_known(i8 %a) { +; CHECK-LABEL: @usub_icmp_op0_known( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.usub.sat.i8(i8 10, i8 [[A:%.*]]) +; CHECK-NEXT: [[C:%.*]] = icmp ule i8 [[B]], 10 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.usub.sat.i8(i8 10, i8 %a) + %c = icmp ule i8 %b, 10 + ret i1 %c +} + +define i1 @usub_icmp_op0_unknown(i8 %a) { +; CHECK-LABEL: @usub_icmp_op0_unknown( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.usub.sat.i8(i8 10, i8 [[A:%.*]]) +; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[B]], 10 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.usub.sat.i8(i8 10, i8 %a) + %c = icmp ult i8 %b, 10 + ret i1 %c +} + +define i1 @usub_icmp_op1_known(i8 %a) { +; CHECK-LABEL: @usub_icmp_op1_known( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 10) +; CHECK-NEXT: [[C:%.*]] = icmp ule i8 [[B]], -11 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.usub.sat.i8(i8 %a, i8 10) + %c = icmp ule i8 %b, 245 + ret i1 %c +} + +define i1 @usub_icmp_op1_unknown(i8 %a) { +; CHECK-LABEL: @usub_icmp_op1_unknown( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 10) +; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[B]], -11 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.usub.sat.i8(i8 %a, i8 10) + %c = icmp ult i8 %b, 245 + ret i1 %c +} + +define i1 @ssub_icmp_op0_pos_known(i8 %a) { +; CHECK-LABEL: @ssub_icmp_op0_pos_known( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.ssub.sat.i8(i8 10, i8 [[A:%.*]]) +; CHECK-NEXT: [[C:%.*]] = icmp sge i8 [[B]], -117 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.ssub.sat.i8(i8 10, i8 %a) + %c = icmp sge i8 %b, -117 + ret i1 %c +} + +define i1 @ssub_icmp_op0_pos_unknown(i8 %a) { +; CHECK-LABEL: @ssub_icmp_op0_pos_unknown( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.ssub.sat.i8(i8 10, i8 [[A:%.*]]) +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[B]], -117 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.ssub.sat.i8(i8 10, i8 %a) + %c = icmp sgt i8 %b, -117 + ret i1 %c +} + +define i1 @ssub_icmp_op0_neg_known(i8 %a) { +; CHECK-LABEL: @ssub_icmp_op0_neg_known( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.ssub.sat.i8(i8 -10, i8 [[A:%.*]]) +; CHECK-NEXT: [[C:%.*]] = icmp sle i8 [[B]], 118 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.ssub.sat.i8(i8 -10, i8 %a) + %c = icmp sle i8 %b, 118 + ret i1 %c +} + +define i1 @ssub_icmp_op0_neg_unknown(i8 %a) { +; CHECK-LABEL: @ssub_icmp_op0_neg_unknown( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.ssub.sat.i8(i8 -10, i8 [[A:%.*]]) +; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[B]], 118 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.ssub.sat.i8(i8 -10, i8 %a) + %c = icmp slt i8 %b, 118 + ret i1 %c +} + +; Peculiar case: ssub.sat(0, x) is never signed min. +define i1 @ssub_icmp_op0_zero(i8 %a) { +; CHECK-LABEL: @ssub_icmp_op0_zero( +; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.ssub.sat.i8(i8 0, i8 [[A:%.*]]) +; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[B]], -128 +; CHECK-NEXT: ret i1 [[C]] +; + %b = call i8 @llvm.ssub.sat.i8(i8 0, i8 %a) + %c = icmp ne i8 %b, -128 + ret i1 %c +}