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 "gtest/gtest.h"
20 template<typename FnTy
>
21 void ForeachKnownBits(unsigned Bits
, FnTy Fn
) {
22 unsigned Max
= 1 << Bits
;
23 KnownBits
Known(Bits
);
24 for (unsigned Zero
= 0; Zero
< Max
; ++Zero
) {
25 for (unsigned One
= 0; One
< Max
; ++One
) {
28 if (Known
.hasConflict())
36 template<typename FnTy
>
37 void ForeachNumInKnownBits(const KnownBits
&Known
, FnTy Fn
) {
38 unsigned Bits
= Known
.getBitWidth();
39 unsigned Max
= 1 << Bits
;
40 for (unsigned N
= 0; N
< Max
; ++N
) {
42 if ((Num
& Known
.Zero
) != 0 || (~Num
& Known
.One
) != 0)
49 TEST(KnownBitsTest
, AddCarryExhaustive
) {
51 ForeachKnownBits(Bits
, [&](const KnownBits
&Known1
) {
52 ForeachKnownBits(Bits
, [&](const KnownBits
&Known2
) {
53 ForeachKnownBits(1, [&](const KnownBits
&KnownCarry
) {
54 // Explicitly compute known bits of the addition by trying all
56 KnownBits
Known(Bits
);
57 Known
.Zero
.setAllBits();
58 Known
.One
.setAllBits();
59 ForeachNumInKnownBits(Known1
, [&](const APInt
&N1
) {
60 ForeachNumInKnownBits(Known2
, [&](const APInt
&N2
) {
61 ForeachNumInKnownBits(KnownCarry
, [&](const APInt
&Carry
) {
63 if (Carry
.getBoolValue())
72 KnownBits KnownComputed
= KnownBits::computeForAddCarry(
73 Known1
, Known2
, KnownCarry
);
74 EXPECT_EQ(Known
.Zero
, KnownComputed
.Zero
);
75 EXPECT_EQ(Known
.One
, KnownComputed
.One
);
81 static void TestAddSubExhaustive(bool IsAdd
) {
83 ForeachKnownBits(Bits
, [&](const KnownBits
&Known1
) {
84 ForeachKnownBits(Bits
, [&](const KnownBits
&Known2
) {
85 KnownBits
Known(Bits
), KnownNSW(Bits
);
86 Known
.Zero
.setAllBits();
87 Known
.One
.setAllBits();
88 KnownNSW
.Zero
.setAllBits();
89 KnownNSW
.One
.setAllBits();
91 ForeachNumInKnownBits(Known1
, [&](const APInt
&N1
) {
92 ForeachNumInKnownBits(Known2
, [&](const APInt
&N2
) {
96 Res
= N1
.sadd_ov(N2
, Overflow
);
98 Res
= N1
.ssub_ov(N2
, Overflow
);
105 KnownNSW
.Zero
&= ~Res
;
110 KnownBits KnownComputed
= KnownBits::computeForAddSub(
111 IsAdd
, /*NSW*/false, Known1
, Known2
);
112 EXPECT_EQ(Known
.Zero
, KnownComputed
.Zero
);
113 EXPECT_EQ(Known
.One
, KnownComputed
.One
);
115 // The NSW calculation is not precise, only check that it's
116 // conservatively correct.
117 KnownBits KnownNSWComputed
= KnownBits::computeForAddSub(
118 IsAdd
, /*NSW*/true, Known1
, Known2
);
119 EXPECT_TRUE(KnownNSWComputed
.Zero
.isSubsetOf(KnownNSW
.Zero
));
120 EXPECT_TRUE(KnownNSWComputed
.One
.isSubsetOf(KnownNSW
.One
));
125 TEST(KnownBitsTest
, AddSubExhaustive
) {
126 TestAddSubExhaustive(true);
127 TestAddSubExhaustive(false);
130 } // end anonymous namespace