Skip to content

Commit 3117794

Browse files
committed
[NFCI][IR] ConstantRangeTest: refactor operation range gatherers
We do the same dance to acquire the "exact" range of an op via an exhaustive approach in many places. Let's not invent the wheel each time.
1 parent 0c0c57f commit 3117794

File tree

1 file changed

+137
-140
lines changed

1 file changed

+137
-140
lines changed

llvm/unittests/IR/ConstantRangeTest.cpp

Lines changed: 137 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -59,107 +59,130 @@ static void ForeachNumInConstantRange(const ConstantRange &CR, Fn TestFn) {
5959
}
6060
}
6161

62-
template<typename Fn1, typename Fn2>
63-
static void TestUnsignedUnaryOpExhaustive(
64-
Fn1 RangeFn, Fn2 IntFn, bool SkipSignedIntMin = false) {
62+
struct OpRangeGathererBase {
63+
void account(const APInt &N);
64+
ConstantRange getRange();
65+
};
66+
67+
struct UnsignedOpRangeGatherer : public OpRangeGathererBase {
68+
APInt Min;
69+
APInt Max;
70+
71+
UnsignedOpRangeGatherer(unsigned Bits)
72+
: Min(APInt::getMaxValue(Bits)), Max(APInt::getMinValue(Bits)) {}
73+
74+
void account(const APInt &N) {
75+
if (N.ult(Min))
76+
Min = N;
77+
if (N.ugt(Max))
78+
Max = N;
79+
}
80+
81+
ConstantRange getRange() {
82+
if (Min.ugt(Max))
83+
return ConstantRange::getEmpty(Min.getBitWidth());
84+
return ConstantRange::getNonEmpty(Min, Max + 1);
85+
}
86+
};
87+
88+
struct SignedOpRangeGatherer : public OpRangeGathererBase {
89+
APInt Min;
90+
APInt Max;
91+
92+
SignedOpRangeGatherer(unsigned Bits)
93+
: Min(APInt::getSignedMaxValue(Bits)),
94+
Max(APInt::getSignedMinValue(Bits)) {}
95+
96+
void account(const APInt &N) {
97+
if (N.slt(Min))
98+
Min = N;
99+
if (N.sgt(Max))
100+
Max = N;
101+
}
102+
103+
ConstantRange getRange() {
104+
if (Min.sgt(Max))
105+
return ConstantRange::getEmpty(Min.getBitWidth());
106+
return ConstantRange::getNonEmpty(Min, Max + 1);
107+
}
108+
};
109+
110+
template <typename Fn1, typename Fn2>
111+
static void TestUnsignedUnaryOpExhaustive(Fn1 RangeFn, Fn2 IntFn,
112+
bool SkipSignedIntMin = false) {
65113
unsigned Bits = 4;
66114
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
67-
APInt Min = APInt::getMaxValue(Bits);
68-
APInt Max = APInt::getMinValue(Bits);
115+
UnsignedOpRangeGatherer R(CR.getBitWidth());
69116
ForeachNumInConstantRange(CR, [&](const APInt &N) {
70117
if (SkipSignedIntMin && N.isMinSignedValue())
71118
return;
72-
73-
APInt AbsN = IntFn(N);
74-
if (AbsN.ult(Min))
75-
Min = AbsN;
76-
if (AbsN.ugt(Max))
77-
Max = AbsN;
119+
R.account(IntFn(N));
78120
});
79121

80-
ConstantRange ResultCR = RangeFn(CR);
81-
if (Min.ugt(Max)) {
82-
EXPECT_TRUE(ResultCR.isEmptySet());
83-
return;
84-
}
122+
ConstantRange ExactCR = R.getRange();
123+
ConstantRange ActualCR = RangeFn(CR);
85124

86-
ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
87-
EXPECT_EQ(Exact, ResultCR);
125+
EXPECT_EQ(ExactCR, ActualCR);
88126
});
89127
}
90128

91-
template<typename Fn1, typename Fn2>
92-
static void TestUnsignedBinOpExhaustive(
93-
Fn1 RangeFn, Fn2 IntFn,
94-
bool SkipZeroRHS = false, bool CorrectnessOnly = false) {
129+
template <typename Fn1, typename Fn2>
130+
static void TestUnsignedBinOpExhaustive(Fn1 RangeFn, Fn2 IntFn,
131+
bool SkipZeroRHS = false,
132+
bool CorrectnessOnly = false) {
95133
unsigned Bits = 4;
96-
EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
97-
const ConstantRange &CR2) {
98-
APInt Min = APInt::getMaxValue(Bits);
99-
APInt Max = APInt::getMinValue(Bits);
100-
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
101-
ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
102-
if (SkipZeroRHS && N2 == 0)
103-
return;
134+
EnumerateTwoConstantRanges(
135+
Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
136+
UnsignedOpRangeGatherer R(CR1.getBitWidth());
137+
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
138+
ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
139+
if (SkipZeroRHS && N2 == 0)
140+
return;
141+
R.account(IntFn(N1, N2));
142+
});
143+
});
104144

105-
APInt N = IntFn(N1, N2);
106-
if (N.ult(Min))
107-
Min = N;
108-
if (N.ugt(Max))
109-
Max = N;
110-
});
111-
});
145+
ConstantRange CR = RangeFn(CR1, CR2);
112146

113-
ConstantRange CR = RangeFn(CR1, CR2);
114-
if (Min.ugt(Max)) {
115-
EXPECT_TRUE(CR.isEmptySet());
116-
return;
117-
}
147+
ConstantRange Exact = R.getRange();
118148

119-
ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
120-
if (CorrectnessOnly) {
121-
EXPECT_TRUE(CR.contains(Exact));
122-
} else {
123-
EXPECT_EQ(Exact, CR);
124-
}
125-
});
149+
if (!CorrectnessOnly) {
150+
EXPECT_EQ(Exact, CR);
151+
return;
152+
}
153+
154+
EXPECT_TRUE(CR.contains(Exact));
155+
if (Exact.isEmptySet())
156+
EXPECT_TRUE(CR.isEmptySet());
157+
});
126158
}
127159

128-
template<typename Fn1, typename Fn2>
129-
static void TestSignedBinOpExhaustive(
130-
Fn1 RangeFn, Fn2 IntFn,
131-
bool SkipZeroRHS = false, bool CorrectnessOnly = false) {
160+
template <typename Fn1, typename Fn2>
161+
static void TestSignedBinOpExhaustive(Fn1 RangeFn, Fn2 IntFn,
162+
bool SkipZeroRHS = false,
163+
bool CorrectnessOnly = false) {
132164
unsigned Bits = 4;
133-
EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
134-
const ConstantRange &CR2) {
135-
APInt Min = APInt::getSignedMaxValue(Bits);
136-
APInt Max = APInt::getSignedMinValue(Bits);
137-
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
138-
ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
139-
if (SkipZeroRHS && N2 == 0)
140-
return;
165+
EnumerateTwoConstantRanges(
166+
Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
167+
SignedOpRangeGatherer R(CR1.getBitWidth());
168+
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
169+
ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
170+
if (SkipZeroRHS && N2 == 0)
171+
return;
141172

142-
APInt N = IntFn(N1, N2);
143-
if (N.slt(Min))
144-
Min = N;
145-
if (N.sgt(Max))
146-
Max = N;
147-
});
148-
});
173+
R.account(IntFn(N1, N2));
174+
});
175+
});
149176

150-
ConstantRange CR = RangeFn(CR1, CR2);
151-
if (Min.sgt(Max)) {
152-
EXPECT_TRUE(CR.isEmptySet());
153-
return;
154-
}
177+
ConstantRange CR = RangeFn(CR1, CR2);
155178

156-
ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
157-
if (CorrectnessOnly) {
158-
EXPECT_TRUE(CR.contains(Exact));
159-
} else {
160-
EXPECT_EQ(Exact, CR);
161-
}
162-
});
179+
ConstantRange Exact = R.getRange();
180+
if (CorrectnessOnly) {
181+
EXPECT_TRUE(CR.contains(Exact));
182+
} else {
183+
EXPECT_EQ(Exact, CR);
184+
}
185+
});
163186
}
164187

165188
ConstantRange ConstantRangeTest::Full(16, true);
@@ -731,35 +754,27 @@ static void TestAddWithNoSignedWrapExhaustive(Fn1 RangeFn, Fn2 IntFn) {
731754
EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
732755
const ConstantRange &CR2) {
733756
ConstantRange CR = RangeFn(CR1, CR2);
734-
APInt Min = APInt::getSignedMaxValue(Bits);
735-
APInt Max = APInt::getSignedMinValue(Bits);
757+
SignedOpRangeGatherer R(CR.getBitWidth());
736758
bool AllOverflow = true;
737759
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
738760
ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
739761
bool IsOverflow = false;
740762
APInt N = IntFn(IsOverflow, N1, N2);
741763
if (!IsOverflow) {
742764
AllOverflow = false;
743-
if (N.slt(Min))
744-
Min = N;
745-
if (N.sgt(Max))
746-
Max = N;
765+
R.account(N);
747766
EXPECT_TRUE(CR.contains(N));
748767
}
749768
});
750769
});
751770

752771
EXPECT_EQ(CR.isEmptySet(), AllOverflow);
753772

754-
if (!CR1.isSignWrappedSet() && !CR2.isSignWrappedSet()) {
755-
if (Min.sgt(Max)) {
756-
EXPECT_TRUE(CR.isEmptySet());
757-
return;
758-
}
773+
if (CR1.isSignWrappedSet() || CR2.isSignWrappedSet())
774+
return;
759775

760-
ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
761-
EXPECT_EQ(Exact, CR);
762-
}
776+
ConstantRange Exact = R.getRange();
777+
EXPECT_EQ(Exact, CR);
763778
});
764779
}
765780

@@ -769,35 +784,27 @@ static void TestAddWithNoUnsignedWrapExhaustive(Fn1 RangeFn, Fn2 IntFn) {
769784
EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
770785
const ConstantRange &CR2) {
771786
ConstantRange CR = RangeFn(CR1, CR2);
772-
APInt Min = APInt::getMaxValue(Bits);
773-
APInt Max = APInt::getMinValue(Bits);
787+
UnsignedOpRangeGatherer R(CR.getBitWidth());
774788
bool AllOverflow = true;
775789
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
776790
ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
777791
bool IsOverflow = false;
778792
APInt N = IntFn(IsOverflow, N1, N2);
779793
if (!IsOverflow) {
780794
AllOverflow = false;
781-
if (N.ult(Min))
782-
Min = N;
783-
if (N.ugt(Max))
784-
Max = N;
795+
R.account(N);
785796
EXPECT_TRUE(CR.contains(N));
786797
}
787798
});
788799
});
789800

790801
EXPECT_EQ(CR.isEmptySet(), AllOverflow);
791802

792-
if (!CR1.isWrappedSet() && !CR2.isWrappedSet()) {
793-
if (Min.ugt(Max)) {
794-
EXPECT_TRUE(CR.isEmptySet());
795-
return;
796-
}
803+
if (CR1.isWrappedSet() || CR2.isWrappedSet())
804+
return;
797805

798-
ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
799-
EXPECT_EQ(Exact, CR);
800-
}
806+
ConstantRange Exact = R.getRange();
807+
EXPECT_EQ(Exact, CR);
801808
});
802809
}
803810

