Skip to content

Commit c679a59

Browse files
Improve getMaxBits for 0 / 0 (#7532)
The result of unsigned integer division cannot have more bits than the dividend. Fixes #7471
1 parent e2b41f2 commit c679a59

File tree

2 files changed

+76
-4
lines changed

2 files changed

+76
-4
lines changed

src/ir/bits.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,19 @@ Index getMaxBits(Expression* curr,
187187
return 32;
188188
}
189189
int32_t bitsRight = getMaxBits(c);
190-
return std::max(0, maxBitsLeft - bitsRight + 1);
190+
// Apply std::min: Result bits cannot exceed dividend bits
191+
return std::min(maxBitsLeft,
192+
std::max(0, maxBitsLeft - bitsRight + 1));
191193
}
192194
return 32;
193195
}
194196
case DivUInt32: {
195197
int32_t maxBitsLeft = getMaxBits(binary->left, localInfoProvider);
196198
if (auto* c = binary->right->dynCast<Const>()) {
197199
int32_t bitsRight = getMaxBits(c);
198-
return std::max(0, maxBitsLeft - bitsRight + 1);
200+
// Apply std::min: Result bits cannot exceed dividend bits
201+
return std::min(maxBitsLeft,
202+
std::max(0, maxBitsLeft - bitsRight + 1));
199203
}
200204
return maxBitsLeft;
201205
}
@@ -282,15 +286,19 @@ Index getMaxBits(Expression* curr,
282286
return 64;
283287
}
284288
int32_t bitsRight = getMaxBits(c);
285-
return std::max(0, maxBitsLeft - bitsRight + 1);
289+
// Apply std::min: Result bits cannot exceed dividend bits
290+
return std::min(maxBitsLeft,
291+
std::max(0, maxBitsLeft - bitsRight + 1));
286292
}
287293
return 64;
288294
}
289295
case DivUInt64: {
290296
int32_t maxBitsLeft = getMaxBits(binary->left, localInfoProvider);
291297
if (auto* c = binary->right->dynCast<Const>()) {
292298
int32_t bitsRight = getMaxBits(c);
293-
return std::max(0, maxBitsLeft - bitsRight + 1);
299+
// Apply std::min: Result bits cannot exceed dividend bits
300+
return std::min(maxBitsLeft,
301+
std::max(0, maxBitsLeft - bitsRight + 1));
294302
}
295303
return maxBitsLeft;
296304
}

