Skip to content

Commit f77a69d

Browse files
authored
OptimizeInstructions: Handle all binary and unary expressions emitting zero bits (#7413)
We have many hardcoded rules, but also have general logic that computes the max bits. If the max bits are 0, we can replace with a 0. Fixes #7406
1 parent 1fd0085 commit f77a69d

File tree

2 files changed

+57
-25
lines changed

2 files changed

+57
-25
lines changed

src/passes/OptimizeInstructions.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,20 @@ struct OptimizeInstructions
304304
return EffectAnalyzer::canReorder(getPassOptions(), *getModule(), a, b);
305305
}
306306

307+
// If an expression can only have zero bits, return a constant 0 (or null if
308+
// we cannot optimize).
309+
Expression* replaceZeroBitsWithZero(Expression* curr) {
310+
// We should never be called with a constant.
311+
assert(!curr->is<Const>());
312+
313+
if (!curr->type.isInteger() || Bits::getMaxBits(curr, this) != 0) {
314+
return nullptr;
315+
}
316+
317+
auto zero = Builder(*getModule()).makeConst(Literal::makeZero(curr->type));
318+
return getDroppedChildrenAndAppend(curr, zero);
319+
}
320+
307321
void visitBinary(Binary* curr) {
308322
// If this contains dead code, don't bother trying to optimize it, the type
309323
// might change (if might not be unreachable if just one arm is, for
@@ -838,6 +852,10 @@ struct OptimizeInstructions
838852
return replaceCurrent(ret);
839853
}
840854
}
855+
// see if we can infer this is a zero
856+
if (auto* ret = replaceZeroBitsWithZero(curr)) {
857+
return replaceCurrent(ret);
858+
}
841859
// finally, try more expensive operations on the curr in
842860
// the case that they have no side effects
843861
if (!effects(curr->left).hasSideEffects()) {
@@ -1101,6 +1119,10 @@ struct OptimizeInstructions
11011119
if (auto* ret = simplifyRoundingsAndConversions(curr)) {
11021120
return replaceCurrent(ret);
11031121
}
1122+
1123+
if (auto* ret = replaceZeroBitsWithZero(curr)) {
1124+
return replaceCurrent(ret);
1125+
}
11041126
}
11051127

