Skip to content

Commit 08428b3

Browse files
authored
OptimizeInstructions: Fix max bits of a local with an unreachable set (#7623)
Previously we set such locals to 64 bits, even if they were i32. This interacted with #7505 which compared the bits to the true bits of the type, which led to 64 != 32, which suggested we knew something nontrivial about the bits, and a misoptimization.
1 parent b109a1e commit 08428b3

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

src/passes/OptimizeInstructions.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ struct LocalScanner : PostWalker<LocalScanner> {
129129
Properties::getFallthrough(curr->value, passOptions, *getModule());
130130
auto& info = localInfo[curr->index];
131131
info.maxBits = std::max(info.maxBits, Bits::getMaxBits(value, this));
132+
info.maxBits = std::min(info.maxBits, getBitsForType(type));
132133
auto signExtBits = LocalInfo::kUnknown;
133134
if (Properties::getSignExtValue(value)) {
134135
signExtBits = Properties::getSignExtBits(value);

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18410,4 +18410,41 @@
1841018410
)
1841118411
)
1841218412
)
18413+
18414+
;; CHECK: (func $local-unreachable-size-matters
18415+
;; CHECK-NEXT: (local $temp i32)
18416+
;; CHECK-NEXT: (local.set $temp
18417+
;; CHECK-NEXT: (i32.const 1)
18418+
;; CHECK-NEXT: )
18419+
;; CHECK-NEXT: (drop
18420+
;; CHECK-NEXT: (i32.and
18421+
;; CHECK-NEXT: (local.get $temp)
18422+
;; CHECK-NEXT: (i32.const 1)
18423+
;; CHECK-NEXT: )
18424+
;; CHECK-NEXT: )
18425+
;; CHECK-NEXT: (local.tee $temp
18426+
;; CHECK-NEXT: (unreachable)
18427+
;; CHECK-NEXT: )
18428+
;; CHECK-NEXT: )
18429+
(func $local-unreachable-size-matters
18430+
;; The local is written 1, then later down we have an unreachable. That
18431+
;; should not confuse us as to the max bits in the local. This is a test for
18432+
;; a bug where any local with an unreachable set got assigned 64 bits, which
18433+
;; is wrong in this case and led to a misoptimization of the |and|. We
18434+
;; should not optimize it away to a 0 (we could in theory optimize it to a
18435+
;; 1, but this pass does not infer locals that precisely).
18436+
(local $temp i32)
18437+
(local.set $temp
18438+
(i32.const 1)
18439+
)
18440+
(drop
18441+
(i32.and
18442+
(local.get $temp)
18443+
(i32.const 1)
18444+
)
18445+
)
18446+
(local.tee $temp
18447+
(unreachable)
18448+
)
18449+
)
1841318450
)

0 commit comments

Comments
 (0)