@@ -809,10 +816,8 @@ static void TestAddWithNoSignedUnsignedWrapExhaustive(Fn1 RangeFn,
809816
EnumerateTwoConstantRanges(
810817
Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
811818
ConstantRange CR = RangeFn(CR1, CR2);
812-
APInt UMin = APInt::getMaxValue(Bits);
813-
APInt UMax = APInt::getMinValue(Bits);
814-
APInt SMin = APInt::getSignedMaxValue(Bits);
815-
APInt SMax = APInt::getSignedMinValue(Bits);
819+
UnsignedOpRangeGatherer UR(CR.getBitWidth());
820+
SignedOpRangeGatherer SR(CR.getBitWidth());
816821
bool AllOverflow = true;
817822
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
818823
ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
@@ -821,33 +826,29 @@ static void TestAddWithNoSignedUnsignedWrapExhaustive(Fn1 RangeFn,
821826
(void) IntFnUnsigned(IsOverflow, N1, N2);
822827
if (!IsSignedOverflow && !IsOverflow) {
823828
AllOverflow = false;
824-
if (N.slt(SMin))
825-
SMin = N;
826-
if (N.sgt(SMax))
827-
SMax = N;
828-
if (N.ult(UMin))
829-
UMin = N;
830-
if (N.ugt(UMax))
831-
UMax = N;
829+
UR.account(N);
830+
SR.account(N);
832831
EXPECT_TRUE(CR.contains(N));
833832
}
834833
});
835834
});
836835

837836
EXPECT_EQ(CR.isEmptySet(), AllOverflow);
838837

839-
if (!CR1.isWrappedSet() && !CR2.isWrappedSet() &&
840-
!CR1.isSignWrappedSet() && !CR2.isSignWrappedSet()) {
841-
if (UMin.ugt(UMax) || SMin.sgt(SMax)) {
842-
EXPECT_TRUE(CR.isEmptySet());
843-
return;
844-
}
838+
if (CR1.isWrappedSet() || CR2.isWrappedSet() ||
839+
CR1.isSignWrappedSet() || CR2.isSignWrappedSet())
840+
return;
845841

846-
ConstantRange Exact =
847-
ConstantRange::getNonEmpty(SMin, SMax + 1)
848-
.intersectWith(ConstantRange::getNonEmpty(UMin, UMax + 1));
849-
EXPECT_EQ(Exact, CR);
842+
ConstantRange ExactUnsignedCR = UR.getRange();
843+
ConstantRange ExactSignedCR = SR.getRange();
844+
845+
if (ExactUnsignedCR.isEmptySet() || ExactSignedCR.isEmptySet()) {
846+
EXPECT_TRUE(CR.isEmptySet());
847+
return;
850848
}
849+
850+
ConstantRange Exact = ExactSignedCR.intersectWith(ExactUnsignedCR);
851+
EXPECT_EQ(Exact, CR);
851852
});
852853
}
853854

@@ -2229,23 +2230,19 @@ TEST_F(ConstantRangeTest, FromKnownBitsExhaustive) {
22292230
if (Known.hasConflict() || Known.isUnknown())
22302231
continue;
22312232

2232-
APInt MinUnsigned = APInt::getMaxValue(Bits);
2233-
APInt MaxUnsigned = APInt::getMinValue(Bits);
2234-
APInt MinSigned = APInt::getSignedMaxValue(Bits);
2235-
APInt MaxSigned = APInt::getSignedMinValue(Bits);
2233+
UnsignedOpRangeGatherer UR(Bits);
2234+
SignedOpRangeGatherer SR(Bits);
22362235
for (unsigned N = 0; N < Max; ++N) {
22372236
APInt Num(Bits, N);
22382237
if ((Num & Known.Zero) != 0 || (~Num & Known.One) != 0)
22392238
continue;
22402239

2241-
if (Num.ult(MinUnsigned)) MinUnsigned = Num;
2242-
if (Num.ugt(MaxUnsigned)) MaxUnsigned = Num;
2243-
if (Num.slt(MinSigned)) MinSigned = Num;
2244-
if (Num.sgt(MaxSigned)) MaxSigned = Num;
2240+
UR.account(Num);
2241+
SR.account(Num);
22452242
}
22462243

2247-
ConstantRange UnsignedCR(MinUnsigned, MaxUnsigned + 1);
2248-
ConstantRange SignedCR(MinSigned, MaxSigned + 1);
2244+
ConstantRange UnsignedCR = UR.getRange();
2245+
ConstantRange SignedCR = SR.getRange();
22492246
EXPECT_EQ(UnsignedCR, ConstantRange::fromKnownBits(Known, false));
22502247
EXPECT_EQ(SignedCR, ConstantRange::fromKnownBits(Known, true));
22512248
}

0 commit comments

Comments
 (0)