From 578c2960c04282352d2169a28fc2e98b4be75064 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 27 Dec 2023 21:36:28 +0800 Subject: [PATCH 1/3] [InstCombine] Add pre-commit tests. NFC. --- llvm/test/Transforms/InstCombine/icmp.ll | 98 +++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index 1f554c7b60256..2ea3fe8cb2ef1 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -5006,7 +5006,6 @@ define i1 @or_positive_sgt_zero_multi_use(i8 %a) { ret i1 %cmp } - define i1 @disjoint_or_sgt_1(i8 %a, i8 %b) { ; CHECK-LABEL: @disjoint_or_sgt_1( ; CHECK-NEXT: [[B1:%.*]] = add nsw i8 [[B:%.*]], 2 @@ -5138,3 +5137,100 @@ entry: %cmp = icmp eq i8 %add2, %add1 ret i1 %cmp } + +define i1 @icmp_ugt_sdiv_by_constant(i64 %x) { +; CHECK-LABEL: @icmp_ugt_sdiv_by_constant( +; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[X:%.*]], 24 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[SDIV]], 384307168202282325 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sdiv = sdiv exact i64 %x, 24 + %cmp = icmp ugt i64 %sdiv, 384307168202282325 + ret i1 %cmp +} + +define i1 @icmp_ult_sdiv_by_constant(i64 %x) { +; CHECK-LABEL: @icmp_ult_sdiv_by_constant( +; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[X:%.*]], 24 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SDIV]], 384307168202282326 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sdiv = sdiv exact i64 %x, 24 + %cmp = icmp ult i64 %sdiv, 384307168202282326 + ret i1 %cmp +} + +; TODO: This should be simplified to icmp slt i64 %x, 0 +define i1 @icmp_ugt_ashr_by_constant(i64 %x) { +; CHECK-LABEL: @icmp_ugt_ashr_by_constant( +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X:%.*]], 9223372036854775804 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sdiv = ashr exact i64 %x, 2 + %cmp = icmp ugt i64 %sdiv, 2305843009213693951 + ret i1 %cmp +} + +define i1 @icmp_ult_ashr_by_constant(i64 %x) { +; CHECK-LABEL: @icmp_ult_ashr_by_constant( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[X:%.*]], -1 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sdiv = ashr exact i64 %x, 2 + %cmp = icmp ult i64 %sdiv, 2305843009213693952 + ret i1 %cmp +} + +; Negative tests +define i1 @icmp_ugt_sdiv_by_constant_without_exact(i64 %x) { +; CHECK-LABEL: @icmp_ugt_sdiv_by_constant_without_exact( +; CHECK-NEXT: [[SDIV:%.*]] = sdiv i64 [[X:%.*]], 24 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[SDIV]], 384307168202282325 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sdiv = sdiv i64 %x, 24 + %cmp = icmp ugt i64 %sdiv, 384307168202282325 + ret i1 %cmp +} + +define i1 @icmp_ugt_udiv_by_constant(i64 %x) { +; CHECK-LABEL: @icmp_ugt_udiv_by_constant( +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X:%.*]], 9223372036854775800 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sdiv = udiv exact i64 %x, 24 + %cmp = icmp ugt i64 %sdiv, 384307168202282325 + ret i1 %cmp +} + +define i1 @icmp_ne_sdiv_by_constant(i64 %x) { +; CHECK-LABEL: @icmp_ne_sdiv_by_constant( +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[X:%.*]], 9223372036854775800 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sdiv = sdiv exact i64 %x, 24 + %cmp = icmp ne i64 %sdiv, 384307168202282325 + ret i1 %cmp +} + +define i1 @icmp_ugt_sdiv_by_constant_wrong_rhs(i64 %x) { +; CHECK-LABEL: @icmp_ugt_sdiv_by_constant_wrong_rhs( +; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[X:%.*]], 24 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[SDIV]], 384307168202282324 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sdiv = sdiv exact i64 %x, 24 + %cmp = icmp ugt i64 %sdiv, 384307168202282324 + ret i1 %cmp +} + +define i1 @icmp_ugt_sdiv_by_negative_constant(i64 %x) { +; CHECK-LABEL: @icmp_ugt_sdiv_by_negative_constant( +; CHECK-NEXT: [[SDIV:%.*]] = sdiv i64 [[X:%.*]], -24 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[SDIV]], -384307168202282326 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sdiv = sdiv i64 %x, -24 + %cmp = icmp ugt i64 %sdiv, -384307168202282326 + ret i1 %cmp +} From 3a386e38283006139356dd6dcdf0d4e89f27efe9 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 27 Dec 2023 21:36:58 +0800 Subject: [PATCH 2/3] [InstCombine] Fold the bound check idiom into sign bit test --- .../InstCombine/InstCombineCompares.cpp | 20 +++++++++++++++++++ llvm/test/Transforms/InstCombine/icmp.ll | 6 ++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index a2ff8f3eef819..07ccec2a7681b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2641,6 +2641,26 @@ Instruction *InstCombinerImpl::foldICmpDivConstant(ICmpInst &Cmp, if (!match(Y, m_APInt(C2))) return nullptr; + // Fold the bound check idiom: + // T *end, *start; + // (size_t)(end - start) > (size_t)(PTRDIFF_MAX / sizeof(T)) + // into: + // (ptrdiff_t)(end - start) < 0 + // i.e.: + // icmp ugt (sdiv exact X, C2), (sdiv signed_max, C2) --> icmp slt X, 0 + // icmp ult (sdiv exact X, C2), (sdiv signed_max, C2) + 1 --> icmp sgt X, -1 + // where C2 is positive. + if (DivIsSigned && Div->isExact() && + (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULT) && + C2->isStrictlyPositive() && + APInt::getSignedMaxValue(C2->getBitWidth()).sdiv(*C2) + + APInt(C2->getBitWidth(), Pred == ICmpInst::ICMP_UGT ? 0 : 1) == + C) + return new ICmpInst( + Pred == ICmpInst::ICMP_UGT ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_SGT, X, + Pred == ICmpInst::ICMP_UGT ? Constant::getNullValue(X->getType()) + : Constant::getAllOnesValue(X->getType())); + // FIXME: If the operand types don't match the type of the divide // then don't attempt this transform. The code below doesn't have the // logic to deal with a signed divide and an unsigned compare (and diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index 2ea3fe8cb2ef1..d51ec90622dcf 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -5140,8 +5140,7 @@ entry: define i1 @icmp_ugt_sdiv_by_constant(i64 %x) { ; CHECK-LABEL: @icmp_ugt_sdiv_by_constant( -; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[X:%.*]], 24 -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[SDIV]], 384307168202282325 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %sdiv = sdiv exact i64 %x, 24 @@ -5151,8 +5150,7 @@ define i1 @icmp_ugt_sdiv_by_constant(i64 %x) { define i1 @icmp_ult_sdiv_by_constant(i64 %x) { ; CHECK-LABEL: @icmp_ult_sdiv_by_constant( -; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[X:%.*]], 24 -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SDIV]], 384307168202282326 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[X:%.*]], -1 ; CHECK-NEXT: ret i1 [[CMP]] ; %sdiv = sdiv exact i64 %x, 24 From e55b9def3a36f233377cc02cbc9e702c66144ca9 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 27 Dec 2023 23:54:42 +0800 Subject: [PATCH 3/3] [InstCombine] Add one-use constraint for the simplification --- .../Transforms/InstCombine/InstCombineCompares.cpp | 2 +- llvm/test/Transforms/InstCombine/icmp.ll | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 07ccec2a7681b..8076dec2732d4 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2650,7 +2650,7 @@ Instruction *InstCombinerImpl::foldICmpDivConstant(ICmpInst &Cmp, // icmp ugt (sdiv exact X, C2), (sdiv signed_max, C2) --> icmp slt X, 0 // icmp ult (sdiv exact X, C2), (sdiv signed_max, C2) + 1 --> icmp sgt X, -1 // where C2 is positive. - if (DivIsSigned && Div->isExact() && + if (DivIsSigned && Div->hasOneUse() && Div->isExact() && (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULT) && C2->isStrictlyPositive() && APInt::getSignedMaxValue(C2->getBitWidth()).sdiv(*C2) + diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index d51ec90622dcf..c2d06754278ce 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -5232,3 +5232,16 @@ define i1 @icmp_ugt_sdiv_by_negative_constant(i64 %x) { %cmp = icmp ugt i64 %sdiv, -384307168202282326 ret i1 %cmp } + +define i1 @icmp_ugt_sdiv_by_constant_multiuse(i64 %x) { +; CHECK-LABEL: @icmp_ugt_sdiv_by_constant_multiuse( +; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[X:%.*]], 24 +; CHECK-NEXT: call void @use_i64(i64 [[SDIV]]) +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[SDIV]], 384307168202282325 +; CHECK-NEXT: ret i1 [[CMP]] +; + %sdiv = sdiv exact i64 %x, 24 + call void @use_i64(i64 %sdiv) + %cmp = icmp ugt i64 %sdiv, 384307168202282325 + ret i1 %cmp +}