KnownBitsTest.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. //===- llvm/unittest/Support/KnownBitsTest.cpp - KnownBits tests ----------===//
  2. //
  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
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements unit tests for KnownBits functions.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "llvm/Support/KnownBits.h"
  13. #include "gtest/gtest.h"
  14. using namespace llvm;
  15. namespace {
  16. template<typename FnTy>
  17. void ForeachKnownBits(unsigned Bits, FnTy Fn) {
  18. unsigned Max = 1 << Bits;
  19. KnownBits Known(Bits);
  20. for (unsigned Zero = 0; Zero < Max; ++Zero) {
  21. for (unsigned One = 0; One < Max; ++One) {
  22. Known.Zero = Zero;
  23. Known.One = One;
  24. if (Known.hasConflict())
  25. continue;
  26. Fn(Known);
  27. }
  28. }
  29. }
  30. template<typename FnTy>
  31. void ForeachNumInKnownBits(const KnownBits &Known, FnTy Fn) {
  32. unsigned Bits = Known.getBitWidth();
  33. unsigned Max = 1 << Bits;
  34. for (unsigned N = 0; N < Max; ++N) {
  35. APInt Num(Bits, N);
  36. if ((Num & Known.Zero) != 0 || (~Num & Known.One) != 0)
  37. continue;
  38. Fn(Num);
  39. }
  40. }
  41. TEST(KnownBitsTest, AddCarryExhaustive) {
  42. unsigned Bits = 4;
  43. ForeachKnownBits(Bits, [&](const KnownBits &Known1) {
  44. ForeachKnownBits(Bits, [&](const KnownBits &Known2) {
  45. ForeachKnownBits(1, [&](const KnownBits &KnownCarry) {
  46. // Explicitly compute known bits of the addition by trying all
  47. // possibilities.
  48. KnownBits Known(Bits);
  49. Known.Zero.setAllBits();
  50. Known.One.setAllBits();
  51. ForeachNumInKnownBits(Known1, [&](const APInt &N1) {
  52. ForeachNumInKnownBits(Known2, [&](const APInt &N2) {
  53. ForeachNumInKnownBits(KnownCarry, [&](const APInt &Carry) {
  54. APInt Add = N1 + N2;
  55. if (Carry.getBoolValue())
  56. ++Add;
  57. Known.One &= Add;
  58. Known.Zero &= ~Add;
  59. });
  60. });
  61. });
  62. KnownBits KnownComputed = KnownBits::computeForAddCarry(
  63. Known1, Known2, KnownCarry);
  64. EXPECT_EQ(Known.Zero, KnownComputed.Zero);
  65. EXPECT_EQ(Known.One, KnownComputed.One);
  66. });
  67. });
  68. });
  69. }
  70. static void TestAddSubExhaustive(bool IsAdd) {
  71. unsigned Bits = 4;
  72. ForeachKnownBits(Bits, [&](const KnownBits &Known1) {
  73. ForeachKnownBits(Bits, [&](const KnownBits &Known2) {
  74. KnownBits Known(Bits), KnownNSW(Bits);
  75. Known.Zero.setAllBits();
  76. Known.One.setAllBits();
  77. KnownNSW.Zero.setAllBits();
  78. KnownNSW.One.setAllBits();
  79. ForeachNumInKnownBits(Known1, [&](const APInt &N1) {
  80. ForeachNumInKnownBits(Known2, [&](const APInt &N2) {
  81. bool Overflow;
  82. APInt Res;
  83. if (IsAdd)
  84. Res = N1.sadd_ov(N2, Overflow);
  85. else
  86. Res = N1.ssub_ov(N2, Overflow);
  87. Known.One &= Res;
  88. Known.Zero &= ~Res;
  89. if (!Overflow) {
  90. KnownNSW.One &= Res;
  91. KnownNSW.Zero &= ~Res;
  92. }
  93. });
  94. });
  95. KnownBits KnownComputed = KnownBits::computeForAddSub(
  96. IsAdd, /*NSW*/false, Known1, Known2);
  97. EXPECT_EQ(Known.Zero, KnownComputed.Zero);
  98. EXPECT_EQ(Known.One, KnownComputed.One);
  99. // The NSW calculation is not precise, only check that it's
  100. // conservatively correct.
  101. KnownBits KnownNSWComputed = KnownBits::computeForAddSub(
  102. IsAdd, /*NSW*/true, Known1, Known2);
  103. EXPECT_TRUE(KnownNSWComputed.Zero.isSubsetOf(KnownNSW.Zero));
  104. EXPECT_TRUE(KnownNSWComputed.One.isSubsetOf(KnownNSW.One));
  105. });
  106. });
  107. }
  108. TEST(KnownBitsTest, AddSubExhaustive) {
  109. TestAddSubExhaustive(true);
  110. TestAddSubExhaustive(false);
  111. }
  112. } // end anonymous namespace