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)
|
||||
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;
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue