1 //===- llvm/unittest/Support/KnownBitsTest.cpp - KnownBits tests ----------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements unit tests for KnownBits functions.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Support/KnownBits.h"
14 #include "KnownBitsTest.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/Twine.h"
18 #include "gtest/gtest.h"
22 using UnaryBitsFn
= llvm::function_ref
<KnownBits(const KnownBits
&)>;
23 using UnaryIntFn
= llvm::function_ref
<std::optional
<APInt
>(const APInt
&)>;
26 llvm::function_ref
<KnownBits(const KnownBits
&, const KnownBits
&)>;
28 llvm::function_ref
<std::optional
<APInt
>(const APInt
&, const APInt
&)>;
30 static testing::AssertionResult
checkResult(Twine Name
, const KnownBits
&Exact
,
31 const KnownBits
&Computed
,
32 ArrayRef
<KnownBits
> Inputs
,
33 bool CheckOptimality
) {
34 if (CheckOptimality
) {
35 // We generally don't want to return conflicting known bits, even if it is
36 // legal for always poison results.
37 if (Exact
.hasConflict() || Computed
== Exact
)
38 return testing::AssertionSuccess();
40 if (Computed
.Zero
.isSubsetOf(Exact
.Zero
) &&
41 Computed
.One
.isSubsetOf(Exact
.One
))
42 return testing::AssertionSuccess();
45 testing::AssertionResult Result
= testing::AssertionFailure();
46 Result
<< Name
<< ": ";
47 Result
<< "Inputs = ";
48 for (const KnownBits
&Input
: Inputs
)
49 Result
<< Input
<< ", ";
50 Result
<< "Computed = " << Computed
<< ", Exact = " << Exact
;
54 static void testUnaryOpExhaustive(StringRef Name
, UnaryBitsFn BitsFn
,
56 bool CheckOptimality
= true) {
57 for (unsigned Bits
: {1, 4}) {
58 ForeachKnownBits(Bits
, [&](const KnownBits
&Known
) {
59 KnownBits Computed
= BitsFn(Known
);
60 KnownBits
Exact(Bits
);
61 Exact
.Zero
.setAllBits();
62 Exact
.One
.setAllBits();
64 ForeachNumInKnownBits(Known
, [&](const APInt
&N
) {
65 if (std::optional
<APInt
> Res
= IntFn(N
)) {
71 if (!Exact
.hasConflict()) {
72 EXPECT_TRUE(checkResult(Name
, Exact
, Computed
, Known
, CheckOptimality
));
78 static void testBinaryOpExhaustive(StringRef Name
, BinaryBitsFn BitsFn
,
80 bool CheckOptimality
= true,
81 bool RefinePoisonToZero
= false) {
82 for (unsigned Bits
: {1, 4}) {
83 ForeachKnownBits(Bits
, [&](const KnownBits
&Known1
) {
84 ForeachKnownBits(Bits
, [&](const KnownBits
&Known2
) {
85 KnownBits Computed
= BitsFn(Known1
, Known2
);
86 KnownBits
Exact(Bits
);
87 Exact
.Zero
.setAllBits();
88 Exact
.One
.setAllBits();
90 ForeachNumInKnownBits(Known1
, [&](const APInt
&N1
) {
91 ForeachNumInKnownBits(Known2
, [&](const APInt
&N2
) {
92 if (std::optional
<APInt
> Res
= IntFn(N1
, N2
)) {
99 if (!Exact
.hasConflict()) {
100 EXPECT_TRUE(checkResult(Name
, Exact
, Computed
, {Known1
, Known2
},
103 // In some cases we choose to return zero if the result is always
105 if (RefinePoisonToZero
&& Exact
.hasConflict() &&
106 !Known1
.hasConflict() && !Known2
.hasConflict()) {
107 EXPECT_TRUE(Computed
.isZero());
116 TEST(KnownBitsTest
, AddCarryExhaustive
) {
118 ForeachKnownBits(Bits
, [&](const KnownBits
&Known1
) {
119 ForeachKnownBits(Bits
, [&](const KnownBits
&Known2
) {
120 ForeachKnownBits(1, [&](const KnownBits
&KnownCarry
) {
121 // Explicitly compute known bits of the addition by trying all
123 KnownBits
Exact(Bits
);
124 Exact
.Zero
.setAllBits();
125 Exact
.One
.setAllBits();
126 ForeachNumInKnownBits(Known1
, [&](const APInt
&N1
) {
127 ForeachNumInKnownBits(Known2
, [&](const APInt
&N2
) {
128 ForeachNumInKnownBits(KnownCarry
, [&](const APInt
&Carry
) {
130 if (Carry
.getBoolValue())
140 KnownBits::computeForAddCarry(Known1
, Known2
, KnownCarry
);
141 if (!Exact
.hasConflict()) {
142 EXPECT_EQ(Exact
, Computed
);
149 static void TestAddSubExhaustive(bool IsAdd
) {
150 Twine Name
= IsAdd
? "add" : "sub";
152 ForeachKnownBits(Bits
, [&](const KnownBits
&Known1
) {
153 ForeachKnownBits(Bits
, [&](const KnownBits
&Known2
) {
154 KnownBits
Exact(Bits
), ExactNSW(Bits
), ExactNUW(Bits
),
155 ExactNSWAndNUW(Bits
);
156 Exact
.Zero
.setAllBits();
157 Exact
.One
.setAllBits();
158 ExactNSW
.Zero
.setAllBits();
159 ExactNSW
.One
.setAllBits();
160 ExactNUW
.Zero
.setAllBits();
161 ExactNUW
.One
.setAllBits();
162 ExactNSWAndNUW
.Zero
.setAllBits();
163 ExactNSWAndNUW
.One
.setAllBits();
165 ForeachNumInKnownBits(Known1
, [&](const APInt
&N1
) {
166 ForeachNumInKnownBits(Known2
, [&](const APInt
&N2
) {
168 bool UnsignedOverflow
;
171 Res
= N1
.uadd_ov(N2
, UnsignedOverflow
);
172 Res
= N1
.sadd_ov(N2
, SignedOverflow
);
174 Res
= N1
.usub_ov(N2
, UnsignedOverflow
);
175 Res
= N1
.ssub_ov(N2
, SignedOverflow
);
181 if (!SignedOverflow
) {
183 ExactNSW
.Zero
&= ~Res
;
186 if (!UnsignedOverflow
) {
188 ExactNUW
.Zero
&= ~Res
;
191 if (!UnsignedOverflow
&& !SignedOverflow
) {
192 ExactNSWAndNUW
.One
&= Res
;
193 ExactNSWAndNUW
.Zero
&= ~Res
;
198 KnownBits Computed
= KnownBits::computeForAddSub(
199 IsAdd
, /*NSW=*/false, /*NUW=*/false, Known1
, Known2
);
200 EXPECT_TRUE(checkResult(Name
, Exact
, Computed
, {Known1
, Known2
},
201 /*CheckOptimality=*/true));
203 KnownBits ComputedNSW
= KnownBits::computeForAddSub(
204 IsAdd
, /*NSW=*/true, /*NUW=*/false, Known1
, Known2
);
205 EXPECT_TRUE(checkResult(Name
+ " nsw", ExactNSW
, ComputedNSW
,
207 /*CheckOptimality=*/true));
209 KnownBits ComputedNUW
= KnownBits::computeForAddSub(
210 IsAdd
, /*NSW=*/false, /*NUW=*/true, Known1
, Known2
);
211 EXPECT_TRUE(checkResult(Name
+ " nuw", ExactNUW
, ComputedNUW
,
213 /*CheckOptimality=*/true));
215 KnownBits ComputedNSWAndNUW
= KnownBits::computeForAddSub(
216 IsAdd
, /*NSW=*/true, /*NUW=*/true, Known1
, Known2
);
217 EXPECT_TRUE(checkResult(Name
+ " nsw nuw", ExactNSWAndNUW
,
218 ComputedNSWAndNUW
, {Known1
, Known2
},
219 /*CheckOptimality=*/true));
224 TEST(KnownBitsTest
, AddSubExhaustive
) {
225 TestAddSubExhaustive(true);
226 TestAddSubExhaustive(false);
229 TEST(KnownBitsTest
, SubBorrowExhaustive
) {
231 ForeachKnownBits(Bits
, [&](const KnownBits
&Known1
) {
232 ForeachKnownBits(Bits
, [&](const KnownBits
&Known2
) {
233 ForeachKnownBits(1, [&](const KnownBits
&KnownBorrow
) {
234 // Explicitly compute known bits of the subtraction by trying all
236 KnownBits
Exact(Bits
);
237 Exact
.Zero
.setAllBits();
238 Exact
.One
.setAllBits();
239 ForeachNumInKnownBits(Known1
, [&](const APInt
&N1
) {
240 ForeachNumInKnownBits(Known2
, [&](const APInt
&N2
) {
241 ForeachNumInKnownBits(KnownBorrow
, [&](const APInt
&Borrow
) {
243 if (Borrow
.getBoolValue())
253 KnownBits::computeForSubBorrow(Known1
, Known2
, KnownBorrow
);
254 if (!Exact
.hasConflict()) {
255 EXPECT_EQ(Exact
, Computed
);
262 TEST(KnownBitsTest
, SignBitUnknown
) {
264 EXPECT_TRUE(Known
.isSignUnknown());
265 Known
.Zero
.setBit(0);
266 EXPECT_TRUE(Known
.isSignUnknown());
267 Known
.Zero
.setBit(1);
268 EXPECT_FALSE(Known
.isSignUnknown());
269 Known
.Zero
.clearBit(0);
270 EXPECT_FALSE(Known
.isSignUnknown());
271 Known
.Zero
.clearBit(1);
272 EXPECT_TRUE(Known
.isSignUnknown());
275 EXPECT_TRUE(Known
.isSignUnknown());
277 EXPECT_FALSE(Known
.isSignUnknown());
278 Known
.One
.clearBit(0);
279 EXPECT_FALSE(Known
.isSignUnknown());
280 Known
.One
.clearBit(1);
281 EXPECT_TRUE(Known
.isSignUnknown());
284 TEST(KnownBitsTest
, BinaryExhaustive
) {
285 testBinaryOpExhaustive(
287 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
288 return Known1
& Known2
;
290 [](const APInt
&N1
, const APInt
&N2
) { return N1
& N2
; });
291 testBinaryOpExhaustive(
293 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
294 return Known1
| Known2
;
296 [](const APInt
&N1
, const APInt
&N2
) { return N1
| N2
; });
297 testBinaryOpExhaustive(
299 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
300 return Known1
^ Known2
;
302 [](const APInt
&N1
, const APInt
&N2
) { return N1
^ N2
; });
303 testBinaryOpExhaustive(
305 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
306 return KnownBits::add(Known1
, Known2
);
308 [](const APInt
&N1
, const APInt
&N2
) { return N1
+ N2
; });
309 testBinaryOpExhaustive(
311 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
312 return KnownBits::sub(Known1
, Known2
);
314 [](const APInt
&N1
, const APInt
&N2
) { return N1
- N2
; });
315 testBinaryOpExhaustive("umax", KnownBits::umax
, APIntOps::umax
);
316 testBinaryOpExhaustive("umin", KnownBits::umin
, APIntOps::umin
);
317 testBinaryOpExhaustive("smax", KnownBits::smax
, APIntOps::smax
);
318 testBinaryOpExhaustive("smin", KnownBits::smin
, APIntOps::smin
);
319 testBinaryOpExhaustive("abdu", KnownBits::abdu
, APIntOps::abdu
);
320 testBinaryOpExhaustive("abds", KnownBits::abds
, APIntOps::abds
);
321 testBinaryOpExhaustive(
323 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
324 return KnownBits::udiv(Known1
, Known2
);
326 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
331 /*CheckOptimality=*/false);
332 testBinaryOpExhaustive(
334 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
335 return KnownBits::udiv(Known1
, Known2
, /*Exact=*/true);
337 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
338 if (N2
.isZero() || !N1
.urem(N2
).isZero())
342 /*CheckOptimality=*/false);
343 testBinaryOpExhaustive(
345 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
346 return KnownBits::sdiv(Known1
, Known2
);
348 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
349 if (N2
.isZero() || (N1
.isMinSignedValue() && N2
.isAllOnes()))
353 /*CheckOptimality=*/false);
354 testBinaryOpExhaustive(
356 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
357 return KnownBits::sdiv(Known1
, Known2
, /*Exact=*/true);
359 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
360 if (N2
.isZero() || (N1
.isMinSignedValue() && N2
.isAllOnes()) ||
361 !N1
.srem(N2
).isZero())
365 /*CheckOptimality=*/false);
366 testBinaryOpExhaustive(
367 "urem", KnownBits::urem
,
368 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
373 /*CheckOptimality=*/false);
374 testBinaryOpExhaustive(
375 "srem", KnownBits::srem
,
376 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
381 /*CheckOptimality=*/false);
382 testBinaryOpExhaustive(
383 "sadd_sat", KnownBits::sadd_sat
,
384 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
385 return N1
.sadd_sat(N2
);
387 testBinaryOpExhaustive(
388 "uadd_sat", KnownBits::uadd_sat
,
389 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
390 return N1
.uadd_sat(N2
);
392 testBinaryOpExhaustive(
393 "ssub_sat", KnownBits::ssub_sat
,
394 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
395 return N1
.ssub_sat(N2
);
397 testBinaryOpExhaustive(
398 "usub_sat", KnownBits::usub_sat
,
399 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
400 return N1
.usub_sat(N2
);
402 testBinaryOpExhaustive(
404 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
405 return KnownBits::shl(Known1
, Known2
);
407 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
408 if (N2
.uge(N2
.getBitWidth()))
412 /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true);
413 testBinaryOpExhaustive(
415 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
416 return KnownBits::shl(Known1
, Known2
, /*NUW=*/true);
418 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
420 APInt Res
= N1
.ushl_ov(N2
, Overflow
);
425 /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true);
426 testBinaryOpExhaustive(
428 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
429 return KnownBits::shl(Known1
, Known2
, /*NUW=*/false, /*NSW=*/true);
431 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
433 APInt Res
= N1
.sshl_ov(N2
, Overflow
);
438 /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true);
439 testBinaryOpExhaustive(
441 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
442 return KnownBits::shl(Known1
, Known2
, /*NUW=*/true, /*NSW=*/true);
444 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
445 bool OverflowUnsigned
, OverflowSigned
;
446 APInt Res
= N1
.ushl_ov(N2
, OverflowUnsigned
);
447 (void)N1
.sshl_ov(N2
, OverflowSigned
);
448 if (OverflowUnsigned
|| OverflowSigned
)
452 /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true);
454 testBinaryOpExhaustive(
456 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
457 return KnownBits::lshr(Known1
, Known2
);
459 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
460 if (N2
.uge(N2
.getBitWidth()))
464 /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true);
465 testBinaryOpExhaustive(
467 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
468 return KnownBits::lshr(Known1
, Known2
, /*ShAmtNonZero=*/false,
471 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
472 if (N2
.uge(N2
.getBitWidth()))
474 if (!N1
.extractBits(N2
.getZExtValue(), 0).isZero())
478 /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true);
479 testBinaryOpExhaustive(
481 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
482 return KnownBits::ashr(Known1
, Known2
);
484 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
485 if (N2
.uge(N2
.getBitWidth()))
489 /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true);
490 testBinaryOpExhaustive(
492 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
493 return KnownBits::ashr(Known1
, Known2
, /*ShAmtNonZero=*/false,
496 [](const APInt
&N1
, const APInt
&N2
) -> std::optional
<APInt
> {
497 if (N2
.uge(N2
.getBitWidth()))
499 if (!N1
.extractBits(N2
.getZExtValue(), 0).isZero())
503 /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true);
504 testBinaryOpExhaustive(
506 [](const KnownBits
&Known1
, const KnownBits
&Known2
) {
507 return KnownBits::mul(Known1
, Known2
);
509 [](const APInt
&N1
, const APInt
&N2
) { return N1
* N2
; },
510 /*CheckOptimality=*/false);
511 testBinaryOpExhaustive(
512 "mulhs", KnownBits::mulhs
,
513 [](const APInt
&N1
, const APInt
&N2
) { return APIntOps::mulhs(N1
, N2
); },
514 /*CheckOptimality=*/false);
515 testBinaryOpExhaustive(
516 "mulhu", KnownBits::mulhu
,
517 [](const APInt
&N1
, const APInt
&N2
) { return APIntOps::mulhu(N1
, N2
); },
518 /*CheckOptimality=*/false);
520 testBinaryOpExhaustive("avgFloorS", KnownBits::avgFloorS
,
521 APIntOps::avgFloorS
);
523 testBinaryOpExhaustive("avgFloorU", KnownBits::avgFloorU
,
524 APIntOps::avgFloorU
);
526 testBinaryOpExhaustive("avgCeilU", KnownBits::avgCeilU
, APIntOps::avgCeilU
);
528 testBinaryOpExhaustive("avgCeilS", KnownBits::avgCeilS
, APIntOps::avgCeilS
);
531 TEST(KnownBitsTest
, UnaryExhaustive
) {
532 testUnaryOpExhaustive(
533 "abs", [](const KnownBits
&Known
) { return Known
.abs(); },
534 [](const APInt
&N
) { return N
.abs(); });
536 testUnaryOpExhaustive(
537 "abs(true)", [](const KnownBits
&Known
) { return Known
.abs(true); },
538 [](const APInt
&N
) -> std::optional
<APInt
> {
539 if (N
.isMinSignedValue())
544 testUnaryOpExhaustive(
545 "blsi", [](const KnownBits
&Known
) { return Known
.blsi(); },
546 [](const APInt
&N
) { return N
& -N
; });
547 testUnaryOpExhaustive(
548 "blsmsk", [](const KnownBits
&Known
) { return Known
.blsmsk(); },
549 [](const APInt
&N
) { return N
^ (N
- 1); });
551 testUnaryOpExhaustive(
553 [](const KnownBits
&Known
) {
554 return KnownBits::mul(Known
, Known
, /*SelfMultiply=*/true);
556 [](const APInt
&N
) { return N
* N
; }, /*CheckOptimality=*/false);
559 TEST(KnownBitsTest
, WideShifts
) {
560 unsigned BitWidth
= 128;
561 KnownBits
Unknown(BitWidth
);
562 KnownBits AllOnes
= KnownBits::makeConstant(APInt::getAllOnes(BitWidth
));
564 KnownBits
ShlResult(BitWidth
);
565 ShlResult
.makeNegative();
566 EXPECT_EQ(KnownBits::shl(AllOnes
, Unknown
), ShlResult
);
567 KnownBits
LShrResult(BitWidth
);
568 LShrResult
.One
.setBit(0);
569 EXPECT_EQ(KnownBits::lshr(AllOnes
, Unknown
), LShrResult
);
570 EXPECT_EQ(KnownBits::ashr(AllOnes
, Unknown
), AllOnes
);
573 TEST(KnownBitsTest
, ICmpExhaustive
) {
575 ForeachKnownBits(Bits
, [&](const KnownBits
&Known1
) {
576 ForeachKnownBits(Bits
, [&](const KnownBits
&Known2
) {
577 bool AllEQ
= true, NoneEQ
= true;
578 bool AllNE
= true, NoneNE
= true;
579 bool AllUGT
= true, NoneUGT
= true;
580 bool AllUGE
= true, NoneUGE
= true;
581 bool AllULT
= true, NoneULT
= true;
582 bool AllULE
= true, NoneULE
= true;
583 bool AllSGT
= true, NoneSGT
= true;
584 bool AllSGE
= true, NoneSGE
= true;
585 bool AllSLT
= true, NoneSLT
= true;
586 bool AllSLE
= true, NoneSLE
= true;
588 ForeachNumInKnownBits(Known1
, [&](const APInt
&N1
) {
589 ForeachNumInKnownBits(Known2
, [&](const APInt
&N2
) {
592 AllUGT
&= N1
.ugt(N2
);
593 AllUGE
&= N1
.uge(N2
);
594 AllULT
&= N1
.ult(N2
);
595 AllULE
&= N1
.ule(N2
);
596 AllSGT
&= N1
.sgt(N2
);
597 AllSGE
&= N1
.sge(N2
);
598 AllSLT
&= N1
.slt(N2
);
599 AllSLE
&= N1
.sle(N2
);
600 NoneEQ
&= !N1
.eq(N2
);
601 NoneNE
&= !N1
.ne(N2
);
602 NoneUGT
&= !N1
.ugt(N2
);
603 NoneUGE
&= !N1
.uge(N2
);
604 NoneULT
&= !N1
.ult(N2
);
605 NoneULE
&= !N1
.ule(N2
);
606 NoneSGT
&= !N1
.sgt(N2
);
607 NoneSGE
&= !N1
.sge(N2
);
608 NoneSLT
&= !N1
.slt(N2
);
609 NoneSLE
&= !N1
.sle(N2
);
613 std::optional
<bool> KnownEQ
= KnownBits::eq(Known1
, Known2
);
614 std::optional
<bool> KnownNE
= KnownBits::ne(Known1
, Known2
);
615 std::optional
<bool> KnownUGT
= KnownBits::ugt(Known1
, Known2
);
616 std::optional
<bool> KnownUGE
= KnownBits::uge(Known1
, Known2
);
617 std::optional
<bool> KnownULT
= KnownBits::ult(Known1
, Known2
);
618 std::optional
<bool> KnownULE
= KnownBits::ule(Known1
, Known2
);
619 std::optional
<bool> KnownSGT
= KnownBits::sgt(Known1
, Known2
);
620 std::optional
<bool> KnownSGE
= KnownBits::sge(Known1
, Known2
);
621 std::optional
<bool> KnownSLT
= KnownBits::slt(Known1
, Known2
);
622 std::optional
<bool> KnownSLE
= KnownBits::sle(Known1
, Known2
);
624 if (Known1
.hasConflict() || Known2
.hasConflict())
627 EXPECT_EQ(AllEQ
|| NoneEQ
, KnownEQ
.has_value());
628 EXPECT_EQ(AllNE
|| NoneNE
, KnownNE
.has_value());
629 EXPECT_EQ(AllUGT
|| NoneUGT
, KnownUGT
.has_value());
630 EXPECT_EQ(AllUGE
|| NoneUGE
, KnownUGE
.has_value());
631 EXPECT_EQ(AllULT
|| NoneULT
, KnownULT
.has_value());
632 EXPECT_EQ(AllULE
|| NoneULE
, KnownULE
.has_value());
633 EXPECT_EQ(AllSGT
|| NoneSGT
, KnownSGT
.has_value());
634 EXPECT_EQ(AllSGE
|| NoneSGE
, KnownSGE
.has_value());
635 EXPECT_EQ(AllSLT
|| NoneSLT
, KnownSLT
.has_value());
636 EXPECT_EQ(AllSLE
|| NoneSLE
, KnownSLE
.has_value());
638 EXPECT_EQ(AllEQ
, KnownEQ
.has_value() && *KnownEQ
);
639 EXPECT_EQ(AllNE
, KnownNE
.has_value() && *KnownNE
);
640 EXPECT_EQ(AllUGT
, KnownUGT
.has_value() && *KnownUGT
);
641 EXPECT_EQ(AllUGE
, KnownUGE
.has_value() && *KnownUGE
);
642 EXPECT_EQ(AllULT
, KnownULT
.has_value() && *KnownULT
);
643 EXPECT_EQ(AllULE
, KnownULE
.has_value() && *KnownULE
);
644 EXPECT_EQ(AllSGT
, KnownSGT
.has_value() && *KnownSGT
);
645 EXPECT_EQ(AllSGE
, KnownSGE
.has_value() && *KnownSGE
);
646 EXPECT_EQ(AllSLT
, KnownSLT
.has_value() && *KnownSLT
);
647 EXPECT_EQ(AllSLE
, KnownSLE
.has_value() && *KnownSLE
);
649 EXPECT_EQ(NoneEQ
, KnownEQ
.has_value() && !*KnownEQ
);
650 EXPECT_EQ(NoneNE
, KnownNE
.has_value() && !*KnownNE
);
651 EXPECT_EQ(NoneUGT
, KnownUGT
.has_value() && !*KnownUGT
);
652 EXPECT_EQ(NoneUGE
, KnownUGE
.has_value() && !*KnownUGE
);
653 EXPECT_EQ(NoneULT
, KnownULT
.has_value() && !*KnownULT
);
654 EXPECT_EQ(NoneULE
, KnownULE
.has_value() && !*KnownULE
);
655 EXPECT_EQ(NoneSGT
, KnownSGT
.has_value() && !*KnownSGT
);
656 EXPECT_EQ(NoneSGE
, KnownSGE
.has_value() && !*KnownSGE
);
657 EXPECT_EQ(NoneSLT
, KnownSLT
.has_value() && !*KnownSLT
);
658 EXPECT_EQ(NoneSLE
, KnownSLE
.has_value() && !*KnownSLE
);
663 TEST(KnownBitsTest
, GetMinMaxVal
) {
665 ForeachKnownBits(Bits
, [&](const KnownBits
&Known
) {
666 APInt Min
= APInt::getMaxValue(Bits
);
667 APInt Max
= APInt::getMinValue(Bits
);
668 ForeachNumInKnownBits(Known
, [&](const APInt
&N
) {
669 Min
= APIntOps::umin(Min
, N
);
670 Max
= APIntOps::umax(Max
, N
);
672 if (!Known
.hasConflict()) {
673 EXPECT_EQ(Min
, Known
.getMinValue());
674 EXPECT_EQ(Max
, Known
.getMaxValue());
679 TEST(KnownBitsTest
, GetSignedMinMaxVal
) {
681 ForeachKnownBits(Bits
, [&](const KnownBits
&Known
) {
682 APInt Min
= APInt::getSignedMaxValue(Bits
);
683 APInt Max
= APInt::getSignedMinValue(Bits
);
684 ForeachNumInKnownBits(Known
, [&](const APInt
&N
) {
685 Min
= APIntOps::smin(Min
, N
);
686 Max
= APIntOps::smax(Max
, N
);
688 if (!Known
.hasConflict()) {
689 EXPECT_EQ(Min
, Known
.getSignedMinValue());
690 EXPECT_EQ(Max
, Known
.getSignedMaxValue());
695 TEST(KnownBitsTest
, CountMaxActiveBits
) {
697 ForeachKnownBits(Bits
, [&](const KnownBits
&Known
) {
698 unsigned Expected
= 0;
699 ForeachNumInKnownBits(Known
, [&](const APInt
&N
) {
700 Expected
= std::max(Expected
, N
.getActiveBits());
702 if (!Known
.hasConflict()) {
703 EXPECT_EQ(Expected
, Known
.countMaxActiveBits());
708 TEST(KnownBitsTest
, CountMaxSignificantBits
) {
710 ForeachKnownBits(Bits
, [&](const KnownBits
&Known
) {
711 unsigned Expected
= 0;
712 ForeachNumInKnownBits(Known
, [&](const APInt
&N
) {
713 Expected
= std::max(Expected
, N
.getSignificantBits());
715 if (!Known
.hasConflict()) {
716 EXPECT_EQ(Expected
, Known
.countMaxSignificantBits());
721 TEST(KnownBitsTest
, SExtOrTrunc
) {
722 const unsigned NarrowerSize
= 4;
723 const unsigned BaseSize
= 6;
724 const unsigned WiderSize
= 8;
725 APInt
NegativeFitsNarrower(BaseSize
, -4, /*isSigned=*/true);
726 APInt
NegativeDoesntFitNarrower(BaseSize
, -28, /*isSigned=*/true);
727 APInt
PositiveFitsNarrower(BaseSize
, 14);
728 APInt
PositiveDoesntFitNarrower(BaseSize
, 36);
729 auto InitKnownBits
= [&](KnownBits
&Res
, const APInt
&Input
) {
730 Res
= KnownBits(Input
.getBitWidth());
735 for (unsigned Size
: {NarrowerSize
, BaseSize
, WiderSize
}) {
736 for (const APInt
&Input
:
737 {NegativeFitsNarrower
, NegativeDoesntFitNarrower
, PositiveFitsNarrower
,
738 PositiveDoesntFitNarrower
}) {
740 InitKnownBits(Test
, Input
);
742 InitKnownBits(Baseline
, Input
.sextOrTrunc(Size
));
743 Test
= Test
.sextOrTrunc(Size
);
744 EXPECT_EQ(Test
, Baseline
);
749 TEST(KnownBitsTest
, SExtInReg
) {
751 for (unsigned FromBits
= 1; FromBits
<= Bits
; ++FromBits
) {
752 ForeachKnownBits(Bits
, [&](const KnownBits
&Known
) {
753 APInt CommonOne
= APInt::getAllOnes(Bits
);
754 APInt CommonZero
= APInt::getAllOnes(Bits
);
755 unsigned ExtBits
= Bits
- FromBits
;
756 ForeachNumInKnownBits(Known
, [&](const APInt
&N
) {
757 APInt Ext
= N
<< ExtBits
;
758 Ext
.ashrInPlace(ExtBits
);
762 KnownBits KnownSExtInReg
= Known
.sextInReg(FromBits
);
763 if (!Known
.hasConflict()) {
764 EXPECT_EQ(CommonOne
, KnownSExtInReg
.One
);
765 EXPECT_EQ(CommonZero
, KnownSExtInReg
.Zero
);
771 TEST(KnownBitsTest
, CommonBitsSet
) {
773 ForeachKnownBits(Bits
, [&](const KnownBits
&Known1
) {
774 ForeachKnownBits(Bits
, [&](const KnownBits
&Known2
) {
775 bool HasCommonBitsSet
= false;
776 ForeachNumInKnownBits(Known1
, [&](const APInt
&N1
) {
777 ForeachNumInKnownBits(Known2
, [&](const APInt
&N2
) {
778 HasCommonBitsSet
|= N1
.intersects(N2
);
781 if (!Known1
.hasConflict() && !Known2
.hasConflict()) {
782 EXPECT_EQ(!HasCommonBitsSet
,
783 KnownBits::haveNoCommonBitsSet(Known1
, Known2
));
789 TEST(KnownBitsTest
, ConcatBits
) {
791 for (unsigned LoBits
= 1; LoBits
< Bits
; ++LoBits
) {
792 unsigned HiBits
= Bits
- LoBits
;
793 ForeachKnownBits(LoBits
, [&](const KnownBits
&KnownLo
) {
794 ForeachKnownBits(HiBits
, [&](const KnownBits
&KnownHi
) {
795 KnownBits KnownAll
= KnownHi
.concat(KnownLo
);
797 EXPECT_EQ(KnownLo
.countMinPopulation() + KnownHi
.countMinPopulation(),
798 KnownAll
.countMinPopulation());
799 EXPECT_EQ(KnownLo
.countMaxPopulation() + KnownHi
.countMaxPopulation(),
800 KnownAll
.countMaxPopulation());
802 KnownBits ExtractLo
= KnownAll
.extractBits(LoBits
, 0);
803 KnownBits ExtractHi
= KnownAll
.extractBits(HiBits
, LoBits
);
805 EXPECT_EQ(KnownLo
.One
.getZExtValue(), ExtractLo
.One
.getZExtValue());
806 EXPECT_EQ(KnownHi
.One
.getZExtValue(), ExtractHi
.One
.getZExtValue());
807 EXPECT_EQ(KnownLo
.Zero
.getZExtValue(), ExtractLo
.Zero
.getZExtValue());
808 EXPECT_EQ(KnownHi
.Zero
.getZExtValue(), ExtractHi
.Zero
.getZExtValue());
814 TEST(KnownBitsTest
, MulExhaustive
) {
815 for (unsigned Bits
: {1, 4}) {
816 ForeachKnownBits(Bits
, [&](const KnownBits
&Known1
) {
817 ForeachKnownBits(Bits
, [&](const KnownBits
&Known2
) {
818 KnownBits Computed
= KnownBits::mul(Known1
, Known2
);
819 KnownBits
Exact(Bits
);
820 Exact
.Zero
.setAllBits();
821 Exact
.One
.setAllBits();
823 ForeachNumInKnownBits(Known1
, [&](const APInt
&N1
) {
824 ForeachNumInKnownBits(Known2
, [&](const APInt
&N2
) {
831 if (!Exact
.hasConflict()) {
832 // Check that the result is optimal for the contiguous known low order
834 APInt Mask
= APInt::getLowBitsSet(
835 Bits
, (Exact
.Zero
| Exact
.One
).countTrailingOnes());
838 Computed
.Zero
&= Mask
;
839 Computed
.One
&= Mask
;
840 EXPECT_TRUE(checkResult("mul", Exact
, Computed
, {Known1
, Known2
},
841 /*CheckOptimality=*/true));
848 } // end anonymous namespace