11061128
void visitSelect(Select* curr) {

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

+35-25
Original file line numberDiff line numberDiff line change
@@ -2833,23 +2833,38 @@
28332833
)
28342834
)
28352835
;; CHECK: (func $sext-24-div (result i32)
2836-
;; CHECK-NEXT: (i32.shr_u
2837-
;; CHECK-NEXT: (i32.const 1)
2838-
;; CHECK-NEXT: (i32.const 1)
2839-
;; CHECK-NEXT: )
2836+
;; CHECK-NEXT: (i32.const 0)
28402837
;; CHECK-NEXT: )
28412838
(func $sext-24-div (result i32)
28422839
(i32.shr_s
28432840
(i32.shl
2844-
(i32.div_s ;; this could be optimizable in theory, but currently we don't look into adds etc.
2845-
(i32.const 1)
2846-
(i32.const 2)
2841+
(i32.div_s ;; we don't precompute this, but we do know the limit on
2842+
(i32.const 1) ;; max bits, and the sign bit cannot be 1, so this all
2843+
(i32.const 2) ;; ends up as zero.
28472844
)
28482845
(i32.const 24)
28492846
)
28502847
(i32.const 24)
28512848
)
28522849
)
2850+
;; CHECK: (func $sext-24-param (param $x i32) (result i32)
2851+
;; CHECK-NEXT: (i32.shr_s
2852+
;; CHECK-NEXT: (i32.shl
2853+
;; CHECK-NEXT: (local.get $x)
2854+
;; CHECK-NEXT: (i32.const 24)
2855+
;; CHECK-NEXT: )
2856+
;; CHECK-NEXT: (i32.const 24)
2857+
;; CHECK-NEXT: )
2858+
;; CHECK-NEXT: )
2859+
(func $sext-24-param (param $x i32) (result i32)
2860+
(i32.shr_s
2861+
(i32.shl
2862+
(local.get $x) ;; we don't know what this is, and so optimize nothing
2863+
(i32.const 24)
2864+
)
2865+
(i32.const 24)
2866+
)
2867+
)
28532868
;; CHECK: (func $sext-24-and-127-128 (result i32)
28542869
;; CHECK-NEXT: (i32.and
28552870
;; CHECK-NEXT: (i32.const 127)
@@ -3178,13 +3193,7 @@
31783193
)
31793194
)
31803195
;; CHECK: (func $sext-24-shr_s-and-masked-sign (result i32)
3181-
;; CHECK-NEXT: (i32.shr_u
3182-
;; CHECK-NEXT: (i32.and
3183-
;; CHECK-NEXT: (i32.const -1)
3184-
;; CHECK-NEXT: (i32.const 2147483647)
3185-
;; CHECK-NEXT: )
3186-
;; CHECK-NEXT: (i32.const 31)
3187-
;; CHECK-NEXT: )
3196+
;; CHECK-NEXT: (i32.const 0)
31883197
;; CHECK-NEXT: )
31893198
(func $sext-24-shr_s-and-masked-sign (result i32)
31903199
(i32.shr_s
@@ -3194,8 +3203,8 @@
31943203
(i32.const -1)
31953204
(i32.const 2147483647)
31963205
)
3197-
(i32.const 31) ;; adjusted after we fixed shift computation to just look at lower 5 bits
3198-
)
3206+
(i32.const 31) ;; no sign bit, so the shift zeroes us out, and
3207+
) ;; later shifts cannot add bits, so the result is 0
31993208
(i32.const 24)
32003209
)
32013210
(i32.const 24)
@@ -6281,7 +6290,7 @@
62816290
;; CHECK: (func $mix-shifts (result i32)
62826291
;; CHECK-NEXT: (i32.shr_u
62836292
;; CHECK-NEXT: (i32.shl
6284-
;; CHECK-NEXT: (i32.const 23)
6293+
;; CHECK-NEXT: (i32.const 65535)
62856294
;; CHECK-NEXT: (i32.const 3)
62866295
;; CHECK-NEXT: )
62876296
;; CHECK-NEXT: (i32.const 8)
@@ -6290,7 +6299,7 @@
62906299
(func $mix-shifts (result i32)
62916300
(i32.shr_s
62926301
(i32.shl
6293-
(i32.const 23)
6302+
(i32.const 65535)
62946303
(i32.const -61)
62956304
)
62966305
(i32.const 168)
@@ -8407,9 +8416,11 @@
84078416
;; CHECK-NEXT: (i32.const 0)
84088417
;; CHECK-NEXT: )
84098418
;; CHECK-NEXT: (drop
8410-
;; CHECK-NEXT: (i32.and
8411-
;; CHECK-NEXT: (call $andZero
8412-
;; CHECK-NEXT: (i32.const 1234)
8419+
;; CHECK-NEXT: (block (result i32)
8420+
;; CHECK-NEXT: (drop
8421+
;; CHECK-NEXT: (call $andZero
8422+
;; CHECK-NEXT: (i32.const 1234)
8423+
;; CHECK-NEXT: )
84138424
;; CHECK-NEXT: )
84148425
;; CHECK-NEXT: (i32.const 0)
84158426
;; CHECK-NEXT: )
@@ -8425,7 +8436,8 @@
84258436
)
84268437
(drop
84278438
(i32.and
8428-
(call $andZero (i32.const 1234)) ;; side effects
8439+
(call $andZero (i32.const 1234)) ;; side effects, we must keep this, but
8440+
;; can drop it.
84298441
(i32.const 0)
84308442
)
84318443
)
@@ -11114,9 +11126,7 @@
1111411126
;; CHECK-NEXT: )
1111511127
;; CHECK-NEXT: )
1111611128
;; CHECK-NEXT: (drop
11117-
;; CHECK-NEXT: (i64.extend_i32_s
11118-
;; CHECK-NEXT: (i32.const 0)
11119-
;; CHECK-NEXT: )
11129+
;; CHECK-NEXT: (i64.const 0)
1112011130
;; CHECK-NEXT: )
1112111131
;; CHECK-NEXT: (drop
1112211132
;; CHECK-NEXT: (i32.const 1)

0 commit comments

Comments
 (0)