@@ -815,7 +815,7 @@ TEST(KnownBitsTest, ConcatBits) {
815
815
}
816
816
}
817
817
818
- TEST (KnownBitsTest, MulExhaustive ) {
818
+ TEST (KnownBitsTest, MulLowBitsExhaustive ) {
819
819
for (unsigned Bits : {1 , 4 }) {
820
820
ForeachKnownBits (Bits, [&](const KnownBits &Known1) {
821
821
ForeachKnownBits (Bits, [&](const KnownBits &Known2) {
@@ -849,4 +849,54 @@ TEST(KnownBitsTest, MulExhaustive) {
849
849
}
850
850
}
851
851
852
+ TEST (KnownBitsTest, MulHighBits) {
853
+ unsigned Bits = 8 ;
854
+ SmallVector<std::pair<int , int >, 4 > TestPairs = {
855
+ {2 , 4 }, {-2 , -4 }, {2 , -4 }, {-2 , 4 }};
856
+ for (auto [K1, K2] : TestPairs) {
857
+ KnownBits Known1 (Bits), Known2 (Bits);
858
+ if (K1 > 0 ) {
859
+ // If we only set the zeros of ~K1, Known1 could be zero. Avoid this case,
860
+ // as we can only set leading ones in the case where LHS and RHS have
861
+ // different signs, when the result is known non-zero.
862
+ Known1.Zero |= ~(K1 | 1 );
863
+ Known1.One |= 1 ;
864
+ } else {
865
+ Known1.One |= K1;
866
+ }
867
+ if (K2 > 0 ) {
868
+ // If we only set the zeros of ~K1, Known1 could be zero. Avoid this case,
869
+ // as we can only set leading ones in the case where LHS and RHS have
870
+ // different signs, when the result is known non-zero.
871
+ Known2.Zero |= ~(K2 | 1 );
872
+ Known2.One |= 1 ;
873
+ } else {
874
+ Known2.One |= K2;
875
+ }
876
+ KnownBits Computed = KnownBits::mul (Known1, Known2);
877
+ KnownBits Exact (Bits);
878
+ Exact.Zero .setAllBits ();
879
+ Exact.One .setAllBits ();
880
+
881
+ ForeachNumInKnownBits (Known1, [&](const APInt &N1) {
882
+ ForeachNumInKnownBits (Known2, [&](const APInt &N2) {
883
+ APInt Res = N1 * N2;
884
+ Exact.One &= Res;
885
+ Exact.Zero &= ~Res;
886
+ });
887
+ });
888
+
889
+ // Check that the high bits are optimal, with the caveat that mul_ov of LHS
890
+ // and RHS doesn't overflow, which is the case for our TestPairs.
891
+ APInt Mask = APInt::getHighBitsSet (
892
+ Bits, (Exact.Zero | Exact.One ).countLeadingOnes ());
893
+ Exact.Zero &= Mask;
894
+ Exact.One &= Mask;
895
+ Computed.Zero &= Mask;
896
+ Computed.One &= Mask;
897
+ EXPECT_TRUE (checkResult (" mul" , Exact, Computed, {Known1, Known2},
898
+ /* CheckOptimality=*/ true ));
899
+ }
900
+ }
901
+
852
902
} // end anonymous namespace
0 commit comments