Skip to content

Commit 3a386e3

Browse files
committed
[InstCombine] Fold the bound check idiom into sign bit test
1 parent 578c296 commit 3a386e3

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2641,6 +2641,26 @@ Instruction *InstCombinerImpl::foldICmpDivConstant(ICmpInst &Cmp,
26412641
if (!match(Y, m_APInt(C2)))
26422642
return nullptr;
26432643

2644+
// Fold the bound check idiom:
2645+
// T *end, *start;
2646+
// (size_t)(end - start) > (size_t)(PTRDIFF_MAX / sizeof(T))
2647+
// into:
2648+
// (ptrdiff_t)(end - start) < 0
2649+
// i.e.:
2650+
// icmp ugt (sdiv exact X, C2), (sdiv signed_max, C2) --> icmp slt X, 0
2651+
// icmp ult (sdiv exact X, C2), (sdiv signed_max, C2) + 1 --> icmp sgt X, -1
2652+
// where C2 is positive.
2653+
if (DivIsSigned && Div->isExact() &&
2654+
(Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULT) &&
2655+
C2->isStrictlyPositive() &&
2656+
APInt::getSignedMaxValue(C2->getBitWidth()).sdiv(*C2) +
2657+
APInt(C2->getBitWidth(), Pred == ICmpInst::ICMP_UGT ? 0 : 1) ==
2658+
C)
2659+
return new ICmpInst(
2660+
Pred == ICmpInst::ICMP_UGT ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_SGT, X,
2661+
Pred == ICmpInst::ICMP_UGT ? Constant::getNullValue(X->getType())
2662+
: Constant::getAllOnesValue(X->getType()));
2663+
26442664
// FIXME: If the operand types don't match the type of the divide
26452665
// then don't attempt this transform. The code below doesn't have the
26462666
// logic to deal with a signed divide and an unsigned compare (and

llvm/test/Transforms/InstCombine/icmp.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5140,8 +5140,7 @@ entry:
51405140

51415141
define i1 @icmp_ugt_sdiv_by_constant(i64 %x) {
51425142
; CHECK-LABEL: @icmp_ugt_sdiv_by_constant(
5143-
; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[X:%.*]], 24
5144-
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[SDIV]], 384307168202282325
5143+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[X:%.*]], 0
51455144
; CHECK-NEXT: ret i1 [[CMP]]
51465145
;
51475146
%sdiv = sdiv exact i64 %x, 24
@@ -5151,8 +5150,7 @@ define i1 @icmp_ugt_sdiv_by_constant(i64 %x) {
51515150

51525151
define i1 @icmp_ult_sdiv_by_constant(i64 %x) {
51535152
; CHECK-LABEL: @icmp_ult_sdiv_by_constant(
5154-
; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[X:%.*]], 24
5155-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SDIV]], 384307168202282326
5153+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[X:%.*]], -1
51565154
; CHECK-NEXT: ret i1 [[CMP]]
51575155
;
51585156
%sdiv = sdiv exact i64 %x, 24

0 commit comments

Comments
 (0)