Skip to content

Commit

Permalink
[InstCombine] Fold and of two ranges differing by mask
Browse files Browse the repository at this point in the history
This is the de Morgan conjugated variant of the existing fold for
ors. Implement this by switching the range code to always work
on ors and perform invert operands at the start and end. This makes
reasoning easier and makes the extension more obviosuly correct.
  • Loading branch information
nikic committed Apr 29, 2022
1 parent 7137526 commit 5515263
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 19 deletions.
16 changes: 8 additions & 8 deletions llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1187,23 +1187,20 @@ static Value *foldAndOrOfICmpsUsingRanges(
if (V1 != V2)
return nullptr;

ConstantRange CR1 = ConstantRange::makeExactICmpRegion(Pred1, C1);
ConstantRange CR1 = ConstantRange::makeExactICmpRegion(
IsAnd ? ICmpInst::getInversePredicate(Pred1) : Pred1, C1);
if (Offset1)
CR1 = CR1.subtract(*Offset1);

ConstantRange CR2 = ConstantRange::makeExactICmpRegion(Pred2, C2);
ConstantRange CR2 = ConstantRange::makeExactICmpRegion(
IsAnd ? ICmpInst::getInversePredicate(Pred2) : Pred2, C2);
if (Offset2)
CR2 = CR2.subtract(*Offset2);

Type *Ty = V1->getType();
Value *NewV = V1;
Optional<ConstantRange> CR =
IsAnd ? CR1.exactIntersectWith(CR2) : CR1.exactUnionWith(CR2);
Optional<ConstantRange> CR = CR1.exactUnionWith(CR2);
if (!CR) {
// TODO: Support and.
if (IsAnd)
return nullptr;

if (!BothHaveOneUse || CR1.isWrappedSet() || CR2.isWrappedSet())
return nullptr;

Expand All @@ -1220,6 +1217,9 @@ static Value *foldAndOrOfICmpsUsingRanges(
NewV = Builder.CreateAnd(NewV, ConstantInt::get(Ty, ~LowerDiff));
}

if (IsAnd)
CR = CR->inverse();

CmpInst::Predicate NewPred;
APInt NewC, Offset;
CR->getEquivalentICmp(NewPred, NewC, Offset);
Expand Down
18 changes: 7 additions & 11 deletions llvm/test/Transforms/InstCombine/and-or-icmps.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1183,12 +1183,10 @@ define i1 @and_ranges_signed_pred(i64 %x) {

define i1 @and_two_ranges_to_mask_and_range(i8 %c) {
; CHECK-LABEL: @and_two_ranges_to_mask_and_range(
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[C:%.*]], -123
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[TMP1]], -26
; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[C]], -91
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 [[TMP2]], -26
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
; CHECK-NEXT: ret i1 [[AND]]
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[C:%.*]], -33
; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], -91
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i8 [[TMP2]], -26
; CHECK-NEXT: ret i1 [[TMP3]]
;
%c.off = add i8 %c, -97
%cmp1 = icmp ugt i8 %c.off, 25
Expand Down Expand Up @@ -1234,11 +1232,9 @@ define i1 @and_two_ranges_to_mask_and_range_different_sizes(i8 %c) {

define i1 @and_two_ranges_to_mask_and_range_no_add_on_one_range(i16 %x) {
; CHECK-LABEL: @and_two_ranges_to_mask_and_range_no_add_on_one_range(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i16 [[X:%.*]], 11
; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[X]], -28
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i16 [[TMP1]], -12
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[TMP2]]
; CHECK-NEXT: ret i1 [[AND]]
; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], -20
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i16 [[TMP1]], 11
; CHECK-NEXT: ret i1 [[TMP2]]
;
%cmp1 = icmp uge i16 %x, 12
%cmp2 = icmp ult i16 %x, 16
Expand Down

0 comments on commit 5515263

Please sign in to comment.