test/lit/passes/optimize-instructions-mvp.wast

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11395,6 +11395,17 @@
1139511395
;; CHECK-NEXT: )
1139611396
;; CHECK-NEXT: )
1139711397
;; CHECK-NEXT: (drop
11398+
;; CHECK-NEXT: (block (result i32)
11399+
;; CHECK-NEXT: (drop
11400+
;; CHECK-NEXT: (i32.div_u
11401+
;; CHECK-NEXT: (i32.const 0)
11402+
;; CHECK-NEXT: (i32.const 0)
11403+
;; CHECK-NEXT: )
11404+
;; CHECK-NEXT: )
11405+
;; CHECK-NEXT: (i32.const 0)
11406+
;; CHECK-NEXT: )
11407+
;; CHECK-NEXT: )
11408+
;; CHECK-NEXT: (drop
1139811409
;; CHECK-NEXT: (i64.extend_i32_u
1139911410
;; CHECK-NEXT: (i64.eq
1140011411
;; CHECK-NEXT: (local.get $y)
@@ -11409,6 +11420,17 @@
1140911420
;; CHECK-NEXT: )
1141011421
;; CHECK-NEXT: )
1141111422
;; CHECK-NEXT: (drop
11423+
;; CHECK-NEXT: (block (result i64)
11424+
;; CHECK-NEXT: (drop
11425+
;; CHECK-NEXT: (i64.div_u
11426+
;; CHECK-NEXT: (i64.const 0)
11427+
;; CHECK-NEXT: (i64.const 0)
11428+
;; CHECK-NEXT: )
11429+
;; CHECK-NEXT: )
11430+
;; CHECK-NEXT: (i64.const 0)
11431+
;; CHECK-NEXT: )
11432+
;; CHECK-NEXT: )
11433+
;; CHECK-NEXT: (drop
1141211434
;; CHECK-NEXT: (i32.ge_u
1141311435
;; CHECK-NEXT: (local.get $x)
1141411436
;; CHECK-NEXT: (i32.const -2)
@@ -11433,6 +11455,17 @@
1143311455
;; CHECK-NEXT: )
1143411456
;; CHECK-NEXT: )
1143511457
;; CHECK-NEXT: (drop
11458+
;; CHECK-NEXT: (block (result i32)
11459+
;; CHECK-NEXT: (drop
11460+
;; CHECK-NEXT: (i32.div_u
11461+
;; CHECK-NEXT: (i32.const 0)
11462+
;; CHECK-NEXT: (i32.const 0)
11463+
;; CHECK-NEXT: )
11464+
;; CHECK-NEXT: )
11465+
;; CHECK-NEXT: (i32.const 0)
11466+
;; CHECK-NEXT: )
11467+
;; CHECK-NEXT: )
11468+
;; CHECK-NEXT: (drop
1143611469
;; CHECK-NEXT: (i64.extend_i32_u
1143711470
;; CHECK-NEXT: (i64.eq
1143811471
;; CHECK-NEXT: (local.get $y)
@@ -11447,6 +11480,17 @@
1144711480
;; CHECK-NEXT: )
1144811481
;; CHECK-NEXT: )
1144911482
;; CHECK-NEXT: (drop
11483+
;; CHECK-NEXT: (block (result i64)
11484+
;; CHECK-NEXT: (drop
11485+
;; CHECK-NEXT: (i64.div_u
11486+
;; CHECK-NEXT: (i64.const 0)
11487+
;; CHECK-NEXT: (i64.const 0)
11488+
;; CHECK-NEXT: )
11489+
;; CHECK-NEXT: )
11490+
;; CHECK-NEXT: (i64.const 0)
11491+
;; CHECK-NEXT: )
11492+
;; CHECK-NEXT: )
11493+
;; CHECK-NEXT: (drop
1145011494
;; CHECK-NEXT: (i32.const 1)
1145111495
;; CHECK-NEXT: )
1145211496
;; CHECK-NEXT: (drop
@@ -11683,6 +11727,11 @@
1168311727
(local.get $x)
1168411728
(i32.const -2147483648)
1168511729
))
11730+
;; i32(0) / i32(0) => i32(0) but still traps
11731+
(drop (i32.div_s
11732+
(i32.const 0)
11733+
(i32.const 0)
11734+
))
1168611735
;; i64(x) / -9223372036854775808 -> x == -9223372036854775808
1168711736
(drop (i64.div_s
1168811737
(local.get $y)
@@ -11693,6 +11742,11 @@
1169311742
(local.get $y)
1169411743
(i64.const -2147483648)
1169511744
))
11745+
;; i64(0) / i64(0) => i64(0) but still traps
11746+
(drop (i64.div_s
11747+
(i64.const 0)
11748+
(i64.const 0)
11749+
))
1169611750

1169711751
;; unsigned divs
1169811752
;; u32(x) / -2 => x >= -2
@@ -11715,6 +11769,11 @@
1171511769
(local.get $x)
1171611770
(i32.const -2147483648)
1171711771
))
11772+
;; i32(0) / i32(0) => i32(0) but still traps
11773+
(drop (i32.div_u
11774+
(i32.const 0)
11775+
(i32.const 0)
11776+
))
1171811777
;; u64(x) / -1 => u64(x == -1)
1171911778
(drop (i64.div_u
1172011779
(local.get $y)
@@ -11725,6 +11784,11 @@
1172511784
(local.get $y)
1172611785
(i64.const -9223372036854775808)
1172711786
))
11787+
;; i64(0) / i64(0) => i64(0) but still traps
11788+
(drop (i64.div_u
11789+
(i64.const 0)
11790+
(i64.const 0)
11791+
))
1172811792

1172911793
;; bool(x) | 1 ==> 1
1173011794
(drop (i32.or

0 commit comments

Comments
 (0)