Skip to content

Commit 6fa13d7

Browse files
authored
[InstCombine] Add additional known bits info for self multiply (#151202)
Closes #151043 https://alive2.llvm.org/ce/z/JyMSk8
1 parent 37fe7a9 commit 6fa13d7

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

llvm/lib/Support/KnownBits.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -888,11 +888,19 @@ KnownBits KnownBits::mul(const KnownBits &LHS, const KnownBits &RHS,
888888
Res.Zero |= (~BottomKnown).getLoBits(ResultBitsKnown);
889889
Res.One = BottomKnown.getLoBits(ResultBitsKnown);
890890

891-
// If we're self-multiplying then bit[1] is guaranteed to be zero.
892-
if (NoUndefSelfMultiply && BitWidth > 1) {
893-
assert(Res.One[1] == 0 &&
894-
"Self-multiplication failed Quadratic Reciprocity!");
895-
Res.Zero.setBit(1);
891+
if (NoUndefSelfMultiply) {
892+
// If X has at least TZ trailing zeroes, then bit (2 * TZ + 1) must be zero.
893+
unsigned TwoTZP1 = 2 * TrailZero0 + 1;
894+
if (TwoTZP1 < BitWidth)
895+
Res.Zero.setBit(TwoTZP1);
896+
897+
// If X has exactly TZ trailing zeros, then bit (2 * TZ + 2) must also be
898+
// zero.
899+
if (TrailZero0 < BitWidth && LHS.One[TrailZero0]) {
900+
unsigned TwoTZP2 = TwoTZP1 + 1;
901+
if (TwoTZP2 < BitWidth)
902+
Res.Zero.setBit(TwoTZP2);
903+
}
896904
}
897905

898906
return Res;

llvm/test/Transforms/InstCombine/known-bits.ll

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,48 @@ define i1 @extract_value_smul_fail(i8 %xx, i8 %yy) {
12441244
ret i1 %r
12451245
}
12461246

1247+
define i8 @known_self_mul_bit_0_set(i8 noundef %x) {
1248+
; CHECK-LABEL: @known_self_mul_bit_0_set(
1249+
; CHECK-NEXT: ret i8 0
1250+
;
1251+
%bit_0_set = or i8 %x, 1
1252+
%self_mul = mul i8 %bit_0_set, %bit_0_set
1253+
%r = and i8 %self_mul, 4
1254+
ret i8 %r
1255+
}
1256+
1257+
define i8 @known_self_mul_bit_0_unset(i8 noundef %x) {
1258+
; CHECK-LABEL: @known_self_mul_bit_0_unset(
1259+
; CHECK-NEXT: ret i8 0
1260+
;
1261+
%bit_0_unset = and i8 %x, -2
1262+
%self_mul = mul i8 %bit_0_unset, %bit_0_unset
1263+
%r = and i8 %self_mul, 8
1264+
ret i8 %r
1265+
}
1266+
1267+
define i8 @known_self_mul_bit_1_set_bit_0_unset(i8 noundef %x) {
1268+
; CHECK-LABEL: @known_self_mul_bit_1_set_bit_0_unset(
1269+
; CHECK-NEXT: ret i8 0
1270+
;
1271+
%lower_2_unset = and i8 %x, -4
1272+
%bit_1_set_bit_0_unset = or disjoint i8 %lower_2_unset, 2
1273+
%self_mul = mul i8 %bit_1_set_bit_0_unset, %bit_1_set_bit_0_unset
1274+
%r = and i8 %self_mul, 24
1275+
ret i8 %r
1276+
}
1277+
1278+
define i4 @known_self_mul_bit_1_set_bit_0_unset_i4(i4 noundef %x) {
1279+
; CHECK-LABEL: @known_self_mul_bit_1_set_bit_0_unset_i4(
1280+
; CHECK-NEXT: ret i4 0
1281+
;
1282+
%lower_2_unset = and i4 %x, -4
1283+
%bit_1_set_bit_0_unset = or disjoint i4 %lower_2_unset, 2
1284+
%self_mul = mul i4 %bit_1_set_bit_0_unset, %bit_1_set_bit_0_unset
1285+
%r = and i4 %self_mul, 24
1286+
ret i4 %r
1287+
}
1288+
12471289
define i8 @known_reduce_or(<2 x i8> %xx) {
12481290
; CHECK-LABEL: @known_reduce_or(
12491291
; CHECK-NEXT: ret i8 1

0 commit comments

Comments
 (0)