forked from OSchip/llvm-project
[InstCombine] Fold and of two ranges differing by mask
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.
This commit is contained in:
parent
713752610e
commit
5515263e44
|
@ -1187,23 +1187,20 @@ static Value *foldAndOrOfICmpsUsingRanges(
|
||||||
if (V1 != V2)
|
if (V1 != V2)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
ConstantRange CR1 = ConstantRange::makeExactICmpRegion(Pred1, C1);
|
ConstantRange CR1 = ConstantRange::makeExactICmpRegion(
|
||||||
|
IsAnd ? ICmpInst::getInversePredicate(Pred1) : Pred1, C1);
|
||||||
if (Offset1)
|
if (Offset1)
|
||||||
CR1 = CR1.subtract(*Offset1);
|
CR1 = CR1.subtract(*Offset1);
|
||||||
|
|
||||||
ConstantRange CR2 = ConstantRange::makeExactICmpRegion(Pred2, C2);
|
ConstantRange CR2 = ConstantRange::makeExactICmpRegion(
|
||||||
|
IsAnd ? ICmpInst::getInversePredicate(Pred2) : Pred2, C2);
|
||||||
if (Offset2)
|
if (Offset2)
|
||||||
CR2 = CR2.subtract(*Offset2);
|
CR2 = CR2.subtract(*Offset2);
|
||||||
|
|
||||||
Type *Ty = V1->getType();
|
Type *Ty = V1->getType();
|
||||||
Value *NewV = V1;
|
Value *NewV = V1;
|
||||||
Optional<ConstantRange> CR =
|
Optional<ConstantRange> CR = CR1.exactUnionWith(CR2);
|
||||||
IsAnd ? CR1.exactIntersectWith(CR2) : CR1.exactUnionWith(CR2);
|
|
||||||
if (!CR) {
|
if (!CR) {
|
||||||
// TODO: Support and.
|
|
||||||
if (IsAnd)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (!BothHaveOneUse || CR1.isWrappedSet() || CR2.isWrappedSet())
|
if (!BothHaveOneUse || CR1.isWrappedSet() || CR2.isWrappedSet())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -1220,6 +1217,9 @@ static Value *foldAndOrOfICmpsUsingRanges(
|
||||||
NewV = Builder.CreateAnd(NewV, ConstantInt::get(Ty, ~LowerDiff));
|
NewV = Builder.CreateAnd(NewV, ConstantInt::get(Ty, ~LowerDiff));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsAnd)
|
||||||
|
CR = CR->inverse();
|
||||||
|
|
||||||
CmpInst::Predicate NewPred;
|
CmpInst::Predicate NewPred;
|
||||||
APInt NewC, Offset;
|
APInt NewC, Offset;
|
||||||
CR->getEquivalentICmp(NewPred, NewC, Offset);
|
CR->getEquivalentICmp(NewPred, NewC, Offset);
|
||||||
|
|
|
@ -1183,12 +1183,10 @@ define i1 @and_ranges_signed_pred(i64 %x) {
|
||||||
|
|
||||||
define i1 @and_two_ranges_to_mask_and_range(i8 %c) {
|
define i1 @and_two_ranges_to_mask_and_range(i8 %c) {
|
||||||
; CHECK-LABEL: @and_two_ranges_to_mask_and_range(
|
; CHECK-LABEL: @and_two_ranges_to_mask_and_range(
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[C:%.*]], -123
|
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[C:%.*]], -33
|
||||||
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[TMP1]], -26
|
; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], -91
|
||||||
; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[C]], -91
|
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i8 [[TMP2]], -26
|
||||||
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 [[TMP2]], -26
|
; CHECK-NEXT: ret i1 [[TMP3]]
|
||||||
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
|
|
||||||
; CHECK-NEXT: ret i1 [[AND]]
|
|
||||||
;
|
;
|
||||||
%c.off = add i8 %c, -97
|
%c.off = add i8 %c, -97
|
||||||
%cmp1 = icmp ugt i8 %c.off, 25
|
%cmp1 = icmp ugt i8 %c.off, 25
|
||||||
|
@ -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) {
|
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-LABEL: @and_two_ranges_to_mask_and_range_no_add_on_one_range(
|
||||||
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i16 [[X:%.*]], 11
|
; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], -20
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[X]], -28
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i16 [[TMP1]], 11
|
||||||
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i16 [[TMP1]], -12
|
; CHECK-NEXT: ret i1 [[TMP2]]
|
||||||
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[TMP2]]
|
|
||||||
; CHECK-NEXT: ret i1 [[AND]]
|
|
||||||
;
|
;
|
||||||
%cmp1 = icmp uge i16 %x, 12
|
%cmp1 = icmp uge i16 %x, 12
|
||||||
%cmp2 = icmp ult i16 %x, 16
|
%cmp2 = icmp ult i16 %x, 16
|
||||||
|
|
Loading…
Reference in New Issue